mirror of
https://github.com/supabase/setup-cli.git
synced 2026-06-29 10:27:05 +00:00
Compare commits
1 Commits
julien/cli
...
feat/cachi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9da7121816 |
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -46,7 +46,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||||
version: [1.178.2, latest, beta]
|
version: [1.0.0, latest]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
- uses: ./
|
- uses: ./
|
||||||
|
|||||||
4
.github/workflows/dependabot.yml
vendored
4
.github/workflows/dependabot.yml
vendored
@@ -20,14 +20,14 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
# Metadata drives the non-major gating used for approval and auto-merge.
|
# Metadata drives the non-major gating used for approval and auto-merge.
|
||||||
- id: meta
|
- id: meta
|
||||||
uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0
|
uses: dependabot/fetch-metadata@ffa630c65fa7e0ecfa0625b5ceda64399aea1b36 # v3.0.0
|
||||||
with:
|
with:
|
||||||
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
|
||||||
- name: Generate token
|
- name: Generate token
|
||||||
id: app-token
|
id: app-token
|
||||||
if: ${{ steps.meta.outputs.update-type == null || steps.meta.outputs.update-type == 'version-update:semver-patch' || steps.meta.outputs.update-type == 'version-update:semver-minor' }}
|
if: ${{ steps.meta.outputs.update-type == null || steps.meta.outputs.update-type == 'version-update:semver-patch' || steps.meta.outputs.update-type == 'version-update:semver-minor' }}
|
||||||
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.APP_ID }}
|
app-id: ${{ secrets.APP_ID }}
|
||||||
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
||||||
|
|||||||
15
.github/workflows/licensed.yml
vendored
15
.github/workflows/licensed.yml
vendored
@@ -1,6 +1,6 @@
|
|||||||
# This workflow refreshes and checks dependency license records used in this
|
# This workflow checks the statuses of cached dependencies used in this action
|
||||||
# action with the help of the Licensed tool. If any licenses are invalid or
|
# with the help of the Licensed tool. If any licenses are invalid or missing,
|
||||||
# missing, this workflow will fail. See: https://github.com/licensee/licensed
|
# this workflow will fail. See: https://github.com/licensee/licensed
|
||||||
|
|
||||||
name: Licensed
|
name: Licensed
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ jobs:
|
|||||||
- name: Setup Ruby
|
- name: Setup Ruby
|
||||||
id: setup-ruby
|
id: setup-ruby
|
||||||
if: steps.license-inputs.outputs.changed == 'true'
|
if: steps.license-inputs.outputs.changed == 'true'
|
||||||
uses: ruby/setup-ruby@97ecb7b512899eb71ab1bf2310a624c6f1589ac6 # v1.308.0
|
uses: ruby/setup-ruby@e65c17d16e57e481586a6a5a0282698790062f92 # v1.300.0
|
||||||
with:
|
with:
|
||||||
ruby-version: ruby
|
ruby-version: ruby
|
||||||
|
|
||||||
@@ -81,11 +81,6 @@ jobs:
|
|||||||
version: 4.x
|
version: 4.x
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Refresh License Cache
|
|
||||||
id: refresh-license-cache
|
|
||||||
if: steps.license-inputs.outputs.changed == 'true'
|
|
||||||
run: licensed cache
|
|
||||||
|
|
||||||
- name: Check Licenses
|
- name: Check Licenses
|
||||||
id: check-licenses
|
id: check-licenses
|
||||||
if: steps.license-inputs.outputs.changed == 'true'
|
if: steps.license-inputs.outputs.changed == 'true'
|
||||||
@@ -116,7 +111,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Setup Ruby
|
- name: Setup Ruby
|
||||||
id: setup-ruby
|
id: setup-ruby
|
||||||
uses: ruby/setup-ruby@97ecb7b512899eb71ab1bf2310a624c6f1589ac6 # v1.308.0
|
uses: ruby/setup-ruby@e65c17d16e57e481586a6a5a0282698790062f92 # v1.300.0
|
||||||
with:
|
with:
|
||||||
ruby-version: ruby
|
ruby-version: ruby
|
||||||
|
|
||||||
|
|||||||
20
.licenses/npm/@actions/tool-cache.dep.yml
Normal file
20
.licenses/npm/@actions/tool-cache.dep.yml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
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: []
|
||||||
26
.licenses/npm/semver.dep.yml
Normal file
26
.licenses/npm/semver.dep.yml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
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: []
|
||||||
79
README.md
79
README.md
@@ -24,41 +24,43 @@ Setup the `supabase` CLI:
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
steps:
|
steps:
|
||||||
- uses: supabase/setup-cli@v3
|
- uses: supabase/setup-cli@v2
|
||||||
```
|
```
|
||||||
|
|
||||||
If `version` is omitted, the action checks the repository root for `bun.lock`,
|
If `version` is omitted, the action checks the repository root for `bun.lock`,
|
||||||
`pnpm-lock.yaml`, or `package-lock.json` and installs the declared `supabase`
|
`pnpm-lock.yaml`, or `package-lock.json` and uses the declared `supabase`
|
||||||
package version through npm. If the lockfile includes package integrity
|
version. If no supported lockfile is present, it falls back to `latest`.
|
||||||
metadata, the action verifies it against the npm registry before installing. If
|
|
||||||
no supported lockfile is present, it falls back to `latest`.
|
|
||||||
|
|
||||||
The action provisions Node.js and npm internally, so runners do not need npm
|
A specific version of the `supabase` CLI can be installed:
|
||||||
preinstalled. Runners must be able to reach the npm registry to install the CLI
|
|
||||||
package.
|
|
||||||
|
|
||||||
A fixed npm-published version, `latest`, or `beta` of the `supabase` CLI can be
|
|
||||||
installed:
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
steps:
|
steps:
|
||||||
- uses: supabase/setup-cli@v3
|
- uses: supabase/setup-cli@v2
|
||||||
with:
|
with:
|
||||||
version: 2.84.2
|
version: 2.84.2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Cache Docker images used by `supabase start` across workflow runs:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
steps:
|
steps:
|
||||||
- uses: supabase/setup-cli@v3
|
- uses: actions/checkout@v6
|
||||||
|
- uses: supabase/setup-cli@v2
|
||||||
with:
|
with:
|
||||||
version: beta
|
version: 2.84.2
|
||||||
|
cache: true
|
||||||
|
- run: supabase start
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The first run still pulls images from the registry. Later runs can restore the
|
||||||
|
same image set from the GitHub Actions cache before `supabase start` runs, and
|
||||||
|
the action saves newly pulled Supabase images at the end of a successful job.
|
||||||
|
|
||||||
Run `supabase db start` to execute all migrations on a fresh database:
|
Run `supabase db start` to execute all migrations on a fresh database:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
steps:
|
steps:
|
||||||
- uses: supabase/setup-cli@v3
|
- uses: supabase/setup-cli@v2
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
- run: supabase init
|
- run: supabase init
|
||||||
@@ -72,9 +74,18 @@ on Windows and macOS runners.
|
|||||||
|
|
||||||
The action supports the following inputs:
|
The action supports the following inputs:
|
||||||
|
|
||||||
| Name | Type | Description | Default | Required |
|
| Name | Type | Description | Default | Required |
|
||||||
| --------- | ------ | ---------------------------------------------------------------- | --------------------------------- | -------- |
|
| ----------- | ------- | ------------------------------------------------------ | --------------------------------- | -------- |
|
||||||
| `version` | String | Supabase CLI `latest`, `beta`, or fixed version published to npm | Root lockfile version or `latest` | false |
|
| `version` | String | Supabase CLI version (or `latest`) | Root lockfile version or `latest` | false |
|
||||||
|
| `cache` | Boolean | Cache Docker images used by Supabase local development | `false` | false |
|
||||||
|
| `cache-key` | String | Explicit cache key for Supabase Docker images | Generated from runner and config | false |
|
||||||
|
|
||||||
|
The action exposes these outputs:
|
||||||
|
|
||||||
|
| Name | Description |
|
||||||
|
| ----------- | ------------------------------------------------------ |
|
||||||
|
| `version` | Version of installed Supabase CLI |
|
||||||
|
| `cache-hit` | Whether an exact Supabase Docker image cache was found |
|
||||||
|
|
||||||
## Advanced Usage
|
## Advanced Usage
|
||||||
|
|
||||||
@@ -82,7 +93,7 @@ Check generated TypeScript types are up-to-date with Postgres schema:
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
steps:
|
steps:
|
||||||
- uses: supabase/setup-cli@v3
|
- uses: supabase/setup-cli@v2
|
||||||
- run: supabase init
|
- run: supabase init
|
||||||
- run: supabase db start
|
- run: supabase db start
|
||||||
- name: Verify generated types match Postgres schema
|
- name: Verify generated types match Postgres schema
|
||||||
@@ -105,7 +116,7 @@ env:
|
|||||||
PROJECT_ID: <project-id>
|
PROJECT_ID: <project-id>
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: supabase/setup-cli@v3
|
- uses: supabase/setup-cli@v2
|
||||||
- run: supabase link --project-ref $PROJECT_ID
|
- run: supabase link --project-ref $PROJECT_ID
|
||||||
- run: supabase db push
|
- run: supabase db push
|
||||||
```
|
```
|
||||||
@@ -114,7 +125,9 @@ Export local Supabase env vars for app tests:
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
steps:
|
steps:
|
||||||
- uses: supabase/setup-cli@v3
|
- uses: supabase/setup-cli@v2
|
||||||
|
with:
|
||||||
|
cache: true
|
||||||
- run: supabase init
|
- run: supabase init
|
||||||
- run: supabase start
|
- run: supabase start
|
||||||
- name: Export local Supabase env vars
|
- name: Export local Supabase env vars
|
||||||
@@ -127,6 +140,22 @@ steps:
|
|||||||
- run: bun test
|
- run: bun test
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Customize the Docker image cache key when the image set depends on your workflow
|
||||||
|
flags, generated config, or monorepo layout:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
- uses: supabase/setup-cli@v2
|
||||||
|
with:
|
||||||
|
cache: true
|
||||||
|
cache-key: supabase-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('supabase/config.toml') }}-start-all
|
||||||
|
- run: supabase start
|
||||||
|
```
|
||||||
|
|
||||||
|
Avoid running `docker system prune -a` before the job ends if you want the
|
||||||
|
post-action cache save to include images pulled by `supabase start`.
|
||||||
|
|
||||||
## Develop
|
## Develop
|
||||||
|
|
||||||
After you've cloned the repository to your local machine or codespace, you'll
|
After you've cloned the repository to your local machine or codespace, you'll
|
||||||
@@ -150,6 +179,12 @@ need to perform a few setup steps before you can work on the action.
|
|||||||
bun test
|
bun test
|
||||||
```
|
```
|
||||||
|
|
||||||
|
1. :package: Build the bundled action entrypoints
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun run build
|
||||||
|
```
|
||||||
|
|
||||||
1. :mag: Run the full local CI suite
|
1. :mag: Run the full local CI suite
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -159,7 +194,7 @@ 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
|
||||||
2. Rebase `v3` branch on `main`
|
2. Rebase `v2` branch on `main`
|
||||||
|
|
||||||
Your action is now published! :rocket:
|
Your action is now published! :rocket:
|
||||||
|
|
||||||
|
|||||||
121
action.yml
121
action.yml
@@ -3,115 +3,22 @@ description: Setup Supabase CLI, supabase, on GitHub Actions runners
|
|||||||
author: Supabase
|
author: Supabase
|
||||||
inputs:
|
inputs:
|
||||||
version:
|
version:
|
||||||
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.
|
description: Version of Supabase CLI to install. If omitted, detect from the root lockfile and otherwise use latest.
|
||||||
|
required: false
|
||||||
|
cache:
|
||||||
|
description: Cache Docker images used by Supabase local development commands.
|
||||||
|
required: false
|
||||||
|
default: "false"
|
||||||
|
cache-key:
|
||||||
|
description: Optional explicit cache key for Supabase Docker images.
|
||||||
required: false
|
required: false
|
||||||
outputs:
|
outputs:
|
||||||
version:
|
version:
|
||||||
description: Version of installed Supabase CLI
|
description: Version of installed Supabase CLI
|
||||||
value: ${{ steps.setup-cli.outputs.version }}
|
cache-hit:
|
||||||
|
description: Whether an exact Supabase Docker image cache was restored.
|
||||||
runs:
|
runs:
|
||||||
using: composite
|
using: node24
|
||||||
steps:
|
main: dist/main.js
|
||||||
- id: bun-download
|
post: dist/post.js
|
||||||
name: Resolve Bun Download URL
|
post-if: success()
|
||||||
shell: sh
|
|
||||||
working-directory: ${{ github.action_path }}
|
|
||||||
run: |
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
if [ "${RUNNER_OS}" != "Linux" ]; then
|
|
||||||
exit 0
|
|
||||||
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
|
|
||||||
|
|
||||||
if [ "${is_musl}" != "true" ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
version="$(cat .bun-version)"
|
|
||||||
case "$(uname -m)" in
|
|
||||||
x86_64) arch="x64" ;;
|
|
||||||
aarch64|arm64) arch="aarch64" ;;
|
|
||||||
*)
|
|
||||||
echo "Unsupported Linux musl architecture: $(uname -m)" >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo "url=https://github.com/oven-sh/bun/releases/download/bun-v${version}/bun-linux-${arch}-musl.zip" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Install Alpine Runtime Dependencies
|
|
||||||
shell: sh
|
|
||||||
run: |
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
if [ "${RUNNER_OS}" != "Linux" ]; 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.
|
|
||||||
if command -v apk >/dev/null 2>&1; then
|
|
||||||
missing_packages=""
|
|
||||||
for package in libstdc++ libgcc; do
|
|
||||||
if ! apk info -e "${package}" >/dev/null 2>&1; then
|
|
||||||
missing_packages="${missing_packages} ${package}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -z "${missing_packages}" ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$(id -u)" != "0" ]; then
|
|
||||||
echo "::error::Alpine/musl containers need${missing_packages} to run Supabase CLI. Add 'apk add --no-cache${missing_packages}' before supabase/setup-cli, or run this job container as root."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
apk add --no-cache ${missing_packages}
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "::error::Linux musl containers need libstdc++ and libgcc to run Supabase CLI. Install them before supabase/setup-cli."
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
- name: Setup Node
|
|
||||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
||||||
with:
|
|
||||||
node-version: 24
|
|
||||||
|
|
||||||
- name: Setup Bun
|
|
||||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
|
||||||
with:
|
|
||||||
bun-version-file: ${{ github.action_path }}/.bun-version
|
|
||||||
bun-download-url: ${{ steps.bun-download.outputs.url }}
|
|
||||||
|
|
||||||
- name: Install Action Dependencies
|
|
||||||
shell: sh
|
|
||||||
working-directory: ${{ github.action_path }}
|
|
||||||
run: bun install --frozen-lockfile --production
|
|
||||||
|
|
||||||
- id: setup-cli
|
|
||||||
name: Setup Supabase CLI
|
|
||||||
shell: sh
|
|
||||||
working-directory: ${{ github.action_path }}
|
|
||||||
env:
|
|
||||||
INPUT_VERSION: ${{ inputs.version }}
|
|
||||||
run: bun src/main.ts
|
|
||||||
|
|||||||
221
bun.lock
221
bun.lock
@@ -5,151 +5,240 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "setup-cli",
|
"name": "setup-cli",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^3.0.1",
|
"@actions/cache": "^6.0.0",
|
||||||
|
"@actions/core": "^3.0.0",
|
||||||
|
"@actions/tool-cache": "^4.0.0",
|
||||||
|
"js-yaml": "^4.1.1",
|
||||||
|
"semver": "^7.7.4",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tsconfig/bun": "^1.0.10",
|
"@tsconfig/bun": "^1.0.10",
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.3.11",
|
||||||
"@typescript/native-preview": "^7.0.0-dev.20260410.1",
|
"@types/js-yaml": "^4.0.9",
|
||||||
"oxfmt": "^0.49.0",
|
"@types/node": "^24",
|
||||||
"oxlint": "^1.64.0",
|
"@types/semver": "^7.7.1",
|
||||||
"oxlint-tsgolint": "^0.22.1",
|
"@typescript/native-preview": "^7.0.0-dev.20260409.1",
|
||||||
|
"oxfmt": "^0.44.0",
|
||||||
|
"oxlint": "^1.59.0",
|
||||||
|
"oxlint-tsgolint": "^0.20.0",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@actions/core": ["@actions/core@3.0.1", "", { "dependencies": { "@actions/exec": "^3.0.0", "@actions/http-client": "^4.0.0" } }, "sha512-a6d/Nwahm9fliVGRhdhofo40HjHQasUPusmc7vBfyky+7Z+P2A1J68zyFVaNcEclc/Se+eO595oAr5nwEIoIUA=="],
|
"@actions/cache": ["@actions/cache@6.0.0", "", { "dependencies": { "@actions/core": "^3.0.0", "@actions/exec": "^3.0.0", "@actions/glob": "^0.6.1", "@actions/http-client": "^4.0.0", "@actions/io": "^3.0.0", "@azure/core-rest-pipeline": "^1.22.0", "@azure/storage-blob": "^12.30.0", "@protobuf-ts/runtime-rpc": "^2.11.1", "semver": "^7.7.3" } }, "sha512-+tCs634SyGBQJ3KU1rtAVabmN/gYiT9WgzTSJzWwdPCLmM3zWrdbysaErKv8HyI6OozClrxNvDgPjJimbHZZvw=="],
|
||||||
|
|
||||||
|
"@actions/core": ["@actions/core@3.0.0", "", { "dependencies": { "@actions/exec": "^3.0.0", "@actions/http-client": "^4.0.0" } }, "sha512-zYt6cz+ivnTmiT/ksRVriMBOiuoUpDCJJlZ5KPl2/FRdvwU3f7MPh9qftvbkXJThragzUZieit2nyHUyw53Seg=="],
|
||||||
|
|
||||||
"@actions/exec": ["@actions/exec@3.0.0", "", { "dependencies": { "@actions/io": "^3.0.2" } }, "sha512-6xH/puSoNBXb72VPlZVm7vQ+svQpFyA96qdDBvhB8eNZOE8LtPf9L4oAsfzK/crCL8YZ+19fKYVnM63Sl+Xzlw=="],
|
"@actions/exec": ["@actions/exec@3.0.0", "", { "dependencies": { "@actions/io": "^3.0.2" } }, "sha512-6xH/puSoNBXb72VPlZVm7vQ+svQpFyA96qdDBvhB8eNZOE8LtPf9L4oAsfzK/crCL8YZ+19fKYVnM63Sl+Xzlw=="],
|
||||||
|
|
||||||
|
"@actions/glob": ["@actions/glob@0.6.1", "", { "dependencies": { "@actions/core": "^3.0.0", "minimatch": "^3.0.4" } }, "sha512-K4+2Ac5ILcf2ySdJCha+Pop9NcKjxqCL4xL4zI50dgB2PbXgC0+AcP011xfH4Of6b4QEJJg8dyZYv7zl4byTsw=="],
|
||||||
|
|
||||||
"@actions/http-client": ["@actions/http-client@4.0.0", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^6.23.0" } }, "sha512-QuwPsgVMsD6qaPD57GLZi9sqzAZCtiJT8kVBCDpLtxhL5MydQ4gS+DrejtZZPdIYyB1e95uCK9Luyds7ybHI3g=="],
|
"@actions/http-client": ["@actions/http-client@4.0.0", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^6.23.0" } }, "sha512-QuwPsgVMsD6qaPD57GLZi9sqzAZCtiJT8kVBCDpLtxhL5MydQ4gS+DrejtZZPdIYyB1e95uCK9Luyds7ybHI3g=="],
|
||||||
|
|
||||||
"@actions/io": ["@actions/io@3.0.2", "", {}, "sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw=="],
|
"@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=="],
|
"@actions/tool-cache": ["@actions/tool-cache@4.0.0", "", { "dependencies": { "@actions/core": "^3.0.0", "@actions/exec": "^3.0.0", "@actions/http-client": "^4.0.0", "@actions/io": "^3.0.0", "semver": "^7.7.3" } }, "sha512-L8P9HbXvpvqjZDveb/fdsa55IVC0trfPgQ4ZwGo6r5af6YDVdM9vMGPZ7rgY2fAT9gGj4PSYd6bYlg3p3jD78A=="],
|
||||||
|
|
||||||
"@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.49.0", "", { "os": "android", "cpu": "arm64" }, "sha512-Ef7SKJqAaH2d7E6eXZZa2OffIShbhFMxnGK0zd93p4qiyTJr75B0qf7lrPD+qQOwcf04BrjYJ0JUxq8d5+yZwg=="],
|
"@azure/abort-controller": ["@azure/abort-controller@2.1.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA=="],
|
||||||
|
|
||||||
"@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.49.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-8x5DN9CsFfb432sHa9NyqX5XisGUdA53LPEGSdv/VniS+v4uEOR8Orv7A9QSB98Xxgp0t6r31DzQA/wpIobGqQ=="],
|
"@azure/core-auth": ["@azure/core-auth@1.10.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-util": "^1.13.0", "tslib": "^2.6.2" } }, "sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg=="],
|
||||||
|
|
||||||
"@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.49.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-e0+DSVzk4ewhMVKNYDaRTmP81jNMBWR1X9al0cVKWS+hDM/dElNqD5zjTOCuLOZc4oOdp2Gx2ldrVL+yYo9TZQ=="],
|
"@azure/core-client": ["@azure/core-client@1.10.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", "@azure/core-rest-pipeline": "^1.22.0", "@azure/core-tracing": "^1.3.0", "@azure/core-util": "^1.13.0", "@azure/logger": "^1.3.0", "tslib": "^2.6.2" } }, "sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w=="],
|
||||||
|
|
||||||
"@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.49.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-W+mjtYtrQvFbXT/uNT+221OBhGRZ8UqNsLxjTWsjZ4GsQnRdvRC/N2NCK86BcamWr7lsTxwpwN3PULnr78sgcQ=="],
|
"@azure/core-http-compat": ["@azure/core-http-compat@2.4.0", "", { "dependencies": { "@azure/abort-controller": "^2.1.2" }, "peerDependencies": { "@azure/core-client": "^1.10.0", "@azure/core-rest-pipeline": "^1.22.0" } }, "sha512-f1P96IB399YiN2ARYHP7EpZi3Bf3wH4SN2lGzrw7JVwm7bbsVYtf2iKSBwTywD2P62NOPZGHFSZi+6jjb75JuA=="],
|
||||||
|
|
||||||
"@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.49.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Rtv6UevV7czDlLqil+NZUe4d8gs8jQo/zScSpumwyf7I+fSdLc+hc8AF3MQC7ymxSMMD9+vfiqQlsIf7wOAzXA=="],
|
"@azure/core-lro": ["@azure/core-lro@2.7.2", "", { "dependencies": { "@azure/abort-controller": "^2.0.0", "@azure/core-util": "^1.2.0", "@azure/logger": "^1.0.0", "tslib": "^2.6.2" } }, "sha512-0YIpccoX8m/k00O7mDDMdJpbr6mf1yWo2dfmxt5A8XVZVVMz2SSKaEbMCeJRvgQ0IaSlqhjT47p4hVIRRy90xw=="],
|
||||||
|
|
||||||
"@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=="],
|
"@azure/core-paging": ["@azure/core-paging@1.6.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA=="],
|
||||||
|
|
||||||
"@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.49.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-JIfWenFhlzx+O8YygyZhoHFzTsdgDhxhbDRnE2iJLnnM5pWKScFvPECO2vOlA7JqJ/9S1g3uzEKuRCkHFwTjvA=="],
|
"@azure/core-rest-pipeline": ["@azure/core-rest-pipeline@1.23.0", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", "@azure/core-tracing": "^1.3.0", "@azure/core-util": "^1.13.0", "@azure/logger": "^1.3.0", "@typespec/ts-http-runtime": "^0.3.4", "tslib": "^2.6.2" } }, "sha512-Evs1INHo+jUjwHi1T6SG6Ua/LHOQBCLuKEEE6efIpt4ZOoNonaT1kP32GoOcdNDbfqsD2445CPri3MubBy5DEQ=="],
|
||||||
|
|
||||||
"@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.49.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-iNzkMPG18jPkwBOZ4/HEjwqfzAjq4RrUQ0CgId/fC1ENvYD5jLVAaU/gWgpiqP1ys07kxSsSggDd1fp3E7mQHw=="],
|
"@azure/core-tracing": ["@azure/core-tracing@1.3.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ=="],
|
||||||
|
|
||||||
"@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.49.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-BPHA/NN3LvoIXiid+iz3BHt5V0Rzx0tXAqRUovwE1NsbDaLG9e8mtv7evDGRIkVQacqTDBv0XL25THHsxSJosQ=="],
|
"@azure/core-util": ["@azure/core-util@1.13.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" } }, "sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A=="],
|
||||||
|
|
||||||
"@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.49.0", "", { "os": "linux", "cpu": "none" }, "sha512-3Eroshe+s69htC9JIL0+zLGQczLtRKezkMhwqQC21VC5Z/fuLvzLfbAOLgJLUq601H8gDYjy7deYycfOBjCvWg=="],
|
"@azure/core-xml": ["@azure/core-xml@1.5.1", "", { "dependencies": { "fast-xml-parser": "^5.5.9", "tslib": "^2.8.1" } }, "sha512-xcNRHqCoSp4AunOALEae6A8f3qATb83gSrm31Iqb01OzblvC3/W/bfXozcq78EzIdzZzuH1bZ2NvRR0TdX709w=="],
|
||||||
|
|
||||||
"@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.49.0", "", { "os": "linux", "cpu": "none" }, "sha512-fnaERGgsxGm0lKAmO72EYR4BA3qBnzBTJBTi6EtUMq1D4R7EexRBMU4voXnx4TXla3SEDl9x4uNp/18SbkPjGg=="],
|
"@azure/logger": ["@azure/logger@1.3.0", "", { "dependencies": { "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" } }, "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA=="],
|
||||||
|
|
||||||
"@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.49.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-rBwasMl1Uul1MCCeTGEFKnOTL7VUxHf+634jWStrQAbzpBJgd5Yz5m4F7exVCsoI8PHn57dNjssXagXLCLB5yA=="],
|
"@azure/storage-blob": ["@azure/storage-blob@12.31.0", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.9.0", "@azure/core-client": "^1.9.3", "@azure/core-http-compat": "^2.2.0", "@azure/core-lro": "^2.2.0", "@azure/core-paging": "^1.6.2", "@azure/core-rest-pipeline": "^1.19.1", "@azure/core-tracing": "^1.2.0", "@azure/core-util": "^1.11.0", "@azure/core-xml": "^1.4.5", "@azure/logger": "^1.1.4", "@azure/storage-common": "^12.3.0", "events": "^3.0.0", "tslib": "^2.8.1" } }, "sha512-DBgNv10aCSxopt92DkTDD0o9xScXeBqPKGmR50FPZQaEcH4JLQ+GEOGEDv19V5BMkB7kxr+m4h6il/cCDPvmHg=="],
|
||||||
|
|
||||||
"@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.49.0", "", { "os": "linux", "cpu": "x64" }, "sha512-BoC/F9xHe2y/deuBGA5Aw7bes07OD2gcL2wlpzTrfImR92vPP7S/k3LBTyspQZCNIVNdagkELcqKELwMLGIfAg=="],
|
"@azure/storage-common": ["@azure/storage-common@12.3.0", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.9.0", "@azure/core-http-compat": "^2.2.0", "@azure/core-rest-pipeline": "^1.19.1", "@azure/core-tracing": "^1.2.0", "@azure/core-util": "^1.11.0", "@azure/logger": "^1.1.4", "events": "^3.3.0", "tslib": "^2.8.1" } }, "sha512-/OFHhy86aG5Pe8dP5tsp+BuJ25JOAl9yaMU3WZbkeoiFMHFtJ7tu5ili7qEdBXNW9G5lDB19trwyI6V49F/8iQ=="],
|
||||||
|
|
||||||
"@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.49.0", "", { "os": "linux", "cpu": "x64" }, "sha512-umY6jFADAo/oztFKl8D/S6vSrG6oBpEskcentiRuz42kZVU2kfDXMWCYavxyZR2bwPjqkHpcHZ6EZFiH3Qj9ZA=="],
|
"@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.44.0", "", { "os": "android", "cpu": "arm" }, "sha512-5UvghMd9SA/yvKTWCAxMAPXS1d2i054UeOf4iFjZjfayTwCINcC3oaSXjtbZfCaEpxgJod7XiOjTtby5yEv/BQ=="],
|
||||||
|
|
||||||
"@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.49.0", "", { "os": "none", "cpu": "arm64" }, "sha512-J85zQMiw2pXiGPK+OusmDvSnJ/dgpgN7VgmB2zOBtgS8F+nsOUfSg9ZEBrwbQscjZ7tkPbm38CG4VF5f53MsiA=="],
|
"@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.44.0", "", { "os": "android", "cpu": "arm64" }, "sha512-IVudM1BWfvrYO++Khtzr8q9n5Rxu7msUvoFMqzGJVdX7HfUXUDHwaH2zHZNB58svx2J56pmCUzophyaPFkcG/A=="],
|
||||||
|
|
||||||
"@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.49.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-38K67XR++CoFFORDd4sMFwUVAnD6msYBdGTei+qvKGrRPO6S2PbrYPNL/eQQ1RgnnxOegNba0YQwg6uRkNcw6A=="],
|
"@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.44.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-eWCLAIKAHfx88EqEP1Ga2yz7qVcqDU5lemn4xck+07bH182hDdprOHjbogyk0In1Djys3T0/pO2JepFnRJ41Mg=="],
|
||||||
|
|
||||||
"@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.49.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-rXVe0HICwQF0dBgbQtBCoYf8x/SidPIdhyQl+iPuJlV7suV+qDv7yUEB3wQ4qC3nOeNxz287SwFXKzyr0kWgEg=="],
|
"@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.44.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-eHTBznHLM49++dwz07MblQ2cOXyIgeedmE3Wgy4ptUESj38/qYZyRi1MPwC9olQJWssMeY6WI3UZ7YmU5ggvyQ=="],
|
||||||
|
|
||||||
"@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.49.0", "", { "os": "win32", "cpu": "x64" }, "sha512-gwWLwSEmBBfIK/Wh7GGd658161o4RKAvHWRaRQbJm571iQXGKfyr7UKsI1vsWvDlNLc30CxJDc8mMmCvJ/kczQ=="],
|
"@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.44.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jLMmbj0u0Ft43QpkUVr/0v1ZfQCGWAvU+WznEHcN3wZC/q6ox7XeSJtk9P36CCpiDSUf3sGnzbIuG1KdEMEDJQ=="],
|
||||||
|
|
||||||
"@oxlint-tsgolint/darwin-arm64": ["@oxlint-tsgolint/darwin-arm64@0.22.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4150Lpgc1YM09GcjA6GSrra1JoPjC7aOpfywLjWEY4vW0Sd1qKzqHF1WRaiw0/qUZ40OATYdv3aRd7ipPkWQbw=="],
|
"@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.44.0", "", { "os": "linux", "cpu": "arm" }, "sha512-n+A/u/ByK1qV8FVGOwyaSpw5NPNl0qlZfgTBqHeGIqr8Qzq1tyWZ4lAaxPoe5mZqE3w88vn3+jZtMxriHPE7tg=="],
|
||||||
|
|
||||||
"@oxlint-tsgolint/darwin-x64": ["@oxlint-tsgolint/darwin-x64@0.22.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-vFWcPWYOgZs4HWcgS1EjUZg33NLcNfEYU49KGImmCfZWkflENrmBYV4HN/C0YeAPum6ZZ/goPSvQrB/cOD+NfA=="],
|
"@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/binding-linux-arm-musleabihf@0.44.0", "", { "os": "linux", "cpu": "arm" }, "sha512-5eax+FkxyCqAi3Rw0mrZFr7+KTt/XweFsbALR+B5ljWBLBl8nHe4ADrUnb1gLEfQCJLl+Ca5FIVD4xEt95AwIw=="],
|
||||||
|
|
||||||
"@oxlint-tsgolint/linux-arm64": ["@oxlint-tsgolint/linux-arm64@0.22.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-6LiUpP0Zir3+29FvBm7Y28q/dBjSHqTZ5MhG1Ckw4fGhI4cAvbcwXaKvbjx1TP7rRmBNOoq/M5xdpHjTb+GAew=="],
|
"@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.44.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-58l8JaHxSGOmOMOG2CIrNsnkRJAj0YcHQCmvNACniOa/vd1iRHhlPajczegzS5jwMENlqgreyiTR9iNlke8qCw=="],
|
||||||
|
|
||||||
"@oxlint-tsgolint/linux-x64": ["@oxlint-tsgolint/linux-x64@0.22.1", "", { "os": "linux", "cpu": "x64" }, "sha512-fuX1hEQfpHauUbXADsfqVhRzrUrGabzGXbj5wsp2vKhV5uk/Rze8Mba9GdjFGECzvXudMGqHqxB4r6jGRdhxVA=="],
|
"@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.44.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-AlObQIXyVRZ96LbtVljtFq0JqH5B92NU+BQeDFrXWBUWlCKAM0wF5GLfIhCLT5kQ3Sl+U0YjRJ7Alqj5hGQaCg=="],
|
||||||
|
|
||||||
"@oxlint-tsgolint/win32-arm64": ["@oxlint-tsgolint/win32-arm64@0.22.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SZidAj+jrbZf9ZjBEYW0tiNZ+KasqB2zgW26qdiPpQSF/DzURnPmXz651IeA9YsmbVdHGIooEHUmev6QJdquA=="],
|
"@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.44.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-YcFE8/q/BbrCiIiM5piwbkA6GwJc5QqhMQp2yDrqQ2fuVkZ7CInb1aIijZ/k8EXc72qXMSwKpVlBv1w/MsGO/A=="],
|
||||||
|
|
||||||
"@oxlint-tsgolint/win32-x64": ["@oxlint-tsgolint/win32-x64@0.22.1", "", { "os": "win32", "cpu": "x64" }, "sha512-QweSk9H5lFh5Y+WUf2Kq/OAN88V6+62ZwGhP38gqdRotI90luXSMkruFTj7Q2rYrzH4ZVNaSqx7NY8JpSfIzqg=="],
|
"@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.44.0", "", { "os": "linux", "cpu": "none" }, "sha512-eOdzs6RqkRzuqNHUX5C8ISN5xfGh4xDww8OEd9YAmc3OWN8oAe5bmlIqQ+rrHLpv58/0BuU48bxkhnIGjA/ATQ=="],
|
||||||
|
|
||||||
"@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.64.0", "", { "os": "android", "cpu": "arm" }, "sha512-2r6Nq3XXGLHEXKkSj8JtmJ6N4gDw431DPFOg0ZoJHlNjnG6HVMm/ksQ10m0HJ8WBvwgMe1L50UHPaYZutCRPCw=="],
|
"@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.44.0", "", { "os": "linux", "cpu": "none" }, "sha512-YBgNTxntD/QvlFUfgvh8bEdwOhXiquX8gaofZJAwYa/Xp1S1DQrFVZEeck7GFktr24DztsSp8N8WtWCBwxs0Hw=="],
|
||||||
|
|
||||||
"@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.64.0", "", { "os": "android", "cpu": "arm64" }, "sha512-ePJMpePgg7fBv+L/hVx1xXRU5/5gd5m0obLA6hPEfLXF3GjpR8idIDbY1dhQYhyz1ms2wdTccSboo6KEd2Oxtg=="],
|
"@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.44.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-GLIh1R6WHWshl/i4QQDNgj0WtT25aRO4HNUWEoitxiywyRdhTFmFEYT2rXlcl9U6/26vhmOqG5cRlMLG3ocaIA=="],
|
||||||
|
|
||||||
"@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.64.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-U4DMLQd10gJLuoSTLSGbfv3bGjTlUNsScm9Dgb8wwBqmCzidf1pE1pXV4doGNxqwH3KtVng1AGTINA0NvkGLvQ=="],
|
"@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.44.0", "", { "os": "linux", "cpu": "x64" }, "sha512-gZOpgTlOsLcLfAF9qgpTr7FIIFSKnQN3hDf/0JvQ4CIwMY7h+eilNjxq/CorqvYcEOu+LRt1W4ZS7KccEHLOdA=="],
|
||||||
|
|
||||||
"@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.64.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-GoRIL48QWm4/TAvjN8pB1nAG+1/uqc9EdnWT9zqHeb6wsmjZtywj8VRe5aGW47Fdb64YtLOsdLqVxOvQuz98Wg=="],
|
"@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.44.0", "", { "os": "linux", "cpu": "x64" }, "sha512-1CyS9JTB+pCUFYFI6pkQGGZaT/AY5gnhHVrQQLhFba6idP9AzVYm1xbdWfywoldTYvjxQJV6x4SuduCIfP3W+A=="],
|
||||||
|
|
||||||
"@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.64.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-5dFkv4tkg7PxJJGS9/OjrJwjhuHczrd3OQOkRE0wHcLM+ncUnULtzEPWjqGOxTXxZnLWcB91bGiIznx89TVXyQ=="],
|
"@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.44.0", "", { "os": "none", "cpu": "arm64" }, "sha512-bmEv70Ak6jLr1xotCbF5TxIKjsmQaiX+jFRtnGtfA03tJPf6VG3cKh96S21boAt3JZc+Vjx8PYcDuLj39vM2Pw=="],
|
||||||
|
|
||||||
"@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.64.0", "", { "os": "linux", "cpu": "arm" }, "sha512-jsBqMLl/uOL5+Kq/+BtK9FrmiNGUbx8SiyZXv+WlUxA45KuwcLu9BfiSIL3I3DBDgWM3yZizDITnTK9BcqNBQg=="],
|
"@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.44.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-yWzB+oCpSnP/dmw85eFLAT5o35Ve5pkGS2uF/UCISpIwDqf1xa7OpmtomiqY/Vzg8VyvMbuf6vroF2khF/+1Vg=="],
|
||||||
|
|
||||||
"@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.64.0", "", { "os": "linux", "cpu": "arm" }, "sha512-1lrj8At/Uuc9GhjrVFBQo0NEjfBrTkzpmtHIGAhNnIXqn1CAyGL+qrztUsXb2GIluJrpl9Q7qRLJOb/NqydacQ=="],
|
"@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.44.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-TcWpo18xEIE3AmIG2kpr3kz5IEhQgnx0lazl2+8L+3eTopOAUevQcmlr4nhguImNWz0OMeOZrYZOhJNCf16nlQ=="],
|
||||||
|
|
||||||
"@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.64.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-HpSQbubwh03mMhAdy2BYtad/fsY8vDFHDAb6bUwuCYg2VD3xCQgn6ArKcO0oZyLCheacKTv4PrF3Mfu5hgoE2g=="],
|
"@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.44.0", "", { "os": "win32", "cpu": "x64" }, "sha512-oj8aLkPJZppIM4CMQNsyir9ybM1Xw/CfGPTSsTnzpVGyljgfbdP0EVUlURiGM0BDrmw5psQ6ArmGCcUY/yABaQ=="],
|
||||||
|
|
||||||
"@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.64.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-00QQ0h0Y7u0G69BgiH3+ky2aaq/QvkDL6DYok8htIuJHxybiux5aQ8jwmg8qIk9wha6UagUP2BAwAzbemcJbpg=="],
|
"@oxlint-tsgolint/darwin-arm64": ["@oxlint-tsgolint/darwin-arm64@0.20.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-KKQcIHZHMxqpHUA1VXIbOG6chNCFkUWbQy6M+AFVtPKkA/3xAeJkJ3njoV66bfzwPHRcWQO+kcj5XqtbkjakoA=="],
|
||||||
|
|
||||||
"@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.64.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-2GaimTV6EMW+s5HS0An3oGbQme3BgHswvfVdGk3EB57Xe9+/gyT+Qd7lNVzb3rtir52vbIPzXfaYArzs5b5zcw=="],
|
"@oxlint-tsgolint/darwin-x64": ["@oxlint-tsgolint/darwin-x64@0.20.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-7HeVMuclGfG+NLZi2ybY0T4fMI7/XxO/208rJk+zEIloKkVnlh11Wd241JMGwgNFXn+MLJbOqOfojDb2Dt4L1g=="],
|
||||||
|
|
||||||
"@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.64.0", "", { "os": "linux", "cpu": "none" }, "sha512-H46AtFb9wypjoVwGdlxrm0DsD809NGmtiK9HiyPKTxkSte2YjhC4S+00rOIrwCaxcyPiGid3Y3OMXp5KMAkGZw=="],
|
"@oxlint-tsgolint/linux-arm64": ["@oxlint-tsgolint/linux-arm64@0.20.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-zxhUwz+WSxE6oWlZLK2z2ps9yC6ebmgoYmjAl0Oa48+GqkZ56NVgo+wb8DURNv6xrggzHStQxqQxe3mK51HZag=="],
|
||||||
|
|
||||||
"@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.64.0", "", { "os": "linux", "cpu": "none" }, "sha512-HEgsidjjvvyzdg82icYkuFCf7REDV7B9JFwbIMbVwrKLBY0MrXX+bku3POn/hduZ2yW91IyVDUMq0Bf02KwXQw=="],
|
"@oxlint-tsgolint/linux-x64": ["@oxlint-tsgolint/linux-x64@0.20.0", "", { "os": "linux", "cpu": "x64" }, "sha512-/1l6FnahC9im8PK+Ekkx/V3yetO/PzZnJegE2FXcv/iXEhbeVxP/ouiTYcUQu9shT1FWJCSNti1VJHH+21Y1dg=="],
|
||||||
|
|
||||||
"@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.64.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-Axvm8qryotmKN00P5w4JapaSjvP2LOSbdbBJiX+2SuHd3QzhW7TUc8skqgw+ahQZ5DmzEYeHCqauvW8f32Ns6Q=="],
|
"@oxlint-tsgolint/win32-arm64": ["@oxlint-tsgolint/win32-arm64@0.20.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-oPZ5Yz8sVdo7P/5q+i3IKeix31eFZ55JAPa1+RGPoe9PoaYVsdMvR6Jvib6YtrqoJnFPlg3fjEjlEPL8VBKYJA=="],
|
||||||
|
|
||||||
"@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.64.0", "", { "os": "linux", "cpu": "x64" }, "sha512-cR60vSd7+m+KRZ3GQGfDxWwahW5RMXg0qlGvAluZr0fTUYvw0H9N9AXAF/M/PMqgytyqvVNmBAkJG9l7U30Y1g=="],
|
"@oxlint-tsgolint/win32-x64": ["@oxlint-tsgolint/win32-x64@0.20.0", "", { "os": "win32", "cpu": "x64" }, "sha512-4stx8RHj3SP9vQyRF/yZbz5igtPvYMEUR8CUoha4BVNZihi39DpCR8qkU7lpjB5Ga1DRMo2pHaA4bdTOMaY4mw=="],
|
||||||
|
|
||||||
"@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-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.59.0", "", { "os": "android", "cpu": "arm" }, "sha512-etYDw/UaEv936AQUd/CRMBVd+e+XuuU6wC+VzOv1STvsTyZenLChepLWqLtnyTTp4YMlM22ypzogDDwqYxv5cg=="],
|
||||||
|
|
||||||
"@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.64.0", "", { "os": "none", "cpu": "arm64" }, "sha512-kfhkGfCdoXLSxEkrhDlJrvBYajGmq+ma4EMc53dsOWTq+rIBOlI0vTBmpZNnM5oH2LY/K/w1HAK+UQEgjgpVUg=="],
|
"@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.59.0", "", { "os": "android", "cpu": "arm64" }, "sha512-TgLc7XVLKH2a4h8j3vn1MDjfK33i9MY60f/bKhRGWyVzbk5LCZ4X01VZG7iHrMmi5vYbAp8//Ponigx03CLsdw=="],
|
||||||
|
|
||||||
"@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.64.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-r/cNKBFieONoVu2bb1KkVouq9W+edDUgHumXJGphCRRj+U0xaD4nanrw8ZOqo0IsutPkEM4vCcGBpak6x5aXMg=="],
|
"@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.59.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DXyFPf5ZKldMLloRHx/B9fsxsiTQomaw7cmEW3YIJko2HgCh+GUhp9gGYwHrqlLJPsEe3dYj9JebjX92D3j3AA=="],
|
||||||
|
|
||||||
"@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.64.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-tUw0xUUwEFVZbpJoeCblkv8SJA4Xz3CdXCJbAnBsiNLyxDrk2tLcxEAS6M73Q7hHHDg3OtwI8vZVK3t5RJt4Gw=="],
|
"@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.59.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-LgvrsdgVLX1qWqIEmNsSmMXJhpAWdtUQ0M+oR0CySwi+9IHWyOGuIL8w8+u/kbZNMyZr4WUyYB5i0+D+AKgkLg=="],
|
||||||
|
|
||||||
"@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.64.0", "", { "os": "win32", "cpu": "x64" }, "sha512-9CBR+LO0JVST87fNTzzNxS5I29jIUO5gxT9i9+M3SDHHALElj9sY1Prf12tad3vIRC6OD7Ehtvvh+sn13vSwHw=="],
|
"@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.59.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-bOJhqX/ny4hrFuTPlyk8foSRx/vLRpxJh0jOOKN2NWW6FScXHPAA5rQbrwdQPcgGB5V8Ua51RS03fke8ssBcug=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-vVUXxYMF9trXCsz4m9H6U0IjehosVHxBzVgJUxly1uz4W1PdDyicaBnpC0KRXsHYretLVe+uS9pJy8iM57Kujw=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-TULQW8YBPGRWg5yZpFPL54HLOnJ3/HiX6VenDPi6YfxB/jlItwSMFh3/hCeSNbh+DAMaE1Py0j5MOaivHkI/9Q=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-Gt54Y4eqSgYJ90xipm24xeyaPV854706o/kiT8oZvUt3VDY7qqxdqyGqchMaujd87ib+/MXvnl9WkK8Cc1BExg=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-3CtsKp7NFB3OfqQzbuAecrY7GIZeiv7AD+xutU4tefVQzlfmTI7/ygWLrvkzsDEjTlMq41rYHxgsn6Yh8tybmA=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-K0diOpT3ncDmOfl9I1HuvpEsAuTxkts0VYwIv/w6Xiy9CdwyPBVX88Ga9l8VlGgMrwBMnSY4xIvVlVY/fkQk7Q=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-xAU7+QDU6kTJJ7mJLOGgo7oOjtAtkKyFZ0Yjdb5cEo3DiCCPFLvyr08rWiQh6evZ7RiUTf+o65NY/bqttzJiQQ=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-KUmZmKlTTyauOnvUNVxK7G40sSSx0+w5l1UhaGsC6KPpOYHenx2oqJTnabmpLJicok7IC+3Y6fXAUOMyexaeJQ=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.59.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-4usRxC8gS0PGdkHnRmwJt/4zrQNZyk6vL0trCxwZSsAKM+OxhB8nKiR+mhjdBbl8lbMh2gc3bZpNN/ik8c4c2A=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-s/rNE2gDmbwAOOP493xk2X7M8LZfI1LJFSSW1+yanz3vuQCFPiHkx4GY+O1HuLUDtkzGlhtMrIcxxzyYLv308w=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-+yYj1udJa2UvvIUmEm0IcKgc0UlPMgz0nsSTvkPL2y6n0uU5LgIHSwVu4AHhrve6j9BpVSoRksnz8c9QcvITJA=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.59.0", "", { "os": "none", "cpu": "arm64" }, "sha512-bUplUb48LYsB3hHlQXP2ZMOenpieWoOyppLAnnAhuPag3MGPnt+7caxE3w/Vl9wpQsTA3gzLntQi9rxWrs7Xqg=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.59.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-/HLsLuz42rWl7h7ePdmMTpHm2HIDmPtcEMYgm5BBEHiEiuNOrzMaUpd2z7UnNni5LGN9obJy2YoAYBLXQwazrA=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.59.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-rUPy+JnanpPwV/aJCPnxAD1fW50+XPI0VkWr7f0vEbqcdsS8NpB24Rw6RsS7SdpFv8Dw+8ugCwao5nCFbqOUSg=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-xkE7puteDS/vUyRngLXW0t8WgdWoS/tfxXjhP/P7SMqPDx+hs44SpssO3h3qmTqECYEuXBUPzcAw5257Ka+ofA=="],
|
||||||
|
|
||||||
|
"@protobuf-ts/runtime": ["@protobuf-ts/runtime@2.11.1", "", {}, "sha512-KuDaT1IfHkugM2pyz+FwiY80ejWrkH1pAtOBOZFuR6SXEFTsnb/jiQWQ1rCIrcKx2BtyxnxW6BWwsVSA/Ie+WQ=="],
|
||||||
|
|
||||||
|
"@protobuf-ts/runtime-rpc": ["@protobuf-ts/runtime-rpc@2.11.1", "", { "dependencies": { "@protobuf-ts/runtime": "^2.11.1" } }, "sha512-4CqqUmNA+/uMz00+d3CYKgElXO9VrEbucjnBFEjqI4GuDrEQ32MaI3q+9qPBvIGOlL4PmHXrzM32vBPWRhQKWQ=="],
|
||||||
|
|
||||||
"@tsconfig/bun": ["@tsconfig/bun@1.0.10", "", {}, "sha512-5AV5YknQjNyoYzZ/8NG0dawqew/wH+x7ANiCfCIn29qo0cdbd1EryvFD1k5NSZWLBMOI/fGqMIaxi58GPIP9Cg=="],
|
"@tsconfig/bun": ["@tsconfig/bun@1.0.10", "", {}, "sha512-5AV5YknQjNyoYzZ/8NG0dawqew/wH+x7ANiCfCIn29qo0cdbd1EryvFD1k5NSZWLBMOI/fGqMIaxi58GPIP9Cg=="],
|
||||||
|
|
||||||
"@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="],
|
"@types/bun": ["@types/bun@1.3.11", "", { "dependencies": { "bun-types": "1.3.11" } }, "sha512-5vPne5QvtpjGpsGYXiFyycfpDF2ECyPcTSsFBMa0fraoxiQyMJ3SmuQIGhzPg2WJuWxVBoxWJ2kClYTcw/4fAg=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@20.19.37", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw=="],
|
"@types/js-yaml": ["@types/js-yaml@4.0.9", "", {}, "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg=="],
|
||||||
|
|
||||||
"@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20260410.1", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260410.1", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260410.1", "@typescript/native-preview-linux-arm": "7.0.0-dev.20260410.1", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260410.1", "@typescript/native-preview-linux-x64": "7.0.0-dev.20260410.1", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260410.1", "@typescript/native-preview-win32-x64": "7.0.0-dev.20260410.1" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-K3TIwBw4XGQM33wW8KUqRU7r6ZY1IqB8chk1u1kT+CDj4iu+eQ6jCXgU7EDxmpJ++gbNcIf8iBYgWgYNssrhZQ=="],
|
"@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="],
|
||||||
|
|
||||||
"@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260410.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bpLYm6woXd8BECzV9AQvPqISVeohpekK1qwpRopvNIxydhRQ4fEjZsS7EtDYpqHAW4/u1uEv07P9/iS6TAL1fQ=="],
|
"@types/semver": ["@types/semver@7.7.1", "", {}, "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA=="],
|
||||||
|
|
||||||
"@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20260410.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-V8bW8g5hgu+bAwGvTqF1kilkkoDgxhxi5egrdMUeWQkR+MIisoBQeaAupqMpLoSkqZsc/kKucM0zwBNC/KRU3Q=="],
|
"@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20260409.1", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260409.1", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260409.1", "@typescript/native-preview-linux-arm": "7.0.0-dev.20260409.1", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260409.1", "@typescript/native-preview-linux-x64": "7.0.0-dev.20260409.1", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260409.1", "@typescript/native-preview-win32-x64": "7.0.0-dev.20260409.1" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-CV1HEMGo1xCySwUJbCQOF+mmrTue8KTJ1Od2kKWhcbOpu8fPBfaqIpbAM6tGLcNEykEjMMTYHc/VTLbMgxdScQ=="],
|
||||||
|
|
||||||
"@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20260410.1", "", { "os": "linux", "cpu": "arm" }, "sha512-NO6Ci65ADadOCr2ycTxOyCgC5kyk+Ryjl8k5c78mz9sKDxYqwEtryFFjLqitAG+rejtJbnUq897WRICjAOwslA=="],
|
"@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260409.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-GcRRnaoeZVrbC47woQ/2t3vPoQcTSjsWPEAQGtwNSdw7Z9TKxG4ES22ghJIQXd3ncTRCMJ+XELnnuqxVutkJ9w=="],
|
||||||
|
|
||||||
"@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20260410.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-MOluRRAhv46s9ScFmePa0InMHmpZ/z0Evc11RrTKsg+bN8BR7sWoAtFq6IujEDK9WVP7YmEYtBRgEfMLuqVojw=="],
|
"@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20260409.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-7s8DXAa0Xpu/8PEjYIc4I36Ju7eVpoz9k3E+3WQdOF8pIPWYohiOj+zi68m9XYQck+rnkjUFo26ThVKqVetoMA=="],
|
||||||
|
|
||||||
"@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20260410.1", "", { "os": "linux", "cpu": "x64" }, "sha512-IofIUrMGjXmZKDEMaRgshzOne0EQZtx9vE/6URHfgmDnWLDKWzz9eQ2qWmvsFD2vOBbgc6GwVWEq6XTHMEfx2A=="],
|
"@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20260409.1", "", { "os": "linux", "cpu": "arm" }, "sha512-fOa07JBUXQpEPq+024g346inYZ2xp63ELuoRq6J0jwDWQ/ftCCuvdQNMncwFhsm1qlMdKT3S68NrnSxX16hiaw=="],
|
||||||
|
|
||||||
"@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20260410.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-TXmE+wovQqRo+qAhaewB0MPB9esgayvSHr6vFlCpHykHqbDl3FUucuC4F8yU6zVOA3UqXTk4/GHeLsAvU7YEgQ=="],
|
"@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20260409.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-cGTzTUqRGlIDwdtkDy6qTrvrqpe27W4CdgnFn0FpxpiWnaIi3wqjlzQ1grtqrqainw/yuPy5hn/I86sQgN6nvA=="],
|
||||||
|
|
||||||
"@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20260410.1", "", { "os": "win32", "cpu": "x64" }, "sha512-dMFT4tdHBe2vVA2WPQMjorT+fzCURRtillevQzz8/bwCEz2uXSnpu4oLRLS5045ppGE0wCFELE+Hq5z2oRddDw=="],
|
"@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20260409.1", "", { "os": "linux", "cpu": "x64" }, "sha512-lQrbc/BJKBxQrR1ttBDU5sYY1Hb2moFQgHL20T6nbapNqGpK4pzy64p+NK39O93D4omiCSk04pkchBCVrMPSAg=="],
|
||||||
|
|
||||||
"bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
|
"@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20260409.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-kmCafMo1xZlYx+9WnfpeZJ2tnB/CcJdR8QPX7j9vqcpe51D7b7Intmr921dD48KGpVh5YgjQ1MEFE5mjGqGMaA=="],
|
||||||
|
|
||||||
"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=="],
|
"@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20260409.1", "", { "os": "win32", "cpu": "x64" }, "sha512-WRd+JpQipTsE15QgYr3w7J0f1NKvGcq2QEgmcq8hB0WZA1X2WhQopNu+MpPQ3tdDD42VjMhm8ZoB8HpuOoXK5w=="],
|
||||||
|
|
||||||
"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=="],
|
"@typespec/ts-http-runtime": ["@typespec/ts-http-runtime@0.3.5", "", { "dependencies": { "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "tslib": "^2.6.2" } }, "sha512-yURCknZhvywvQItHMMmFSo+fq5arCUIyz/CVk7jD89MSai7dkaX8ufjCWp3NttLojoTVbcE72ri+be/TnEbMHw=="],
|
||||||
|
|
||||||
"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=="],
|
"agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
|
||||||
|
|
||||||
|
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
|
||||||
|
|
||||||
|
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||||
|
|
||||||
|
"brace-expansion": ["brace-expansion@1.1.13", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w=="],
|
||||||
|
|
||||||
|
"bun-types": ["bun-types@1.3.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-1KGPpoxQWl9f6wcZh57LvrPIInQMn2TQ7jsgxqpRzg+l0QPOFvJVH7HmvHo/AiPgwXy+/Thf6Ov3EdVn1vOabg=="],
|
||||||
|
|
||||||
|
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
||||||
|
|
||||||
|
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||||
|
|
||||||
|
"events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="],
|
||||||
|
|
||||||
|
"fast-xml-builder": ["fast-xml-builder@1.1.4", "", { "dependencies": { "path-expression-matcher": "^1.1.3" } }, "sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg=="],
|
||||||
|
|
||||||
|
"fast-xml-parser": ["fast-xml-parser@5.5.11", "", { "dependencies": { "fast-xml-builder": "^1.1.4", "path-expression-matcher": "^1.4.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-QL0eb0YbSTVWF6tTf1+LEMSgtCEjBYPpnAjoLC8SscESlAjXEIRJ7cHtLG0pLeDFaZLa4VKZLArtA/60ZS7vyA=="],
|
||||||
|
|
||||||
|
"http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="],
|
||||||
|
|
||||||
|
"https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
|
||||||
|
|
||||||
|
"js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
|
||||||
|
|
||||||
|
"minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
|
||||||
|
|
||||||
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||||
|
|
||||||
|
"oxfmt": ["oxfmt@0.44.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.44.0", "@oxfmt/binding-android-arm64": "0.44.0", "@oxfmt/binding-darwin-arm64": "0.44.0", "@oxfmt/binding-darwin-x64": "0.44.0", "@oxfmt/binding-freebsd-x64": "0.44.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.44.0", "@oxfmt/binding-linux-arm-musleabihf": "0.44.0", "@oxfmt/binding-linux-arm64-gnu": "0.44.0", "@oxfmt/binding-linux-arm64-musl": "0.44.0", "@oxfmt/binding-linux-ppc64-gnu": "0.44.0", "@oxfmt/binding-linux-riscv64-gnu": "0.44.0", "@oxfmt/binding-linux-riscv64-musl": "0.44.0", "@oxfmt/binding-linux-s390x-gnu": "0.44.0", "@oxfmt/binding-linux-x64-gnu": "0.44.0", "@oxfmt/binding-linux-x64-musl": "0.44.0", "@oxfmt/binding-openharmony-arm64": "0.44.0", "@oxfmt/binding-win32-arm64-msvc": "0.44.0", "@oxfmt/binding-win32-ia32-msvc": "0.44.0", "@oxfmt/binding-win32-x64-msvc": "0.44.0" }, "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-lnncqvHewyRvaqdrnntVIrZV2tEddz8lbvPsQzG/zlkfvgZkwy0HP1p/2u1aCDToeg1jb9zBpbJdfkV73Itw+w=="],
|
||||||
|
|
||||||
|
"oxlint": ["oxlint@1.59.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.59.0", "@oxlint/binding-android-arm64": "1.59.0", "@oxlint/binding-darwin-arm64": "1.59.0", "@oxlint/binding-darwin-x64": "1.59.0", "@oxlint/binding-freebsd-x64": "1.59.0", "@oxlint/binding-linux-arm-gnueabihf": "1.59.0", "@oxlint/binding-linux-arm-musleabihf": "1.59.0", "@oxlint/binding-linux-arm64-gnu": "1.59.0", "@oxlint/binding-linux-arm64-musl": "1.59.0", "@oxlint/binding-linux-ppc64-gnu": "1.59.0", "@oxlint/binding-linux-riscv64-gnu": "1.59.0", "@oxlint/binding-linux-riscv64-musl": "1.59.0", "@oxlint/binding-linux-s390x-gnu": "1.59.0", "@oxlint/binding-linux-x64-gnu": "1.59.0", "@oxlint/binding-linux-x64-musl": "1.59.0", "@oxlint/binding-openharmony-arm64": "1.59.0", "@oxlint/binding-win32-arm64-msvc": "1.59.0", "@oxlint/binding-win32-ia32-msvc": "1.59.0", "@oxlint/binding-win32-x64-msvc": "1.59.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.18.0" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-0xBLeGGjP4vD9pygRo8iuOkOzEU1MqOnfiOl7KYezL/QvWL8NUg6n03zXc7ZVqltiOpUxBk2zgHI3PnRIEdAvw=="],
|
||||||
|
|
||||||
|
"oxlint-tsgolint": ["oxlint-tsgolint@0.20.0", "", { "optionalDependencies": { "@oxlint-tsgolint/darwin-arm64": "0.20.0", "@oxlint-tsgolint/darwin-x64": "0.20.0", "@oxlint-tsgolint/linux-arm64": "0.20.0", "@oxlint-tsgolint/linux-x64": "0.20.0", "@oxlint-tsgolint/win32-arm64": "0.20.0", "@oxlint-tsgolint/win32-x64": "0.20.0" }, "bin": { "tsgolint": "bin/tsgolint.js" } }, "sha512-/Uc9TQyN1l8w9QNvXtVHYtz+SzDJHKpb5X0UnHodl0BVzijUPk0LPlDOHAvogd1UI+iy9ZSF6gQxEqfzUxCULQ=="],
|
||||||
|
|
||||||
|
"path-expression-matcher": ["path-expression-matcher@1.5.0", "", {}, "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ=="],
|
||||||
|
|
||||||
|
"semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||||
|
|
||||||
|
"strnum": ["strnum@2.2.3", "", {}, "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg=="],
|
||||||
|
|
||||||
"tinypool": ["tinypool@2.1.0", "", {}, "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw=="],
|
"tinypool": ["tinypool@2.1.0", "", {}, "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw=="],
|
||||||
|
|
||||||
|
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
|
|
||||||
"tunnel": ["tunnel@0.0.6", "", {}, "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="],
|
"tunnel": ["tunnel@0.0.6", "", {}, "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="],
|
||||||
|
|
||||||
"undici": ["undici@6.24.1", "", {}, "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA=="],
|
"undici": ["undici@6.24.1", "", {}, "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA=="],
|
||||||
|
|
||||||
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||||
|
|
||||||
|
"bun-types/@types/node": ["@types/node@20.19.37", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw=="],
|
||||||
|
|
||||||
|
"bun-types/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
94560
dist/main.js
vendored
Normal file
94560
dist/main.js
vendored
Normal file
File diff suppressed because one or more lines are too long
73430
dist/post.js
vendored
Normal file
73430
dist/post.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -7,11 +7,7 @@ The action supports `ubuntu-latest`, `windows-latest`, and `macos-latest`, and
|
|||||||
adds the requested `supabase` version to `PATH` for the rest of the job.
|
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`,
|
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 npm
|
`pnpm-lock.yaml`, or `package-lock.json` and otherwise falls back to `latest`.
|
||||||
`latest`.
|
|
||||||
|
|
||||||
The action provisions Node.js and npm internally; runners only need network
|
|
||||||
access to the npm registry.
|
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
@@ -28,27 +24,34 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
- uses: supabase/setup-cli@v3
|
- uses: supabase/setup-cli@v2
|
||||||
- run: supabase init
|
- run: supabase init
|
||||||
- run: supabase db start
|
- run: supabase db start
|
||||||
```
|
```
|
||||||
|
|
||||||
To pin a fixed npm-published CLI version:
|
To pin a specific CLI version:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: supabase/setup-cli@v3
|
- uses: supabase/setup-cli@v2
|
||||||
with:
|
with:
|
||||||
version: 2.84.2
|
version: 2.84.2
|
||||||
```
|
```
|
||||||
|
|
||||||
To test the current beta release:
|
To cache the Docker images pulled by `supabase start`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: supabase/setup-cli@v3
|
- uses: supabase/setup-cli@v2
|
||||||
with:
|
with:
|
||||||
version: beta
|
version: 2.84.2
|
||||||
|
cache: true
|
||||||
|
- run: supabase start
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The first run pulls the images from the registry. Later runs can restore the
|
||||||
|
same image archive from the GitHub Actions cache before `supabase start` runs.
|
||||||
|
Use `cache-key` when your workflow flags or generated config change the image
|
||||||
|
set.
|
||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
|
|
||||||
- **Source Code**: <https://github.com/supabase/setup-cli>
|
- **Source Code**: <https://github.com/supabase/setup-cli>
|
||||||
|
|||||||
30
package.json
30
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "setup-cli",
|
"name": "setup-cli",
|
||||||
"version": "3.0.0",
|
"version": "2.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Supabase CLI GitHub Action",
|
"description": "Supabase CLI GitHub Action",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@@ -14,25 +14,33 @@
|
|||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"all": "bun run format && bun run lint && bun run coverage",
|
"all": "bun run format && bun run lint && bun run coverage && bun run build",
|
||||||
"ci": "bun run format:check && bun run lint && bun run coverage",
|
"build": "bun build src/main.ts src/post.ts --target=node --format=esm --outdir=dist",
|
||||||
|
"ci": "bun run format:check && bun run lint && bun run coverage && bun run build",
|
||||||
"coverage": "bun test --coverage --coverage-reporter=text --coverage-reporter=lcov",
|
"coverage": "bun test --coverage --coverage-reporter=text --coverage-reporter=lcov",
|
||||||
"format": "bun x oxfmt --write . '!coverage/**'",
|
"format": "bun x oxfmt --write . '!coverage/**' '!dist/**'",
|
||||||
"format:check": "bun x oxfmt --check . '!coverage/**'",
|
"format:check": "bun x oxfmt --check . '!coverage/**' '!dist/**'",
|
||||||
"lint": "bun x oxlint --deny-warnings --type-aware --type-check --tsconfig tsconfig.json src",
|
"lint": "bun x oxlint --deny-warnings --type-aware --type-check --tsconfig tsconfig.json src",
|
||||||
"test": "bun test",
|
"test": "bun test",
|
||||||
"typecheck": "bun x tsgo -p tsconfig.json --noEmit"
|
"typecheck": "bun x tsgo -p tsconfig.json --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^3.0.1"
|
"@actions/cache": "^6.0.0",
|
||||||
|
"@actions/core": "^3.0.0",
|
||||||
|
"@actions/tool-cache": "^4.0.0",
|
||||||
|
"js-yaml": "^4.1.1",
|
||||||
|
"semver": "^7.7.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tsconfig/bun": "^1.0.10",
|
"@tsconfig/bun": "^1.0.10",
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.3.11",
|
||||||
"@typescript/native-preview": "^7.0.0-dev.20260410.1",
|
"@types/js-yaml": "^4.0.9",
|
||||||
"oxfmt": "^0.49.0",
|
"@types/node": "^24",
|
||||||
"oxlint": "^1.64.0",
|
"@types/semver": "^7.7.1",
|
||||||
"oxlint-tsgolint": "^0.22.1"
|
"@typescript/native-preview": "^7.0.0-dev.20260409.1",
|
||||||
|
"oxfmt": "^0.44.0",
|
||||||
|
"oxlint": "^1.59.0",
|
||||||
|
"oxlint-tsgolint": "^0.20.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"bun": ">=1.3.10"
|
"bun": ">=1.3.10"
|
||||||
|
|||||||
168
src/cache.test.ts
Normal file
168
src/cache.test.ts
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||||
|
import os from "node:os";
|
||||||
|
import path from "node:path";
|
||||||
|
import { afterEach, expect, mock, spyOn, test } from "bun:test";
|
||||||
|
import * as cacheAction from "@actions/cache";
|
||||||
|
import * as core from "@actions/core";
|
||||||
|
import {
|
||||||
|
collectDockerImageRefs,
|
||||||
|
createDockerImageCacheKey,
|
||||||
|
restoreDockerImageCache,
|
||||||
|
saveDockerImageCache,
|
||||||
|
} from "./cache";
|
||||||
|
|
||||||
|
const originalRunnerTemp = process.env.RUNNER_TEMP;
|
||||||
|
const originalWorkspace = process.env.GITHUB_WORKSPACE;
|
||||||
|
const tempDirs = new Set<string>();
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
mock.restore();
|
||||||
|
process.env.RUNNER_TEMP = originalRunnerTemp;
|
||||||
|
process.env.GITHUB_WORKSPACE = originalWorkspace;
|
||||||
|
|
||||||
|
for (const dir of tempDirs) {
|
||||||
|
rmSync(dir, { force: true, recursive: true });
|
||||||
|
}
|
||||||
|
tempDirs.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
function createTempDir(prefix: string): string {
|
||||||
|
const dir = mkdtempSync(path.join(os.tmpdir(), prefix));
|
||||||
|
tempDirs.add(dir);
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
test("creates a docker image cache key from runner, version, registry, and config", () => {
|
||||||
|
const workspace = createTempDir("setup-cli-workspace-");
|
||||||
|
mkdirSync(path.join(workspace, "supabase"), { recursive: true });
|
||||||
|
writeFileSync(path.join(workspace, "supabase", "config.toml"), 'project_id = "test"\n');
|
||||||
|
process.env.GITHUB_WORKSPACE = workspace;
|
||||||
|
|
||||||
|
const key = createDockerImageCacheKey("supabase 2.84.2", "ghcr.io");
|
||||||
|
|
||||||
|
expect(key).toStartWith(`supabase-cli-containers-v1-${process.platform}-${process.arch}-`);
|
||||||
|
expect(key).toContain("supabase-2.84.2-ghcr.io-");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("collects images from labeled containers and Supabase image repositories", async () => {
|
||||||
|
const run = mock(async (_file: string, args: string[]) => {
|
||||||
|
if (args[0] === "ps") {
|
||||||
|
return {
|
||||||
|
stdout: "ghcr.io/supabase/postgres:15.8.1\ncustom/image:latest\n",
|
||||||
|
stderr: "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
stdout:
|
||||||
|
"ghcr.io/supabase/studio:2026.04.08\npublic.ecr.aws/supabase/kong:2.8.1\nlibrary/postgres:16\n<none>:<none>\n",
|
||||||
|
stderr: "",
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(await collectDockerImageRefs(run)).toEqual([
|
||||||
|
"custom/image:latest",
|
||||||
|
"ghcr.io/supabase/postgres:15.8.1",
|
||||||
|
"ghcr.io/supabase/studio:2026.04.08",
|
||||||
|
"public.ecr.aws/supabase/kong:2.8.1",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("restore skips docker and cache calls when cache input is disabled", async () => {
|
||||||
|
const run = mock(async () => ({ stdout: "", stderr: "" }));
|
||||||
|
const restoreCache = spyOn(cacheAction, "restoreCache").mockImplementation(async () => undefined);
|
||||||
|
const spies = {
|
||||||
|
getBooleanInput: spyOn(core, "getBooleanInput").mockImplementation(() => false),
|
||||||
|
getInput: spyOn(core, "getInput").mockImplementation(() => ""),
|
||||||
|
setOutput: spyOn(core, "setOutput").mockImplementation(() => {}),
|
||||||
|
saveState: spyOn(core, "saveState").mockImplementation(() => {}),
|
||||||
|
};
|
||||||
|
|
||||||
|
await restoreDockerImageCache("supabase 2.84.2", "ghcr.io", run);
|
||||||
|
|
||||||
|
expect(spies.setOutput).toHaveBeenCalledWith("cache-hit", "false");
|
||||||
|
expect(spies.saveState).toHaveBeenCalledWith("cache-enabled", "false");
|
||||||
|
expect(run).not.toHaveBeenCalled();
|
||||||
|
expect(restoreCache).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("restore loads a docker archive on exact cache hit", async () => {
|
||||||
|
const temp = createTempDir("setup-cli-runner-");
|
||||||
|
process.env.RUNNER_TEMP = temp;
|
||||||
|
const calls: string[][] = [];
|
||||||
|
const run = mock(async (_file: string, args: string[]) => {
|
||||||
|
calls.push(args);
|
||||||
|
return { stdout: "ok\n", stderr: "" };
|
||||||
|
});
|
||||||
|
const restoreCache = spyOn(cacheAction, "restoreCache").mockImplementation(
|
||||||
|
async (paths: string[], key: string) => {
|
||||||
|
writeFileSync(paths[0]!, "archive");
|
||||||
|
return key;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const spies = {
|
||||||
|
getBooleanInput: spyOn(core, "getBooleanInput").mockImplementation(() => true),
|
||||||
|
getInput: spyOn(core, "getInput").mockImplementation((name: string) =>
|
||||||
|
name === "cache-key" ? "cache-key" : "",
|
||||||
|
),
|
||||||
|
setOutput: spyOn(core, "setOutput").mockImplementation(() => {}),
|
||||||
|
saveState: spyOn(core, "saveState").mockImplementation(() => {}),
|
||||||
|
info: spyOn(core, "info").mockImplementation(() => {}),
|
||||||
|
warning: spyOn(core, "warning").mockImplementation(() => {}),
|
||||||
|
};
|
||||||
|
|
||||||
|
await restoreDockerImageCache("supabase 2.84.2", "ghcr.io", run);
|
||||||
|
|
||||||
|
expect(restoreCache).toHaveBeenCalledWith(
|
||||||
|
[path.join(temp, "setup-supabase-cli", "supabase-cli-docker-images.tar")],
|
||||||
|
"cache-key",
|
||||||
|
);
|
||||||
|
expect(spies.setOutput).toHaveBeenCalledWith("cache-hit", "true");
|
||||||
|
expect(spies.saveState).toHaveBeenCalledWith("cache-hit", "true");
|
||||||
|
expect(calls).toContainEqual([
|
||||||
|
"load",
|
||||||
|
"-i",
|
||||||
|
path.join(temp, "setup-supabase-cli", "supabase-cli-docker-images.tar"),
|
||||||
|
]);
|
||||||
|
expect(spies.warning).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("post saves collected Supabase docker images", async () => {
|
||||||
|
const temp = createTempDir("setup-cli-runner-");
|
||||||
|
process.env.RUNNER_TEMP = temp;
|
||||||
|
const calls: string[][] = [];
|
||||||
|
const run = mock(async (_file: string, args: string[]) => {
|
||||||
|
calls.push(args);
|
||||||
|
if (args[0] === "ps") {
|
||||||
|
return { stdout: "ghcr.io/supabase/postgres:15.8.1\n", stderr: "" };
|
||||||
|
}
|
||||||
|
if (args[0] === "image") {
|
||||||
|
return { stdout: "ghcr.io/supabase/studio:2026.04.08\n", stderr: "" };
|
||||||
|
}
|
||||||
|
return { stdout: "ok\n", stderr: "" };
|
||||||
|
});
|
||||||
|
const saveCache = spyOn(cacheAction, "saveCache").mockImplementation(async () => 1);
|
||||||
|
const state = new Map([
|
||||||
|
["cache-enabled", "true"],
|
||||||
|
["cache-hit", "false"],
|
||||||
|
["cache-primary-key", "cache-key"],
|
||||||
|
["cache-archive-path", path.join(temp, "setup-supabase-cli", "supabase-cli-docker-images.tar")],
|
||||||
|
]);
|
||||||
|
spyOn(core, "getState").mockImplementation((name: string) => state.get(name) ?? "");
|
||||||
|
spyOn(core, "info").mockImplementation(() => {});
|
||||||
|
spyOn(core, "warning").mockImplementation(() => {});
|
||||||
|
|
||||||
|
await saveDockerImageCache(run);
|
||||||
|
|
||||||
|
expect(calls).toContainEqual([
|
||||||
|
"save",
|
||||||
|
"-o",
|
||||||
|
path.join(temp, "setup-supabase-cli", "supabase-cli-docker-images.tar"),
|
||||||
|
"ghcr.io/supabase/postgres:15.8.1",
|
||||||
|
"ghcr.io/supabase/studio:2026.04.08",
|
||||||
|
]);
|
||||||
|
expect(saveCache).toHaveBeenCalledWith(
|
||||||
|
[path.join(temp, "setup-supabase-cli", "supabase-cli-docker-images.tar")],
|
||||||
|
"cache-key",
|
||||||
|
);
|
||||||
|
});
|
||||||
254
src/cache.ts
Normal file
254
src/cache.ts
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
import * as cache from "@actions/cache";
|
||||||
|
import * as core from "@actions/core";
|
||||||
|
import { execFile as execFileCallback } from "node:child_process";
|
||||||
|
import { createHash } from "node:crypto";
|
||||||
|
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
||||||
|
import os from "node:os";
|
||||||
|
import path from "node:path";
|
||||||
|
import { promisify } from "node:util";
|
||||||
|
|
||||||
|
const CLI_CONFIG_REGISTRY = "SUPABASE_INTERNAL_IMAGE_REGISTRY";
|
||||||
|
const CACHE_ARCHIVE = "supabase-cli-docker-images.tar";
|
||||||
|
const CACHE_DIR = "setup-supabase-cli";
|
||||||
|
const CACHE_KEY_VERSION = "v1";
|
||||||
|
const DEFAULT_REGISTRY = "public.ecr.aws";
|
||||||
|
const GHCR_REGISTRY = "ghcr.io";
|
||||||
|
const CACHE_INPUT = "cache";
|
||||||
|
const CACHE_KEY_INPUT = "cache-key";
|
||||||
|
const CACHE_HIT_OUTPUT = "cache-hit";
|
||||||
|
const STATE_ENABLED = "cache-enabled";
|
||||||
|
const STATE_PRIMARY_KEY = "cache-primary-key";
|
||||||
|
const STATE_ARCHIVE_PATH = "cache-archive-path";
|
||||||
|
const STATE_CACHE_HIT = "cache-hit";
|
||||||
|
const CLI_PROJECT_LABEL = "com.supabase.cli.project";
|
||||||
|
const SUPABASE_IMAGE_PREFIXES = ["ghcr.io/supabase/", "public.ecr.aws/supabase/", "supabase/"];
|
||||||
|
|
||||||
|
type ExecFile = (
|
||||||
|
file: string,
|
||||||
|
args: string[],
|
||||||
|
options?: { maxBuffer?: number },
|
||||||
|
) => Promise<{ stdout: string; stderr: string }>;
|
||||||
|
|
||||||
|
const execFile = promisify(execFileCallback) as ExecFile;
|
||||||
|
|
||||||
|
function sanitizeCacheKeyPart(value: string): string {
|
||||||
|
return value.replace(/[^A-Za-z0-9_.-]/g, "-").replace(/-+/g, "-");
|
||||||
|
}
|
||||||
|
|
||||||
|
function hashFile(filePath: string): string | null {
|
||||||
|
if (!existsSync(filePath)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return createHash("sha256").update(readFileSync(filePath)).digest("hex");
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getConfigHash(): string {
|
||||||
|
const workspaceRoot = process.env.GITHUB_WORKSPACE?.trim();
|
||||||
|
if (!workspaceRoot) {
|
||||||
|
return "no-config";
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashFile(path.join(workspaceRoot, "supabase", "config.toml")) ?? "no-config";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCacheArchivePath(): string {
|
||||||
|
const runnerTemp = process.env.RUNNER_TEMP?.trim() || os.tmpdir();
|
||||||
|
return path.join(runnerTemp, CACHE_DIR, CACHE_ARCHIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getImageRegistry(): string {
|
||||||
|
return process.env[CLI_CONFIG_REGISTRY]?.trim() || DEFAULT_REGISTRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getGhcrImageRegistry(): string {
|
||||||
|
return GHCR_REGISTRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createDockerImageCacheKey(installedVersion: string, registry: string): string {
|
||||||
|
return [
|
||||||
|
"supabase-cli-containers",
|
||||||
|
CACHE_KEY_VERSION,
|
||||||
|
sanitizeCacheKeyPart(process.platform),
|
||||||
|
sanitizeCacheKeyPart(process.arch),
|
||||||
|
sanitizeCacheKeyPart(installedVersion),
|
||||||
|
sanitizeCacheKeyPart(registry),
|
||||||
|
getConfigHash(),
|
||||||
|
].join("-");
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPrimaryCacheKey(installedVersion: string, registry: string): string {
|
||||||
|
const cacheKeyInput = core.getInput(CACHE_KEY_INPUT).trim();
|
||||||
|
if (cacheKeyInput) {
|
||||||
|
return cacheKeyInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
return createDockerImageCacheKey(installedVersion, registry);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function isDockerAvailable(run: ExecFile = execFile): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
await run("docker", ["version"]);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runDocker(args: string[], run: ExecFile = execFile): Promise<string> {
|
||||||
|
const { stdout } = await run("docker", args, { maxBuffer: 1024 * 1024 * 16 });
|
||||||
|
return stdout;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeImageRefs(output: string): string[] {
|
||||||
|
return output
|
||||||
|
.split(/\r?\n/)
|
||||||
|
.map((line) => line.trim())
|
||||||
|
.filter((line) => line.length > 0 && !line.includes("<none>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSupabaseImageRef(ref: string): boolean {
|
||||||
|
return SUPABASE_IMAGE_PREFIXES.some((prefix) => ref.startsWith(prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function collectDockerImageRefs(run: ExecFile = execFile): Promise<string[]> {
|
||||||
|
const refs = new Set<string>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const output = await runDocker(
|
||||||
|
["ps", "-a", "--filter", `label=${CLI_PROJECT_LABEL}`, "--format", "{{.Image}}"],
|
||||||
|
run,
|
||||||
|
);
|
||||||
|
for (const ref of normalizeImageRefs(output)) {
|
||||||
|
refs.add(ref);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
core.warning(
|
||||||
|
`Could not list Supabase CLI containers for Docker image cache: ${error instanceof Error ? error.message : String(error)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const output = await runDocker(["image", "ls", "--format", "{{.Repository}}:{{.Tag}}"], run);
|
||||||
|
for (const ref of normalizeImageRefs(output).filter(isSupabaseImageRef)) {
|
||||||
|
refs.add(ref);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
core.warning(
|
||||||
|
`Could not list Docker images for Supabase image cache: ${error instanceof Error ? error.message : String(error)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...refs].sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function restoreDockerImageCache(
|
||||||
|
installedVersion: string,
|
||||||
|
registry: string,
|
||||||
|
run: ExecFile = execFile,
|
||||||
|
): Promise<void> {
|
||||||
|
const enabled = core.getBooleanInput(CACHE_INPUT);
|
||||||
|
core.setOutput(CACHE_HIT_OUTPUT, "false");
|
||||||
|
core.saveState(STATE_ENABLED, String(enabled));
|
||||||
|
|
||||||
|
if (!enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const archivePath = getCacheArchivePath();
|
||||||
|
const primaryKey = getPrimaryCacheKey(installedVersion, registry);
|
||||||
|
mkdirSync(path.dirname(archivePath), { recursive: true });
|
||||||
|
core.saveState(STATE_PRIMARY_KEY, primaryKey);
|
||||||
|
core.saveState(STATE_ARCHIVE_PATH, archivePath);
|
||||||
|
core.saveState(STATE_CACHE_HIT, "false");
|
||||||
|
|
||||||
|
if (!(await isDockerAvailable(run))) {
|
||||||
|
core.warning("Docker is not available. Skipping Supabase Docker image cache restore.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let matchedKey: string | undefined;
|
||||||
|
try {
|
||||||
|
matchedKey = await cache.restoreCache([archivePath], primaryKey);
|
||||||
|
} catch (error) {
|
||||||
|
core.warning(
|
||||||
|
`Could not restore Supabase Docker image cache: ${error instanceof Error ? error.message : String(error)}`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!matchedKey) {
|
||||||
|
core.info("No Supabase Docker image cache found.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cacheHit = matchedKey === primaryKey;
|
||||||
|
core.setOutput(CACHE_HIT_OUTPUT, String(cacheHit));
|
||||||
|
core.saveState(STATE_CACHE_HIT, String(cacheHit));
|
||||||
|
|
||||||
|
if (!existsSync(archivePath)) {
|
||||||
|
core.warning("Supabase Docker image cache was restored, but the archive is missing.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await runDocker(["load", "-i", archivePath], run);
|
||||||
|
core.info("Loaded Supabase Docker images from cache.");
|
||||||
|
} catch (error) {
|
||||||
|
core.warning(
|
||||||
|
`Could not load Supabase Docker image cache: ${error instanceof Error ? error.message : String(error)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function saveDockerImageCache(run: ExecFile = execFile): Promise<void> {
|
||||||
|
if (core.getState(STATE_ENABLED) !== "true") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (core.getState(STATE_CACHE_HIT) === "true") {
|
||||||
|
core.info("Supabase Docker image cache hit. Skipping cache save.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const primaryKey = core.getState(STATE_PRIMARY_KEY);
|
||||||
|
const archivePath = core.getState(STATE_ARCHIVE_PATH) || getCacheArchivePath();
|
||||||
|
if (!primaryKey) {
|
||||||
|
core.warning("Supabase Docker image cache key is missing. Skipping cache save.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(await isDockerAvailable(run))) {
|
||||||
|
core.warning("Docker is not available. Skipping Supabase Docker image cache save.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const imageRefs = await collectDockerImageRefs(run);
|
||||||
|
if (imageRefs.length === 0) {
|
||||||
|
core.warning("No Supabase Docker images found to cache.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdirSync(path.dirname(archivePath), { recursive: true });
|
||||||
|
try {
|
||||||
|
await runDocker(["save", "-o", archivePath, ...imageRefs], run);
|
||||||
|
} catch (error) {
|
||||||
|
core.warning(
|
||||||
|
`Could not create Supabase Docker image archive: ${error instanceof Error ? error.message : String(error)}`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await cache.saveCache([archivePath], primaryKey);
|
||||||
|
core.info(`Saved ${imageRefs.length} Supabase Docker image(s) to cache.`);
|
||||||
|
} catch (error) {
|
||||||
|
core.warning(
|
||||||
|
`Could not save Supabase Docker image cache: ${error instanceof Error ? error.message : String(error)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
576
src/main.test.ts
576
src/main.test.ts
@@ -1,29 +1,22 @@
|
|||||||
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||||
import os from "node:os";
|
import os from "node:os";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import process from "node:process";
|
import process from "node:process";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
import { afterEach, expect, mock, spyOn, test } from "bun:test";
|
import { afterEach, expect, mock, spyOn, test } from "bun:test";
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
|
import * as tc from "@actions/tool-cache";
|
||||||
|
|
||||||
|
const repo = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
|
||||||
|
const defaultEntrypoint = fileURLToPath(new URL("./main.ts", import.meta.url));
|
||||||
const CLI_CONFIG_REGISTRY = "SUPABASE_INTERNAL_IMAGE_REGISTRY";
|
const CLI_CONFIG_REGISTRY = "SUPABASE_INTERNAL_IMAGE_REGISTRY";
|
||||||
const originalPath = process.env.PATH;
|
|
||||||
const originalRunnerTemp = process.env.RUNNER_TEMP;
|
|
||||||
const originalWorkspace = process.env.GITHUB_WORKSPACE;
|
const originalWorkspace = process.env.GITHUB_WORKSPACE;
|
||||||
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;
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
mock.restore();
|
mock.restore();
|
||||||
process.env.PATH = originalPath;
|
|
||||||
process.env.RUNNER_TEMP = originalRunnerTemp;
|
|
||||||
process.env.GITHUB_WORKSPACE = originalWorkspace;
|
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_LOG;
|
|
||||||
delete process.env.FAKE_NPM_PACKAGE_VERSION;
|
|
||||||
delete process.env.FAKE_NPM_POSTINSTALL;
|
|
||||||
delete process.env.SUPABASE_SETUP_CLI_NPM;
|
|
||||||
|
|
||||||
for (const dir of tempDirs) {
|
for (const dir of tempDirs) {
|
||||||
rmSync(dir, { force: true, recursive: true });
|
rmSync(dir, { force: true, recursive: true });
|
||||||
@@ -31,14 +24,32 @@ afterEach(() => {
|
|||||||
tempDirs.clear();
|
tempDirs.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
function createTempDir(prefix: string): string {
|
function createFakeCli(versionOutput: string): string {
|
||||||
const dir = mkdtempSync(path.join(os.tmpdir(), prefix));
|
const dir = mkdtempSync(path.join(os.tmpdir(), "setup-cli-"));
|
||||||
tempDirs.add(dir);
|
tempDirs.add(dir);
|
||||||
|
|
||||||
|
if (process.platform === "win32") {
|
||||||
|
writeFileSync(
|
||||||
|
path.join(dir, "supabase.cmd"),
|
||||||
|
versionOutput ? `@echo off\r\necho ${versionOutput}\r\n` : "@echo off\r\n",
|
||||||
|
);
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
const escapedOutput = versionOutput.replaceAll("'", "'\"'\"'");
|
||||||
|
writeFileSync(
|
||||||
|
path.join(dir, "supabase"),
|
||||||
|
versionOutput
|
||||||
|
? `#!/usr/bin/env bash\nprintf '%s\\n' '${escapedOutput}'\n`
|
||||||
|
: "#!/usr/bin/env bash\n",
|
||||||
|
);
|
||||||
|
Bun.spawnSync(["chmod", "+x", path.join(dir, "supabase")]);
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createWorkspace(files: Record<string, string>): string {
|
function createWorkspace(files: Record<string, string>): string {
|
||||||
const dir = createTempDir("setup-cli-workspace-");
|
const dir = mkdtempSync(path.join(os.tmpdir(), "setup-cli-workspace-"));
|
||||||
|
tempDirs.add(dir);
|
||||||
|
|
||||||
for (const [relativePath, content] of Object.entries(files)) {
|
for (const [relativePath, content] of Object.entries(files)) {
|
||||||
const filePath = path.join(dir, relativePath);
|
const filePath = path.join(dir, relativePath);
|
||||||
@@ -54,7 +65,6 @@ function createBunLock(
|
|||||||
options: {
|
options: {
|
||||||
includeDependency?: boolean;
|
includeDependency?: boolean;
|
||||||
includePackageEntry?: boolean;
|
includePackageEntry?: boolean;
|
||||||
integrity?: string;
|
|
||||||
useDevDependency?: boolean;
|
useDevDependency?: boolean;
|
||||||
} = {},
|
} = {},
|
||||||
): string {
|
): string {
|
||||||
@@ -80,7 +90,7 @@ ${
|
|||||||
"supabase@${version}",
|
"supabase@${version}",
|
||||||
"",
|
"",
|
||||||
{},
|
{},
|
||||||
"${options.integrity ?? "sha512-bun"}"
|
"sha512-test"
|
||||||
]`
|
]`
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
@@ -91,12 +101,7 @@ ${
|
|||||||
|
|
||||||
function createPnpmLock(
|
function createPnpmLock(
|
||||||
version: string,
|
version: string,
|
||||||
options: {
|
options: { asString?: boolean; includeVersion?: boolean; useDevDependency?: boolean } = {},
|
||||||
asString?: boolean;
|
|
||||||
includeVersion?: boolean;
|
|
||||||
integrity?: string;
|
|
||||||
useDevDependency?: boolean;
|
|
||||||
} = {},
|
|
||||||
): string {
|
): string {
|
||||||
const dependencyKey = options.useDevDependency ? "devDependencies" : "dependencies";
|
const dependencyKey = options.useDevDependency ? "devDependencies" : "dependencies";
|
||||||
|
|
||||||
@@ -114,11 +119,11 @@ ${options.includeVersion === false ? "" : ` version: ${version}`}`
|
|||||||
packages:
|
packages:
|
||||||
supabase@${version}:
|
supabase@${version}:
|
||||||
resolution:
|
resolution:
|
||||||
integrity: ${options.integrity ?? "sha512-pnpm"}
|
integrity: sha512-test
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createPackageLock(version: string, integrity = "sha512-package-lock"): string {
|
function createPackageLock(version: string): string {
|
||||||
return JSON.stringify(
|
return JSON.stringify(
|
||||||
{
|
{
|
||||||
name: "app",
|
name: "app",
|
||||||
@@ -130,7 +135,6 @@ function createPackageLock(version: string, integrity = "sha512-package-lock"):
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
"node_modules/supabase": {
|
"node_modules/supabase": {
|
||||||
integrity,
|
|
||||||
version,
|
version,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -140,139 +144,24 @@ function createPackageLock(version: string, integrity = "sha512-package-lock"):
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createFakeNpm(): string {
|
function createActionSpies(inputVersion: string, cliDir: string, expectedUrlFragment: string) {
|
||||||
const root = createTempDir("setup-cli-fake-npm-");
|
|
||||||
const binDir = path.join(root, "bin");
|
|
||||||
const scriptPath = path.join(root, "fake-npm.js");
|
|
||||||
mkdirSync(binDir, { recursive: true });
|
|
||||||
writeFileSync(
|
|
||||||
scriptPath,
|
|
||||||
`import { appendFileSync, mkdirSync, 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");
|
|
||||||
|
|
||||||
if (args[0] === "view") {
|
|
||||||
const bin =
|
|
||||||
process.env.FAKE_NPM_BIN === "missing"
|
|
||||||
? undefined
|
|
||||||
: { supabase: process.env.FAKE_NPM_BIN ?? "dist/supabase.js" };
|
|
||||||
const scripts = process.env.FAKE_NPM_POSTINSTALL
|
|
||||||
? { postinstall: process.env.FAKE_NPM_POSTINSTALL }
|
|
||||||
: {};
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args[0] !== "install") {
|
|
||||||
console.error("Unexpected npm command: " + args.join(" "));
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const prefixIndex = args.indexOf("--prefix");
|
|
||||||
const prefix = prefixIndex === -1 ? undefined : args[prefixIndex + 1];
|
|
||||||
if (!prefix) {
|
|
||||||
console.error("Missing --prefix");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const binDir = path.join(prefix, "node_modules", ".bin");
|
|
||||||
mkdirSync(binDir, { recursive: true });
|
|
||||||
|
|
||||||
if (process.platform === "win32") {
|
|
||||||
writeFileSync(
|
|
||||||
path.join(binDir, "supabase.cmd"),
|
|
||||||
process.env.FAKE_CLI_VERSION ? "@echo off\\r\\necho " + process.env.FAKE_CLI_VERSION + "\\r\\n" : "@echo off\\r\\n",
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
writeFileSync(
|
|
||||||
path.join(binDir, "supabase"),
|
|
||||||
process.env.FAKE_CLI_VERSION
|
|
||||||
? "#!/usr/bin/env bash\\nprintf '%s\\\\n' '" + process.env.FAKE_CLI_VERSION.replaceAll("'", "'\\\\''") + "'\\n"
|
|
||||||
: "#!/usr/bin/env bash\\n",
|
|
||||||
{ mode: 0o755 },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (process.platform === "win32") {
|
|
||||||
writeFileSync(
|
|
||||||
path.join(binDir, "npm.cmd"),
|
|
||||||
`@echo off\r\n"${process.execPath}" "${scriptPath}" %*\r\n`,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
writeFileSync(
|
|
||||||
path.join(binDir, "npm"),
|
|
||||||
`#!/usr/bin/env bash\nexec "${process.execPath}" "${scriptPath}" "$@"\n`,
|
|
||||||
{ mode: 0o755 },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return binDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
function installFakeNpm(
|
|
||||||
versionOutput = "supabase 2.101.0",
|
|
||||||
options: {
|
|
||||||
bin?: string;
|
|
||||||
integrity?: string;
|
|
||||||
packageVersion?: string;
|
|
||||||
postinstall?: string;
|
|
||||||
} = {},
|
|
||||||
): string {
|
|
||||||
const binDir = createFakeNpm();
|
|
||||||
const logPath = path.join(createTempDir("setup-cli-fake-npm-log-"), "npm.log");
|
|
||||||
writeFileSync(logPath, "");
|
|
||||||
process.env.FAKE_CLI_VERSION = versionOutput;
|
|
||||||
process.env.FAKE_NPM_BIN = options.bin ?? "dist/supabase.js";
|
|
||||||
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.postinstall) {
|
|
||||||
process.env.FAKE_NPM_POSTINSTALL = options.postinstall;
|
|
||||||
}
|
|
||||||
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",
|
|
||||||
);
|
|
||||||
|
|
||||||
return logPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
function readNpmCalls(logPath: string): string[][] {
|
|
||||||
return readFileSync(logPath, "utf8")
|
|
||||||
.trim()
|
|
||||||
.split("\n")
|
|
||||||
.filter(Boolean)
|
|
||||||
.map((line) => JSON.parse(line) as string[]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function viewMetadataCall(spec: string): string[] {
|
|
||||||
return ["view", spec, "version", "bin", "scripts", "dist.integrity", "--json"];
|
|
||||||
}
|
|
||||||
|
|
||||||
function createActionSpies(inputVersion: string) {
|
|
||||||
return {
|
return {
|
||||||
|
getInput: spyOn(core, "getInput").mockImplementation((name: string) =>
|
||||||
|
name === "version" ? inputVersion : "",
|
||||||
|
),
|
||||||
|
getBooleanInput: spyOn(core, "getBooleanInput").mockImplementation(() => false),
|
||||||
|
setOutput: spyOn(core, "setOutput").mockImplementation(() => {}),
|
||||||
addPath: spyOn(core, "addPath").mockImplementation(() => {}),
|
addPath: spyOn(core, "addPath").mockImplementation(() => {}),
|
||||||
exportVariable: spyOn(core, "exportVariable").mockImplementation(() => {}),
|
exportVariable: spyOn(core, "exportVariable").mockImplementation(() => {}),
|
||||||
getInput: spyOn(core, "getInput").mockReturnValue(inputVersion),
|
saveState: spyOn(core, "saveState").mockImplementation(() => {}),
|
||||||
|
info: spyOn(core, "info").mockImplementation(() => {}),
|
||||||
|
warning: spyOn(core, "warning").mockImplementation(() => {}),
|
||||||
setFailed: spyOn(core, "setFailed").mockImplementation(() => {}),
|
setFailed: spyOn(core, "setFailed").mockImplementation(() => {}),
|
||||||
setOutput: spyOn(core, "setOutput").mockImplementation(() => {}),
|
downloadTool: spyOn(tc, "downloadTool").mockImplementation(async (url: string) => {
|
||||||
|
expect(url).toContain(expectedUrlFragment);
|
||||||
|
return path.join(os.tmpdir(), "supabase-cli.tar.gz");
|
||||||
|
}),
|
||||||
|
extractTar: spyOn(tc, "extractTar").mockImplementation(async () => cliDir),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,69 +173,106 @@ async function getMainModule(): Promise<typeof import("./main.ts")> {
|
|||||||
return mainModule;
|
return mainModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
test("uses an explicit npm package version when provided", async () => {
|
test("awaits the action entrypoint with omitted version and latest fallback", async () => {
|
||||||
const { resolvePackage } = await getMainModule();
|
process.env.GITHUB_WORKSPACE = repo;
|
||||||
|
const cliDir = createFakeCli("supabase 2.84.2");
|
||||||
expect(resolvePackage("v2.101.0")).toEqual({
|
let startDownload!: () => void;
|
||||||
spec: "supabase@2.101.0",
|
let finishDownload!: () => void;
|
||||||
version: "2.101.0",
|
const downloadStarted = new Promise<void>((resolve) => {
|
||||||
|
startDownload = resolve;
|
||||||
});
|
});
|
||||||
});
|
const downloadFinished = new Promise<string>((resolve) => {
|
||||||
|
finishDownload = () => resolve(path.join(os.tmpdir(), "supabase-cli.tar.gz"));
|
||||||
test("uses an explicit npm dist-tag when provided", async () => {
|
|
||||||
const { resolvePackage } = await getMainModule();
|
|
||||||
|
|
||||||
expect(resolvePackage("beta")).toEqual({
|
|
||||||
spec: "supabase@beta",
|
|
||||||
version: "beta",
|
|
||||||
});
|
});
|
||||||
|
const spies = {
|
||||||
|
getInput: spyOn(core, "getInput").mockImplementation((name: string) =>
|
||||||
|
name === "version" ? "" : "",
|
||||||
|
),
|
||||||
|
getBooleanInput: spyOn(core, "getBooleanInput").mockImplementation(() => false),
|
||||||
|
setOutput: spyOn(core, "setOutput").mockImplementation(() => {}),
|
||||||
|
addPath: spyOn(core, "addPath").mockImplementation(() => {}),
|
||||||
|
exportVariable: spyOn(core, "exportVariable").mockImplementation(() => {}),
|
||||||
|
saveState: spyOn(core, "saveState").mockImplementation(() => {}),
|
||||||
|
info: spyOn(core, "info").mockImplementation(() => {}),
|
||||||
|
warning: spyOn(core, "warning").mockImplementation(() => {}),
|
||||||
|
setFailed: spyOn(core, "setFailed").mockImplementation(() => {}),
|
||||||
|
downloadTool: spyOn(tc, "downloadTool").mockImplementation(async (url: string) => {
|
||||||
|
expect(url).toContain("/latest/download/");
|
||||||
|
startDownload();
|
||||||
|
return downloadFinished;
|
||||||
|
}),
|
||||||
|
extractTar: spyOn(tc, "extractTar").mockImplementation(async () => cliDir),
|
||||||
|
};
|
||||||
|
const originalArgv1 = process.argv[1];
|
||||||
|
process.argv[1] = defaultEntrypoint;
|
||||||
|
|
||||||
|
try {
|
||||||
|
let importSettled = false;
|
||||||
|
const entrypoint = import(`./main.ts?entrypoint=${Date.now()}`).finally(() => {
|
||||||
|
importSettled = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
await downloadStarted;
|
||||||
|
await Bun.sleep(0);
|
||||||
|
|
||||||
|
expect(importSettled).toBe(false);
|
||||||
|
|
||||||
|
finishDownload();
|
||||||
|
await entrypoint;
|
||||||
|
} finally {
|
||||||
|
process.argv[1] = originalArgv1 ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 2.84.2");
|
||||||
|
expect(spies.addPath).toHaveBeenCalledWith(cliDir);
|
||||||
|
expect(spies.exportVariable).toHaveBeenCalledWith(CLI_CONFIG_REGISTRY, "ghcr.io");
|
||||||
|
expect(spies.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("rejects unsupported npm package selectors", async () => {
|
test("uses the root bun.lock version when version is omitted", 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({
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
"bun.lock": createBunLock("2.41.0", { integrity: "sha512-bun-lock" }),
|
"bun.lock": createBunLock("2.41.0"),
|
||||||
});
|
});
|
||||||
const { resolvePackage } = await getMainModule();
|
const cliDir = createFakeCli("supabase 2.41.0");
|
||||||
|
const spies = createActionSpies("", cliDir, "/download/v2.41.0/supabase_");
|
||||||
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
expect(resolvePackage("")).toEqual({
|
await run();
|
||||||
integrity: "sha512-bun-lock",
|
|
||||||
spec: "supabase@2.41.0",
|
expect(spies.downloadTool).not.toHaveBeenCalledWith(expect.stringContaining("/latest/download/"));
|
||||||
version: "2.41.0",
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 2.41.0");
|
||||||
});
|
expect(spies.exportVariable).toHaveBeenCalledWith(CLI_CONFIG_REGISTRY, "ghcr.io");
|
||||||
|
expect(spies.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("uses the root pnpm-lock.yaml resolution when version is omitted", async () => {
|
test("uses the root pnpm-lock.yaml version when version is omitted", async () => {
|
||||||
process.env.GITHUB_WORKSPACE = createWorkspace({
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
"pnpm-lock.yaml": createPnpmLock("2.42.0", { integrity: "sha512-pnpm-lock" }),
|
"pnpm-lock.yaml": createPnpmLock("2.42.0"),
|
||||||
});
|
});
|
||||||
const { resolvePackage } = await getMainModule();
|
const cliDir = createFakeCli("supabase 2.42.0");
|
||||||
|
const spies = createActionSpies("", cliDir, "/download/v2.42.0/supabase_");
|
||||||
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
expect(resolvePackage("")).toEqual({
|
await run();
|
||||||
integrity: "sha512-pnpm-lock",
|
|
||||||
spec: "supabase@2.42.0",
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 2.42.0");
|
||||||
version: "2.42.0",
|
expect(spies.exportVariable).toHaveBeenCalledWith(CLI_CONFIG_REGISTRY, "ghcr.io");
|
||||||
});
|
expect(spies.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("uses the root package-lock.json resolution when version is omitted", async () => {
|
test("uses the root package-lock.json version when version is omitted", async () => {
|
||||||
process.env.GITHUB_WORKSPACE = createWorkspace({
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
"package-lock.json": createPackageLock("2.43.0", "sha512-package-lock"),
|
"package-lock.json": createPackageLock("2.43.0"),
|
||||||
});
|
});
|
||||||
const { resolvePackage } = await getMainModule();
|
const cliDir = createFakeCli("supabase 2.43.0");
|
||||||
|
const spies = createActionSpies("", cliDir, "/download/v2.43.0/supabase_");
|
||||||
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
expect(resolvePackage("")).toEqual({
|
await run();
|
||||||
integrity: "sha512-package-lock",
|
|
||||||
spec: "supabase@2.43.0",
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 2.43.0");
|
||||||
version: "2.43.0",
|
expect(spies.exportVariable).toHaveBeenCalledWith(CLI_CONFIG_REGISTRY, "ghcr.io");
|
||||||
});
|
expect(spies.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("falls through malformed lockfiles and uses the next supported root lockfile", async () => {
|
test("falls through malformed lockfiles and uses the next supported root lockfile", async () => {
|
||||||
@@ -354,47 +280,58 @@ test("falls through malformed lockfiles and uses the next supported root lockfil
|
|||||||
"bun.lock": "{ not valid",
|
"bun.lock": "{ not valid",
|
||||||
"package-lock.json": createPackageLock("2.44.0"),
|
"package-lock.json": createPackageLock("2.44.0"),
|
||||||
});
|
});
|
||||||
const { resolvePackage } = await getMainModule();
|
const cliDir = createFakeCli("supabase 2.44.0");
|
||||||
|
const spies = createActionSpies("", cliDir, "/download/v2.44.0/supabase_");
|
||||||
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
expect(resolvePackage("")).toEqual({
|
await run();
|
||||||
integrity: "sha512-package-lock",
|
|
||||||
spec: "supabase@2.44.0",
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 2.44.0");
|
||||||
version: "2.44.0",
|
expect(spies.exportVariable).toHaveBeenCalledWith(CLI_CONFIG_REGISTRY, "ghcr.io");
|
||||||
});
|
expect(spies.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("falls back to latest when version is omitted and no supported root lockfile is present", async () => {
|
test("falls back to latest when version is omitted and no supported root lockfile is present", async () => {
|
||||||
process.env.GITHUB_WORKSPACE = createWorkspace({
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
"README.md": "# app\n",
|
"README.md": "# app\n",
|
||||||
});
|
});
|
||||||
const { resolvePackage } = await getMainModule();
|
const cliDir = createFakeCli("supabase 2.84.2");
|
||||||
|
const spies = createActionSpies("", cliDir, "/latest/download/");
|
||||||
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
expect(resolvePackage("")).toEqual({
|
await run();
|
||||||
spec: "supabase@latest",
|
|
||||||
version: "latest",
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 2.84.2");
|
||||||
});
|
expect(spies.exportVariable).toHaveBeenCalledWith(CLI_CONFIG_REGISTRY, "ghcr.io");
|
||||||
|
expect(spies.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("falls back to latest when version is omitted and no workspace is available", async () => {
|
test("falls back to latest when version is omitted and no workspace is available", async () => {
|
||||||
delete process.env.GITHUB_WORKSPACE;
|
delete process.env.GITHUB_WORKSPACE;
|
||||||
const { resolvePackage } = await getMainModule();
|
const cliDir = createFakeCli("supabase 2.84.2");
|
||||||
|
const spies = createActionSpies("", cliDir, "/latest/download/");
|
||||||
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
expect(resolvePackage("")).toEqual({
|
await run();
|
||||||
spec: "supabase@latest",
|
|
||||||
version: "latest",
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 2.84.2");
|
||||||
});
|
expect(spies.exportVariable).toHaveBeenCalledWith(CLI_CONFIG_REGISTRY, "ghcr.io");
|
||||||
|
expect(spies.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("uses the declared bun.lock version when the resolved package entry is missing", async () => {
|
test("uses the declared bun.lock version when the resolved package entry is missing", async () => {
|
||||||
process.env.GITHUB_WORKSPACE = createWorkspace({
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
"bun.lock": createBunLock("2.44.1", { includePackageEntry: false, useDevDependency: true }),
|
"bun.lock": createBunLock("2.44.1", { includePackageEntry: false, useDevDependency: true }),
|
||||||
});
|
});
|
||||||
const { resolvePackage } = await getMainModule();
|
const cliDir = createFakeCli("supabase 2.44.1");
|
||||||
|
const spies = createActionSpies("", cliDir, "/download/v2.44.1/supabase_");
|
||||||
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
expect(resolvePackage("")).toEqual({
|
await run();
|
||||||
spec: "supabase@2.44.1",
|
|
||||||
version: "2.44.1",
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 2.44.1");
|
||||||
});
|
expect(spies.exportVariable).toHaveBeenCalledWith(CLI_CONFIG_REGISTRY, "ghcr.io");
|
||||||
|
expect(spies.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("falls through bun.lock without supabase and uses a pnpm string dependency version", async () => {
|
test("falls through bun.lock without supabase and uses a pnpm string dependency version", async () => {
|
||||||
@@ -402,183 +339,86 @@ test("falls through bun.lock without supabase and uses a pnpm string dependency
|
|||||||
"bun.lock": createBunLock("2.47.0", { includeDependency: false }),
|
"bun.lock": createBunLock("2.47.0", { includeDependency: false }),
|
||||||
"pnpm-lock.yaml": createPnpmLock("2.47.0", { asString: true }),
|
"pnpm-lock.yaml": createPnpmLock("2.47.0", { asString: true }),
|
||||||
});
|
});
|
||||||
const { resolvePackage } = await getMainModule();
|
const cliDir = createFakeCli("supabase 2.47.0");
|
||||||
|
const spies = createActionSpies("", cliDir, "/download/v2.47.0/supabase_");
|
||||||
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
expect(resolvePackage("")).toEqual({
|
await run();
|
||||||
integrity: "sha512-pnpm",
|
|
||||||
spec: "supabase@2.47.0",
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 2.47.0");
|
||||||
version: "2.47.0",
|
expect(spies.exportVariable).toHaveBeenCalledWith(CLI_CONFIG_REGISTRY, "ghcr.io");
|
||||||
|
expect(spies.setFailed).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("falls through malformed pnpm lockfiles and uses the next supported root lockfile", async () => {
|
||||||
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
|
"pnpm-lock.yaml": "not: [valid",
|
||||||
|
"package-lock.json": createPackageLock("2.48.0"),
|
||||||
});
|
});
|
||||||
|
const cliDir = createFakeCli("supabase 2.48.0");
|
||||||
|
const spies = createActionSpies("", cliDir, "/download/v2.48.0/supabase_");
|
||||||
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 2.48.0");
|
||||||
|
expect(spies.exportVariable).toHaveBeenCalledWith(CLI_CONFIG_REGISTRY, "ghcr.io");
|
||||||
|
expect(spies.setFailed).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("falls through unreadable bun.lock paths and malformed package-lock files to latest", async () => {
|
||||||
|
const workspace = createWorkspace({
|
||||||
|
"package-lock.json": "{ invalid",
|
||||||
|
});
|
||||||
|
mkdirSync(path.join(workspace, "bun.lock"), { recursive: true });
|
||||||
|
process.env.GITHUB_WORKSPACE = workspace;
|
||||||
|
const cliDir = createFakeCli("supabase 2.84.2");
|
||||||
|
const spies = createActionSpies("", cliDir, "/latest/download/");
|
||||||
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 2.84.2");
|
||||||
|
expect(spies.exportVariable).toHaveBeenCalledWith(CLI_CONFIG_REGISTRY, "ghcr.io");
|
||||||
|
expect(spies.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("falls back to latest when a pnpm dependency entry has no concrete version", async () => {
|
test("falls back to latest when a pnpm dependency entry has no concrete version", async () => {
|
||||||
process.env.GITHUB_WORKSPACE = createWorkspace({
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
"pnpm-lock.yaml": createPnpmLock("2.49.0", { includeVersion: false }),
|
"pnpm-lock.yaml": createPnpmLock("2.49.0", { includeVersion: false }),
|
||||||
});
|
});
|
||||||
const { resolvePackage } = await getMainModule();
|
const cliDir = createFakeCli("supabase 2.84.2");
|
||||||
|
const spies = createActionSpies("", cliDir, "/latest/download/");
|
||||||
expect(resolvePackage("")).toEqual({
|
|
||||||
spec: "supabase@latest",
|
|
||||||
version: "latest",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("installs the CLI with npm into an isolated prefix", async () => {
|
|
||||||
const logPath = installFakeNpm();
|
|
||||||
const { installCli } = await getMainModule();
|
|
||||||
|
|
||||||
const cliPath = await installCli({
|
|
||||||
spec: "supabase@2.101.0",
|
|
||||||
version: "2.101.0",
|
|
||||||
});
|
|
||||||
|
|
||||||
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=true",
|
|
||||||
"supabase@2.101.0",
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("allows install scripts for legacy npm packages that declare a postinstall", async () => {
|
|
||||||
const logPath = installFakeNpm("supabase 1.178.2", {
|
|
||||||
bin: "bin/supabase",
|
|
||||||
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",
|
|
||||||
"--ignore-scripts=false",
|
|
||||||
"supabase@1.178.2",
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("verifies lockfile integrity before installing", async () => {
|
|
||||||
const logPath = installFakeNpm("supabase 2.101.0", { integrity: "sha512-lock" });
|
|
||||||
const { installCli } = await getMainModule();
|
|
||||||
|
|
||||||
await installCli({
|
|
||||||
integrity: "sha512-lock",
|
|
||||||
spec: "supabase@2.101.0",
|
|
||||||
version: "2.101.0",
|
|
||||||
});
|
|
||||||
|
|
||||||
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=true",
|
|
||||||
"supabase@2.101.0",
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("fails when lockfile integrity does not match the registry", async () => {
|
|
||||||
installFakeNpm("supabase 2.101.0", { integrity: "sha512-registry" });
|
|
||||||
const { installCli } = await getMainModule();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await installCli({
|
|
||||||
integrity: "sha512-lock",
|
|
||||||
spec: "supabase@2.101.0",
|
|
||||||
version: "2.101.0",
|
|
||||||
});
|
|
||||||
throw new Error("Expected installCli to reject");
|
|
||||||
} catch (error) {
|
|
||||||
expect(error).toEqual(
|
|
||||||
new Error("Lockfile integrity for supabase@2.101.0 does not match the npm registry"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
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", { integrity: "sha512-package-lock" });
|
|
||||||
process.env.GITHUB_WORKSPACE = createWorkspace({
|
|
||||||
"package-lock.json": createPackageLock("2.43.0", "sha512-package-lock"),
|
|
||||||
});
|
|
||||||
const spies = createActionSpies("");
|
|
||||||
const { run } = await getMainModule();
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
await run();
|
await run();
|
||||||
|
|
||||||
expect(readNpmCalls(logPath)[0]).toEqual(viewMetadataCall("supabase@2.43.0"));
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 2.84.2");
|
||||||
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");
|
expect(spies.exportVariable).toHaveBeenCalledWith(CLI_CONFIG_REGISTRY, "ghcr.io");
|
||||||
expect(spies.setFailed).not.toHaveBeenCalled();
|
expect(spies.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("explicit version overrides detected root lockfiles", async () => {
|
test("explicit version overrides detected root lockfiles", async () => {
|
||||||
installFakeNpm("supabase 1.1.6");
|
|
||||||
process.env.GITHUB_WORKSPACE = createWorkspace({
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
"bun.lock": createBunLock("2.45.0"),
|
"bun.lock": createBunLock("2.45.0"),
|
||||||
});
|
});
|
||||||
const spies = createActionSpies("1.1.6");
|
const cliDir = createFakeCli("supabase 1.0.0");
|
||||||
|
const spies = createActionSpies("1.0.0", cliDir, "/download/v1.0.0/supabase_1.0.0_");
|
||||||
const { run } = await getMainModule();
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
await run();
|
await run();
|
||||||
|
|
||||||
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 1.1.6");
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 1.0.0");
|
||||||
expect(spies.exportVariable).not.toHaveBeenCalled();
|
expect(spies.exportVariable).not.toHaveBeenCalled();
|
||||||
expect(spies.setFailed).not.toHaveBeenCalled();
|
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("");
|
|
||||||
process.env.GITHUB_WORKSPACE = createWorkspace({
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
"package-lock.json": createPackageLock("2.46.0", "sha512-test"),
|
"package-lock.json": createPackageLock("2.46.0"),
|
||||||
});
|
});
|
||||||
const spies = createActionSpies("");
|
const cliDir = createFakeCli("");
|
||||||
|
const spies = createActionSpies("", cliDir, "/download/v2.46.0/supabase_");
|
||||||
const { run } = await getMainModule();
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
await run();
|
await run();
|
||||||
|
|||||||
303
src/main.ts
303
src/main.ts
@@ -1,31 +1,18 @@
|
|||||||
import { semver } from "bun";
|
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import { existsSync, mkdtempSync, readFileSync } from "node:fs";
|
import * as tc from "@actions/tool-cache";
|
||||||
import os from "node:os";
|
import { load as loadYaml } from "js-yaml";
|
||||||
|
import * as semver from "semver";
|
||||||
|
import { execFile as execFileCallback } from "node:child_process";
|
||||||
|
import { existsSync, readFileSync } from "node:fs";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
|
import { promisify } from "node:util";
|
||||||
|
import { getGhcrImageRegistry, getImageRegistry, restoreDockerImageCache } from "./cache";
|
||||||
|
|
||||||
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 DEFAULT_VERSION = "latest";
|
const DEFAULT_VERSION = "latest";
|
||||||
const NPM_PACKAGE = "supabase";
|
const execFile = promisify(execFileCallback);
|
||||||
const NPM_EXECUTABLE_ENV = "SUPABASE_SETUP_CLI_NPM";
|
|
||||||
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;
|
|
||||||
version: string;
|
|
||||||
integrity?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type PackageMetadata = {
|
|
||||||
version?: unknown;
|
|
||||||
bin?: unknown;
|
|
||||||
scripts?: unknown;
|
|
||||||
"dist.integrity"?: unknown;
|
|
||||||
};
|
|
||||||
|
|
||||||
type BunLock = {
|
type BunLock = {
|
||||||
workspaces?: {
|
workspaces?: {
|
||||||
@@ -43,12 +30,6 @@ type PnpmDependency =
|
|||||||
version?: string;
|
version?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type PnpmPackage = {
|
|
||||||
resolution?: {
|
|
||||||
integrity?: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
type PnpmLock = {
|
type PnpmLock = {
|
||||||
importers?: {
|
importers?: {
|
||||||
".": {
|
".": {
|
||||||
@@ -56,16 +37,19 @@ type PnpmLock = {
|
|||||||
devDependencies?: Record<string, PnpmDependency>;
|
devDependencies?: Record<string, PnpmDependency>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
packages?: Record<string, PnpmPackage>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type PackageLock = {
|
type PackageLock = {
|
||||||
packages?: Record<string, { integrity?: string; version?: string }>;
|
packages?: Record<string, { version?: string }>;
|
||||||
dependencies?: Record<string, { integrity?: string; version?: string }>;
|
dependencies?: Record<string, { version?: string }>;
|
||||||
};
|
};
|
||||||
|
|
||||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
function getArchivePlatform(platform: NodeJS.Platform): string {
|
||||||
return typeof value === "object" && value !== null;
|
return platform === "win32" ? "windows" : platform;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getArchiveArch(arch: NodeJS.Architecture): string {
|
||||||
|
return arch === "x64" ? "amd64" : arch;
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractConcreteVersion(raw: string | undefined): string | null {
|
function extractConcreteVersion(raw: string | undefined): string | null {
|
||||||
@@ -73,41 +57,10 @@ function extractConcreteVersion(raw: string | undefined): string | null {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const match = raw.match(CONCRETE_VERSION_EXTRACT_PATTERN);
|
const match = raw.match(/\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?/);
|
||||||
return match?.[0] ?? null;
|
return match?.[0] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = normalizeSupportedVersion(version);
|
|
||||||
|
|
||||||
return {
|
|
||||||
spec: `${NPM_PACKAGE}@${normalizedVersion}`,
|
|
||||||
version: normalizedVersion,
|
|
||||||
integrity,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function readWorkspaceLockfile(workspaceRoot: string, filename: string): string | null {
|
function readWorkspaceLockfile(workspaceRoot: string, filename: string): string | null {
|
||||||
const filePath = path.join(workspaceRoot, filename);
|
const filePath = path.join(workspaceRoot, filename);
|
||||||
|
|
||||||
@@ -122,7 +75,7 @@ function readWorkspaceLockfile(workspaceRoot: string, filename: string): string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function detectResolutionFromBunLock(workspaceRoot: string): PackageResolution | null {
|
function detectVersionFromBunLock(workspaceRoot: string): string | null {
|
||||||
const text = readWorkspaceLockfile(workspaceRoot, "bun.lock");
|
const text = readWorkspaceLockfile(workspaceRoot, "bun.lock");
|
||||||
|
|
||||||
if (!text) {
|
if (!text) {
|
||||||
@@ -133,28 +86,24 @@ function detectResolutionFromBunLock(workspaceRoot: string): PackageResolution |
|
|||||||
const lockfile = JSON.parse(text.replace(/,\s*([}\]])/g, "$1")) as BunLock;
|
const lockfile = JSON.parse(text.replace(/,\s*([}\]])/g, "$1")) as BunLock;
|
||||||
const rootWorkspace = lockfile.workspaces?.[""];
|
const rootWorkspace = lockfile.workspaces?.[""];
|
||||||
const declaredVersion =
|
const declaredVersion =
|
||||||
rootWorkspace?.dependencies?.[NPM_PACKAGE] ?? rootWorkspace?.devDependencies?.[NPM_PACKAGE];
|
rootWorkspace?.dependencies?.supabase ?? rootWorkspace?.devDependencies?.supabase;
|
||||||
|
|
||||||
if (!declaredVersion) {
|
if (!declaredVersion) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const resolvedPackage = lockfile.packages?.[NPM_PACKAGE];
|
const resolvedPackage = lockfile.packages?.supabase;
|
||||||
if (Array.isArray(resolvedPackage) && typeof resolvedPackage[0] === "string") {
|
if (Array.isArray(resolvedPackage) && typeof resolvedPackage[0] === "string") {
|
||||||
const version = extractConcreteVersion(resolvedPackage[0]);
|
return extractConcreteVersion(resolvedPackage[0]);
|
||||||
const integrity = typeof resolvedPackage[3] === "string" ? resolvedPackage[3] : undefined;
|
|
||||||
|
|
||||||
return version ? toPackageResolution(version, integrity) : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const version = extractConcreteVersion(declaredVersion);
|
return extractConcreteVersion(declaredVersion);
|
||||||
return version ? toPackageResolution(version) : null;
|
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function detectResolutionFromPnpmLock(workspaceRoot: string): PackageResolution | null {
|
function detectVersionFromPnpmLock(workspaceRoot: string): string | null {
|
||||||
const text = readWorkspaceLockfile(workspaceRoot, "pnpm-lock.yaml");
|
const text = readWorkspaceLockfile(workspaceRoot, "pnpm-lock.yaml");
|
||||||
|
|
||||||
if (!text) {
|
if (!text) {
|
||||||
@@ -162,32 +111,22 @@ function detectResolutionFromPnpmLock(workspaceRoot: string): PackageResolution
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const lockfile = Bun.YAML.parse(text) as PnpmLock;
|
const lockfile = loadYaml(text) as PnpmLock;
|
||||||
const rootImporter = lockfile.importers?.["."];
|
const rootImporter = lockfile.importers?.["."];
|
||||||
const dependency =
|
const dependency =
|
||||||
rootImporter?.dependencies?.[NPM_PACKAGE] ?? rootImporter?.devDependencies?.[NPM_PACKAGE];
|
rootImporter?.dependencies?.supabase ?? rootImporter?.devDependencies?.supabase;
|
||||||
const version =
|
|
||||||
typeof dependency === "string"
|
|
||||||
? extractConcreteVersion(dependency)
|
|
||||||
: extractConcreteVersion(dependency?.version);
|
|
||||||
|
|
||||||
if (!version) {
|
if (typeof dependency === "string") {
|
||||||
return null;
|
return extractConcreteVersion(dependency);
|
||||||
}
|
}
|
||||||
|
|
||||||
const integrity = Object.entries(lockfile.packages ?? {}).find(
|
return extractConcreteVersion(dependency?.version);
|
||||||
([packageKey]) =>
|
|
||||||
packageKey === `${NPM_PACKAGE}@${version}` ||
|
|
||||||
packageKey.startsWith(`/${NPM_PACKAGE}@${version}`),
|
|
||||||
)?.[1].resolution?.integrity;
|
|
||||||
|
|
||||||
return toPackageResolution(version, integrity);
|
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function detectResolutionFromPackageLock(workspaceRoot: string): PackageResolution | null {
|
function detectVersionFromPackageLock(workspaceRoot: string): string | null {
|
||||||
const text = readWorkspaceLockfile(workspaceRoot, "package-lock.json");
|
const text = readWorkspaceLockfile(workspaceRoot, "package-lock.json");
|
||||||
|
|
||||||
if (!text) {
|
if (!text) {
|
||||||
@@ -196,171 +135,69 @@ function detectResolutionFromPackageLock(workspaceRoot: string): PackageResoluti
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const lockfile = JSON.parse(text) as PackageLock;
|
const lockfile = JSON.parse(text) as PackageLock;
|
||||||
const packageEntry = lockfile.packages?.[`node_modules/${NPM_PACKAGE}`];
|
|
||||||
const dependencyEntry = lockfile.dependencies?.[NPM_PACKAGE];
|
|
||||||
const version =
|
|
||||||
extractConcreteVersion(packageEntry?.version) ??
|
|
||||||
extractConcreteVersion(dependencyEntry?.version);
|
|
||||||
|
|
||||||
return version
|
return (
|
||||||
? toPackageResolution(version, packageEntry?.integrity ?? dependencyEntry?.integrity)
|
extractConcreteVersion(lockfile.packages?.["node_modules/supabase"]?.version) ??
|
||||||
: null;
|
extractConcreteVersion(lockfile.dependencies?.supabase?.version)
|
||||||
|
);
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resolvePackage(inputVersion: string): PackageResolution {
|
function resolveVersion(inputVersion: string): string {
|
||||||
const requestedVersion = inputVersion.trim();
|
const requestedVersion = inputVersion.trim();
|
||||||
|
|
||||||
if (requestedVersion) {
|
if (requestedVersion) {
|
||||||
return toPackageResolution(requestedVersion);
|
return requestedVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
const workspaceRoot = process.env.GITHUB_WORKSPACE?.trim();
|
const workspaceRoot = process.env.GITHUB_WORKSPACE?.trim();
|
||||||
|
|
||||||
if (!workspaceRoot) {
|
if (!workspaceRoot) {
|
||||||
return toPackageResolution(DEFAULT_VERSION);
|
return DEFAULT_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
detectResolutionFromBunLock(workspaceRoot) ??
|
detectVersionFromBunLock(workspaceRoot) ??
|
||||||
detectResolutionFromPnpmLock(workspaceRoot) ??
|
detectVersionFromPnpmLock(workspaceRoot) ??
|
||||||
detectResolutionFromPackageLock(workspaceRoot) ??
|
detectVersionFromPackageLock(workspaceRoot) ??
|
||||||
toPackageResolution(DEFAULT_VERSION)
|
DEFAULT_VERSION
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function verifyPackageIntegrity(resolution: PackageResolution, metadata: PackageMetadata): void {
|
export function getDownloadUrl(version: string): string {
|
||||||
if (!resolution.integrity) {
|
const platform = getArchivePlatform(process.platform);
|
||||||
return;
|
const arch = getArchiveArch(process.arch);
|
||||||
|
const filename = `supabase_${platform}_${arch}.tar.gz`;
|
||||||
|
|
||||||
|
if (version.toLowerCase() === "latest") {
|
||||||
|
return `https://github.com/supabase/cli/releases/latest/download/${filename}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const registryIntegrity = metadata["dist.integrity"];
|
if (semver.compare(version, REGISTRY_VERSION) === -1) {
|
||||||
if (registryIntegrity !== resolution.integrity) {
|
return `https://github.com/supabase/cli/releases/download/v${version}/supabase_${version}_${platform}_${arch}.tar.gz`;
|
||||||
throw new Error(`Lockfile integrity for ${resolution.spec} does not match the npm registry`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return `https://github.com/supabase/cli/releases/download/v${version}/${filename}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getPackageMetadata(resolution: PackageResolution): Promise<PackageMetadata> {
|
function getSupabaseExecutable(cliPath: string): string {
|
||||||
const output = await runNpm([
|
const names =
|
||||||
"view",
|
process.platform === "win32" ? ["supabase.exe", "supabase.cmd", "supabase"] : ["supabase"];
|
||||||
resolution.spec,
|
|
||||||
"version",
|
|
||||||
"bin",
|
|
||||||
"scripts",
|
|
||||||
"dist.integrity",
|
|
||||||
"--json",
|
|
||||||
]);
|
|
||||||
const metadata = JSON.parse(output) as unknown;
|
|
||||||
|
|
||||||
if (!isRecord(metadata)) {
|
for (const name of names) {
|
||||||
throw new Error(`Could not read npm metadata for ${resolution.spec}`);
|
const executable = path.join(cliPath, name);
|
||||||
}
|
if (existsSync(executable)) {
|
||||||
|
return executable;
|
||||||
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 {
|
|
||||||
return !(isRecord(metadata.scripts) && typeof metadata.scripts.postinstall === "string");
|
|
||||||
}
|
|
||||||
|
|
||||||
function createInstallRoot(): string {
|
|
||||||
const tempRoot = process.env.RUNNER_TEMP?.trim() || os.tmpdir();
|
|
||||||
return mkdtempSync(path.join(tempRoot, "setup-cli-"));
|
|
||||||
}
|
|
||||||
|
|
||||||
async function runNpm(args: string[]): Promise<string> {
|
|
||||||
const executable = process.env[NPM_EXECUTABLE_ENV]?.trim() || "npm";
|
|
||||||
const proc = Bun.spawn([executable, ...args], {
|
|
||||||
env: process.env,
|
|
||||||
stderr: "pipe",
|
|
||||||
stdout: "pipe",
|
|
||||||
});
|
|
||||||
const [stdout, stderr, exitCode] = await Promise.all([
|
|
||||||
new Response(proc.stdout).text(),
|
|
||||||
new Response(proc.stderr).text(),
|
|
||||||
proc.exited,
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (exitCode !== 0) {
|
|
||||||
throw new Error(stderr.trim() || `npm ${args.join(" ")} failed`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return stdout;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function installCli(resolution: PackageResolution): Promise<string> {
|
|
||||||
const metadata = await getPackageMetadata(resolution);
|
|
||||||
verifyPackageMetadata(resolution, metadata);
|
|
||||||
verifyPackageIntegrity(resolution, metadata);
|
|
||||||
|
|
||||||
const installRoot = createInstallRoot();
|
|
||||||
|
|
||||||
await runNpm([
|
|
||||||
"install",
|
|
||||||
"--prefix",
|
|
||||||
installRoot,
|
|
||||||
"--omit=dev",
|
|
||||||
"--include=optional",
|
|
||||||
"--no-audit",
|
|
||||||
"--no-fund",
|
|
||||||
"--no-package-lock",
|
|
||||||
`--ignore-scripts=${shouldIgnoreInstallScripts(metadata)}`,
|
|
||||||
resolution.spec,
|
|
||||||
]);
|
|
||||||
|
|
||||||
return path.join(installRoot, "node_modules", ".bin");
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCliExecutablePath(cliPath: string): string {
|
|
||||||
if (process.platform !== "win32") {
|
|
||||||
return path.join(cliPath, "supabase");
|
|
||||||
}
|
|
||||||
|
|
||||||
const cmdPath = path.join(cliPath, "supabase.cmd");
|
|
||||||
if (existsSync(cmdPath)) {
|
|
||||||
return cmdPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
const exePath = path.join(cliPath, "supabase.exe");
|
|
||||||
if (existsSync(exePath)) {
|
|
||||||
return exePath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return path.join(cliPath, "supabase");
|
return path.join(cliPath, "supabase");
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function determineInstalledVersion(cliPath: string): Promise<string> {
|
export async function determineInstalledVersion(cliPath: string): Promise<string> {
|
||||||
const executable = getCliExecutablePath(cliPath);
|
const { stdout } = await execFile(getSupabaseExecutable(cliPath), ["--version"]);
|
||||||
const proc = Bun.spawn([executable, "--version"], {
|
|
||||||
stderr: "pipe",
|
|
||||||
stdout: "pipe",
|
|
||||||
});
|
|
||||||
const [stdout, stderr, exitCode] = await Promise.all([
|
|
||||||
new Response(proc.stdout).text(),
|
|
||||||
new Response(proc.stderr).text(),
|
|
||||||
proc.exited,
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (exitCode !== 0) {
|
|
||||||
throw new Error(stderr.trim() || "Could not determine installed Supabase CLI version");
|
|
||||||
}
|
|
||||||
|
|
||||||
const version = stdout.trim();
|
const version = stdout.trim();
|
||||||
if (!version) {
|
if (!version) {
|
||||||
throw new Error("Could not determine installed Supabase CLI version");
|
throw new Error("Could not determine installed Supabase CLI version");
|
||||||
@@ -369,26 +206,20 @@ export async function determineInstalledVersion(cliPath: string): Promise<string
|
|||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldUseGhcrRegistry(requestedVersion: string, installedVersion: string): boolean {
|
|
||||||
if (requestedVersion.toLowerCase() === DEFAULT_VERSION) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const concreteVersion = extractConcreteVersion(installedVersion);
|
|
||||||
return concreteVersion !== null && semver.order(concreteVersion, REGISTRY_VERSION) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function run(): Promise<void> {
|
export async function run(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const resolution = resolvePackage(core.getInput("version"));
|
const version = resolveVersion(core.getInput("version"));
|
||||||
const cliPath = await installCli(resolution);
|
const tarball = await tc.downloadTool(getDownloadUrl(version));
|
||||||
|
const cliPath = await tc.extractTar(tarball);
|
||||||
const installedVersion = await determineInstalledVersion(cliPath);
|
const installedVersion = await determineInstalledVersion(cliPath);
|
||||||
core.setOutput("version", installedVersion);
|
core.setOutput("version", installedVersion);
|
||||||
core.addPath(cliPath);
|
core.addPath(cliPath);
|
||||||
|
|
||||||
if (shouldUseGhcrRegistry(resolution.version, installedVersion)) {
|
if (version.toLowerCase() === "latest" || semver.compare(version, REGISTRY_VERSION) >= 0) {
|
||||||
core.exportVariable(CLI_CONFIG_REGISTRY, "ghcr.io");
|
core.exportVariable(CLI_CONFIG_REGISTRY, getGhcrImageRegistry());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await restoreDockerImageCache(installedVersion, getImageRegistry());
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
core.setFailed(error instanceof Error ? error.message : String(error));
|
core.setFailed(error instanceof Error ? error.message : String(error));
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/post.ts
Normal file
17
src/post.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import * as core from "@actions/core";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
import { saveDockerImageCache } from "./cache";
|
||||||
|
|
||||||
|
export async function run(): Promise<void> {
|
||||||
|
try {
|
||||||
|
await saveDockerImageCache();
|
||||||
|
} catch (error) {
|
||||||
|
core.warning(
|
||||||
|
`Supabase Docker image cache post step failed: ${error instanceof Error ? error.message : String(error)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
||||||
|
await run();
|
||||||
|
}
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": "@tsconfig/bun/tsconfig.json",
|
"extends": "@tsconfig/bun/tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"types": ["bun", "node"]
|
||||||
|
},
|
||||||
"include": ["src"]
|
"include": ["src"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user