Compare commits

..

2 Commits

Author SHA1 Message Date
Prashansa Kulshrestha
adc7f6c42c docs: document the v3 tag publish flow (#455)
## Summary

- The Publish section still said to "Rebase \`v3\` branch on \`main\`",
but \`v3\` is a moving tag, not a branch — that instruction has been
stale since the v3.0.0 release moved the action to the tag-based
versioning convention.
- Documents the actual publish flow: create a \`vX.Y.Z\` release, wait
for its E2E run to pass, then move the \`v3\` tag with \`git tag -f\` +
\`git push --force\`.
- Adds a note that \`v1\`/\`v2\` predate this convention and remain real
branches, so contributors aren't confused by the difference.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-24 07:42:47 +02:00
Julien Goux
45a513f8c6 fix: allow registry fallback in supported CLI versions (#453)
The action currently pins every recent CLI to GHCR, which disables the
CLI's registry fallback and leaves image pulls exposed to GHCR
throttling.

Use the installed CLI version to keep the GHCR default for versions
before v2.108.0 and allow fallback for newer versions. Preserve a
caller's explicit registry choice.
2026-09-24 09:34:55 +05:30
4 changed files with 81 additions and 14 deletions

View File

@@ -173,13 +173,30 @@ need to perform a few setup steps before you can work on the action.
## Publish ## Publish
1. Create a new GitHub release 1. Create a new GitHub release tagged `v3.X.Y`, targeting the commit on `main`
2. Rebase `v3` branch on `main` you want to publish:
```bash
gh release create v3.X.Y --target <merge-commit-sha> --title v3.X.Y --notes "..."
```
2. Wait for the tag's E2E workflow run to pass
3. Move the `v3` major-version tag to that same commit:
```bash
git fetch --force origin main --tags
git tag -f v3 <merge-commit-sha>
git push --force origin refs/tags/v3
```
Your action is now published! :rocket: Your action is now published! :rocket:
See the > [!NOTE]
[versioning documentation](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md) >
> `v3` is a moving tag, not a branch — it always points at the latest
> `v3.x.y` release, per the
> [versioning documentation](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md).
> `v1` and `v2` predate this convention and remain real branches.
## Validate ## Validate

View File

@@ -157,7 +157,7 @@ runs:
- name: Setup Node - name: Setup Node
if: ${{ steps.node-runtime.outputs.setup-node == 'true' }} if: ${{ steps.node-runtime.outputs.setup-node == 'true' }}
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with: with:
node-version: 24 node-version: 24

View File

@@ -10,6 +10,7 @@ const originalPath = process.env.PATH;
const originalNpmUserconfig = process.env.NPM_CONFIG_USERCONFIG; const originalNpmUserconfig = process.env.NPM_CONFIG_USERCONFIG;
const originalRunnerTemp = process.env.RUNNER_TEMP; const originalRunnerTemp = process.env.RUNNER_TEMP;
const originalWorkspace = process.env.GITHUB_WORKSPACE; const originalWorkspace = process.env.GITHUB_WORKSPACE;
const originalImageRegistry = process.env.SUPABASE_INTERNAL_IMAGE_REGISTRY;
const tempDirs = new Set<string>(); const tempDirs = new Set<string>();
let mainModule: typeof import("./main.ts") | null = null; let mainModule: typeof import("./main.ts") | null = null;
@@ -21,8 +22,21 @@ afterEach(() => {
} else { } else {
process.env.NPM_CONFIG_USERCONFIG = originalNpmUserconfig; process.env.NPM_CONFIG_USERCONFIG = originalNpmUserconfig;
} }
process.env.RUNNER_TEMP = originalRunnerTemp; if (originalRunnerTemp === undefined) {
process.env.GITHUB_WORKSPACE = originalWorkspace; delete process.env.RUNNER_TEMP;
} else {
process.env.RUNNER_TEMP = originalRunnerTemp;
}
if (originalWorkspace === undefined) {
delete process.env.GITHUB_WORKSPACE;
} else {
process.env.GITHUB_WORKSPACE = originalWorkspace;
}
if (originalImageRegistry === undefined) {
delete process.env.SUPABASE_INTERNAL_IMAGE_REGISTRY;
} else {
process.env.SUPABASE_INTERNAL_IMAGE_REGISTRY = originalImageRegistry;
}
delete process.env.FAKE_CLI_VERSION; delete process.env.FAKE_CLI_VERSION;
delete process.env.FAKE_NPM_BIN; delete process.env.FAKE_NPM_BIN;
delete process.env.FAKE_NPM_INTEGRITY; delete process.env.FAKE_NPM_INTEGRITY;
@@ -743,6 +757,41 @@ test("explicit version overrides detected root lockfiles", async () => {
expect(spies.setFailed).not.toHaveBeenCalled(); expect(spies.setFailed).not.toHaveBeenCalled();
}); });
test("pins legacy installed CLI versions to GHCR", async () => {
installFakeNpm("supabase 2.107.0");
const spies = createActionSpies("2.107.0");
const { run } = await getMainModule();
await run();
expect(spies.exportVariable).toHaveBeenCalledWith(CLI_CONFIG_REGISTRY, "ghcr.io");
expect(spies.setFailed).not.toHaveBeenCalled();
});
test("uses the CLI registry fallback for installed versions that support it", async () => {
installFakeNpm("supabase 2.108.0");
const spies = createActionSpies("latest");
const { run } = await getMainModule();
await run();
expect(spies.exportVariable).not.toHaveBeenCalled();
expect(spies.setFailed).not.toHaveBeenCalled();
});
test("preserves an explicitly configured image registry for legacy CLI versions", async () => {
installFakeNpm("supabase 2.107.0");
process.env.SUPABASE_INTERNAL_IMAGE_REGISTRY = "registry.example.test";
const spies = createActionSpies("2.107.0");
const { run } = await getMainModule();
await run();
expect(spies.exportVariable).not.toHaveBeenCalled();
expect(process.env.SUPABASE_INTERNAL_IMAGE_REGISTRY).toBe("registry.example.test");
expect(spies.setFailed).not.toHaveBeenCalled();
});
test("fails when the installed CLI does not report a version", async () => { test("fails when the installed CLI does not report a version", async () => {
installFakeNpm(""); installFakeNpm("");
process.env.GITHUB_WORKSPACE = createWorkspace({ process.env.GITHUB_WORKSPACE = createWorkspace({

View File

@@ -7,6 +7,7 @@ import { fileURLToPath } from "node:url";
export const CLI_CONFIG_REGISTRY = "SUPABASE_INTERNAL_IMAGE_REGISTRY"; export const CLI_CONFIG_REGISTRY = "SUPABASE_INTERNAL_IMAGE_REGISTRY";
const REGISTRY_VERSION = "1.28.0"; const REGISTRY_VERSION = "1.28.0";
const FALLBACK_VERSION = "2.108.0";
const DEFAULT_VERSION = "latest"; const DEFAULT_VERSION = "latest";
const NPM_PACKAGE = "supabase"; const NPM_PACKAGE = "supabase";
const NPM_EXECUTABLE_ENV = "SUPABASE_SETUP_CLI_NPM"; const NPM_EXECUTABLE_ENV = "SUPABASE_SETUP_CLI_NPM";
@@ -379,13 +380,13 @@ export async function determineInstalledVersion(cliPath: string): Promise<string
return version; return version;
} }
function shouldUseGhcrRegistry(requestedVersion: string, installedVersion: string): boolean { function shouldUseGhcrRegistry(installedVersion: string): boolean {
if (requestedVersion.toLowerCase() === DEFAULT_VERSION) {
return true;
}
const concreteVersion = extractConcreteVersion(installedVersion); const concreteVersion = extractConcreteVersion(installedVersion);
return concreteVersion !== null && semver.order(concreteVersion, REGISTRY_VERSION) >= 0; return (
concreteVersion !== null &&
semver.order(concreteVersion, REGISTRY_VERSION) >= 0 &&
semver.order(concreteVersion, FALLBACK_VERSION) < 0
);
} }
export async function run(): Promise<void> { export async function run(): Promise<void> {
@@ -396,7 +397,7 @@ export async function run(): Promise<void> {
core.setOutput("version", installedVersion); core.setOutput("version", installedVersion);
core.addPath(cliPath); core.addPath(cliPath);
if (shouldUseGhcrRegistry(resolution.version, installedVersion)) { if (shouldUseGhcrRegistry(installedVersion) && !process.env[CLI_CONFIG_REGISTRY]) {
core.exportVariable(CLI_CONFIG_REGISTRY, "ghcr.io"); core.exportVariable(CLI_CONFIG_REGISTRY, "ghcr.io");
} }
} catch (error) { } catch (error) {