diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e58bd32..8e07e54 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1,13 @@ +# Default all repository changes to the CLI team. * @supabase/cli + +# Files that Dependabot updates. Either owner satisfies code-owner review; `supabase-oss` +# approves only Dependabot PRs, through dependabot.yml. +/.github/workflows/*.yml @supabase/cli @supabase-oss +/action.yml @supabase/cli @supabase-oss +/package.json @supabase/cli @supabase-oss +/bun.lock @supabase/cli @supabase-oss + +# Dependabot PRs touching this workflow still need a maintainer: it runs with secrets. +# Last matching pattern wins. +/.github/workflows/dependabot.yml @supabase/cli diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 40fb228..959db5a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,6 +8,7 @@ on: - reopened - ready_for_review - converted_to_draft + merge_group: push: branches: - main @@ -85,7 +86,7 @@ jobs: supabase -h ci: - if: ${{ always() && github.event_name == 'pull_request' }} + if: ${{ always() && (github.event_name == 'pull_request' || github.event_name == 'merge_group') }} name: CI runs-on: ubuntu-latest needs: [validate, test, github-release-fallback] diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml index c5e213c..9032b3f 100644 --- a/.github/workflows/dependabot.yml +++ b/.github/workflows/dependabot.yml @@ -1,29 +1,67 @@ # Adapted from https://docs.github.com/en/code-security/dependabot/working-with-dependabot/automating-dependabot-with-github-actions#enable-auto-merge-on-a-pull-request name: Dependabot auto-merge -on: pull_request +on: + # Dependabot-triggered pull_request runs get no Actions or environment secrets. Only this + # event lets the job use the auto-approve environment's secret. The job never checks out or + # runs code from the pull request. + # jactionlint ignore=dangerous-triggers + pull_request_target: + types: [opened, reopened, synchronize, ready_for_review] + branches: [main] concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} cancel-in-progress: true -permissions: - pull-requests: write - contents: write +permissions: {} jobs: dependabot: + name: Approve and enable auto-merge runs-on: ubuntu-latest timeout-minutes: 10 - # Only act on PRs opened by Dependabot from branches in this repository. - if: github.actor == 'dependabot[bot]' && github.repository == github.event.pull_request.head.repo.full_name + # The first condition checks who opened the pull request. The second checks who caused this + # event, so a person pushing to a Dependabot pull request does not get it approved. Only + # branches in this repository qualify. + # jactionlint ignore=bot-conditions + if: >- + github.event.pull_request.user.login == 'dependabot[bot]' && + github.event.sender.login == 'dependabot[bot]' && + github.event.pull_request.head.repo.full_name == github.repository && + !github.event.pull_request.draft + # Holds `AUTO_APPROVE_PR_PAT`; the environment only deploys from the default branch. + environment: auto-approve + # The built-in token only reads; the PAT approves and the app token enables auto-merge. + permissions: + pull-requests: read + contents: read steps: + # pull_request_target is safe here because this job never checks out PR code. # Metadata drives the non-major gating used for approval and auto-merge. - id: meta uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0 with: github-token: "${{ secrets.GITHUB_TOKEN }}" + # The org ruleset requires a code-owner review, which an app approval cannot satisfy. + # `supabase-oss` is a co-owner of the files Dependabot updates (see CODEOWNERS). A rewritten + # PR keeps its approval; skipping it avoids stacking a review per push. + - name: Approve a PR + if: ${{ steps.meta.outputs.update-type == null || steps.meta.outputs.update-type == 'version-update:semver-patch' || steps.meta.outputs.update-type == 'version-update:semver-minor' }} + run: | + set -euo pipefail + decision="$(GH_TOKEN="$READ_TOKEN" gh pr view --repo "$GITHUB_REPOSITORY" "$PR_NUMBER" --json reviewDecision --jq .reviewDecision)" + if [ "$decision" != "APPROVED" ]; then + gh pr review --approve --repo "$GITHUB_REPOSITORY" "$PR_NUMBER" + fi + env: + GH_TOKEN: ${{ secrets.AUTO_APPROVE_PR_PAT }} + READ_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.pull_request.number }} + + # The built-in GITHUB_TOKEN cannot add pull requests to a merge queue, and the merge group + # it would create would not trigger the required checks. - name: Generate token id: app-token if: ${{ steps.meta.outputs.update-type == null || steps.meta.outputs.update-type == 'version-update:semver-patch' || steps.meta.outputs.update-type == 'version-update:semver-minor' }} @@ -31,17 +69,12 @@ jobs: with: app-id: ${{ secrets.APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - - - name: Approve a PR - if: ${{ steps.meta.outputs.update-type == null || steps.meta.outputs.update-type == 'version-update:semver-patch' || steps.meta.outputs.update-type == 'version-update:semver-minor' }} - run: gh pr review --approve "$PR_URL" - env: - PR_URL: ${{ github.event.pull_request.html_url }} - GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} + permission-contents: write + permission-pull-requests: write - name: Enable auto-merge for Dependabot PRs if: ${{ steps.meta.outputs.update-type == null || steps.meta.outputs.update-type == 'version-update:semver-patch' || steps.meta.outputs.update-type == 'version-update:semver-minor' }} - run: gh pr merge --auto --squash "$PR_URL" + run: gh pr merge --auto --squash --repo "$GITHUB_REPOSITORY" "$PR_NUMBER" env: - PR_URL: ${{ github.event.pull_request.html_url }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ steps.app-token.outputs.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index aa5cec0..aa4c946 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -7,6 +7,7 @@ on: - reopened - ready_for_review - converted_to_draft + merge_group: push: branches: - main @@ -69,7 +70,7 @@ jobs: - run: supabase start e2e-check: - if: ${{ always() && github.event_name == 'pull_request' }} + if: ${{ always() && (github.event_name == 'pull_request' || github.event_name == 'merge_group') }} name: E2E runs-on: ubuntu-latest needs: [e2e] diff --git a/.github/workflows/licensed.yml b/.github/workflows/licensed.yml index 423de7a..688a4cd 100644 --- a/.github/workflows/licensed.yml +++ b/.github/workflows/licensed.yml @@ -6,6 +6,7 @@ name: Licensed on: pull_request: + merge_group: push: branches: - main @@ -38,15 +39,26 @@ jobs: id: license-inputs env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + EVENT_NAME: ${{ github.event_name }} PR_NUMBER: ${{ github.event.pull_request.number }} + MERGE_BASE_SHA: ${{ github.event.merge_group.base_sha }} + MERGE_HEAD_SHA: ${{ github.event.merge_group.head_sha }} REPOSITORY: ${{ github.repository }} run: | - if [[ "${{ github.event_name }}" != "pull_request" ]]; then + if [[ "$EVENT_NAME" == "pull_request" ]]; then + gh api "repos/${REPOSITORY}/pulls/${PR_NUMBER}/files" --paginate --jq '.[].filename' > changed-files.txt + elif [[ "$EVENT_NAME" == "merge_group" ]]; then + gh api "repos/${REPOSITORY}/compare/${MERGE_BASE_SHA}...${MERGE_HEAD_SHA}" --jq '.files[].filename' > changed-files.txt + # The compare API lists at most 300 files; check everything when the list may be cut off. + if (( $(wc -l < changed-files.txt) >= 300 )); then + echo "changed=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + else echo "changed=true" >> "$GITHUB_OUTPUT" exit 0 fi - gh api "repos/${REPOSITORY}/pulls/${PR_NUMBER}/files" --paginate --jq '.[].filename' > changed-files.txt if grep -Eq '^(\.github/workflows/licensed\.yml|\.licensed\.yml|\.licenses/.*|bun\.lock|package\.json)$' changed-files.txt; then echo "changed=true" >> "$GITHUB_OUTPUT" else