mirror of
https://github.com/supabase/setup-cli.git
synced 2026-09-27 05:07:02 +00:00
Compare commits
9 Commits
codex/npm-
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
abb4947a33 | ||
|
|
aa3515eac4 | ||
|
|
c44671e41e | ||
|
|
6ffe784b57 | ||
|
|
fddb7422b0 | ||
|
|
46f7f98c7f | ||
|
|
00444eea07 | ||
|
|
4c16bf7a1f | ||
|
|
23ef4b0416 |
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
@@ -46,13 +46,12 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
version: [1.0.0, latest]
|
||||
version: [1.178.2, latest, beta]
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: ./
|
||||
with:
|
||||
version: ${{ matrix.version }}
|
||||
github-token: ${{ github.token }}
|
||||
- run: supabase -h
|
||||
|
||||
ci:
|
||||
|
||||
2
.github/workflows/e2e.yml
vendored
2
.github/workflows/e2e.yml
vendored
@@ -47,6 +47,8 @@ jobs:
|
||||
exclude:
|
||||
- version: 1.178.2
|
||||
pg_major: 17
|
||||
- version: latest
|
||||
pg_major: 14
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
|
||||
4
.github/workflows/licensed.yml
vendored
4
.github/workflows/licensed.yml
vendored
@@ -71,7 +71,7 @@ jobs:
|
||||
- name: Setup Ruby
|
||||
id: setup-ruby
|
||||
if: steps.license-inputs.outputs.changed == 'true'
|
||||
uses: ruby/setup-ruby@97ecb7b512899eb71ab1bf2310a624c6f1589ac6 # v1.308.0
|
||||
uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
|
||||
with:
|
||||
ruby-version: ruby
|
||||
|
||||
@@ -116,7 +116,7 @@ jobs:
|
||||
|
||||
- name: Setup Ruby
|
||||
id: setup-ruby
|
||||
uses: ruby/setup-ruby@97ecb7b512899eb71ab1bf2310a624c6f1589ac6 # v1.308.0
|
||||
uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
|
||||
with:
|
||||
ruby-version: ruby
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
name: "@actions/tool-cache"
|
||||
version: 4.0.0
|
||||
type: npm
|
||||
summary: Actions tool-cache lib
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/tool-cache
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE.md
|
||||
text: |-
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright 2019 GitHub
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
notices: []
|
||||
@@ -1,26 +0,0 @@
|
||||
---
|
||||
name: semver
|
||||
version: 7.7.4
|
||||
type: npm
|
||||
summary: The semantic version parser used by npm.
|
||||
homepage:
|
||||
license: isc
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
notices: []
|
||||
51
README.md
51
README.md
@@ -24,7 +24,7 @@ Setup the `supabase` CLI:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: supabase/setup-cli@v2
|
||||
- uses: supabase/setup-cli@v3
|
||||
```
|
||||
|
||||
If `version` is omitted, the action checks the repository root for `bun.lock`,
|
||||
@@ -33,20 +33,47 @@ package version through npm. If the lockfile includes package integrity
|
||||
metadata, the action verifies it against the npm registry before installing. If
|
||||
no supported lockfile is present, it falls back to `latest`.
|
||||
|
||||
A specific version of the `supabase` CLI can be installed:
|
||||
The action uses an existing Node.js/npm runtime when one is already available,
|
||||
and requires Node.js 20 or newer. On non-musl runners without Node.js or npm, it
|
||||
provisions them internally. Runners must be able to reach the npm registry to
|
||||
install the CLI package.
|
||||
|
||||
When running in Alpine or other Linux musl containers, the action uses Alpine's
|
||||
`nodejs` and `npm` packages instead of `actions/setup-node`, because the
|
||||
standard Node.js runner binaries target glibc. Root containers can have missing
|
||||
runtime packages installed automatically. Non-root containers must include
|
||||
Node.js 20+ and the runtime packages in the image before the action runs:
|
||||
|
||||
```dockerfile
|
||||
FROM alpine:3.20
|
||||
|
||||
RUN apk add --no-cache libstdc++ libgcc nodejs npm
|
||||
|
||||
USER 1000:1000
|
||||
```
|
||||
|
||||
A fixed npm-published version, `latest`, or `beta` of the `supabase` CLI can be
|
||||
installed:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: supabase/setup-cli@v2
|
||||
- uses: supabase/setup-cli@v3
|
||||
with:
|
||||
version: 2.84.2
|
||||
```
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: supabase/setup-cli@v3
|
||||
with:
|
||||
version: beta
|
||||
```
|
||||
|
||||
Run `supabase db start` to execute all migrations on a fresh database:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: supabase/setup-cli@v2
|
||||
- uses: supabase/setup-cli@v3
|
||||
with:
|
||||
version: latest
|
||||
- run: supabase init
|
||||
@@ -60,10 +87,9 @@ on Windows and macOS runners.
|
||||
|
||||
The action supports the following inputs:
|
||||
|
||||
| Name | Type | Description | Default | Required |
|
||||
| -------------- | ------ | ---------------------------------------------------------------- | --------------------------------- | -------- |
|
||||
| `version` | String | Supabase CLI version (or `latest`) | Root lockfile version or `latest` | false |
|
||||
| `github-token` | String | Deprecated; no longer used now that installs resolve through npm | | false |
|
||||
| Name | Type | Description | Default | Required |
|
||||
| --------- | ------ | ---------------------------------------------------------------- | --------------------------------- | -------- |
|
||||
| `version` | String | Supabase CLI `latest`, `beta`, or fixed version published to npm | Root lockfile version or `latest` | false |
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
@@ -71,7 +97,7 @@ Check generated TypeScript types are up-to-date with Postgres schema:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: supabase/setup-cli@v2
|
||||
- uses: supabase/setup-cli@v3
|
||||
- run: supabase init
|
||||
- run: supabase db start
|
||||
- name: Verify generated types match Postgres schema
|
||||
@@ -94,7 +120,7 @@ env:
|
||||
PROJECT_ID: <project-id>
|
||||
|
||||
steps:
|
||||
- uses: supabase/setup-cli@v2
|
||||
- uses: supabase/setup-cli@v3
|
||||
- run: supabase link --project-ref $PROJECT_ID
|
||||
- run: supabase db push
|
||||
```
|
||||
@@ -103,7 +129,7 @@ Export local Supabase env vars for app tests:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: supabase/setup-cli@v2
|
||||
- uses: supabase/setup-cli@v3
|
||||
- run: supabase init
|
||||
- run: supabase start
|
||||
- name: Export local Supabase env vars
|
||||
@@ -148,7 +174,7 @@ need to perform a few setup steps before you can work on the action.
|
||||
## Publish
|
||||
|
||||
1. Create a new GitHub release
|
||||
2. Rebase `v2` branch on `main`
|
||||
2. Rebase `v3` branch on `main`
|
||||
|
||||
Your action is now published! :rocket:
|
||||
|
||||
@@ -165,7 +191,6 @@ steps:
|
||||
- uses: ./
|
||||
with:
|
||||
version: latest
|
||||
github-token: ${{ github.token }}
|
||||
```
|
||||
|
||||
The CI workflow provides fast smoke coverage across GitHub-hosted runners, and
|
||||
|
||||
120
action.yml
120
action.yml
@@ -3,10 +3,7 @@ description: Setup Supabase CLI, supabase, on GitHub Actions runners
|
||||
author: Supabase
|
||||
inputs:
|
||||
version:
|
||||
description: Version of Supabase CLI to install. If omitted, detect from the root lockfile and otherwise use latest.
|
||||
required: false
|
||||
github-token:
|
||||
description: Deprecated. The action now installs through npm and does not use GitHub release API requests.
|
||||
description: Supabase CLI version to install. Supports latest, beta, or a fixed version published to npm. If omitted, detect from the root lockfile and otherwise use latest.
|
||||
required: false
|
||||
outputs:
|
||||
version:
|
||||
@@ -22,17 +19,18 @@ runs:
|
||||
run: |
|
||||
set -eu
|
||||
|
||||
if [ "${RUNNER_OS}" != "Linux" ]; then
|
||||
exit 0
|
||||
is_musl=false
|
||||
|
||||
if [ "${RUNNER_OS}" = "Linux" ]; then
|
||||
# setup-bun does not detect Linux musl yet, so Alpine-like containers need the musl asset explicitly.
|
||||
if [ -f /etc/alpine-release ]; then
|
||||
is_musl=true
|
||||
elif command -v ldd >/dev/null 2>&1 && ldd --version 2>&1 | grep -qi musl; then
|
||||
is_musl=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# setup-bun does not detect Linux musl yet, so Alpine-like containers need the musl asset explicitly.
|
||||
is_musl=false
|
||||
if [ -f /etc/alpine-release ]; then
|
||||
is_musl=true
|
||||
elif command -v ldd >/dev/null 2>&1 && ldd --version 2>&1 | grep -qi musl; then
|
||||
is_musl=true
|
||||
fi
|
||||
echo "is-musl=${is_musl}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
if [ "${is_musl}" != "true" ]; then
|
||||
exit 0
|
||||
@@ -55,30 +53,41 @@ runs:
|
||||
run: |
|
||||
set -eu
|
||||
|
||||
if [ "${RUNNER_OS}" != "Linux" ]; then
|
||||
if [ "${{ steps.bun-download.outputs.is-musl }}" != "true" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
is_musl=false
|
||||
if [ -f /etc/alpine-release ]; then
|
||||
is_musl=true
|
||||
elif command -v ldd >/dev/null 2>&1 && ldd --version 2>&1 | grep -qi musl; then
|
||||
is_musl=true
|
||||
fi
|
||||
|
||||
if [ "${is_musl}" != "true" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Bun's musl binary and the Supabase CLI shim both dynamically link libstdc++ and libgcc.
|
||||
# Alpine/musl containers need runtime packages for Bun and the npm CLI shim.
|
||||
# actions/setup-node uses glibc Node builds, so install Alpine's Node/npm instead.
|
||||
if command -v apk >/dev/null 2>&1; then
|
||||
missing_packages=""
|
||||
prefer_apk_bin=false
|
||||
for package in libstdc++ libgcc; do
|
||||
if ! apk info -e "${package}" >/dev/null 2>&1; then
|
||||
missing_packages="${missing_packages} ${package}"
|
||||
fi
|
||||
done
|
||||
|
||||
if ! command -v node >/dev/null 2>&1 || ! node -p 'process.versions.node' >/dev/null 2>&1; then
|
||||
if [ -x /usr/bin/node ] && PATH="/usr/bin:${PATH}" /usr/bin/node -p 'process.versions.node' >/dev/null 2>&1; then
|
||||
prefer_apk_bin=true
|
||||
else
|
||||
missing_packages="${missing_packages} nodejs"
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! command -v npm >/dev/null 2>&1 || ! npm --version >/dev/null 2>&1; then
|
||||
if [ -x /usr/bin/npm ] && PATH="/usr/bin:${PATH}" /usr/bin/npm --version >/dev/null 2>&1; then
|
||||
prefer_apk_bin=true
|
||||
else
|
||||
missing_packages="${missing_packages} npm"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${prefer_apk_bin}" = "true" ]; then
|
||||
echo "/usr/bin" >> "$GITHUB_PATH"
|
||||
fi
|
||||
|
||||
if [ -z "${missing_packages}" ]; then
|
||||
exit 0
|
||||
fi
|
||||
@@ -89,12 +98,69 @@ runs:
|
||||
fi
|
||||
|
||||
apk add --no-cache ${missing_packages}
|
||||
if echo " ${missing_packages} " | grep -Eq ' (nodejs|npm) '; then
|
||||
echo "/usr/bin" >> "$GITHUB_PATH"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "::error::Linux musl containers need libstdc++ and libgcc to run Supabase CLI. Install them before supabase/setup-cli."
|
||||
echo "::error::Linux musl containers need libstdc++, libgcc, nodejs, and npm to run Supabase CLI. Install them before supabase/setup-cli."
|
||||
exit 1
|
||||
|
||||
- id: node-runtime
|
||||
name: Resolve Node Runtime
|
||||
shell: sh
|
||||
run: |
|
||||
set -eu
|
||||
|
||||
node_version=""
|
||||
node_major=""
|
||||
has_npm=false
|
||||
|
||||
if command -v node >/dev/null 2>&1; then
|
||||
node_version="$(node -p 'process.versions.node' 2>/dev/null || true)"
|
||||
node_major="${node_version%%.*}"
|
||||
fi
|
||||
|
||||
if command -v npm >/dev/null 2>&1; then
|
||||
has_npm=true
|
||||
fi
|
||||
|
||||
if [ -n "${node_version}" ] && [ "${has_npm}" = "true" ]; then
|
||||
case "${node_major}" in
|
||||
''|*[!0-9]*)
|
||||
echo "::error::Could not determine Node.js version from '${node_version}'. Supabase CLI npm installs require Node.js 20 or newer."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "${node_major}" -lt 20 ]; then
|
||||
echo "::error::Supabase CLI npm installs require Node.js 20 or newer, but found Node.js ${node_version}. Set up Node.js 20+ before supabase/setup-cli, or use a runner image with Node.js 20+ and npm."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "setup-node=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "${{ steps.bun-download.outputs.is-musl }}" = "true" ]; then
|
||||
echo "::error::Linux musl containers need Node.js 20 or newer and npm from musl-compatible packages. Install libstdc++, libgcc, nodejs, and npm before supabase/setup-cli, or run this job container as root so the action can install them."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "${node_version}" ] || [ "${has_npm}" = "true" ]; then
|
||||
echo "::error::Supabase CLI npm installs need both Node.js 20+ and npm. Found Node.js '${node_version:-missing}' and npm '${has_npm}'. Configure both before supabase/setup-cli."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "setup-node=true" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Setup Node
|
||||
if: ${{ steps.node-runtime.outputs.setup-node == 'true' }}
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
with:
|
||||
node-version: 24
|
||||
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
||||
with:
|
||||
|
||||
100
bun.lock
100
bun.lock
@@ -11,9 +11,9 @@
|
||||
"@tsconfig/bun": "^1.0.10",
|
||||
"@types/bun": "^1.3.14",
|
||||
"@typescript/native-preview": "^7.0.0-dev.20260410.1",
|
||||
"oxfmt": "^0.49.0",
|
||||
"oxlint": "^1.64.0",
|
||||
"oxlint-tsgolint": "^0.22.1",
|
||||
"oxfmt": "^0.58.0",
|
||||
"oxlint": "^1.73.0",
|
||||
"oxlint-tsgolint": "^0.24.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -26,93 +26,93 @@
|
||||
|
||||
"@actions/io": ["@actions/io@3.0.2", "", {}, "sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw=="],
|
||||
|
||||
"@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.49.0", "", { "os": "android", "cpu": "arm" }, "sha512-HbifJ84prIh9+55CTPAU35JdRQrwg47y16cGerCC+iejSKOuHXYo2WDql6l7cQlzrYVtc3f4UWY+dBj2lRmOeA=="],
|
||||
"@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.58.0", "", { "os": "android", "cpu": "arm" }, "sha512-Uz62sHduGGPftXtILGyxdSW4PX82rUg+rfdNqhsgxe881g4rIoXlIqmZQ6HVKcF4f+F8qMhdD03Bx5u7gmeTdg=="],
|
||||
|
||||
"@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.49.0", "", { "os": "android", "cpu": "arm64" }, "sha512-Ef7SKJqAaH2d7E6eXZZa2OffIShbhFMxnGK0zd93p4qiyTJr75B0qf7lrPD+qQOwcf04BrjYJ0JUxq8d5+yZwg=="],
|
||||
"@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.58.0", "", { "os": "android", "cpu": "arm64" }, "sha512-rD0lRaJp1b+9vw6X4A2dJWKukd6X8yxiicN4JxXcXayolmUypRZxk+lKR+fVOu5q/iYc0fh5fR4bgmfOfVlbaA=="],
|
||||
|
||||
"@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.49.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-8x5DN9CsFfb432sHa9NyqX5XisGUdA53LPEGSdv/VniS+v4uEOR8Orv7A9QSB98Xxgp0t6r31DzQA/wpIobGqQ=="],
|
||||
"@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.58.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-uzbPPk7O6M+w2K65vcQ1woga3wgP8zghjL1KOG5b6qJ8dvYHZJ1VShaslg2KOK6yQIwCQtcMCXqLBM6sqXUNTg=="],
|
||||
|
||||
"@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.49.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-e0+DSVzk4ewhMVKNYDaRTmP81jNMBWR1X9al0cVKWS+hDM/dElNqD5zjTOCuLOZc4oOdp2Gx2ldrVL+yYo9TZQ=="],
|
||||
"@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.58.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-L0nKYDxU32oxeQqJj21W9SlIMnf81VZEhyah6iDvFhf5q0oynq498Fopth7blErUJVBpVtxQ98RMCfMPqpJX6w=="],
|
||||
|
||||
"@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.49.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-W+mjtYtrQvFbXT/uNT+221OBhGRZ8UqNsLxjTWsjZ4GsQnRdvRC/N2NCK86BcamWr7lsTxwpwN3PULnr78sgcQ=="],
|
||||
"@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.58.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-woNwfD58dC5PGS9LSLSD5JYfo/EFK5iG9vhDWkcCg3q78ag7KC8bpDqgvPHrMoXpx83OLXxoSOhu6z8FsVTHlg=="],
|
||||
|
||||
"@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.49.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Rtv6UevV7czDlLqil+NZUe4d8gs8jQo/zScSpumwyf7I+fSdLc+hc8AF3MQC7ymxSMMD9+vfiqQlsIf7wOAzXA=="],
|
||||
"@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.58.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Sqs8nMLxuQpY21NKJ1u4stPDmO5hskBCNNh2E3AdCfI1QqWtf4m+Qn4mGEIUO4KGmuq3SWc/SZ80uy5IiwTCDw=="],
|
||||
|
||||
"@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/binding-linux-arm-musleabihf@0.49.0", "", { "os": "linux", "cpu": "arm" }, "sha512-sBi+8C/Q/MdKa5FL8ibAUCdhFBGFH7HFN/Qoyd5xQbZ/0ky3NMPpKfIBpaH0lhK2dXkGLczVQUoZ+xuNSerCdQ=="],
|
||||
"@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/binding-linux-arm-musleabihf@0.58.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Vd4exzBI5B5hB9m22JiTQzIL23WvHo/Pe+sNXPNeBLXSP9swCBPKCEBRwKpmpQzYhlgYaCgfPcGXPKAJBRIiZQ=="],
|
||||
|
||||
"@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.49.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-JIfWenFhlzx+O8YygyZhoHFzTsdgDhxhbDRnE2iJLnnM5pWKScFvPECO2vOlA7JqJ/9S1g3uzEKuRCkHFwTjvA=="],
|
||||
"@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.58.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-bUWi5mHV+4Vi56RLHE1h6q/HHfwAIT3XoB9vJAVeRzfu5NriXM8y6eeJu0vlKa0C9kq2rq1sOWRClhdLHPocrg=="],
|
||||
|
||||
"@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.49.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-iNzkMPG18jPkwBOZ4/HEjwqfzAjq4RrUQ0CgId/fC1ENvYD5jLVAaU/gWgpiqP1ys07kxSsSggDd1fp3E7mQHw=="],
|
||||
"@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.58.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-2ZHxemzgHcjtktAuVUwSoyXmGo/t+aF5tS1ciPpPei4rhSyrz3JOqDosXXrmhN/yLUSzJjtuW7ToTWqfQpCj2w=="],
|
||||
|
||||
"@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.49.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-BPHA/NN3LvoIXiid+iz3BHt5V0Rzx0tXAqRUovwE1NsbDaLG9e8mtv7evDGRIkVQacqTDBv0XL25THHsxSJosQ=="],
|
||||
"@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.58.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-AwKkVwjVmFQ3bcO7j0McGYAqCKH2a326fswfofng/E8VewCT/raeeGQr4huVhY704deK8AWASSTlxzMj0eZc6Q=="],
|
||||
|
||||
"@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.49.0", "", { "os": "linux", "cpu": "none" }, "sha512-3Eroshe+s69htC9JIL0+zLGQczLtRKezkMhwqQC21VC5Z/fuLvzLfbAOLgJLUq601H8gDYjy7deYycfOBjCvWg=="],
|
||||
"@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.58.0", "", { "os": "linux", "cpu": "none" }, "sha512-xsRpTxfUnJF8D3AUKko/qyWdjw4GZVHlCVFuGlzSCTeewLmykKINW8em1+wx+axsDVtJJcMtvsiaXggXxrlHgw=="],
|
||||
|
||||
"@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.49.0", "", { "os": "linux", "cpu": "none" }, "sha512-fnaERGgsxGm0lKAmO72EYR4BA3qBnzBTJBTi6EtUMq1D4R7EexRBMU4voXnx4TXla3SEDl9x4uNp/18SbkPjGg=="],
|
||||
"@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.58.0", "", { "os": "linux", "cpu": "none" }, "sha512-Z4AYOTcy7nYEIiXwD62PlerimyYRcfJOgUbQAEBjXz098kxKuERBlRntofGy69HHhe9E0TLVNMl1yspVNu+efw=="],
|
||||
|
||||
"@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.49.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-rBwasMl1Uul1MCCeTGEFKnOTL7VUxHf+634jWStrQAbzpBJgd5Yz5m4F7exVCsoI8PHn57dNjssXagXLCLB5yA=="],
|
||||
"@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.58.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-A3nhhtZPC/TKVWOPj9q/H3p2znJDCcHWYlJBhWL8hGq/bFmBaNBHC8Np6E581yVq1w9Mi3rMDNzDalWvtUfJtQ=="],
|
||||
|
||||
"@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.49.0", "", { "os": "linux", "cpu": "x64" }, "sha512-BoC/F9xHe2y/deuBGA5Aw7bes07OD2gcL2wlpzTrfImR92vPP7S/k3LBTyspQZCNIVNdagkELcqKELwMLGIfAg=="],
|
||||
"@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.58.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2g+tVkgwqphw8R4hgo+kF4oz8+P5RwVOtr9+irsC7uwEp0e9j7Crw8kDGKL20uYlLPD7g02DqA61mC/UNYx98A=="],
|
||||
|
||||
"@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.49.0", "", { "os": "linux", "cpu": "x64" }, "sha512-umY6jFADAo/oztFKl8D/S6vSrG6oBpEskcentiRuz42kZVU2kfDXMWCYavxyZR2bwPjqkHpcHZ6EZFiH3Qj9ZA=="],
|
||||
"@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.58.0", "", { "os": "linux", "cpu": "x64" }, "sha512-rc15P6AbyyB7426aN8AakLd02Trb3a6ML/mmfAQeVHJEfVofWLcWIrBdy6zDEY+DIaL/s8E4GGPboVw+oP3+EA=="],
|
||||
|
||||
"@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.49.0", "", { "os": "none", "cpu": "arm64" }, "sha512-J85zQMiw2pXiGPK+OusmDvSnJ/dgpgN7VgmB2zOBtgS8F+nsOUfSg9ZEBrwbQscjZ7tkPbm38CG4VF5f53MsiA=="],
|
||||
"@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.58.0", "", { "os": "none", "cpu": "arm64" }, "sha512-ZWoTM27/HYPOh9iq86DAbhPu9nXb8qKvvGU/h8OfliyVUFAMMNTLDkGsWDKKnDqIkqvZ9+dXlgUOsH1LYO3O7g=="],
|
||||
|
||||
"@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.49.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-38K67XR++CoFFORDd4sMFwUVAnD6msYBdGTei+qvKGrRPO6S2PbrYPNL/eQQ1RgnnxOegNba0YQwg6uRkNcw6A=="],
|
||||
"@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.58.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-LHZnqFXe2dEfkRI4XdZS/57nEOT/I4UCRX5IyM9v4GYW9XwQCjGe1IUK59SuKw3POwvcgWQ4pme2cYXmNqTNPg=="],
|
||||
|
||||
"@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.49.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-rXVe0HICwQF0dBgbQtBCoYf8x/SidPIdhyQl+iPuJlV7suV+qDv7yUEB3wQ4qC3nOeNxz287SwFXKzyr0kWgEg=="],
|
||||
"@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.58.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-mZKpg20TpheCJym1rarcZCUJeW1sSruw8zAAaCYWvuVfwIUDN1CXdrPU/JgCWReXTCTrEfCB8Wyo3hh9jSZ2EA=="],
|
||||
|
||||
"@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.49.0", "", { "os": "win32", "cpu": "x64" }, "sha512-gwWLwSEmBBfIK/Wh7GGd658161o4RKAvHWRaRQbJm571iQXGKfyr7UKsI1vsWvDlNLc30CxJDc8mMmCvJ/kczQ=="],
|
||||
"@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.58.0", "", { "os": "win32", "cpu": "x64" }, "sha512-N/wUU4N5PZ2orBtI+Ko7MnMfYLfE7K91UrGMY/c/pYyHR3lA9kwst1XugkZx+92YcRh/Eo+iv2eTESSWXfiZPA=="],
|
||||
|
||||
"@oxlint-tsgolint/darwin-arm64": ["@oxlint-tsgolint/darwin-arm64@0.22.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4150Lpgc1YM09GcjA6GSrra1JoPjC7aOpfywLjWEY4vW0Sd1qKzqHF1WRaiw0/qUZ40OATYdv3aRd7ipPkWQbw=="],
|
||||
"@oxlint-tsgolint/darwin-arm64": ["@oxlint-tsgolint/darwin-arm64@0.24.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-C2uMmwK5Bc4ri4ysZ6sA8Rcu+A5zBQTp6ml2u0CLLbRZp4kMFPV3yWk8B5DK9Aw7y9bbjogIm75tUwGLFzlsYQ=="],
|
||||
|
||||
"@oxlint-tsgolint/darwin-x64": ["@oxlint-tsgolint/darwin-x64@0.22.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-vFWcPWYOgZs4HWcgS1EjUZg33NLcNfEYU49KGImmCfZWkflENrmBYV4HN/C0YeAPum6ZZ/goPSvQrB/cOD+NfA=="],
|
||||
"@oxlint-tsgolint/darwin-x64": ["@oxlint-tsgolint/darwin-x64@0.24.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-Wgvt/1lRbDxmoNqWQKKcL+UIiqLmdJ+EWLpQa1qzoNVAfNB0PJpa82/8dH1twT/3rSs4zrP5TXPWl4juB71WuQ=="],
|
||||
|
||||
"@oxlint-tsgolint/linux-arm64": ["@oxlint-tsgolint/linux-arm64@0.22.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-6LiUpP0Zir3+29FvBm7Y28q/dBjSHqTZ5MhG1Ckw4fGhI4cAvbcwXaKvbjx1TP7rRmBNOoq/M5xdpHjTb+GAew=="],
|
||||
"@oxlint-tsgolint/linux-arm64": ["@oxlint-tsgolint/linux-arm64@0.24.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-PB1rxII7KV83+ASY4sSkXtqvpij6ME66+QCRL49uksi/ofs2Rf/UVboYr095n0Rkbl2wgvlsHGl6DHC361jQUQ=="],
|
||||
|
||||
"@oxlint-tsgolint/linux-x64": ["@oxlint-tsgolint/linux-x64@0.22.1", "", { "os": "linux", "cpu": "x64" }, "sha512-fuX1hEQfpHauUbXADsfqVhRzrUrGabzGXbj5wsp2vKhV5uk/Rze8Mba9GdjFGECzvXudMGqHqxB4r6jGRdhxVA=="],
|
||||
"@oxlint-tsgolint/linux-x64": ["@oxlint-tsgolint/linux-x64@0.24.0", "", { "os": "linux", "cpu": "x64" }, "sha512-xcz3CxKmjTQLREtE/UShh+ruWmm9nAb7UM9zKcD65BStiuYgOakAKkPHl4YS5DztpVcDrE0+HqbOolTlRKYWmw=="],
|
||||
|
||||
"@oxlint-tsgolint/win32-arm64": ["@oxlint-tsgolint/win32-arm64@0.22.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SZidAj+jrbZf9ZjBEYW0tiNZ+KasqB2zgW26qdiPpQSF/DzURnPmXz651IeA9YsmbVdHGIooEHUmev6QJdquA=="],
|
||||
"@oxlint-tsgolint/win32-arm64": ["@oxlint-tsgolint/win32-arm64@0.24.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-A2i6ZGBec3i20S7RaxkgHc6r3HYtD5Mn7j/mb22NkTz14u0JuudvTu6JggAnbGMcv8+dBKQI//EasxSPJLD8pw=="],
|
||||
|
||||
"@oxlint-tsgolint/win32-x64": ["@oxlint-tsgolint/win32-x64@0.22.1", "", { "os": "win32", "cpu": "x64" }, "sha512-QweSk9H5lFh5Y+WUf2Kq/OAN88V6+62ZwGhP38gqdRotI90luXSMkruFTj7Q2rYrzH4ZVNaSqx7NY8JpSfIzqg=="],
|
||||
"@oxlint-tsgolint/win32-x64": ["@oxlint-tsgolint/win32-x64@0.24.0", "", { "os": "win32", "cpu": "x64" }, "sha512-0ZbGd9qRB6zs82moekaKdEvncRANq49EAwfNX62JpTS46feXUhKAuoyVDvZMj6Rywejylrmmu79Wo6faYCo4Ew=="],
|
||||
|
||||
"@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.64.0", "", { "os": "android", "cpu": "arm" }, "sha512-2r6Nq3XXGLHEXKkSj8JtmJ6N4gDw431DPFOg0ZoJHlNjnG6HVMm/ksQ10m0HJ8WBvwgMe1L50UHPaYZutCRPCw=="],
|
||||
"@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.73.0", "", { "os": "android", "cpu": "arm" }, "sha512-HZQRN/UMBu+Ut+/9MiAChkbP4qZqrNOWBcNI45vOT40GVhbGR0JgHB87L48D4iAqFQIdVmeQYtV9RF89AjTKkg=="],
|
||||
|
||||
"@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.64.0", "", { "os": "android", "cpu": "arm64" }, "sha512-ePJMpePgg7fBv+L/hVx1xXRU5/5gd5m0obLA6hPEfLXF3GjpR8idIDbY1dhQYhyz1ms2wdTccSboo6KEd2Oxtg=="],
|
||||
"@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.73.0", "", { "os": "android", "cpu": "arm64" }, "sha512-Gp+KJRylv2aW7thRpG5p1KTxZq4ZJFbWowrKzufNq9d3ssl3r3JviYV45/+p+7CN1Nv0zDd1e8Ex0b/HUDq4TQ=="],
|
||||
|
||||
"@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.64.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-U4DMLQd10gJLuoSTLSGbfv3bGjTlUNsScm9Dgb8wwBqmCzidf1pE1pXV4doGNxqwH3KtVng1AGTINA0NvkGLvQ=="],
|
||||
"@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.73.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-3de96NdtXhxERMjIz7wsp2HYMY6pMQycGxFWac2mFecAx6VeARF/IqFb1QIaqiCRIdfzBwzTed+pCTCoiS+CYA=="],
|
||||
|
||||
"@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.64.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-GoRIL48QWm4/TAvjN8pB1nAG+1/uqc9EdnWT9zqHeb6wsmjZtywj8VRe5aGW47Fdb64YtLOsdLqVxOvQuz98Wg=="],
|
||||
"@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.73.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-5zx/uPW32TiaOeVY1dQ/H5iOf0K1HOdFKOJhLqGl4o63+i1fpzoqqu/mKtd7OFgFjNCdhlyTGgjVkQTZm1ELcg=="],
|
||||
|
||||
"@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.64.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-5dFkv4tkg7PxJJGS9/OjrJwjhuHczrd3OQOkRE0wHcLM+ncUnULtzEPWjqGOxTXxZnLWcB91bGiIznx89TVXyQ=="],
|
||||
"@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.73.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-qNe4gKHaGnLuZJ8toUg90JAa0S2vTVvDw+0bRi3q1avXZXDT4u5mMeECf3nD4HYrbdn1O7dXqWut4onY/yx/Xg=="],
|
||||
|
||||
"@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.64.0", "", { "os": "linux", "cpu": "arm" }, "sha512-jsBqMLl/uOL5+Kq/+BtK9FrmiNGUbx8SiyZXv+WlUxA45KuwcLu9BfiSIL3I3DBDgWM3yZizDITnTK9BcqNBQg=="],
|
||||
"@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.73.0", "", { "os": "linux", "cpu": "arm" }, "sha512-cCehYh5hTbfShm/fxTD6wwrGUWIpvX+N5OxmAMhFhDeTGXvw+BeNj889tpxsFQ9ZLatQ6wImuY8tsKLZ+FMz7w=="],
|
||||
|
||||
"@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.64.0", "", { "os": "linux", "cpu": "arm" }, "sha512-1lrj8At/Uuc9GhjrVFBQo0NEjfBrTkzpmtHIGAhNnIXqn1CAyGL+qrztUsXb2GIluJrpl9Q7qRLJOb/NqydacQ=="],
|
||||
"@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.73.0", "", { "os": "linux", "cpu": "arm" }, "sha512-d5j5GDU/2dMgjVhw7TQT9ITrsIr1Y02KEXKyVGIXUkD+KiaxE9TP65FS2ZdgTBemQvoRL+gSBdbrIm3cQIeacg=="],
|
||||
|
||||
"@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.64.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-HpSQbubwh03mMhAdy2BYtad/fsY8vDFHDAb6bUwuCYg2VD3xCQgn6ArKcO0oZyLCheacKTv4PrF3Mfu5hgoE2g=="],
|
||||
"@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.73.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-Eyf1SrP3+yR1DI3OJgOY2Pvrr9dWP9TK37xPaDYycwTtlGlI45erJAVIfH5/m/xosDt6BupJYEFi47bvbTuuyw=="],
|
||||
|
||||
"@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.64.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-00QQ0h0Y7u0G69BgiH3+ky2aaq/QvkDL6DYok8htIuJHxybiux5aQ8jwmg8qIk9wha6UagUP2BAwAzbemcJbpg=="],
|
||||
"@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.73.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-IlT/OJApEDKaMmCooHuncgJZbbCe7T5QIWmTZBEtYscWvzPQuuEinVcid6kwQRVQOUdb7PUCz4jQHnaYXdfJXw=="],
|
||||
|
||||
"@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.64.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-2GaimTV6EMW+s5HS0An3oGbQme3BgHswvfVdGk3EB57Xe9+/gyT+Qd7lNVzb3rtir52vbIPzXfaYArzs5b5zcw=="],
|
||||
"@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.73.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-L+JYcb/vdg5fmcH08V6o0YYLU28cTH1SPNulwJdvK9NK49aXSkYy6oNpKBmddArVOXYqNepriDGiZ04G54kh1Q=="],
|
||||
|
||||
"@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.64.0", "", { "os": "linux", "cpu": "none" }, "sha512-H46AtFb9wypjoVwGdlxrm0DsD809NGmtiK9HiyPKTxkSte2YjhC4S+00rOIrwCaxcyPiGid3Y3OMXp5KMAkGZw=="],
|
||||
"@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.73.0", "", { "os": "linux", "cpu": "none" }, "sha512-Qtk0g3bKV6OwWjIm7R8kQN1uOZRKQt/MODK2a8QfkwhTpXBD53ozx5XLVWLGDQAVyp2otLW4D2wB98XfAfMPGA=="],
|
||||
|
||||
"@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.64.0", "", { "os": "linux", "cpu": "none" }, "sha512-HEgsidjjvvyzdg82icYkuFCf7REDV7B9JFwbIMbVwrKLBY0MrXX+bku3POn/hduZ2yW91IyVDUMq0Bf02KwXQw=="],
|
||||
"@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.73.0", "", { "os": "linux", "cpu": "none" }, "sha512-wX0NQKZVxltkAOVmzFcpOaMpdaUvsq1Eqpx9tkAfl71UdkTlSo1R4AdAnGccR1Fm2+TzFgZ22CyyGuZ41RDr/A=="],
|
||||
|
||||
"@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.64.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-Axvm8qryotmKN00P5w4JapaSjvP2LOSbdbBJiX+2SuHd3QzhW7TUc8skqgw+ahQZ5DmzEYeHCqauvW8f32Ns6Q=="],
|
||||
"@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.73.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-vPe7UGBMWyiLTtnqS4xxgMQFSFGmtQwhwCxuiw6lXygaO6bVt0D8dFVg8Xv05eaiN3ybC0HXXHUAohFMFvqoCQ=="],
|
||||
|
||||
"@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.64.0", "", { "os": "linux", "cpu": "x64" }, "sha512-cR60vSd7+m+KRZ3GQGfDxWwahW5RMXg0qlGvAluZr0fTUYvw0H9N9AXAF/M/PMqgytyqvVNmBAkJG9l7U30Y1g=="],
|
||||
"@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.73.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2CwIWr9cemFC/CbRBWZvuk5mffz6ObmfFkfcC/9rTQ7f+icNhYr2kOjf9Rt8lLvugvkdGDOmkoVoFFHh6ClCTw=="],
|
||||
|
||||
"@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.64.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2u/aPZ9pEg7HnvZPDsHxUGNnrpr4qaHi+mCgLgpt+LYRzPrS4Px4wPfkIdRdr2GvKnaYyt+XSlto0Vm5sbStTg=="],
|
||||
"@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.73.0", "", { "os": "linux", "cpu": "x64" }, "sha512-nDadfJgg7NBBxG0N560wOe7LLX5QiYp6qBaI7viuk5EUORFBktU/NfV0MbTqU3gTqQDCh4VyxKdo5VADxk9w8Q=="],
|
||||
|
||||
"@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.64.0", "", { "os": "none", "cpu": "arm64" }, "sha512-kfhkGfCdoXLSxEkrhDlJrvBYajGmq+ma4EMc53dsOWTq+rIBOlI0vTBmpZNnM5oH2LY/K/w1HAK+UQEgjgpVUg=="],
|
||||
"@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.73.0", "", { "os": "none", "cpu": "arm64" }, "sha512-wGjJC+NLH9xP+IKGn9RDW94ojJR/wPbg5WCnQjj/oReaOtCQthr8ws1zICe77JFmo4ouUdeTHHZL/ESGiF6Pmw=="],
|
||||
|
||||
"@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.64.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-r/cNKBFieONoVu2bb1KkVouq9W+edDUgHumXJGphCRRj+U0xaD4nanrw8ZOqo0IsutPkEM4vCcGBpak6x5aXMg=="],
|
||||
"@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.73.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-I7X47GPGljw225YUQ5SbC/rb1Kkdrd0yQf0x+hYxeKS6DpfjMbo9ccQPQ6LNY6BoJQ1sHhgDUGuMn5Vg5gHT6w=="],
|
||||
|
||||
"@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.64.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-tUw0xUUwEFVZbpJoeCblkv8SJA4Xz3CdXCJbAnBsiNLyxDrk2tLcxEAS6M73Q7hHHDg3OtwI8vZVK3t5RJt4Gw=="],
|
||||
"@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.73.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-5lWj+3h+74Fm1jYOO9qkJA4xkAlZA099DkXppuXsk7UpnpZLttsefrZU469vChGaG6hcSqrkKXQOvMTZtbjeNg=="],
|
||||
|
||||
"@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.64.0", "", { "os": "win32", "cpu": "x64" }, "sha512-9CBR+LO0JVST87fNTzzNxS5I29jIUO5gxT9i9+M3SDHHALElj9sY1Prf12tad3vIRC6OD7Ehtvvh+sn13vSwHw=="],
|
||||
"@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.73.0", "", { "os": "win32", "cpu": "x64" }, "sha512-WaNRvh4f6zY9CvUQk2YoA1O90ieWrIklI84+HXFr9Isjz9CSESrdqo/RtIYt4Dll/cAchqGDMehfaZd0vqEFZw=="],
|
||||
|
||||
"@tsconfig/bun": ["@tsconfig/bun@1.0.10", "", {}, "sha512-5AV5YknQjNyoYzZ/8NG0dawqew/wH+x7ANiCfCIn29qo0cdbd1EryvFD1k5NSZWLBMOI/fGqMIaxi58GPIP9Cg=="],
|
||||
|
||||
@@ -138,11 +138,11 @@
|
||||
|
||||
"bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
|
||||
|
||||
"oxfmt": ["oxfmt@0.49.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.49.0", "@oxfmt/binding-android-arm64": "0.49.0", "@oxfmt/binding-darwin-arm64": "0.49.0", "@oxfmt/binding-darwin-x64": "0.49.0", "@oxfmt/binding-freebsd-x64": "0.49.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.49.0", "@oxfmt/binding-linux-arm-musleabihf": "0.49.0", "@oxfmt/binding-linux-arm64-gnu": "0.49.0", "@oxfmt/binding-linux-arm64-musl": "0.49.0", "@oxfmt/binding-linux-ppc64-gnu": "0.49.0", "@oxfmt/binding-linux-riscv64-gnu": "0.49.0", "@oxfmt/binding-linux-riscv64-musl": "0.49.0", "@oxfmt/binding-linux-s390x-gnu": "0.49.0", "@oxfmt/binding-linux-x64-gnu": "0.49.0", "@oxfmt/binding-linux-x64-musl": "0.49.0", "@oxfmt/binding-openharmony-arm64": "0.49.0", "@oxfmt/binding-win32-arm64-msvc": "0.49.0", "@oxfmt/binding-win32-ia32-msvc": "0.49.0", "@oxfmt/binding-win32-x64-msvc": "0.49.0" }, "peerDependencies": { "svelte": "^5.0.0" }, "optionalPeers": ["svelte"], "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-IAHFMdlJSWe+oAr65dx22UvjCtV9DBMisAuLnKpDqMQrctzCkGnj3QRwNHm0d+uwSWPalsDF8ZYLz9rh6nH2IQ=="],
|
||||
"oxfmt": ["oxfmt@0.58.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.58.0", "@oxfmt/binding-android-arm64": "0.58.0", "@oxfmt/binding-darwin-arm64": "0.58.0", "@oxfmt/binding-darwin-x64": "0.58.0", "@oxfmt/binding-freebsd-x64": "0.58.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.58.0", "@oxfmt/binding-linux-arm-musleabihf": "0.58.0", "@oxfmt/binding-linux-arm64-gnu": "0.58.0", "@oxfmt/binding-linux-arm64-musl": "0.58.0", "@oxfmt/binding-linux-ppc64-gnu": "0.58.0", "@oxfmt/binding-linux-riscv64-gnu": "0.58.0", "@oxfmt/binding-linux-riscv64-musl": "0.58.0", "@oxfmt/binding-linux-s390x-gnu": "0.58.0", "@oxfmt/binding-linux-x64-gnu": "0.58.0", "@oxfmt/binding-linux-x64-musl": "0.58.0", "@oxfmt/binding-openharmony-arm64": "0.58.0", "@oxfmt/binding-win32-arm64-msvc": "0.58.0", "@oxfmt/binding-win32-ia32-msvc": "0.58.0", "@oxfmt/binding-win32-x64-msvc": "0.58.0" }, "peerDependencies": { "svelte": "^5.0.0", "vite-plus": "*" }, "optionalPeers": ["svelte", "vite-plus"], "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-8feG/7NVEHDVwc1OUpP6Pks+TnaDFUw2jLLFIMi5bcmmwxAX2wBQvjSzj62RRTYBf2Op1Wt8xbkmagmPTR5ETg=="],
|
||||
|
||||
"oxlint": ["oxlint@1.64.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.64.0", "@oxlint/binding-android-arm64": "1.64.0", "@oxlint/binding-darwin-arm64": "1.64.0", "@oxlint/binding-darwin-x64": "1.64.0", "@oxlint/binding-freebsd-x64": "1.64.0", "@oxlint/binding-linux-arm-gnueabihf": "1.64.0", "@oxlint/binding-linux-arm-musleabihf": "1.64.0", "@oxlint/binding-linux-arm64-gnu": "1.64.0", "@oxlint/binding-linux-arm64-musl": "1.64.0", "@oxlint/binding-linux-ppc64-gnu": "1.64.0", "@oxlint/binding-linux-riscv64-gnu": "1.64.0", "@oxlint/binding-linux-riscv64-musl": "1.64.0", "@oxlint/binding-linux-s390x-gnu": "1.64.0", "@oxlint/binding-linux-x64-gnu": "1.64.0", "@oxlint/binding-linux-x64-musl": "1.64.0", "@oxlint/binding-openharmony-arm64": "1.64.0", "@oxlint/binding-win32-arm64-msvc": "1.64.0", "@oxlint/binding-win32-ia32-msvc": "1.64.0", "@oxlint/binding-win32-x64-msvc": "1.64.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.22.1" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-Star3SNpWPeWFPw7kRXIhXUSn6fdiAl25q15CQzH/9WaOtG6e9CWTc25vNZOCr4PE1yEP1GtKJKIKglhj3OmEQ=="],
|
||||
"oxlint": ["oxlint@1.73.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.73.0", "@oxlint/binding-android-arm64": "1.73.0", "@oxlint/binding-darwin-arm64": "1.73.0", "@oxlint/binding-darwin-x64": "1.73.0", "@oxlint/binding-freebsd-x64": "1.73.0", "@oxlint/binding-linux-arm-gnueabihf": "1.73.0", "@oxlint/binding-linux-arm-musleabihf": "1.73.0", "@oxlint/binding-linux-arm64-gnu": "1.73.0", "@oxlint/binding-linux-arm64-musl": "1.73.0", "@oxlint/binding-linux-ppc64-gnu": "1.73.0", "@oxlint/binding-linux-riscv64-gnu": "1.73.0", "@oxlint/binding-linux-riscv64-musl": "1.73.0", "@oxlint/binding-linux-s390x-gnu": "1.73.0", "@oxlint/binding-linux-x64-gnu": "1.73.0", "@oxlint/binding-linux-x64-musl": "1.73.0", "@oxlint/binding-openharmony-arm64": "1.73.0", "@oxlint/binding-win32-arm64-msvc": "1.73.0", "@oxlint/binding-win32-ia32-msvc": "1.73.0", "@oxlint/binding-win32-x64-msvc": "1.73.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.24.0", "vite-plus": "*" }, "optionalPeers": ["oxlint-tsgolint", "vite-plus"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-u91G9TJzU6yqKWNZUYprQB07W7YvntZXaRxQ6CkoytepYhLWUXWsr1M8zUJ34VatNPuUAr3Z8GH+O2A331CluQ=="],
|
||||
|
||||
"oxlint-tsgolint": ["oxlint-tsgolint@0.22.1", "", { "optionalDependencies": { "@oxlint-tsgolint/darwin-arm64": "0.22.1", "@oxlint-tsgolint/darwin-x64": "0.22.1", "@oxlint-tsgolint/linux-arm64": "0.22.1", "@oxlint-tsgolint/linux-x64": "0.22.1", "@oxlint-tsgolint/win32-arm64": "0.22.1", "@oxlint-tsgolint/win32-x64": "0.22.1" }, "bin": { "tsgolint": "bin/tsgolint.js" } }, "sha512-YUSGSLUnoolsu8gxISEDio3q1rtsCozwfOzASUn3DT2mR2EeQ93uEEnen7s+6LpF+lyTQFln1pQfqwBh/fsVEg=="],
|
||||
"oxlint-tsgolint": ["oxlint-tsgolint@0.24.0", "", { "optionalDependencies": { "@oxlint-tsgolint/darwin-arm64": "0.24.0", "@oxlint-tsgolint/darwin-x64": "0.24.0", "@oxlint-tsgolint/linux-arm64": "0.24.0", "@oxlint-tsgolint/linux-x64": "0.24.0", "@oxlint-tsgolint/win32-arm64": "0.24.0", "@oxlint-tsgolint/win32-x64": "0.24.0" }, "bin": { "tsgolint": "bin/tsgolint.js" } }, "sha512-giCk5sEvG02d5tzPmFMX3hem8ndzEEu1xvGYS5OwNfO2WGl6ZVxt5LjE0yiMDoz94INI7XkXwgFAQiydPvVHDw=="],
|
||||
|
||||
"tinypool": ["tinypool@2.1.0", "", {}, "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw=="],
|
||||
|
||||
|
||||
@@ -7,7 +7,12 @@ The action supports `ubuntu-latest`, `windows-latest`, and `macos-latest`, and
|
||||
adds the requested `supabase` version to `PATH` for the rest of the job.
|
||||
|
||||
If `version` is omitted, the action checks the repository root for `bun.lock`,
|
||||
`pnpm-lock.yaml`, or `package-lock.json` and otherwise falls back to `latest`.
|
||||
`pnpm-lock.yaml`, or `package-lock.json` and otherwise falls back to npm
|
||||
`latest`.
|
||||
|
||||
The action uses an existing Node.js/npm runtime when one is already available,
|
||||
and requires Node.js 20 or newer. On non-musl runners without Node.js or npm, it
|
||||
provisions them internally. Runners only need network access to the npm registry.
|
||||
|
||||
## Quick Start
|
||||
|
||||
@@ -24,19 +29,27 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: supabase/setup-cli@v2
|
||||
- uses: supabase/setup-cli@v3
|
||||
- run: supabase init
|
||||
- run: supabase db start
|
||||
```
|
||||
|
||||
To pin a specific CLI version:
|
||||
To pin a fixed npm-published CLI version:
|
||||
|
||||
```yaml
|
||||
- uses: supabase/setup-cli@v2
|
||||
- uses: supabase/setup-cli@v3
|
||||
with:
|
||||
version: 2.84.2
|
||||
```
|
||||
|
||||
To test the current beta release:
|
||||
|
||||
```yaml
|
||||
- uses: supabase/setup-cli@v3
|
||||
with:
|
||||
version: beta
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
- **Source Code**: <https://github.com/supabase/setup-cli>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "setup-cli",
|
||||
"version": "2.0.0",
|
||||
"version": "3.0.0",
|
||||
"private": true,
|
||||
"description": "Supabase CLI GitHub Action",
|
||||
"keywords": [
|
||||
@@ -30,9 +30,9 @@
|
||||
"@tsconfig/bun": "^1.0.10",
|
||||
"@types/bun": "^1.3.14",
|
||||
"@typescript/native-preview": "^7.0.0-dev.20260410.1",
|
||||
"oxfmt": "^0.49.0",
|
||||
"oxlint": "^1.64.0",
|
||||
"oxlint-tsgolint": "^0.22.1"
|
||||
"oxfmt": "^0.58.0",
|
||||
"oxlint": "^1.73.0",
|
||||
"oxlint-tsgolint": "^0.24.0"
|
||||
},
|
||||
"engines": {
|
||||
"bun": ">=1.3.10"
|
||||
|
||||
304
src/main.test.ts
304
src/main.test.ts
@@ -1,4 +1,4 @@
|
||||
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import process from "node:process";
|
||||
@@ -7,6 +7,7 @@ import * as core from "@actions/core";
|
||||
|
||||
const CLI_CONFIG_REGISTRY = "SUPABASE_INTERNAL_IMAGE_REGISTRY";
|
||||
const originalPath = process.env.PATH;
|
||||
const originalNpmUserconfig = process.env.NPM_CONFIG_USERCONFIG;
|
||||
const originalRunnerTemp = process.env.RUNNER_TEMP;
|
||||
const originalWorkspace = process.env.GITHUB_WORKSPACE;
|
||||
const tempDirs = new Set<string>();
|
||||
@@ -15,11 +16,23 @@ let mainModule: typeof import("./main.ts") | null = null;
|
||||
afterEach(() => {
|
||||
mock.restore();
|
||||
process.env.PATH = originalPath;
|
||||
if (originalNpmUserconfig === undefined) {
|
||||
delete process.env.NPM_CONFIG_USERCONFIG;
|
||||
} else {
|
||||
process.env.NPM_CONFIG_USERCONFIG = originalNpmUserconfig;
|
||||
}
|
||||
process.env.RUNNER_TEMP = originalRunnerTemp;
|
||||
process.env.GITHUB_WORKSPACE = originalWorkspace;
|
||||
delete process.env.FAKE_CLI_VERSION;
|
||||
delete process.env.FAKE_NPM_BIN;
|
||||
delete process.env.FAKE_NPM_INTEGRITY;
|
||||
delete process.env.FAKE_NPM_CWD_LOG;
|
||||
delete process.env.FAKE_NPM_ENV_LOG;
|
||||
delete process.env.FAKE_NPM_LOG;
|
||||
delete process.env.FAKE_NPM_PACKAGE_VERSION;
|
||||
delete process.env.FAKE_NPM_PREFIX_CONFIG_LOG;
|
||||
delete process.env.FAKE_NPM_SCRIPTS;
|
||||
delete process.env.SETUP_CLI_TEST_WORKSPACE;
|
||||
delete process.env.SUPABASE_SETUP_CLI_NPM;
|
||||
|
||||
for (const dir of tempDirs) {
|
||||
@@ -144,14 +157,41 @@ function createFakeNpm(): string {
|
||||
mkdirSync(binDir, { recursive: true });
|
||||
writeFileSync(
|
||||
scriptPath,
|
||||
`import { appendFileSync, mkdirSync, writeFileSync } from "node:fs";
|
||||
`import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
appendFileSync(process.env.FAKE_NPM_LOG, JSON.stringify(args) + "\\n");
|
||||
appendFileSync(process.env.FAKE_NPM_CWD_LOG, process.cwd() + "\\n");
|
||||
appendFileSync(
|
||||
process.env.FAKE_NPM_ENV_LOG,
|
||||
JSON.stringify({ NPM_CONFIG_USERCONFIG: process.env.NPM_CONFIG_USERCONFIG ?? null }) + "\\n",
|
||||
);
|
||||
|
||||
function recordConfig(configPath) {
|
||||
appendFileSync(
|
||||
process.env.FAKE_NPM_PREFIX_CONFIG_LOG,
|
||||
JSON.stringify(existsSync(configPath) ? readFileSync(configPath, "utf8") : null) + "\\n",
|
||||
);
|
||||
}
|
||||
|
||||
if (args[0] === "view") {
|
||||
console.log(JSON.stringify(process.env.FAKE_NPM_INTEGRITY ?? "sha512-test"));
|
||||
recordConfig(path.join(process.cwd(), ".npmrc"));
|
||||
|
||||
const bin =
|
||||
process.env.FAKE_NPM_BIN === "missing"
|
||||
? undefined
|
||||
: { supabase: process.env.FAKE_NPM_BIN ?? "dist/supabase.js" };
|
||||
const scripts = process.env.FAKE_NPM_SCRIPTS ? JSON.parse(process.env.FAKE_NPM_SCRIPTS) : {};
|
||||
|
||||
console.log(
|
||||
JSON.stringify({
|
||||
version: process.env.FAKE_NPM_PACKAGE_VERSION ?? "2.101.0",
|
||||
bin,
|
||||
scripts,
|
||||
"dist.integrity": process.env.FAKE_NPM_INTEGRITY ?? "sha512-test",
|
||||
}),
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
@@ -169,6 +209,7 @@ if (!prefix) {
|
||||
|
||||
const binDir = path.join(prefix, "node_modules", ".bin");
|
||||
mkdirSync(binDir, { recursive: true });
|
||||
recordConfig(path.join(prefix, ".npmrc"));
|
||||
|
||||
if (process.platform === "win32") {
|
||||
writeFileSync(
|
||||
@@ -203,19 +244,47 @@ if (process.platform === "win32") {
|
||||
return binDir;
|
||||
}
|
||||
|
||||
function installFakeNpm(versionOutput = "supabase 2.101.0", integrity = "sha512-test"): string {
|
||||
function installFakeNpm(
|
||||
versionOutput = "supabase 2.101.0",
|
||||
options: {
|
||||
bin?: string;
|
||||
integrity?: string;
|
||||
packageVersion?: string;
|
||||
scripts?: Record<string, string>;
|
||||
} = {},
|
||||
): string {
|
||||
const binDir = createFakeNpm();
|
||||
const cwdLogPath = path.join(createTempDir("setup-cli-fake-npm-cwd-log-"), "npm-cwd.log");
|
||||
const envLogPath = path.join(createTempDir("setup-cli-fake-npm-env-log-"), "npm-env.log");
|
||||
const logPath = path.join(createTempDir("setup-cli-fake-npm-log-"), "npm.log");
|
||||
const prefixConfigLogPath = path.join(
|
||||
createTempDir("setup-cli-fake-npm-prefix-config-log-"),
|
||||
"npm-prefix-config.log",
|
||||
);
|
||||
writeFileSync(cwdLogPath, "");
|
||||
writeFileSync(envLogPath, "");
|
||||
writeFileSync(logPath, "");
|
||||
writeFileSync(prefixConfigLogPath, "");
|
||||
process.env.FAKE_CLI_VERSION = versionOutput;
|
||||
process.env.FAKE_NPM_INTEGRITY = integrity;
|
||||
process.env.FAKE_NPM_BIN = options.bin ?? "dist/supabase.js";
|
||||
process.env.FAKE_NPM_CWD_LOG = cwdLogPath;
|
||||
process.env.FAKE_NPM_ENV_LOG = envLogPath;
|
||||
process.env.FAKE_NPM_INTEGRITY = options.integrity ?? "sha512-test";
|
||||
process.env.FAKE_NPM_LOG = logPath;
|
||||
process.env.FAKE_NPM_PACKAGE_VERSION =
|
||||
options.packageVersion ??
|
||||
versionOutput.match(/\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/)?.[0] ??
|
||||
"2.101.0";
|
||||
if (options.scripts) {
|
||||
process.env.FAKE_NPM_SCRIPTS = JSON.stringify(options.scripts);
|
||||
}
|
||||
process.env.PATH = `${binDir}${path.delimiter}${originalPath ?? ""}`;
|
||||
process.env.RUNNER_TEMP = createTempDir("setup-cli-runner-temp-");
|
||||
process.env.SUPABASE_SETUP_CLI_NPM = path.join(
|
||||
binDir,
|
||||
process.platform === "win32" ? "npm.cmd" : "npm",
|
||||
);
|
||||
process.env.FAKE_NPM_PREFIX_CONFIG_LOG = prefixConfigLogPath;
|
||||
|
||||
return logPath;
|
||||
}
|
||||
@@ -228,6 +297,33 @@ function readNpmCalls(logPath: string): string[][] {
|
||||
.map((line) => JSON.parse(line) as string[]);
|
||||
}
|
||||
|
||||
function readNpmCwds(): string[] {
|
||||
return readFileSync(process.env.FAKE_NPM_CWD_LOG ?? "", "utf8")
|
||||
.trim()
|
||||
.split("\n")
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
function readNpmEnvs(): Array<{ NPM_CONFIG_USERCONFIG: string | null }> {
|
||||
return readFileSync(process.env.FAKE_NPM_ENV_LOG ?? "", "utf8")
|
||||
.trim()
|
||||
.split("\n")
|
||||
.filter(Boolean)
|
||||
.map((line) => JSON.parse(line) as { NPM_CONFIG_USERCONFIG: string | null });
|
||||
}
|
||||
|
||||
function readNpmPrefixConfigs(): Array<string | null> {
|
||||
return readFileSync(process.env.FAKE_NPM_PREFIX_CONFIG_LOG ?? "", "utf8")
|
||||
.trim()
|
||||
.split("\n")
|
||||
.filter(Boolean)
|
||||
.map((line) => JSON.parse(line) as string | null);
|
||||
}
|
||||
|
||||
function viewMetadataCall(spec: string): string[] {
|
||||
return ["view", spec, "version", "bin", "scripts", "dist.integrity", "--json", "--offline=false"];
|
||||
}
|
||||
|
||||
function createActionSpies(inputVersion: string) {
|
||||
return {
|
||||
addPath: spyOn(core, "addPath").mockImplementation(() => {}),
|
||||
@@ -255,6 +351,23 @@ test("uses an explicit npm package version when provided", async () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("uses an explicit npm dist-tag when provided", async () => {
|
||||
const { resolvePackage } = await getMainModule();
|
||||
|
||||
expect(resolvePackage("beta")).toEqual({
|
||||
spec: "supabase@beta",
|
||||
version: "beta",
|
||||
});
|
||||
});
|
||||
|
||||
test("rejects unsupported npm package selectors", async () => {
|
||||
const { resolvePackage } = await getMainModule();
|
||||
|
||||
expect(() => resolvePackage("hotfix")).toThrow(
|
||||
'Unsupported Supabase CLI version "hotfix". Use latest, beta, or a fixed npm package version like 2.101.0.',
|
||||
);
|
||||
});
|
||||
|
||||
test("uses the root bun.lock resolution when version is omitted", async () => {
|
||||
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||
"bun.lock": createBunLock("2.41.0", { integrity: "sha512-bun-lock" }),
|
||||
@@ -379,22 +492,163 @@ test("installs the CLI with npm into an isolated prefix", async () => {
|
||||
|
||||
expect(cliPath).toContain(`${path.sep}node_modules${path.sep}.bin`);
|
||||
expect(readNpmCalls(logPath)).toEqual([
|
||||
viewMetadataCall("supabase@2.101.0"),
|
||||
[
|
||||
"install",
|
||||
"--prefix",
|
||||
expect.any(String),
|
||||
"--omit=dev",
|
||||
"--include=optional",
|
||||
"--no-audit",
|
||||
"--no-fund",
|
||||
"--no-package-lock",
|
||||
"--ignore-scripts",
|
||||
"--offline=false",
|
||||
"--bin-links=true",
|
||||
"--ignore-scripts=true",
|
||||
"supabase@2.101.0",
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
test("runs npm with caller workspace config and action-owned overrides", async () => {
|
||||
const workspace = createWorkspace({
|
||||
".npmrc": [
|
||||
"registry=https://registry.example.test",
|
||||
"@internal:registry=https://registry.internal.example.test",
|
||||
"//registry.example.test/:_authToken=${NPM_TOKEN}",
|
||||
"//registry.example.test/:certfile=certs/client.pem",
|
||||
"//registry.example.test/:keyfile=certs/client-key.pem",
|
||||
"always-auth",
|
||||
'cafile="certs/project-ca.pem"',
|
||||
'userconfig="${SETUP_CLI_TEST_WORKSPACE}/.npmrc-ci"',
|
||||
"globalconfig=.npmrc-global",
|
||||
"bin-links=false",
|
||||
"offline=true",
|
||||
"package-lock=true",
|
||||
].join("\n"),
|
||||
".npmrc-ci": [
|
||||
"registry=https://delegated-registry.example.test",
|
||||
"//registry.example.test/:_password=delegated",
|
||||
"cafile=certs/delegated-ca.pem",
|
||||
"bin-links=false",
|
||||
"offline=true",
|
||||
].join("\n"),
|
||||
".npmrc-global": [
|
||||
"registry=https://global-registry.example.test",
|
||||
"//registry.example.test/:username=global",
|
||||
].join("\n"),
|
||||
"certs/client-key.pem": "client-key",
|
||||
"certs/client.pem": "client",
|
||||
"certs/delegated-ca.pem": "delegated-ca",
|
||||
"certs/project-ca.pem": "project-ca",
|
||||
});
|
||||
process.env.SETUP_CLI_TEST_WORKSPACE = workspace;
|
||||
const userconfigPath = path.join(createTempDir("setup-cli-userconfig-"), ".npmrc");
|
||||
writeFileSync(userconfigPath, "//registry.example.test/:username=existing\n");
|
||||
process.env.NPM_CONFIG_USERCONFIG = userconfigPath;
|
||||
process.env.GITHUB_WORKSPACE = workspace;
|
||||
const logPath = installFakeNpm();
|
||||
const { installCli } = await getMainModule();
|
||||
|
||||
await installCli({
|
||||
spec: "supabase@2.101.0",
|
||||
version: "2.101.0",
|
||||
});
|
||||
|
||||
const realWorkspace = realpathSync(workspace);
|
||||
const npmCwds = readNpmCwds().map((cwd) => realpathSync(cwd));
|
||||
expect(npmCwds).toEqual([realWorkspace, realWorkspace]);
|
||||
expect(readNpmEnvs().map((env) => env.NPM_CONFIG_USERCONFIG)).toEqual([
|
||||
userconfigPath,
|
||||
userconfigPath,
|
||||
]);
|
||||
expect(readNpmPrefixConfigs()).toEqual([
|
||||
readFileSync(path.join(workspace, ".npmrc"), "utf8"),
|
||||
null,
|
||||
]);
|
||||
expect(readNpmCalls(logPath)).toEqual([
|
||||
viewMetadataCall("supabase@2.101.0"),
|
||||
[
|
||||
"install",
|
||||
"--prefix",
|
||||
expect.any(String),
|
||||
"--omit=dev",
|
||||
"--include=optional",
|
||||
"--no-audit",
|
||||
"--no-fund",
|
||||
"--no-package-lock",
|
||||
"--offline=false",
|
||||
"--bin-links=true",
|
||||
"--ignore-scripts=true",
|
||||
"supabase@2.101.0",
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
test("allows install scripts for legacy npm packages that declare a preinstall", async () => {
|
||||
const logPath = installFakeNpm("supabase 1.15.1", {
|
||||
bin: "bin/supabase",
|
||||
scripts: { preinstall: "node scripts/preinstall.js" },
|
||||
});
|
||||
const { installCli } = await getMainModule();
|
||||
|
||||
await installCli({
|
||||
spec: "supabase@1.15.1",
|
||||
version: "1.15.1",
|
||||
});
|
||||
|
||||
expect(readNpmCalls(logPath)).toEqual([
|
||||
viewMetadataCall("supabase@1.15.1"),
|
||||
[
|
||||
"install",
|
||||
"--prefix",
|
||||
expect.any(String),
|
||||
"--omit=dev",
|
||||
"--include=optional",
|
||||
"--no-audit",
|
||||
"--no-fund",
|
||||
"--no-package-lock",
|
||||
"--offline=false",
|
||||
"--bin-links=true",
|
||||
"--ignore-scripts=false",
|
||||
"supabase@1.15.1",
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
test("allows install scripts for npm packages that declare a postinstall", async () => {
|
||||
const logPath = installFakeNpm("supabase 1.178.2", {
|
||||
bin: "bin/supabase",
|
||||
scripts: { postinstall: "node scripts/postinstall.js" },
|
||||
});
|
||||
const { installCli } = await getMainModule();
|
||||
|
||||
await installCli({
|
||||
spec: "supabase@1.178.2",
|
||||
version: "1.178.2",
|
||||
});
|
||||
|
||||
expect(readNpmCalls(logPath)).toEqual([
|
||||
viewMetadataCall("supabase@1.178.2"),
|
||||
[
|
||||
"install",
|
||||
"--prefix",
|
||||
expect.any(String),
|
||||
"--omit=dev",
|
||||
"--include=optional",
|
||||
"--no-audit",
|
||||
"--no-fund",
|
||||
"--no-package-lock",
|
||||
"--offline=false",
|
||||
"--bin-links=true",
|
||||
"--ignore-scripts=false",
|
||||
"supabase@1.178.2",
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
test("verifies lockfile integrity before installing", async () => {
|
||||
const logPath = installFakeNpm("supabase 2.101.0", "sha512-lock");
|
||||
const logPath = installFakeNpm("supabase 2.101.0", { integrity: "sha512-lock" });
|
||||
const { installCli } = await getMainModule();
|
||||
|
||||
await installCli({
|
||||
@@ -404,23 +658,26 @@ test("verifies lockfile integrity before installing", async () => {
|
||||
});
|
||||
|
||||
expect(readNpmCalls(logPath)).toEqual([
|
||||
["view", "supabase@2.101.0", "dist.integrity", "--json"],
|
||||
viewMetadataCall("supabase@2.101.0"),
|
||||
[
|
||||
"install",
|
||||
"--prefix",
|
||||
expect.any(String),
|
||||
"--omit=dev",
|
||||
"--include=optional",
|
||||
"--no-audit",
|
||||
"--no-fund",
|
||||
"--no-package-lock",
|
||||
"--ignore-scripts",
|
||||
"--offline=false",
|
||||
"--bin-links=true",
|
||||
"--ignore-scripts=true",
|
||||
"supabase@2.101.0",
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
test("fails when lockfile integrity does not match the registry", async () => {
|
||||
installFakeNpm("supabase 2.101.0", "sha512-registry");
|
||||
installFakeNpm("supabase 2.101.0", { integrity: "sha512-registry" });
|
||||
const { installCli } = await getMainModule();
|
||||
|
||||
try {
|
||||
@@ -437,8 +694,25 @@ test("fails when lockfile integrity does not match the registry", async () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("fails when the npm package does not expose a Supabase CLI executable", async () => {
|
||||
installFakeNpm("supabase 2.101.0", { bin: "missing" });
|
||||
const { installCli } = await getMainModule();
|
||||
|
||||
try {
|
||||
await installCli({
|
||||
spec: "supabase@2.101.0",
|
||||
version: "2.101.0",
|
||||
});
|
||||
throw new Error("Expected installCli to reject");
|
||||
} catch (error) {
|
||||
expect(error).toEqual(
|
||||
new Error("The npm package supabase@2.101.0 does not expose a supabase executable"),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test("runs the action with a package-lock resolution", async () => {
|
||||
const logPath = installFakeNpm("supabase 2.43.0", "sha512-package-lock");
|
||||
const logPath = installFakeNpm("supabase 2.43.0", { integrity: "sha512-package-lock" });
|
||||
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||
"package-lock.json": createPackageLock("2.43.0", "sha512-package-lock"),
|
||||
});
|
||||
@@ -447,7 +721,7 @@ test("runs the action with a package-lock resolution", async () => {
|
||||
|
||||
await run();
|
||||
|
||||
expect(readNpmCalls(logPath)[0]).toEqual(["view", "supabase@2.43.0", "dist.integrity", "--json"]);
|
||||
expect(readNpmCalls(logPath)[0]).toEqual(viewMetadataCall("supabase@2.43.0"));
|
||||
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 2.43.0");
|
||||
expect(spies.addPath).toHaveBeenCalledWith(expect.stringContaining("node_modules"));
|
||||
expect(spies.exportVariable).toHaveBeenCalledWith(CLI_CONFIG_REGISTRY, "ghcr.io");
|
||||
@@ -455,16 +729,16 @@ test("runs the action with a package-lock resolution", async () => {
|
||||
});
|
||||
|
||||
test("explicit version overrides detected root lockfiles", async () => {
|
||||
installFakeNpm("supabase 1.0.0");
|
||||
installFakeNpm("supabase 1.1.6");
|
||||
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||
"bun.lock": createBunLock("2.45.0"),
|
||||
});
|
||||
const spies = createActionSpies("1.0.0");
|
||||
const spies = createActionSpies("1.1.6");
|
||||
const { run } = await getMainModule();
|
||||
|
||||
await run();
|
||||
|
||||
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 1.0.0");
|
||||
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 1.1.6");
|
||||
expect(spies.exportVariable).not.toHaveBeenCalled();
|
||||
expect(spies.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
97
src/main.ts
97
src/main.ts
@@ -10,6 +10,10 @@ const REGISTRY_VERSION = "1.28.0";
|
||||
const DEFAULT_VERSION = "latest";
|
||||
const NPM_PACKAGE = "supabase";
|
||||
const NPM_EXECUTABLE_ENV = "SUPABASE_SETUP_CLI_NPM";
|
||||
const INSTALL_LIFECYCLE_SCRIPTS = ["preinstall", "install", "postinstall"] as const;
|
||||
const SUPPORTED_DIST_TAGS = new Set([DEFAULT_VERSION, "beta"]);
|
||||
const CONCRETE_VERSION_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
||||
const CONCRETE_VERSION_EXTRACT_PATTERN = /\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?/;
|
||||
|
||||
type PackageResolution = {
|
||||
spec: string;
|
||||
@@ -17,6 +21,13 @@ type PackageResolution = {
|
||||
integrity?: string;
|
||||
};
|
||||
|
||||
type PackageMetadata = {
|
||||
version?: unknown;
|
||||
bin?: unknown;
|
||||
scripts?: unknown;
|
||||
"dist.integrity"?: unknown;
|
||||
};
|
||||
|
||||
type BunLock = {
|
||||
workspaces?: {
|
||||
"": {
|
||||
@@ -54,12 +65,16 @@ type PackageLock = {
|
||||
dependencies?: Record<string, { integrity?: string; version?: string }>;
|
||||
};
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === "object" && value !== null;
|
||||
}
|
||||
|
||||
function extractConcreteVersion(raw: string | undefined): string | null {
|
||||
if (!raw) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const match = raw.match(/\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?/);
|
||||
const match = raw.match(CONCRETE_VERSION_EXTRACT_PATTERN);
|
||||
return match?.[0] ?? null;
|
||||
}
|
||||
|
||||
@@ -67,8 +82,25 @@ function normalizeVersion(version: string): string {
|
||||
return version.replace(/^v/i, "");
|
||||
}
|
||||
|
||||
function normalizeSupportedVersion(version: string): string {
|
||||
const normalizedVersion = normalizeVersion(version.trim());
|
||||
const distTag = normalizedVersion.toLowerCase();
|
||||
|
||||
if (SUPPORTED_DIST_TAGS.has(distTag)) {
|
||||
return distTag;
|
||||
}
|
||||
|
||||
if (CONCRETE_VERSION_PATTERN.test(normalizedVersion)) {
|
||||
return normalizedVersion;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Unsupported Supabase CLI version "${version}". Use latest, beta, or a fixed npm package version like 2.101.0.`,
|
||||
);
|
||||
}
|
||||
|
||||
function toPackageResolution(version: string, integrity?: string): PackageResolution {
|
||||
const normalizedVersion = normalizeVersion(version);
|
||||
const normalizedVersion = normalizeSupportedVersion(version);
|
||||
|
||||
return {
|
||||
spec: `${NPM_PACKAGE}@${normalizedVersion}`,
|
||||
@@ -200,19 +232,60 @@ export function resolvePackage(inputVersion: string): PackageResolution {
|
||||
);
|
||||
}
|
||||
|
||||
async function verifyExpectedIntegrity(resolution: PackageResolution): Promise<void> {
|
||||
function verifyPackageIntegrity(resolution: PackageResolution, metadata: PackageMetadata): void {
|
||||
if (!resolution.integrity) {
|
||||
return;
|
||||
}
|
||||
|
||||
const output = await runNpm(["view", resolution.spec, "dist.integrity", "--json"]);
|
||||
const registryIntegrity = JSON.parse(output) as unknown;
|
||||
|
||||
const registryIntegrity = metadata["dist.integrity"];
|
||||
if (registryIntegrity !== resolution.integrity) {
|
||||
throw new Error(`Lockfile integrity for ${resolution.spec} does not match the npm registry`);
|
||||
}
|
||||
}
|
||||
|
||||
async function getPackageMetadata(resolution: PackageResolution): Promise<PackageMetadata> {
|
||||
const output = await runNpm([
|
||||
"view",
|
||||
resolution.spec,
|
||||
"version",
|
||||
"bin",
|
||||
"scripts",
|
||||
"dist.integrity",
|
||||
"--json",
|
||||
"--offline=false",
|
||||
]);
|
||||
const metadata = JSON.parse(output) as unknown;
|
||||
|
||||
if (!isRecord(metadata)) {
|
||||
throw new Error(`Could not read npm metadata for ${resolution.spec}`);
|
||||
}
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
function verifyPackageMetadata(resolution: PackageResolution, metadata: PackageMetadata): void {
|
||||
if (typeof metadata.version !== "string" || !CONCRETE_VERSION_PATTERN.test(metadata.version)) {
|
||||
throw new Error(`Could not resolve a fixed npm version for ${resolution.spec}`);
|
||||
}
|
||||
|
||||
const bin = metadata.bin;
|
||||
const hasSupabaseBin =
|
||||
typeof bin === "string" || (isRecord(bin) && typeof bin[NPM_PACKAGE] === "string");
|
||||
|
||||
if (!hasSupabaseBin) {
|
||||
throw new Error(`The npm package ${resolution.spec} does not expose a supabase executable`);
|
||||
}
|
||||
}
|
||||
|
||||
function shouldIgnoreInstallScripts(metadata: PackageMetadata): boolean {
|
||||
const scripts = metadata.scripts;
|
||||
|
||||
return !(
|
||||
isRecord(scripts) &&
|
||||
INSTALL_LIFECYCLE_SCRIPTS.some((script) => typeof scripts[script] === "string")
|
||||
);
|
||||
}
|
||||
|
||||
function createInstallRoot(): string {
|
||||
const tempRoot = process.env.RUNNER_TEMP?.trim() || os.tmpdir();
|
||||
return mkdtempSync(path.join(tempRoot, "setup-cli-"));
|
||||
@@ -221,6 +294,7 @@ function createInstallRoot(): string {
|
||||
async function runNpm(args: string[]): Promise<string> {
|
||||
const executable = process.env[NPM_EXECUTABLE_ENV]?.trim() || "npm";
|
||||
const proc = Bun.spawn([executable, ...args], {
|
||||
cwd: process.env.GITHUB_WORKSPACE?.trim() ?? process.cwd(),
|
||||
env: process.env,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
@@ -239,19 +313,24 @@ async function runNpm(args: string[]): Promise<string> {
|
||||
}
|
||||
|
||||
export async function installCli(resolution: PackageResolution): Promise<string> {
|
||||
await verifyExpectedIntegrity(resolution);
|
||||
|
||||
const installRoot = createInstallRoot();
|
||||
|
||||
const metadata = await getPackageMetadata(resolution);
|
||||
verifyPackageMetadata(resolution, metadata);
|
||||
verifyPackageIntegrity(resolution, metadata);
|
||||
|
||||
await runNpm([
|
||||
"install",
|
||||
"--prefix",
|
||||
installRoot,
|
||||
"--omit=dev",
|
||||
"--include=optional",
|
||||
"--no-audit",
|
||||
"--no-fund",
|
||||
"--no-package-lock",
|
||||
"--ignore-scripts",
|
||||
"--offline=false",
|
||||
"--bin-links=true",
|
||||
`--ignore-scripts=${shouldIgnoreInstallScripts(metadata)}`,
|
||||
resolution.spec,
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user