From 70c670199c059b24431d38dc0a06c63ab1246f79 Mon Sep 17 00:00:00 2001 From: yifeliu Date: Tue, 28 Jul 2026 15:57:38 -0700 Subject: [PATCH] [CI] add basic ci --- .github/PULL_REQUEST_TEMPLATE.md | 19 ++++++ .github/dependabot.yml | 60 ++++++++++++++++++ .github/labeler.yml | 47 ++++++++++++++ .github/labels.yml | 94 +++++++++++++++++++++++++++ .github/workflows/ci.yml | 102 ++++++++++++++++++++++++++++++ .github/workflows/codeql.yml | 60 ++++++++++++++++++ .github/workflows/pr-labeler.yml | 21 ++++++ .github/workflows/pre-commit.yml | 76 ++++++++++++++++++++++ .github/workflows/sync-labels.yml | 27 ++++++++ LICENSE | 2 +- 10 files changed, 507 insertions(+), 1 deletion(-) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/dependabot.yml create mode 100644 .github/labeler.yml create mode 100644 .github/labels.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/codeql.yml create mode 100644 .github/workflows/pr-labeler.yml create mode 100644 .github/workflows/pre-commit.yml create mode 100644 .github/workflows/sync-labels.yml diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..db2c892 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,19 @@ +## What this PR does + + + +## Why we need it + + + +Fixes # + +## How to test + + + +## Checklist + +- [ ] Tests added/updated (if applicable) +- [ ] Docs updated (if applicable) +- [ ] `make test` passes locally diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..6973c0e --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,60 @@ +version: 2 +updates: + # Backend Go module + - package-ecosystem: "gomod" + directory: "/backend" + schedule: + interval: "weekly" + day: "saturday" + labels: + - "dependencies" + - "backend" + groups: + k8s: + patterns: + - "k8s.io/*" + - "sigs.k8s.io/*" + ignore: + # Pin to the client-go line that matches the cluster we target; major and + # minor bumps here change API behavior and should be deliberate. + - dependency-name: "k8s.io/*" + update-types: ["version-update:semver-major", "version-update:semver-minor"] + - dependency-name: "sigs.k8s.io/*" + update-types: ["version-update:semver-major", "version-update:semver-minor"] + + # Frontend npm package + - package-ecosystem: "npm" + directory: "/frontend" + schedule: + interval: "weekly" + day: "saturday" + labels: + - "dependencies" + - "frontend" + groups: + # Next.js and React move together; separate PRs tend to break the build. + next: + patterns: + - "next" + - "eslint-config-next" + react: + patterns: + - "react" + - "react-dom" + - "@types/react" + - "@types/react-dom" + testing: + patterns: + - "vitest" + - "@vitest/*" + - "@testing-library/*" + + # GitHub Actions used by the workflows + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + day: "saturday" + labels: + - "dependencies" + - "ci" diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000..e2b7842 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,47 @@ +# Auto-labeling rules applied by .github/workflows/pr-labeler.yml. +# Paths are repo-root relative; in OME these same labels were scoped under +# web-console/. + +# Frontend +frontend: + - changed-files: + - any-glob-to-any-file: 'frontend/**/*' + +# Backend +backend: + - changed-files: + - any-glob-to-any-file: 'backend/**/*' + +# CI/CD +ci: + - changed-files: + - any-glob-to-any-file: + - '.github/**/*' + - '.pre-commit-config.yaml' + - 'Makefile' + +# Documentation +documentation: + - changed-files: + - any-glob-to-any-file: + - '**/*.md' + +# Tests +tests: + - changed-files: + - any-glob-to-any-file: + - 'backend/**/*_test.go' + - 'frontend/src/**/*.test.*' + - 'frontend/src/**/*.spec.*' + - 'frontend/src/test/**/*' + +# Dependencies +dependencies: + - changed-files: + - any-glob-to-any-file: + - 'backend/go.mod' + - 'backend/go.sum' + - 'frontend/package.json' + - 'frontend/package-lock.json' + - 'go.work' + - 'go.work.sum' diff --git a/.github/labels.yml b/.github/labels.yml new file mode 100644 index 0000000..7a3f8bc --- /dev/null +++ b/.github/labels.yml @@ -0,0 +1,94 @@ +# Label definitions synced by .github/workflows/sync-labels.yml. +# Colors are carried over from the OME repository so the two stay visually consistent. + +# ============================================================================= +# Component Labels +# ============================================================================= +- name: frontend + color: "F472B6" + description: "Frontend/UI changes" + +- name: backend + color: "DB2777" + description: "Backend API changes" + +- name: ci + color: "BFD4F2" + description: "CI/CD changes" + +- name: documentation + color: "0075CA" + description: "Documentation changes" + +- name: dependencies + color: "0366D6" + description: "Dependency updates" + +- name: tests + color: "C2E0C6" + description: "Test changes" + +# ============================================================================= +# Kind Labels +# ============================================================================= +- name: kind/bug + color: "D73A4A" + description: "Something isn't working" + +- name: kind/feature + color: "A2EEEF" + description: "New feature or request" + +- name: kind/enhancement + color: "84B6EB" + description: "Improvement to existing functionality" + +- name: kind/documentation + color: "0075CA" + description: "Documentation improvements" + +- name: kind/cleanup + color: "FEF2C0" + description: "Code cleanup or refactoring" + +- name: kind/breaking-change + color: "B60205" + description: "Breaking change" + +# ============================================================================= +# Priority Labels +# ============================================================================= +- name: priority/critical + color: "B60205" + description: "Critical priority" + +- name: priority/high + color: "D93F0B" + description: "High priority" + +- name: priority/medium + color: "FBCA04" + description: "Medium priority" + +- name: priority/low + color: "0E8A16" + description: "Low priority" + +# ============================================================================= +# Status Labels +# ============================================================================= +- name: status/wip + color: "FBCA04" + description: "Work in progress" + +- name: status/blocked + color: "B60205" + description: "Blocked by another issue or PR" + +- name: status/needs-review + color: "0E8A16" + description: "Needs review" + +- name: status/needs-rebase + color: "E99695" + description: "Needs rebase on main" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9a5c33d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,102 @@ +name: CI + +on: + push: + branches: [main, release-*] + pull_request: + branches: [main, release-*] + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + # Frontend checks - lint, format, typecheck, build, test + frontend: + name: Frontend + runs-on: ubuntu-latest + timeout-minutes: 15 + defaults: + run: + working-directory: frontend + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: '23' + cache: npm + cache-dependency-path: frontend/package-lock.json + + - name: Install dependencies + run: npm ci + + - name: Run ESLint + run: npm run lint + + - name: Run Prettier check + run: npm run format:check + + - name: Run TypeScript type check + run: npm run typecheck + + - name: Build + run: npm run build + + - name: Run tests + run: npm run test + + # Backend checks - vet, build, test + backend: + name: Backend + runs-on: ubuntu-latest + timeout-minutes: 10 + defaults: + run: + working-directory: backend + steps: + - name: Checkout code + uses: actions/checkout@v6 + + # Version comes from go.work so CI can never drift from the repo. + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.work + cache: true + cache-dependency-path: backend/go.sum + + - name: Download dependencies + run: go mod download + + - name: Run go vet + run: go vet ./... + + - name: Build + run: go build ./... + + - name: Run tests + run: go test -race ./... + + # Single job for branch protection to require. + summary: + name: CI Summary + runs-on: ubuntu-latest + needs: [frontend, backend] + if: always() + steps: + - name: Check results + run: | + # Treat anything other than success (failure, cancelled, skipped) as a + # failure, so a cancelled job can never report the suite as green. + if [[ "${{ needs.frontend.result }}" != "success" ]] || \ + [[ "${{ needs.backend.result }}" != "success" ]]; then + echo "::error::CI failed (frontend=${{ needs.frontend.result }}, backend=${{ needs.backend.result }})" + exit 1 + fi + echo "CI passed successfully" diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..056b084 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,60 @@ +name: CodeQL + +# The backend holds cluster credentials and the frontend renders cluster data, +# so both sides are worth scanning. +on: + push: + branches: [main] + pull_request: + branches: [main] + schedule: + # Weekly, so newly published queries reach the default branch without a push. + - cron: '30 4 * * 1' + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + security-events: write + actions: read + contents: read + strategy: + fail-fast: false + matrix: + include: + - language: go + build-mode: autobuild + - language: javascript-typescript + build-mode: none + steps: + - name: Checkout code + uses: actions/checkout@v6 + + # autobuild for Go needs a toolchain matching the workspace. + - name: Setup Go + if: matrix.language == 'go' + uses: actions/setup-go@v6 + with: + go-version-file: go.work + cache: true + cache-dependency-path: backend/go.sum + + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + + - name: Perform CodeQL analysis + uses: github/codeql-action/analyze@v4 + with: + category: /language:${{ matrix.language }} diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml new file mode 100644 index 0000000..649391e --- /dev/null +++ b/.github/workflows/pr-labeler.yml @@ -0,0 +1,21 @@ +name: Auto Label PRs + +on: + pull_request_target: + types: [opened, synchronize, reopened] + +permissions: + contents: read + pull-requests: write + +jobs: + label: + runs-on: ubuntu-latest + steps: + - name: Auto-label by file changes + uses: actions/labeler@v6 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" + configuration-path: .github/labeler.yml + # Never strip labels a human added by hand. + sync-labels: false diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000..b1d89fe --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,76 @@ +name: Pre-commit + +# Pull requests only. On a push to main the checkout leaves HEAD on the main +# branch, which the no-commit-to-branch hook is designed to reject. +on: + pull_request: + branches: [main, release-*] + types: [opened, synchronize, reopened] + +permissions: + contents: read + pull-requests: write + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + pre-commit: + name: Pre-commit Checks + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.work + cache: true + cache-dependency-path: backend/go.sum + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: '23' + cache: npm + cache-dependency-path: frontend/package-lock.json + + # The prettier-check, eslint and typecheck hooks shell out to the + # frontend's local binaries, so node_modules must exist first. + - name: Install frontend dependencies + working-directory: frontend + run: npm ci + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Install pre-commit + run: pip install pre-commit + + - name: Run pre-commit (commit stage) + id: pre-commit + run: pre-commit run --all-files --show-diff-on-failure + + - name: Run pre-commit (push stage) + id: pre-commit-push + run: pre-commit run --all-files --hook-stage pre-push --show-diff-on-failure + + - name: Post failure comment on PR + if: failure() && (steps.pre-commit.outcome == 'failure' || steps.pre-commit-push.outcome == 'failure') + uses: actions/github-script@v7 + with: + script: | + const body = `⚠️ **Pre-commit checks failed**\n\nPlease run the following locally and commit the fixes:\n\`\`\`bash\npre-commit run --all-files\npre-commit run --all-files --hook-stage pre-push\ngit add -u && git commit\n\`\`\`\nSee [CONTRIBUTING.md](../blob/main/CONTRIBUTING.md#pre-commit-check) for setup instructions.`; + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: body + }); diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml new file mode 100644 index 0000000..e801345 --- /dev/null +++ b/.github/workflows/sync-labels.yml @@ -0,0 +1,27 @@ +name: Sync Labels + +on: + push: + branches: + - main + paths: + - '.github/labels.yml' + workflow_dispatch: + +permissions: + contents: read + issues: write + +jobs: + sync: + name: Sync repository labels + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Sync labels + uses: EndBug/label-sync@v2 + with: + config-file: .github/labels.yml + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/LICENSE b/LICENSE index b49bfd7..7705003 100644 --- a/LICENSE +++ b/LICENSE @@ -48,7 +48,7 @@ "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally - submitted to the Licensor for inclusion in the Work by the copyright owner + submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent