Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .bun-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.4.2
1.4.4
5 changes: 2 additions & 3 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,10 @@ runs:
commit: ${{ steps.sticky.outputs.commit }}

- name: Install toolchains
uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4.3.0
uses: jdx/mise-action@8418fedb1110381a0d3ba51a7a415d7c1b884550 # v5.2.2
with:
version: 2026.9.0
version: 2026.10.17
install_args: ${{ inputs.tools }}
cache_key: ${{ inputs.tools != '' && format('mise-{0}-{1}-{2}-{3}', runner.os, runner.arch, inputs.tools, hashFiles('mise.toml', 'mise.lock', '.node-version', '.bun-version', 'package.json')) || '' }}

- name: Resolve pnpm store path
if: inputs.dependency-cache == 'true'
Expand Down
10 changes: 9 additions & 1 deletion .github/jactionlint.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
require-commit-hash: true # actions, reusable workflows and docker:// must be pinned to a full SHA / @sha256 digest
rules:
missing-timeout: off
concurrency-limits: off
unpinned-uses: error # actions, reusable workflows and docker:// must be pinned to a full SHA / @sha256 digest
self-hosted-runner:
labels:
- arm-runner
Expand All @@ -8,3 +11,8 @@ self-hosted-runner:
- blacksmith-8vcpu-ubuntu-2404
- blacksmith-8vcpu-windows-2025
- blacksmith-32vcpu-ubuntu-2404
paths:
# Other projects' repositories, pulled in as git submodules. CI never checks them out.
".repos/**":
ignore:
- ".*"
3 changes: 1 addition & 2 deletions .github/scripts/ai-review/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*
* `resolveDecision` is the pure orchestration function (I/O injected) a test
* can drive without the network; `main()` wires up the real GitHub I/O,
* writes `should_run`/`pr_number`/`head_ref`/`trigger` to `$GITHUB_OUTPUT`,
* writes `should_run`/`pr_number`/`head_sha`/`trigger` to `$GITHUB_OUTPUT`,
* and surfaces the skip reason (if any) in `$GITHUB_STEP_SUMMARY`.
*
* Run in CI as: `bun .github/scripts/ai-review/resolve.ts`.
Expand Down Expand Up @@ -374,7 +374,6 @@ function writeOutputs(result: ResolveResult, prNumber: number): void {
const entries: Record<string, string> = {
should_run: String(result.shouldRun),
pr_number: String(prNumber),
head_ref: `refs/pull/${prNumber}/head`,
head_sha: result.headSha ?? "",
trigger: result.trigger,
};
Expand Down
12 changes: 9 additions & 3 deletions .github/workflows/ai-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ on:
description: "PR number to review"
required: true
type: string
# A `/ai-review` comment on a pull request starts a review. The resolve job checks who
# commented, and the one job that can write to the pull request runs code from the default
# branch only, never from the pull request.
# jactionlint ignore=dangerous-triggers
issue_comment:
types:
- created
Expand Down Expand Up @@ -65,7 +69,6 @@ jobs:
outputs:
should_run: ${{ steps.resolve.outputs.should_run }}
pr_number: ${{ steps.resolve.outputs.pr_number }}
head_ref: ${{ steps.resolve.outputs.head_ref }}
# Every job reviews this commit, so a push during the run is never reported as reviewed.
head_sha: ${{ steps.resolve.outputs.head_sha }}
trigger: ${{ steps.resolve.outputs.trigger }}
Expand Down Expand Up @@ -161,7 +164,10 @@ jobs:
# behavior mid-rollout. Installed from the trusted checkout with npm config isolation so a
# PR-supplied `.npmrc` in the untrusted `pr` checkout can never redirect this install to a
# hostile registry.
# 2.1.280 is the first release that accepts claude-opus-5-5.
# 2.1.280 is the first release that accepts claude-opus-5-5. The CLI is installed on its
# own, not through the repository's lockfile, so nothing in the pull request's checkout
# can change what gets installed.
# jactionlint ignore=adhoc-packages
- name: Install Claude Code CLI
working-directory: trusted
run: |
Expand Down Expand Up @@ -544,7 +550,7 @@ jobs:
steps:
# Security-critical: this is the only job with write permission, so it must only ever
# execute trusted base-branch code — never the PR head. Checking out `develop` explicitly
# (never `needs.resolve.outputs.head_ref`) keeps a malicious PR from smuggling a script
# (never the PR's own ref) keeps a malicious PR from smuggling a script
# change into the one job that can write back to the PR. (For `pull_request` events GitHub
# runs the workflow file from the PR's own ref; acceptable since the auto path only admits
# same-repo PRs, whose authors hold write access anyway, and fork PRs run with a read-only
Expand Down
12 changes: 9 additions & 3 deletions .github/workflows/apply-release-notes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ jobs:
outputs:
authorized: ${{ steps.check.outputs.authorized }}
steps:
# App token needs org membership read, repo write to edit the release, and PR write to
# comment and close.
# The token reads the approver's team membership and comments on the pull request.
- id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
client-id: ${{ vars.GH_APP_CLIENT_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
permission-members: read
permission-pull-requests: write

- name: Authorize approver against supabase/cli team
id: check
Expand Down Expand Up @@ -66,11 +67,16 @@ jobs:
contents: write
pull-requests: write
steps:
# The token edits the GitHub release, deletes the branch, and comments on and closes the
# pull request. The script below runs from the pull request's own checkout, so the token
# must not be able to change workflow files.
- id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
client-id: ${{ vars.GH_APP_CLIENT_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
permission-contents: write
permission-pull-requests: write

# Checkout the PR head so reviewer edits made before approval are captured;
# apply-release-notes.ts reads from the working tree.
Expand Down Expand Up @@ -99,7 +105,7 @@ jobs:
exit 1
fi
echo "==> Applying notes for $tag"
pnpm exec bun apps/cli/scripts/apply-release-notes.ts --tag "$tag"
bun apps/cli/scripts/apply-release-notes.ts --tag "$tag"
release_url="https://github.com/${{ github.repository }}/releases/tag/${tag}"
gh pr comment "$PR_NUMBER" --repo "${{ github.repository }}" --body \
"Applied to [${tag}](${release_url}) after approval by @${APPROVER}."
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/bot-pr-auto-merge.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
name: Bot PR auto-merge

on:
# 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: [develop]
Expand All @@ -14,6 +17,9 @@ jobs:
# Other apps (coding agents, CI vendors) also open PRs here and still need a maintainer.
# Release-notes PRs are published by a maintainer approval and must never merge. Branch sync
# PRs land by fast-forward on a maintainer approval, never by a squash.
# The first condition checks who opened the pull request. The second checks who caused this
# event, so a person pushing to a bot's pull request does not get it approved.
# jactionlint ignore=bot-conditions
if: >-
contains(fromJSON('["dependabot[bot]", "supabase-cli-releaser[bot]"]'), github.event.pull_request.user.login) &&
contains(fromJSON('["dependabot[bot]", "supabase-cli-releaser[bot]"]'), github.event.sender.login) &&
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build-cli-artifacts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,11 @@ jobs:
rcodesign --version

- name: Sync versions
run: pnpm exec bun apps/cli/scripts/sync-versions.ts --version "${VERSION}"
run: bun apps/cli/scripts/sync-versions.ts --version "${VERSION}"

- name: Build CLI artifacts
timeout-minutes: ${{ inputs.build_timeout_minutes }}
run: pnpm exec bun apps/cli/scripts/build.ts --version "${VERSION}"
run: bun apps/cli/scripts/build.ts --version "${VERSION}"

- name: Verify build artifacts
run: |
Expand Down
137 changes: 137 additions & 0 deletions .github/workflows/cli-go-ci.yml

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧐 this file should be deleted — looks like this comment correctly determined that but i'm not sure how to proceed. do we delete these files ourselves or is there something we should be doing so the releaser bot handles it?

Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
name: CI

on:
pull_request:
paths:
- apps/cli-go/**
merge_group:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 MAJOR · merge-resolution · source: claude+codex

The merge resolution restores Go CI on next after its Go module and toolchain configuration were removed. Its unfiltered merge_group trigger runs jobs that reference the missing module, producing failed checks and potentially blocking a required merge-queue check.

Evidence: sync-resolution.diff:4-5 records the modify/delete conflict retaining this workflow. .github/workflows/cli-go-ci.yml:7 enables merge_group without filters; lines 28 and 119 require apps/cli-go/go.mod; lines 99-100 request go and golangci-lint; lines 105-107 disable linter installation and select apps/cli-go; line 137 defaults shell steps to that directory. The checked-out apps/ directory contains no cli-go, and mise.toml:3-5 configures only jactionlint and shellcheck.

Suggested fix: Preserve next's deletion of .github/workflows/cli-go-ci.yml when resolving the modify/delete conflict.

push:
branches:
- develop
paths:
- apps/cli-go/**

permissions:
contents: read

jobs:
test:
name: Test
runs-on: blacksmith-8vcpu-ubuntu-2404
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: apps/cli-go/go.mod
cache: true

# Required by: internal/utils/credentials/keyring_test.go
- uses: t1m0thyj/unlock-keyring@cbcf205c879ebd86add70bab3a6abfcce59a5cae # v1.2.0
- run: |
set -o pipefail
pkgs=$(go list ./pkg/... | grep -Ev 'pkg/api' | paste -sd ',' -)
go tool gotestsum -- -race -v -count=1 ./... \
-coverpkg="./cmd/...,./internal/...,${pkgs}" -coverprofile=coverage.out

# internal/start (docker-compose/v2, buildx, moby/buildkit, k8s client-go,
# aws-sdk-go-v2, notary, secret-detector) was deleted outright as
# unreachable (CLI-1966) -- this guards against silently reintroducing
# that dependency tree via some other package, since nothing else checks
# the shipped binary's size on every change.
- name: Verify the heavy orchestration dependency tree stays out of the module
run: |
set -euo pipefail
go list -deps . > /tmp/deps.txt
! grep -Eq \
'docker/compose|docker/buildx|moby/buildkit|k8s\.io/client-go|aws-sdk-go-v2' \
/tmp/deps.txt

- name: Check existing coverage cache
id: coverage-cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: apps/cli-go/coverage.out
key: cli-go-coverage-${{ github.run_id }}-v1
lookup-only: true

- name: Save coverage cache
if: steps.coverage-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: apps/cli-go/coverage.out
key: cli-go-coverage-${{ github.run_id }}-v1

coverage:
name: Coverage
needs:
- test
runs-on: blacksmith-8vcpu-ubuntu-2404
steps:
- name: Restore coverage cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: apps/cli-go/coverage.out
key: cli-go-coverage-${{ github.run_id }}-v1
fail-on-cache-miss: true
- name: Move coverage report
run: cp apps/cli-go/coverage.out coverage.out
working-directory: .
- uses: coverallsapp/github-action@8d6379e14d29928660c4ba802d8e85393440b329 # v2.3.8
with:
file: coverage.out
format: golang

lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- uses: jdx/mise-action@8418fedb1110381a0d3ba51a7a415d7c1b884550 # v5.2.2
with:
version: 2026.10.17
install_args: >-
go
golangci-lint

- uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9.3.0
with:
args: --timeout 5m --verbose
install-mode: none
only-new-issues: true
working-directory: apps/cli-go

codegen:
name: Codegen
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: apps/cli-go/go.mod
cache: true

# Regenerates from the committed api/v1-openapi.yaml snapshot, so this
# check is hermetic: it fails only when a pull request leaves pkg/api out
# of sync with the snapshot it was generated from. It deliberately does
# not compare against the live upstream spec -- doing so made unrelated
# pull requests fail together whenever staging drifted ahead of the
# committed snapshot. That drift is the API Sync workflow's job.
- run: go generate
- run: |
if ! git diff --ignore-space-at-eol --exit-code --quiet pkg; then
echo "Detected uncommitted changes after codegen. See status below:"
git diff
exit 1
fi
defaults:
run:
working-directory: apps/cli-go
44 changes: 44 additions & 0 deletions .github/workflows/cli-go-tag-pkg.yml

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as above

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Tag pkg

on:
workflow_dispatch:
inputs:
version:
description: "pkg version to tag (e.g. v1.2.2)"
required: true
type: string

permissions: {}

jobs:
tag:
name: Create pkg tag
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: develop
fetch-depth: 0
persist-credentials: false

- name: Create and push pkg tag
run: |
VERSION="${INPUTS_VERSION}"
if ! [[ "$VERSION" =~ ^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then
echo "Error: version '$VERSION' does not match semver format (e.g. v1.2.2)"
exit 1
fi
TAG="pkg/$VERSION"
if git rev-parse "$TAG" >/dev/null 2>&1; then
echo "Error: tag '$TAG' already exists"
exit 1
fi
git tag "$TAG"
git push origin "$TAG"
env:
INPUTS_VERSION: ${{ inputs.version }}
defaults:
run:
working-directory: apps/cli-go
9 changes: 5 additions & 4 deletions .github/workflows/close-stale-issues-and-prs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ on:
type: string
default: "security,pinned,do-not-close,keep-open,do not merge"

permissions:
contents: read
issues: write
pull-requests: write
permissions: {}

concurrency:
group: close-stale-issues-and-prs
Expand All @@ -35,6 +32,10 @@ jobs:
close-stale:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
issues: write
pull-requests: write
steps:
- name: Close stale issues and PRs
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
Expand Down
Loading
Loading