mirror of
https://github.com/supabase/setup-cli.git
synced 2026-09-27 13:17:04 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b97e5256c | ||
|
|
ab058987d8 |
@@ -1,18 +1,21 @@
|
|||||||
import { getCliPath, getDownloadArchive, getDownloadUrl } from '../src/utils'
|
import { getCliPath, getDownloadArchive, getDownloadUrl } from '../src/utils'
|
||||||
import { CLI_CONFIG_REGISTRY } from '../src/main'
|
import { shouldPinGhcrRegistry } from '../src/main'
|
||||||
import * as os from 'os'
|
|
||||||
import * as process from 'process'
|
|
||||||
import * as cp from 'child_process'
|
|
||||||
import * as path from 'path'
|
|
||||||
import * as fs from 'fs'
|
|
||||||
import * as yaml from 'js-yaml'
|
|
||||||
import * as url from 'url'
|
|
||||||
import { afterEach, expect, jest, test } from '@jest/globals'
|
import { afterEach, expect, jest, test } from '@jest/globals'
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.restoreAllMocks()
|
jest.restoreAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('pins GHCR for legacy CLI versions until registry fallback support', () => {
|
||||||
|
expect(shouldPinGhcrRegistry('1.28.0', undefined)).toBe(true)
|
||||||
|
expect(shouldPinGhcrRegistry('2.107.0', undefined)).toBe(true)
|
||||||
|
expect(shouldPinGhcrRegistry('2.108.0', undefined)).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('preserves a configured image registry', () => {
|
||||||
|
expect(shouldPinGhcrRegistry('2.107.0', 'registry.example.test')).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
test('gets download url to binary', async () => {
|
test('gets download url to binary', async () => {
|
||||||
const url = await getDownloadUrl('1.28.0')
|
const url = await getDownloadUrl('1.28.0')
|
||||||
expect(
|
expect(
|
||||||
@@ -138,26 +141,3 @@ test('keeps unversioned archive url to binary before Supabase CLI v2.99.0', asyn
|
|||||||
expect(url).not.toContain('supabase_2.98.2_')
|
expect(url).not.toContain('supabase_2.98.2_')
|
||||||
expect(url).toMatch(/\.tar\.gz$/)
|
expect(url).toMatch(/\.tar\.gz$/)
|
||||||
})
|
})
|
||||||
|
|
||||||
// shows how the runner will run a javascript action with env / stdout protocol
|
|
||||||
test('runs main action', () => {
|
|
||||||
const { env, execPath } = process
|
|
||||||
const repo = path.dirname(path.dirname(url.fileURLToPath(import.meta.url)))
|
|
||||||
const config = path.join(repo, 'action.yml')
|
|
||||||
const action = yaml.load(fs.readFileSync(config, 'utf8')) as {
|
|
||||||
inputs: { version: { default: string } }
|
|
||||||
}
|
|
||||||
const ip = path.join(repo, 'dist', 'index.js')
|
|
||||||
const stdout = cp
|
|
||||||
.execFileSync(execPath, [ip], {
|
|
||||||
env: {
|
|
||||||
...env,
|
|
||||||
RUNNER_TEMP: os.tmpdir(),
|
|
||||||
INPUT_VERSION: action.inputs.version.default
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.toString()
|
|
||||||
expect
|
|
||||||
.stringContaining(`::set-env name=${CLI_CONFIG_REGISTRY}::`)
|
|
||||||
.asymmetricMatch(stdout)
|
|
||||||
})
|
|
||||||
|
|||||||
33
dist/index.js
generated
vendored
33
dist/index.js
generated
vendored
@@ -60534,6 +60534,29 @@ const getDownloadArchive = async (version, platform = os__default.platform(), ar
|
|||||||
const getCliPath = (extractedPath, archiveFormat) => {
|
const getCliPath = (extractedPath, archiveFormat) => {
|
||||||
return archiveFormat === 'apk' ? `${extractedPath}/usr/bin` : extractedPath;
|
return archiveFormat === 'apk' ? `${extractedPath}/usr/bin` : extractedPath;
|
||||||
};
|
};
|
||||||
|
const installAlpineRuntimeDependencies = async (archiveFormat) => {
|
||||||
|
if (archiveFormat !== 'apk') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await doExec('command -v apk');
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
throw new Error('Linux musl containers need libstdc++ and libgcc to run Supabase CLI. Install them before supabase/setup-cli.');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await doExec('apk info -e libstdc++ libgcc');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
const { stdout } = await doExec('id -u');
|
||||||
|
if (stdout.trim() !== '0') {
|
||||||
|
throw new Error("Alpine/musl containers need libstdc++ and libgcc to run Supabase CLI. Add 'apk add --no-cache libstdc++ libgcc' before supabase/setup-cli, or run this job container as root.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The Supabase CLI shim in the apk dynamically links these Alpine runtime libraries.
|
||||||
|
await doExec('apk add --no-cache libstdc++ libgcc');
|
||||||
|
};
|
||||||
const determineInstalledVersion = async () => {
|
const determineInstalledVersion = async () => {
|
||||||
const { stdout } = await doExec('supabase --version');
|
const { stdout } = await doExec('supabase --version');
|
||||||
const version = stdout.trim();
|
const version = stdout.trim();
|
||||||
@@ -60544,6 +60567,11 @@ const determineInstalledVersion = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const CLI_CONFIG_REGISTRY = 'SUPABASE_INTERNAL_IMAGE_REGISTRY';
|
const CLI_CONFIG_REGISTRY = 'SUPABASE_INTERNAL_IMAGE_REGISTRY';
|
||||||
|
const REGISTRY_VERSION = '1.28.0';
|
||||||
|
const FALLBACK_VERSION = '2.108.0';
|
||||||
|
const shouldPinGhcrRegistry = (installedVersion, configuredRegistry) => !configuredRegistry &&
|
||||||
|
semverExports.gte(installedVersion, REGISTRY_VERSION) &&
|
||||||
|
semverExports.lt(installedVersion, FALLBACK_VERSION);
|
||||||
/**
|
/**
|
||||||
* The main function for the action.
|
* The main function for the action.
|
||||||
*
|
*
|
||||||
@@ -60562,13 +60590,14 @@ async function run() {
|
|||||||
? await extractZip(pathToArchive)
|
? await extractZip(pathToArchive)
|
||||||
: await extractTar(pathToArchive);
|
: await extractTar(pathToArchive);
|
||||||
const pathToCLI = getCliPath(extractedPath, download.format);
|
const pathToCLI = getCliPath(extractedPath, download.format);
|
||||||
|
await installAlpineRuntimeDependencies(download.format);
|
||||||
// Expose the tool by adding it to the PATH
|
// Expose the tool by adding it to the PATH
|
||||||
addPath(pathToCLI);
|
addPath(pathToCLI);
|
||||||
// Expose installed tool version
|
// Expose installed tool version
|
||||||
const determinedVersion = await determineInstalledVersion();
|
const determinedVersion = await determineInstalledVersion();
|
||||||
setOutput('version', determinedVersion);
|
setOutput('version', determinedVersion);
|
||||||
// Use GHCR mirror by default
|
// Use GHCR for CLI versions without registry fallback support.
|
||||||
if (version.toLowerCase() === 'latest' || semverExports.gte(version, '1.28.0')) {
|
if (shouldPinGhcrRegistry(determinedVersion.replace(/^supabase\s+/i, '').replace(/^v/i, ''), process.env[CLI_CONFIG_REGISTRY])) {
|
||||||
exportVariable(CLI_CONFIG_REGISTRY, 'ghcr.io');
|
exportVariable(CLI_CONFIG_REGISTRY, 'ghcr.io');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
dist/index.js.map
generated
vendored
2
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
26
src/main.ts
26
src/main.ts
@@ -1,13 +1,24 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import * as tc from '@actions/tool-cache'
|
import * as tc from '@actions/tool-cache'
|
||||||
import { gte } from 'semver'
|
import { gte, lt } from 'semver'
|
||||||
import {
|
import {
|
||||||
getDownloadArchive,
|
getDownloadArchive,
|
||||||
determineInstalledVersion,
|
determineInstalledVersion,
|
||||||
getCliPath
|
getCliPath,
|
||||||
|
installAlpineRuntimeDependencies
|
||||||
} from './utils.js'
|
} from './utils.js'
|
||||||
|
|
||||||
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 FALLBACK_VERSION = '2.108.0'
|
||||||
|
|
||||||
|
export const shouldPinGhcrRegistry = (
|
||||||
|
installedVersion: string,
|
||||||
|
configuredRegistry: string | undefined
|
||||||
|
): boolean =>
|
||||||
|
!configuredRegistry &&
|
||||||
|
gte(installedVersion, REGISTRY_VERSION) &&
|
||||||
|
lt(installedVersion, FALLBACK_VERSION)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main function for the action.
|
* The main function for the action.
|
||||||
@@ -37,6 +48,8 @@ export async function run(): Promise<void> {
|
|||||||
: await tc.extractTar(pathToArchive)
|
: await tc.extractTar(pathToArchive)
|
||||||
const pathToCLI = getCliPath(extractedPath, download.format)
|
const pathToCLI = getCliPath(extractedPath, download.format)
|
||||||
|
|
||||||
|
await installAlpineRuntimeDependencies(download.format)
|
||||||
|
|
||||||
// Expose the tool by adding it to the PATH
|
// Expose the tool by adding it to the PATH
|
||||||
core.addPath(pathToCLI)
|
core.addPath(pathToCLI)
|
||||||
|
|
||||||
@@ -44,8 +57,13 @@ export async function run(): Promise<void> {
|
|||||||
const determinedVersion = await determineInstalledVersion()
|
const determinedVersion = await determineInstalledVersion()
|
||||||
core.setOutput('version', determinedVersion)
|
core.setOutput('version', determinedVersion)
|
||||||
|
|
||||||
// Use GHCR mirror by default
|
// Use GHCR for CLI versions without registry fallback support.
|
||||||
if (version.toLowerCase() === 'latest' || gte(version, '1.28.0')) {
|
if (
|
||||||
|
shouldPinGhcrRegistry(
|
||||||
|
determinedVersion.replace(/^supabase\s+/i, '').replace(/^v/i, ''),
|
||||||
|
process.env[CLI_CONFIG_REGISTRY]
|
||||||
|
)
|
||||||
|
) {
|
||||||
core.exportVariable(CLI_CONFIG_REGISTRY, 'ghcr.io')
|
core.exportVariable(CLI_CONFIG_REGISTRY, 'ghcr.io')
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
31
src/utils.ts
31
src/utils.ts
@@ -157,6 +157,37 @@ export const getCliPath = (
|
|||||||
return archiveFormat === 'apk' ? `${extractedPath}/usr/bin` : extractedPath
|
return archiveFormat === 'apk' ? `${extractedPath}/usr/bin` : extractedPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const installAlpineRuntimeDependencies = async (
|
||||||
|
archiveFormat: ArchiveFormat
|
||||||
|
): Promise<void> => {
|
||||||
|
if (archiveFormat !== 'apk') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await doExec('command -v apk')
|
||||||
|
} catch {
|
||||||
|
throw new Error(
|
||||||
|
'Linux musl containers need libstdc++ and libgcc to run Supabase CLI. Install them before supabase/setup-cli.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await doExec('apk info -e libstdc++ libgcc')
|
||||||
|
return
|
||||||
|
} catch {
|
||||||
|
const { stdout } = await doExec('id -u')
|
||||||
|
if (stdout.trim() !== '0') {
|
||||||
|
throw new Error(
|
||||||
|
"Alpine/musl containers need libstdc++ and libgcc to run Supabase CLI. Add 'apk add --no-cache libstdc++ libgcc' before supabase/setup-cli, or run this job container as root."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Supabase CLI shim in the apk dynamically links these Alpine runtime libraries.
|
||||||
|
await doExec('apk add --no-cache libstdc++ libgcc')
|
||||||
|
}
|
||||||
|
|
||||||
export const getDownloadUrl = async (
|
export const getDownloadUrl = async (
|
||||||
version: string,
|
version: string,
|
||||||
githubToken?: string
|
githubToken?: string
|
||||||
|
|||||||
Reference in New Issue
Block a user