name: Frontend License Report Workflow on: push: branches: - V2 paths: - "frontend/package.json" - "frontend/package-lock.json" - "frontend/scripts/generate-licenses.js" pull_request: branches: - V2 paths: - "frontend/package.json" - "frontend/package-lock.json" - "frontend/scripts/generate-licenses.js" permissions: contents: read jobs: generate-frontend-license-report: runs-on: ubuntu-latest permissions: contents: write pull-requests: write repository-projects: write # Required for enabling automerge steps: - name: Harden Runner uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit - name: Checkout PR head (default) uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 persist-credentials: false - name: Setup GitHub App Bot if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false) id: setup-bot uses: ./.github/actions/setup-bot with: app-id: ${{ secrets.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - name: Checkout BASE branch (safe script) if: github.event_name == 'pull_request' uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ github.event.pull_request.base.sha }} path: base fetch-depth: 1 persist-credentials: false - name: Set up Node.js uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 with: node-version: '18' cache: 'npm' cache-dependency-path: frontend/package-lock.json - name: Install frontend dependencies working-directory: frontend env: NPM_CONFIG_IGNORE_SCRIPTS: "true" run: npm ci --ignore-scripts --audit=false --fund=false - name: Generate frontend license report (internal PR) if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false working-directory: frontend env: PR_IS_FORK: "false" run: npm run generate-licenses - name: Generate frontend license report (fork PRs, pinned) if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true env: NPM_CONFIG_IGNORE_SCRIPTS: "true" working-directory: frontend run: | mkdir -p src/assets npx --yes license-report --only=prod --output=json > src/assets/3rdPartyLicenses.json - name: Postprocess with project script (BASE version) if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true env: PR_IS_FORK: "true" run: | node base/frontend/scripts/generate-licenses.js \ --input frontend/src/assets/3rdPartyLicenses.json - name: Copy postprocessed artifacts back (fork PRs) if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true run: | mkdir -p frontend/src/assets if [ -f "base/frontend/src/assets/3rdPartyLicenses.json" ]; then cp base/frontend/src/assets/3rdPartyLicenses.json frontend/src/assets/3rdPartyLicenses.json fi if [ -f "base/frontend/src/assets/license-warnings.json" ]; then cp base/frontend/src/assets/license-warnings.json frontend/src/assets/license-warnings.json fi - name: Check for license warnings run: | if [ -f "frontend/src/assets/license-warnings.json" ]; then echo "LICENSE_WARNINGS_EXIST=true" >> $GITHUB_ENV else echo "LICENSE_WARNINGS_EXIST=false" >> $GITHUB_ENV fi # PR Event: Check licenses and comment on PR - name: Delete previous license check comments if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: github-token: ${{ steps.setup-bot.outputs.token }} script: | const { owner, repo } = context.repo; const prNumber = context.issue.number; // Get all comments on the PR const { data: comments } = await github.rest.issues.listComments({ owner, repo, issue_number: prNumber, per_page: 100 }); // Filter for license check comments const licenseComments = comments.filter(comment => comment.body.includes('## ✅ Frontend License Check Passed') || comment.body.includes('## ❌ Frontend License Check Failed') ); // Delete old license check comments for (const comment of licenseComments) { console.log(`Deleting old license check comment: ${comment.id}`); await github.rest.issues.deleteComment({ owner, repo, comment_id: comment.id }); } - name: Summarize results (fork PRs) if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true run: | { echo "## Frontend License Check" echo "" if [ "${LICENSE_WARNINGS_EXIST}" = "true" ]; then echo "❌ **Failed** – incompatible or unknown licenses found." if [ -f "frontend/src/assets/license-warnings.json" ]; then echo "" echo "### Warnings" jq -r '.warnings[] | "- \(.message)"' frontend/src/assets/license-warnings.json || true fi else echo "✅ **Passed** – no license warnings detected." fi echo "" echo "_Note: This is a fork PR. PR comments are disabled; use this summary._" } >> "$GITHUB_STEP_SUMMARY" - name: Comment on PR - License Check Results if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: github-token: ${{ steps.setup-bot.outputs.token }} script: | const { owner, repo } = context.repo; const prNumber = context.issue.number; const hasWarnings = process.env.LICENSE_WARNINGS_EXIST === 'true'; let commentBody; if (hasWarnings) { // Read warnings file to get specific issues const fs = require('fs'); let warningDetails = ''; try { const warnings = JSON.parse(fs.readFileSync('frontend/src/assets/license-warnings.json', 'utf8')); warningDetails = warnings.warnings.map(w => `- ${w.message}`).join('\n'); } catch (e) { warningDetails = 'Unable to read warning details'; } commentBody = `## ❌ Frontend License Check Failed The frontend license check has detected compatibility warnings that require review: ${warningDetails} **Action Required:** Please review these licenses to ensure they are acceptable for your use case before merging. _This check will fail the PR until license issues are resolved._`; } else { commentBody = `## ✅ Frontend License Check Passed All frontend licenses have been validated and no compatibility warnings were detected. The frontend license report has been updated successfully.`; } await github.rest.issues.createComment({ owner, repo, issue_number: prNumber, body: commentBody }); - name: Fail workflow if license warnings exist (PR only) if: github.event_name == 'pull_request' && env.LICENSE_WARNINGS_EXIST == 'true' run: | echo "❌ License warnings detected. Failing the workflow." exit 1 # Push Event: Commit license files and create PR - name: Commit changes (Push only) if: github.event_name == 'push' run: | git add frontend/src/assets/3rdPartyLicenses.json # Note: Do NOT commit license-warnings.json - it's only for PR review git diff --staged --quiet || echo "CHANGES_DETECTED=true" >> $GITHUB_ENV - name: Prepare PR body (Push only) if: github.event_name == 'push' run: | PR_BODY="Auto-generated by ${{ steps.setup-bot.outputs.app-slug }}[bot] This PR updates the frontend license report based on changes to package.json dependencies." if [ "${{ env.LICENSE_WARNINGS_EXIST }}" = "true" ]; then PR_BODY="$PR_BODY ## ⚠️ License Compatibility Warnings The following licenses may require review for corporate compatibility: $(cat frontend/src/assets/license-warnings.json | jq -r '.warnings[].message') Please review these licenses to ensure they are acceptable for your use case." fi echo "PR_BODY<> $GITHUB_ENV echo "$PR_BODY" >> $GITHUB_ENV echo "EOF" >> $GITHUB_ENV - name: Create Pull Request (Push only) id: cpr if: github.event_name == 'push' && env.CHANGES_DETECTED == 'true' uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 with: token: ${{ steps.setup-bot.outputs.token }} commit-message: "Update Frontend 3rd Party Licenses" committer: ${{ steps.setup-bot.outputs.committer }} author: ${{ steps.setup-bot.outputs.committer }} signoff: true branch: update-frontend-3rd-party-licenses base: V2 title: "Update Frontend 3rd Party Licenses" body: ${{ env.PR_BODY }} labels: Licenses,github-actions,frontend draft: false delete-branch: true sign-commits: true - name: Enable Pull Request Automerge (Push only) if: github.event_name == 'push' && steps.cpr.outputs.pull-request-operation == 'created' && env.LICENSE_WARNINGS_EXIST == 'false' run: gh pr merge --squash --auto "${{ steps.cpr.outputs.pull-request-number }}" env: GH_TOKEN: ${{ steps.setup-bot.outputs.token }} - name: Add review required label (Push only) if: github.event_name == 'push' && steps.cpr.outputs.pull-request-operation == 'created' && env.LICENSE_WARNINGS_EXIST == 'true' run: gh pr edit "${{ steps.cpr.outputs.pull-request-number }}" --add-label "license-review-required" env: GH_TOKEN: ${{ steps.setup-bot.outputs.token }}