-
Notifications
You must be signed in to change notification settings - Fork 16
chore: refactor workflows for improved parallelization #303
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 12 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
c239e85
chore: refactor workflows for improved parallelization
sapientpants fd7c733
fix: remove unused sbom generation
sapientpants 0b33278
feat: add console output to Trivy scan for visibility
sapientpants 102e51d
fix: switch Trivy to table format for console visibility
sapientpants 474c4c1
Revert "fix: switch Trivy to table format for console visibility"
sapientpants 9013170
fix: ensure Trivy SARIF upload completes before workflow fails
sapientpants 0f25610
feat: upload Trivy SARIF results as downloadable artifact
sapientpants d2eca3e
refactor: consolidate Trivy scans into single step
sapientpants e0931c4
refactor: simplify Trivy scan workflow
sapientpants 2951108
feat: enhance Trivy scanning with additional security checks
sapientpants f4da681
refactor: simplify Trivy artifact naming
sapientpants 386ed87
chore: enable Trivy debug output and progress logging
sapientpants e601f6f
fix: only fail on fixable CRITICAL/HIGH vulnerabilities
sapientpants 3a5697a
fix: fail on any fixable vulnerability regardless of severity
sapientpants 3848fff
fix: upgrade OpenSSL to fix CVE-2025-9230, CVE-2025-9231, CVE-2025-9232
sapientpants 56170aa
fix: configure Trivy to accept GPL and MPL licenses
sapientpants 3cf6674
fix: add GPL and LGPL variants to Trivy license ignore list
sapientpants b9691de
fix: remove license scanner from Trivy configuration
sapientpants 9158ef6
chore: update trivy
sapientpants 205274a
chore: update trivy
sapientpants 8be12ef
chore: refactor GitHub Actions workflow structure
sapientpants 3cbc836
fix: create dedicated CodeQL workflow to resolve Security tab warnings
sapientpants 528b1b2
chore: cleanup unused workflow files and update CodeQL schedule
sapientpants ed1da31
fix: add conditionals to prevent workflow steps when no version change
sapientpants File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -48,41 +48,25 @@ jobs: | |
| # Parallel security scans to identify vulnerabilities before release | ||
| # ============================================================================= | ||
|
|
||
| # CodeQL: Static analysis for security vulnerabilities | ||
| # Scans TypeScript/JavaScript for common security issues (XSS, SQL injection, etc.) | ||
| codeql: | ||
| security: | ||
| uses: ./.github/workflows/reusable-security.yml | ||
| with: | ||
| generate-sbom: false # SBOM generated during release for consistency | ||
| run-osv-scan: false # OSV scan runs separately below | ||
| run-codeql: true # Enable CodeQL analysis | ||
|
|
||
| # OSV (Open Source Vulnerabilities) scanning | ||
| # Uses Google's official action for comprehensive dependency vulnerability checks | ||
| # UPDATE: Quarterly review for new scanner versions (currently v2.2.1) | ||
| vulnerability: | ||
| uses: google/osv-scanner-action/.github/workflows/[email protected] | ||
| with: | ||
| # Scan entire project including all manifests (package.json, pnpm-lock.yaml) | ||
| scan-args: |- | ||
| ./ | ||
| permissions: | ||
| security-events: write # Required to upload findings to Security tab | ||
| actions: read | ||
| contents: read | ||
|
|
||
| # ============================================================================= | ||
| # UNIFIED BUILD PHASE | ||
| # Single build job that creates artifacts to be reused throughout the workflow | ||
| # ============================================================================= | ||
|
|
||
| build-once: | ||
| name: Build TypeScript Once | ||
| build: | ||
| name: Build TypeScript | ||
| # Runs after validation passes | ||
| needs: [validate, codeql, vulnerability] | ||
| needs: [validate, security] | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| artifact-name: dist-${{ github.sha }} | ||
| changed: ${{ steps.version.outputs.changed }} | ||
| version: ${{ steps.version.outputs.version }} | ||
| tag_sha: ${{ steps.tag.outputs.sha }} | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
|
|
@@ -137,69 +121,15 @@ jobs: | |
| build-manifest.json | ||
| retention-days: 1 # Only needed for this workflow run | ||
|
|
||
| # ============================================================================= | ||
| # VERSION DETERMINATION PHASE | ||
| # Determines version and creates tag BEFORE building release artifacts | ||
| # ============================================================================= | ||
|
|
||
| version: | ||
| # Now depends on build-once to have compiled code available | ||
| needs: [build-once] | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| changed: ${{ steps.version.outputs.changed }} # true if version changed | ||
| version: ${{ steps.version.outputs.version }} # semantic version number | ||
| tag_sha: ${{ steps.tag.outputs.sha }} # SHA of the created tag | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 # Full history needed for changeset detection | ||
| # SECURITY: Use RELEASE_TOKEN if available for protected branch pushes | ||
| # Falls back to GITHUB_TOKEN for standard permissions | ||
| token: ${{ secrets.RELEASE_TOKEN || secrets.GITHUB_TOKEN }} | ||
|
|
||
| # ============================================================================= | ||
| # ENVIRONMENT SETUP | ||
| # Consistent toolchain setup matching package.json requirements | ||
| # ============================================================================= | ||
|
|
||
| - name: Download build artifact | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: ${{ needs.build-once.outputs.artifact-name }} | ||
|
|
||
| - name: Install pnpm | ||
| uses: pnpm/action-setup@v4 | ||
| with: | ||
| version: 10.17.0 | ||
| run_install: false | ||
| standalone: true | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: 22 | ||
| cache: pnpm | ||
|
|
||
| - name: Install dependencies | ||
| run: pnpm install --frozen-lockfile | ||
|
|
||
| # ============================================================================= | ||
| # VERSION MANAGEMENT | ||
| # Determines if release needed based on changesets | ||
| # ============================================================================= | ||
|
|
||
| - name: Version packages | ||
| id: version | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| # Custom script validates changesets and determines version | ||
| # Only checks for version changes, doesn't update files | ||
| # FAILS IF: feat/fix commits exist without changesets | ||
| # Outputs: changed=true/false, version=X.Y.Z | ||
| node .github/scripts/version-and-release.js --check-only | ||
| node .github/scripts/version-and-release.js | ||
|
|
||
| - name: Create and push tag | ||
| # Create tag BEFORE building artifacts so they're associated with the tag | ||
|
|
@@ -230,13 +160,13 @@ jobs: | |
|
|
||
| prepare-release-assets: | ||
| # Builds release artifacts using the tagged commit | ||
| needs: [version, build-once] | ||
| if: needs.version.outputs.changed == 'true' | ||
| needs: [build] | ||
| if: needs.build.outputs.changed == 'true' | ||
| uses: ./.github/workflows/reusable-prepare-assets.yml | ||
| with: | ||
| version: ${{ needs.version.outputs.version }} | ||
| tag_sha: ${{ needs.version.outputs.tag_sha }} | ||
| build_artifact: ${{ needs.build-once.outputs.artifact-name }} | ||
| version: ${{ needs.build.outputs.version }} | ||
| tag_sha: ${{ needs.build.outputs.tag_sha }} | ||
| build_artifact: ${{ needs.build.outputs.artifact-name }} | ||
| enable_docker: ${{ vars.ENABLE_DOCKER_RELEASE == 'true' }} | ||
| docker_platforms: 'linux/amd64,linux/arm64' | ||
| enable_npm: ${{ vars.ENABLE_NPM_RELEASE == 'true' }} | ||
|
|
@@ -249,7 +179,7 @@ jobs: | |
| commit-version: | ||
| name: Commit Version Changes | ||
| # Only runs after all assets are successfully prepared | ||
| needs: [prepare-release-assets, version, build-once] | ||
| needs: [prepare-release-assets, build] | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| version: ${{ needs.prepare-release-assets.outputs.version }} | ||
|
|
@@ -263,7 +193,7 @@ jobs: | |
| - name: Download build artifact | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: ${{ needs.build-once.outputs.artifact-name }} | ||
| name: ${{ needs.build.outputs.artifact-name }} | ||
|
|
||
| - name: Install pnpm | ||
| # Required for updating package.json version | ||
|
|
@@ -326,7 +256,7 @@ jobs: | |
| create-release: | ||
| name: Create GitHub Release | ||
| # Only runs after version is committed | ||
| needs: [commit-version, prepare-release-assets, build-once, version] | ||
| needs: [commit-version, prepare-release-assets, build] | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| released: ${{ steps.release.outputs.released }} | ||
|
|
@@ -341,7 +271,7 @@ jobs: | |
| - name: Download build artifact | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: ${{ needs.build-once.outputs.artifact-name }} | ||
| name: ${{ needs.build.outputs.artifact-name }} | ||
|
|
||
| - name: Install pnpm | ||
| uses: pnpm/action-setup@v4 | ||
|
|
@@ -366,7 +296,7 @@ jobs: | |
| - name: Create release artifacts | ||
| run: | | ||
| VERSION="${{ needs.prepare-release-assets.outputs.version }}" | ||
| TAG_SHA="${{ needs.version.outputs.tag_sha }}" | ||
| TAG_SHA="${{ needs.build.outputs.tag_sha }}" | ||
| tar -czf dist-${VERSION}-${TAG_SHA:0:7}.tar.gz dist/ | ||
| zip -r dist-${VERSION}-${TAG_SHA:0:7}.zip dist/ | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,43 +40,14 @@ jobs: | |
| uses: ./.github/workflows/reusable-validate.yml | ||
| secrets: | ||
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | ||
| with: | ||
| validate-changesets: true | ||
|
|
||
| # CodeQL: Static security analysis for TypeScript/JavaScript | ||
| # Security: Static security analysis for TypeScript/JavaScript | ||
| # Scans for: XSS, injection attacks, insecure patterns | ||
| # Results appear in Security tab of the PR | ||
| codeql: | ||
| security: | ||
| uses: ./.github/workflows/reusable-security.yml | ||
| with: | ||
| generate-sbom: false # Skip SBOM for PRs (generated at release) | ||
| run-osv-scan: false # OSV runs separately below | ||
| run-codeql: true # Enable CodeQL scanning | ||
|
|
||
| # OSV: Dependency vulnerability scanning | ||
| # Uses Google's database of known vulnerabilities | ||
| # UPDATE: Check quarterly for new versions (currently v2.2.2) | ||
| vulnerability: | ||
| uses: google/osv-scanner-action/.github/workflows/[email protected] | ||
|
|
||
| # ============================================================================= | ||
| # WORKFLOW VALIDATION | ||
| # Lint GitHub Actions workflow files for errors | ||
| # ============================================================================= | ||
|
|
||
| # Actionlint: Validate GitHub Actions workflow syntax and best practices | ||
| # Catches: undefined outputs, typos, bash errors, incorrect action inputs | ||
| actionlint: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Run actionlint | ||
| # Uses the official actionlint Docker action | ||
| # Automatically detects all workflow files in .github/workflows/ | ||
| uses: reviewdog/action-actionlint@v1 | ||
| with: | ||
| fail_level: error # Fail the job if errors are found | ||
| reporter: github-pr-check # Report errors as PR checks | ||
|
|
||
| # ============================================================================= | ||
| # DOCKER CONTAINER VALIDATION | ||
|
|
@@ -94,47 +65,6 @@ jobs: | |
| save-artifact: false # Don't save artifact for PRs | ||
| image-name: 'sonarqube-mcp-server-pr' | ||
|
|
||
| # ============================================================================= | ||
| # CHANGESET VALIDATION | ||
| # Ensures features and fixes have proper changelog entries | ||
| # ============================================================================= | ||
|
|
||
| # Changeset check - runs in parallel with other jobs | ||
| changeset: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 # Full history needed to compare with main | ||
|
|
||
| - name: Install pnpm | ||
| uses: pnpm/action-setup@v4 | ||
| with: | ||
| version: 10.17.0 # Pinned: Match package.json packageManager | ||
| run_install: false | ||
| standalone: true | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: 22 # Pinned: Match package.json engines.node | ||
| cache: pnpm | ||
|
|
||
| - name: Install dependencies | ||
| run: pnpm install --frozen-lockfile | ||
|
|
||
| - name: Fetch main branch | ||
| # Need main branch to compare changesets | ||
| run: git fetch origin main:main | ||
|
|
||
| - name: Changeset status | ||
| # Validates that changesets exist for features/fixes | ||
| # FAILS IF: feat/fix commits exist without changesets | ||
| # To fix: Run 'pnpm changeset' and commit the generated file | ||
| # For non-code changes: Run 'pnpm changeset --empty' | ||
| run: pnpm changeset:status | ||
|
|
||
| # ============================================================================= | ||
| # FINAL STATUS CHECK | ||
| # Single job to verify all parallel checks succeeded | ||
|
|
@@ -143,7 +73,7 @@ jobs: | |
| # Final status check - ensures all jobs passed | ||
| # Required for branch protection rules | ||
| pr-status: | ||
| needs: [validate, codeql, vulnerability, actionlint, changeset, docker] | ||
| needs: [validate, security, docker] | ||
| if: always() # Run even if previous jobs failed | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
|
|
@@ -152,11 +82,8 @@ jobs: | |
| # This single check can be used as a required status check | ||
| # FAILS IF: Any validation job failed | ||
| # Common failures: | ||
| # - validate: Tests fail, coverage below 80%, lint errors | ||
| # - codeql: Security vulnerabilities detected | ||
| # - vulnerability: Vulnerable dependencies found | ||
| # - actionlint: Workflow syntax errors or best practice violations | ||
| # - changeset: Missing changeset for feat/fix commits | ||
| # - validate: Tests fail, coverage below 80%, lint errors, workflow errors, missing changesets | ||
| # - security: Security vulnerabilities, vulnerable dependencies, audit failures | ||
| # - docker: Container vulnerabilities or build failures (when enabled) | ||
| run: | | ||
| # Check Docker job status | ||
|
|
@@ -176,18 +103,12 @@ jobs: | |
| fi | ||
|
|
||
| if [ "${{ needs.validate.result }}" != "success" ] || \ | ||
| [ "${{ needs.codeql.result }}" != "success" ] || \ | ||
| [ "${{ needs.vulnerability.result }}" != "success" ] || \ | ||
| [ "${{ needs.actionlint.result }}" != "success" ] || \ | ||
| [ "${{ needs.changeset.result }}" != "success" ] || \ | ||
| [ "${{ needs.security.result }}" != "success" ] || \ | ||
| [ "$DOCKER_FAILED" == "true" ]; then | ||
| echo "❌ PR validation failed" | ||
| # Check individual job results for debugging | ||
| echo "Validate: ${{ needs.validate.result }}" | ||
| echo "CodeQL: ${{ needs.codeql.result }}" | ||
| echo "Vulnerability: ${{ needs.vulnerability.result }}" | ||
| echo "Actionlint: ${{ needs.actionlint.result }}" | ||
| echo "Changeset: ${{ needs.changeset.result }}" | ||
| echo "Security: ${{ needs.security.result }}" | ||
| echo "Docker: ${{ needs.docker.result }}" | ||
| exit 1 | ||
| fi | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -176,30 +176,43 @@ jobs: | |
|
|
||
| - name: Run Trivy vulnerability scanner | ||
| # SECURITY: Scan image for vulnerabilities before any distribution | ||
| # FAILS IF: Critical or high vulnerabilities found (configurable) | ||
| # NOTE: Multi-platform OCI exports cannot be scanned from tar files | ||
| # Will fail workflow if CRITICAL or HIGH vulnerabilities found | ||
| if: steps.build-config.outputs.can_load == 'true' || !contains(inputs.platforms, ',') | ||
| uses: aquasecurity/[email protected] | ||
| with: | ||
| input: ${{ steps.scan-config.outputs.scan_input }} | ||
| image-ref: ${{ steps.scan-config.outputs.scan_image_ref }} | ||
| format: 'sarif' # GitHub Security format | ||
| exit-code: '1' # Fail if vulnerabilities found | ||
| format: 'sarif' | ||
| hide-progress: false | ||
| output: 'trivy-results.sarif' | ||
| severity: 'CRITICAL,HIGH' # Fail on serious vulnerabilities | ||
| ignore-unfixed: false # Include unfixed CVEs | ||
| exit-code: '1' # Fail workflow if vulnerabilities found | ||
| trivyignores: '.trivyignore' # Use ignore file for false positives | ||
| severity: 'CRITICAL,HIGH' | ||
| scanners: 'vuln,secret,misconfig,license' | ||
| ignore-unfixed: false | ||
| trivyignores: '.trivyignore' | ||
| version: 'latest' | ||
| env: | ||
| TRIVY_DEBUG: 'true' | ||
|
|
||
| - name: Upload Trivy results to GitHub Security | ||
| # Always upload results, even if scan fails | ||
| # Results viewable at: Security > Code scanning alerts | ||
| # Only upload if Trivy actually ran (not for multi-platform builds) | ||
| if: always() && (steps.build-config.outputs.can_load == 'true' || !contains(inputs.platforms, ',')) | ||
| uses: github/codeql-action/upload-sarif@v3 | ||
| with: | ||
| sarif_file: 'trivy-results.sarif' | ||
| category: 'container-scan-${{ github.event_name }}' | ||
|
|
||
| - name: Upload Trivy SARIF as artifact | ||
| # Upload SARIF file as artifact for debugging and inspection | ||
| if: always() && (steps.build-config.outputs.can_load == 'true' || !contains(inputs.platforms, ',')) | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: trivy-${{ github.sha }} | ||
| path: trivy-results.sarif | ||
| retention-days: 7 | ||
|
|
||
| # ============================================================================= | ||
| # ARTIFACT STORAGE | ||
| # Save Docker image for reuse in publish workflow | ||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.