diff --git a/.boundaries-baseline.json b/.boundaries-baseline.json index 4ca677e4538..95a7a4e2fed 100644 --- a/.boundaries-baseline.json +++ b/.boundaries-baseline.json @@ -1,3 +1,3 @@ { - "issues": 163 + "issues": 152 } diff --git a/.github/workflows/util-update-boundaries-baseline.yml b/.github/workflows/util-update-boundaries-baseline.yml new file mode 100644 index 00000000000..baab13cc3d5 --- /dev/null +++ b/.github/workflows/util-update-boundaries-baseline.yml @@ -0,0 +1,108 @@ +name: 'Util: Update Boundaries Baseline' + +on: + schedule: + # Run every day at 03:00 UTC + - cron: '0 3 * * *' + workflow_dispatch: # Allow manual trigger for testing + +permissions: {} + +jobs: + update-baseline: + name: Lower boundaries baseline + # Default-branch-only: a dispatch from a feature branch would cut the update + # branch from that branch's HEAD and automerge it into master. + if: | + github.ref_name == github.event.repository.default_branch && + (github.event_name == 'workflow_dispatch' || + (github.event_name == 'schedule' && github.repository == 'n8n-io/n8n')) + runs-on: ${{ vars.RUNNER_PROVIDER == 'github' && 'ubuntu-latest' || 'blacksmith-4vcpu-ubuntu-2204' }} + # Least-privilege GITHUB_TOKEN: checkout only needs read. The branch push and + # the PR use the scoped app token below. + permissions: + contents: read + outputs: + pull-request-number: ${{ steps.create-pr.outputs.pull-request-number }} + steps: + - name: Generate GitHub App Token + id: generate-token + uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 + with: + app-id: ${{ secrets.N8N_ASSISTANT_APP_ID }} + private-key: ${{ secrets.N8N_ASSISTANT_PRIVATE_KEY }} + permission-contents: write + permission-pull-requests: write + + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + token: ${{ steps.generate-token.outputs.token }} + # create-pull-request pushes with its own token input, not the git remote creds. + persist-credentials: false + + # The baseline is the post-build count, so the full build must run first. + # See scripts/check-boundaries.mjs. + - name: Setup Node.js, install dependencies and build + uses: ./.github/actions/setup-nodejs + + # The check script writes the current count as is. The nightly only lowers + # the number: a higher count means master regressed, and raising the + # baseline would hide that from every PR. + - name: Recount boundaries issues + id: recount + run: | + BEFORE="$(node -p 'require("./.boundaries-baseline.json").issues')" + pnpm boundaries:baseline + AFTER="$(node -p 'require("./.boundaries-baseline.json").issues')" + echo "before=$BEFORE" >> "$GITHUB_OUTPUT" + echo "after=$AFTER" >> "$GITHUB_OUTPUT" + if [ "$AFTER" -gt "$BEFORE" ]; then + git checkout -- .boundaries-baseline.json + echo "::error::Boundaries issues on master ($AFTER) exceed the baseline ($BEFORE). The baseline is not raised. Fix the regression on master." + exit 1 + fi + if [ "$AFTER" -eq "$BEFORE" ]; then + echo "Baseline unchanged at $BEFORE issues" + echo "has_changes=false" >> "$GITHUB_OUTPUT" + else + echo "Baseline lowered from $BEFORE to $AFTER issues" + echo "has_changes=true" >> "$GITHUB_OUTPUT" + fi + + - name: Create Pull Request + if: steps.recount.outputs.has_changes == 'true' + id: create-pr + uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 + with: + token: ${{ steps.generate-token.outputs.token }} + commit-message: 'chore: Lower boundaries baseline (no-changelog)' + labels: 'automation:scheduled-update' + title: 'chore: Lower boundaries baseline (no-changelog)' + body: | + This automated PR lowers the `turbo boundaries` ratchet baseline + from ${{ steps.recount.outputs.before }} to ${{ steps.recount.outputs.after }} issues. + + Master has fewer undeclared-dependency and reach-in import issues + than the committed baseline. This PR locks in the lower count so + new violations cannot use the slack. + + The nightly never raises the baseline. A count above the baseline + fails the workflow instead. + + _Generated by the nightly boundaries baseline workflow._ + branch: update-boundaries-baseline + base: master + delete-branch: true + author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> + committer: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> + + approve-and-automerge: + needs: [update-baseline] + if: needs.update-baseline.outputs.pull-request-number != '' + # The callee's app credentials live on the release environment and cannot + # be forwarded as named secrets by the caller. + uses: ./.github/workflows/util-approve-and-set-automerge.yml # zizmor: ignore[secrets-inherit] + secrets: inherit + with: + pull-request-number: ${{ needs.update-baseline.outputs.pull-request-number }} diff --git a/scripts/check-boundaries.mjs b/scripts/check-boundaries.mjs index be1154c6726..ac36e7226d2 100644 --- a/scripts/check-boundaries.mjs +++ b/scripts/check-boundaries.mjs @@ -6,8 +6,10 @@ * committed baseline — new code stays clean, the backlog burns down over time. * * Mirrors the incremental-cleanup approach already used by the Playwright - * janitor (`.janitor-baseline.json`). Baseline is updated manually after real - * fixes, never automatically. + * janitor (`.janitor-baseline.json`). The nightly workflow + * `util-update-boundaries-baseline.yml` lowers the baseline when master has + * fewer issues. Nothing raises it automatically: a count above the baseline + * fails the nightly instead. * * The baseline is the POST-BUILD count: CI's lint job builds dependencies before * this check runs, and built dist trees surface ~8 extra issues that a cold