mirror of
https://github.com/supabase/setup-cli.git
synced 2026-06-28 09:57:03 +00:00
Compare commits
34 Commits
v1.7.1
...
feat/cachi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9da7121816 | ||
|
|
60819041ae | ||
|
|
c099ad8c4a | ||
|
|
afb0a590ff | ||
|
|
7fef86c665 | ||
|
|
337fb0dfcc | ||
|
|
33d1b579ff | ||
|
|
24d47d8ec3 | ||
|
|
2eca1b4d35 | ||
|
|
60645042c4 | ||
|
|
03559d0a6c | ||
|
|
ebf138c296 | ||
|
|
a9704fecfc | ||
|
|
e82fd0a973 | ||
|
|
169739ac91 | ||
|
|
832d9fbee4 | ||
|
|
c0041dbbe7 | ||
|
|
b3c3690a21 | ||
|
|
8d15f45354 | ||
|
|
5fe22a90da | ||
|
|
dbf012d182 | ||
|
|
8e888912ee | ||
|
|
e097e166e2 | ||
|
|
50efa8da6c | ||
|
|
18bccce61c | ||
|
|
792cd74615 | ||
|
|
940ab20eae | ||
|
|
378c226754 | ||
|
|
09c22066b0 | ||
|
|
b989d8a37c | ||
|
|
f168e5726b | ||
|
|
f350ac5cb5 | ||
|
|
763f7fff3f | ||
|
|
08dbecc658 |
1
.bun-version
Normal file
1
.bun-version
Normal file
@@ -0,0 +1 @@
|
|||||||
|
1.3.10
|
||||||
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -1,3 +0,0 @@
|
|||||||
* text=auto eol=lf
|
|
||||||
|
|
||||||
dist/** -diff linguist-generated=true
|
|
||||||
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -1 +1 @@
|
|||||||
* @supabase/dev-workflows
|
* @supabase/cli
|
||||||
|
|||||||
5
.github/codeql/codeql-config.yml
vendored
5
.github/codeql/codeql-config.yml
vendored
@@ -1,5 +0,0 @@
|
|||||||
name: JavaScript CodeQL Configuration
|
|
||||||
|
|
||||||
paths-ignore:
|
|
||||||
- node_modules
|
|
||||||
- dist
|
|
||||||
33
.github/dependabot.yml
vendored
33
.github/dependabot.yml
vendored
@@ -4,28 +4,33 @@ updates:
|
|||||||
directory: /
|
directory: /
|
||||||
schedule:
|
schedule:
|
||||||
interval: weekly
|
interval: weekly
|
||||||
|
day: tuesday
|
||||||
|
time: "09:00"
|
||||||
|
timezone: Europe/Paris
|
||||||
|
open-pull-requests-limit: 1
|
||||||
groups:
|
groups:
|
||||||
actions-minor:
|
actions-minor-patch:
|
||||||
|
patterns:
|
||||||
|
- "*"
|
||||||
update-types:
|
update-types:
|
||||||
- minor
|
- minor
|
||||||
- patch
|
- patch
|
||||||
|
|
||||||
- package-ecosystem: npm
|
- package-ecosystem: bun
|
||||||
directory: /
|
directory: /
|
||||||
schedule:
|
schedule:
|
||||||
interval: daily
|
interval: weekly
|
||||||
|
day: tuesday
|
||||||
|
time: "09:00"
|
||||||
|
timezone: Europe/Paris
|
||||||
|
open-pull-requests-limit: 1
|
||||||
|
cooldown:
|
||||||
|
semver-minor-days: 7
|
||||||
|
semver-patch-days: 2
|
||||||
groups:
|
groups:
|
||||||
npm-development:
|
bun-minor-patch:
|
||||||
dependency-type: development
|
patterns:
|
||||||
|
- "*"
|
||||||
update-types:
|
update-types:
|
||||||
- minor
|
- minor
|
||||||
- patch
|
- patch
|
||||||
npm-production:
|
|
||||||
dependency-type: production
|
|
||||||
update-types:
|
|
||||||
- patch
|
|
||||||
ignore:
|
|
||||||
# nodejs types is pinned to runtime version
|
|
||||||
- dependency-name: '@types/node'
|
|
||||||
update-types:
|
|
||||||
- version-update:semver-major
|
|
||||||
|
|||||||
68
.github/workflows/ci.yml
vendored
Normal file
68
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- synchronize
|
||||||
|
- reopened
|
||||||
|
- ready_for_review
|
||||||
|
- converted_to_draft
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
validate:
|
||||||
|
if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.draft }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 15
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
||||||
|
with:
|
||||||
|
bun-version-file: .bun-version
|
||||||
|
- run: bun install --frozen-lockfile
|
||||||
|
- run: bun run ci
|
||||||
|
|
||||||
|
test:
|
||||||
|
if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.draft }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
timeout-minutes: 20
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||||
|
version: [1.0.0, latest]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
- uses: ./
|
||||||
|
with:
|
||||||
|
version: ${{ matrix.version }}
|
||||||
|
- run: supabase -h
|
||||||
|
|
||||||
|
ci:
|
||||||
|
if: ${{ always() && github.event_name == 'pull_request' }}
|
||||||
|
name: CI
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [validate, test]
|
||||||
|
timeout-minutes: 5
|
||||||
|
steps:
|
||||||
|
- run: |
|
||||||
|
validate_result="${{ needs.validate.result }}"
|
||||||
|
test_result="${{ needs.test.result }}"
|
||||||
|
[[ "$validate_result" == "success" || "$validate_result" == "skipped" ]]
|
||||||
|
[[ "$test_result" == "success" || "$test_result" == "skipped" ]]
|
||||||
47
.github/workflows/codeql-analysis.yml
vendored
47
.github/workflows/codeql-analysis.yml
vendored
@@ -1,47 +0,0 @@
|
|||||||
name: CodeQL
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
schedule:
|
|
||||||
- cron: '31 7 * * 3'
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
checks: write
|
|
||||||
contents: read
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
analyze:
|
|
||||||
name: Analyze
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
language:
|
|
||||||
- typescript
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
id: checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
id: initialize
|
|
||||||
uses: github/codeql-action/init@v3
|
|
||||||
with:
|
|
||||||
config-file: .github/codeql/codeql-config.yml
|
|
||||||
languages: ${{ matrix.language }}
|
|
||||||
source-root: src
|
|
||||||
|
|
||||||
- name: Autobuild
|
|
||||||
id: autobuild
|
|
||||||
uses: github/codeql-action/autobuild@v3
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
id: analyze
|
|
||||||
uses: github/codeql-action/analyze@v3
|
|
||||||
34
.github/workflows/dependabot.yml
vendored
34
.github/workflows/dependabot.yml
vendored
@@ -3,6 +3,10 @@ name: Dependabot auto-merge
|
|||||||
|
|
||||||
on: pull_request
|
on: pull_request
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
contents: write
|
contents: write
|
||||||
@@ -10,29 +14,33 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
dependabot:
|
dependabot:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# Checking the actor will prevent your Action run failing on non-Dependabot
|
timeout-minutes: 10
|
||||||
# PRs but also ensures that it only does work for Dependabot PRs.
|
# Only act on PRs opened by Dependabot from branches in this repository.
|
||||||
if: ${{ github.actor == 'dependabot[bot]' }}
|
if: github.actor == 'dependabot[bot]' && github.repository == github.event.pull_request.head.repo.full_name
|
||||||
steps:
|
steps:
|
||||||
# This first step will fail if there's no metadata and so the approval
|
# Metadata drives the non-major gating used for approval and auto-merge.
|
||||||
# will not occur.
|
|
||||||
- id: meta
|
- id: meta
|
||||||
uses: dependabot/fetch-metadata@v2
|
uses: dependabot/fetch-metadata@ffa630c65fa7e0ecfa0625b5ceda64399aea1b36 # v3.0.0
|
||||||
with:
|
with:
|
||||||
github-token: '${{ secrets.GITHUB_TOKEN }}'
|
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
|
||||||
|
- name: Generate 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' }}
|
||||||
|
uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.APP_ID }}
|
||||||
|
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
# Here the PR gets approved.
|
|
||||||
- name: Approve a PR
|
- name: Approve a PR
|
||||||
if: ${{steps.meta.outputs.update-type != 'version-update:semver-major'}}
|
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' }}
|
||||||
run: gh pr review --approve "$PR_URL"
|
run: gh pr review --approve "$PR_URL"
|
||||||
env:
|
env:
|
||||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||||
|
|
||||||
# Finally, this sets the PR to allow auto-merging for patch and minor
|
|
||||||
# updates if all checks pass
|
|
||||||
- name: Enable auto-merge for Dependabot PRs
|
- name: Enable auto-merge for Dependabot PRs
|
||||||
if: ${{steps.meta.outputs.update-type != 'version-update:semver-major'}}
|
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' }}
|
||||||
run: gh pr merge --auto --squash "$PR_URL"
|
run: gh pr merge --auto --squash "$PR_URL"
|
||||||
env:
|
env:
|
||||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||||
|
|||||||
71
.github/workflows/e2e.yml
vendored
Normal file
71
.github/workflows/e2e.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
name: E2E
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- synchronize
|
||||||
|
- reopened
|
||||||
|
- ready_for_review
|
||||||
|
- converted_to_draft
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
tags:
|
||||||
|
- "v[0-9]+.[0-9]+.[0-9]+"
|
||||||
|
schedule:
|
||||||
|
# * is a special character in YAML so you have to quote this string
|
||||||
|
- cron: "30 1,9 * * *"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
e2e: # make sure the action works on a clean machine without building
|
||||||
|
if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.draft }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 45
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
version:
|
||||||
|
- 1.178.2
|
||||||
|
- 2.33.0
|
||||||
|
- latest
|
||||||
|
pg_major:
|
||||||
|
- 14
|
||||||
|
- 15
|
||||||
|
- 17
|
||||||
|
exclude:
|
||||||
|
- version: 1.178.2
|
||||||
|
pg_major: 17
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- uses: ./
|
||||||
|
with:
|
||||||
|
version: ${{ matrix.version }}
|
||||||
|
- run: supabase init
|
||||||
|
- run: |
|
||||||
|
sed -i -E "s|^(major_version) .*|\\1 = ${{ matrix.pg_major }}|" supabase/config.toml
|
||||||
|
- run: supabase start
|
||||||
|
|
||||||
|
e2e-check:
|
||||||
|
if: ${{ always() && github.event_name == 'pull_request' }}
|
||||||
|
name: E2E
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [e2e]
|
||||||
|
timeout-minutes: 5
|
||||||
|
steps:
|
||||||
|
- run: |
|
||||||
|
e2e_result="${{ needs.e2e.result }}"
|
||||||
|
[[ "$e2e_result" == "success" || "$e2e_result" == "skipped" ]]
|
||||||
125
.github/workflows/licensed.yml
vendored
125
.github/workflows/licensed.yml
vendored
@@ -9,61 +9,134 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
paths:
|
||||||
|
- .github/workflows/licensed.yml
|
||||||
|
- .licensed.yml
|
||||||
|
- .licenses/**
|
||||||
|
- bun.lock
|
||||||
|
- package.json
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
concurrency:
|
||||||
contents: write
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
licensed:
|
check-licenses:
|
||||||
name: Check Licenses
|
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||||
|
name: Licensed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 15
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: read
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- name: Detect license inputs
|
||||||
|
id: license-inputs
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
|
REPOSITORY: ${{ github.repository }}
|
||||||
|
run: |
|
||||||
|
if [[ "${{ github.event_name }}" != "pull_request" ]]; then
|
||||||
|
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
gh api "repos/${REPOSITORY}/pulls/${PR_NUMBER}/files" --paginate --jq '.[].filename' > changed-files.txt
|
||||||
|
if grep -Eq '^(\.github/workflows/licensed\.yml|\.licensed\.yml|\.licenses/.*|bun\.lock|package\.json)$' changed-files.txt; then
|
||||||
|
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "changed=false" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
id: checkout
|
id: checkout
|
||||||
uses: actions/checkout@v4
|
if: steps.license-inputs.outputs.changed == 'true'
|
||||||
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Bun
|
||||||
id: setup-node
|
id: setup-bun
|
||||||
uses: actions/setup-node@v4
|
if: steps.license-inputs.outputs.changed == 'true'
|
||||||
|
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
bun-version-file: .bun-version
|
||||||
cache: npm
|
|
||||||
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
id: npm-ci
|
id: bun-install
|
||||||
run: npm ci
|
if: steps.license-inputs.outputs.changed == 'true'
|
||||||
|
run: bun install --frozen-lockfile
|
||||||
|
|
||||||
- name: Setup Ruby
|
- name: Setup Ruby
|
||||||
id: setup-ruby
|
id: setup-ruby
|
||||||
uses: ruby/setup-ruby@v1
|
if: steps.license-inputs.outputs.changed == 'true'
|
||||||
|
uses: ruby/setup-ruby@e65c17d16e57e481586a6a5a0282698790062f92 # v1.300.0
|
||||||
with:
|
with:
|
||||||
ruby-version: ruby
|
ruby-version: ruby
|
||||||
|
|
||||||
- uses: licensee/setup-licensed@v1.3.2
|
- uses: licensee/setup-licensed@0d52e575b3258417672be0dff2f115d7db8771d8 # v1.3.2
|
||||||
|
if: steps.license-inputs.outputs.changed == 'true'
|
||||||
with:
|
with:
|
||||||
version: 4.x
|
version: 4.x
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
# If this is a workflow_dispatch event, update the cached licenses.
|
- name: Check Licenses
|
||||||
- if: ${{ github.event_name == 'workflow_dispatch' }}
|
id: check-licenses
|
||||||
name: Update Licenses
|
if: steps.license-inputs.outputs.changed == 'true'
|
||||||
|
run: licensed status
|
||||||
|
|
||||||
|
update-licenses:
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||||
|
name: Update Licenses
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 15
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
id: checkout
|
||||||
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
|
||||||
|
- name: Setup Bun
|
||||||
|
id: setup-bun
|
||||||
|
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
||||||
|
with:
|
||||||
|
bun-version-file: .bun-version
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
id: bun-install
|
||||||
|
run: bun install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Setup Ruby
|
||||||
|
id: setup-ruby
|
||||||
|
uses: ruby/setup-ruby@e65c17d16e57e481586a6a5a0282698790062f92 # v1.300.0
|
||||||
|
with:
|
||||||
|
ruby-version: ruby
|
||||||
|
|
||||||
|
- uses: licensee/setup-licensed@0d52e575b3258417672be0dff2f115d7db8771d8 # v1.3.2
|
||||||
|
with:
|
||||||
|
version: 4.x
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Update License Cache
|
||||||
id: update-licenses
|
id: update-licenses
|
||||||
run: licensed cache
|
run: licensed cache
|
||||||
|
|
||||||
# Then, commit the updated licenses to the repository.
|
- name: Format License Files
|
||||||
- if: ${{ github.event_name == 'workflow_dispatch' }}
|
id: format-licenses
|
||||||
name: Commit Licenses
|
run: bun x oxfmt --write .licensed.yml .licenses
|
||||||
|
|
||||||
|
- name: Commit Licenses
|
||||||
id: commit-licenses
|
id: commit-licenses
|
||||||
run: |
|
run: |
|
||||||
git config --local user.email "licensed-ci@users.noreply.github.com"
|
git config --local user.email "licensed-ci@users.noreply.github.com"
|
||||||
git config --local user.name "licensed-ci"
|
git config --local user.name "licensed-ci"
|
||||||
git add .
|
git add .licenses .licensed.yml
|
||||||
|
if git diff --cached --quiet; then
|
||||||
|
echo "No license cache changes to commit."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
git commit -m "Auto-update license files"
|
git commit -m "Auto-update license files"
|
||||||
git push
|
git push
|
||||||
|
|
||||||
# Last, check the status of the cached licenses.
|
|
||||||
- name: Check Licenses
|
|
||||||
id: check-licenses
|
|
||||||
run: licensed status
|
|
||||||
|
|||||||
56
.github/workflows/linter.yml
vendored
56
.github/workflows/linter.yml
vendored
@@ -1,56 +0,0 @@
|
|||||||
# This workflow will lint the entire codebase using the
|
|
||||||
# `super-linter/super-linter` action.
|
|
||||||
#
|
|
||||||
# For more information, see the super-linter repository:
|
|
||||||
# https://github.com/super-linter/super-linter
|
|
||||||
name: Lint Codebase
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: read
|
|
||||||
statuses: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lint:
|
|
||||||
name: Lint Codebase
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
id: checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
id: setup-node
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version-file: .node-version
|
|
||||||
cache: npm
|
|
||||||
|
|
||||||
- name: Install Dependencies
|
|
||||||
id: install
|
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Lint Codebase
|
|
||||||
id: super-linter
|
|
||||||
uses: super-linter/super-linter/slim@v8
|
|
||||||
env:
|
|
||||||
DEFAULT_BRANCH: main
|
|
||||||
FILTER_REGEX_EXCLUDE: dist/**/*
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
LINTER_RULES_PATH: ${{ github.workspace }}
|
|
||||||
VALIDATE_ALL_CODEBASE: true
|
|
||||||
VALIDATE_JAVASCRIPT_ES: false
|
|
||||||
VALIDATE_JAVASCRIPT_STANDARD: false
|
|
||||||
VALIDATE_JSCPD: false
|
|
||||||
VALIDATE_TYPESCRIPT_ES: false
|
|
||||||
VALIDATE_JSON: false
|
|
||||||
VALIDATE_TYPESCRIPT_STANDARD: false
|
|
||||||
45
.github/workflows/start.yml
vendored
45
.github/workflows/start.yml
vendored
@@ -1,45 +0,0 @@
|
|||||||
name: CLI Start
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
tags:
|
|
||||||
- 'v[0-9]+.[0-9]+.[0-9]+'
|
|
||||||
schedule:
|
|
||||||
# * is a special character in YAML so you have to quote this string
|
|
||||||
- cron: '30 1,9 * * *'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
e2e: # make sure the action works on a clean machine without building
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
version:
|
|
||||||
- 1.178.2
|
|
||||||
- 2.33.0
|
|
||||||
- latest
|
|
||||||
pg_major:
|
|
||||||
- 14
|
|
||||||
- 15
|
|
||||||
- 17
|
|
||||||
exclude:
|
|
||||||
- version: 1.178.2
|
|
||||||
pg_major: 17
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: ./
|
|
||||||
with:
|
|
||||||
version: ${{ matrix.version }}
|
|
||||||
- run: supabase init
|
|
||||||
- run:
|
|
||||||
sed -i -E "s|^(major_version) .*|\1 = ${{ matrix.pg_major }}|"
|
|
||||||
supabase/config.toml
|
|
||||||
- run: supabase start
|
|
||||||
68
.github/workflows/test.yml
vendored
68
.github/workflows/test.yml
vendored
@@ -1,68 +0,0 @@
|
|||||||
name: 'build-test'
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version-file: .node-version
|
|
||||||
cache: npm
|
|
||||||
- run: npm ci
|
|
||||||
- run: npm run all
|
|
||||||
|
|
||||||
- id: diff
|
|
||||||
run: |
|
|
||||||
if [ ! -d dist/ ]; then
|
|
||||||
echo "Expected dist/ directory does not exist. See status below:"
|
|
||||||
ls -la ./
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if [ "$(git diff --ignore-space-at-eol --text dist/ | wc -l)" -gt "0" ]; then
|
|
||||||
echo "Detected uncommitted changes after build. See status below:"
|
|
||||||
git diff --ignore-space-at-eol --text dist/
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Upload the mismatched version as a workflow artifact.
|
|
||||||
- if: ${{ failure() && steps.diff.outcome == 'failure' }}
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: dist
|
|
||||||
path: dist/
|
|
||||||
|
|
||||||
test:
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
|
||||||
version: [1.0.0, latest]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: ./
|
|
||||||
with:
|
|
||||||
version: ${{ matrix.version }}
|
|
||||||
- run: supabase -h
|
|
||||||
|
|
||||||
check:
|
|
||||||
if: ${{ always() && github.event.pull_request }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [test]
|
|
||||||
steps:
|
|
||||||
- run: |
|
|
||||||
result="${{ needs.test.result }}"
|
|
||||||
[[ $result == "success" || $result == "skipped" ]]
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,7 +1,6 @@
|
|||||||
# Dependency directory
|
# Dependency directory
|
||||||
node_modules
|
node_modules
|
||||||
|
bun.lockb
|
||||||
# Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
*.log
|
*.log
|
||||||
|
|||||||
@@ -13,6 +13,4 @@ allowed:
|
|||||||
- other
|
- other
|
||||||
|
|
||||||
ignored:
|
ignored:
|
||||||
npm:
|
npm: []
|
||||||
# Used by Rollup.js when building in GitHub Actions
|
|
||||||
- '@rollup/rollup-linux-x64-gnu'
|
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
---
|
---
|
||||||
name: "@actions/core"
|
name: "@actions/core"
|
||||||
version: 1.11.1
|
version: 3.0.0
|
||||||
type: npm
|
type: npm
|
||||||
summary: Actions core lib
|
summary: Actions core lib
|
||||||
homepage: https://github.com/actions/toolkit/tree/main/packages/core
|
homepage: https://github.com/actions/toolkit/tree/main/packages/core
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: LICENSE.md
|
- sources: LICENSE.md
|
||||||
text: |-
|
text: |-
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright 2019 GitHub
|
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:
|
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 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.
|
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: []
|
notices: []
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
---
|
---
|
||||||
name: "@actions/exec"
|
name: "@actions/exec"
|
||||||
version: 1.1.1
|
version: 3.0.0
|
||||||
type: npm
|
type: npm
|
||||||
summary: Actions exec lib
|
summary: Actions exec lib
|
||||||
homepage: https://github.com/actions/toolkit/tree/main/packages/exec
|
homepage: https://github.com/actions/toolkit/tree/main/packages/exec
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: LICENSE.md
|
- sources: LICENSE.md
|
||||||
text: |-
|
text: |-
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright 2019 GitHub
|
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:
|
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 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.
|
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: []
|
notices: []
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
---
|
---
|
||||||
name: "@actions/http-client"
|
name: "@actions/http-client"
|
||||||
version: 2.2.3
|
version: 4.0.0
|
||||||
type: npm
|
type: npm
|
||||||
summary: Actions Http Client
|
summary: Actions Http Client
|
||||||
homepage: https://github.com/actions/toolkit/tree/main/packages/http-client
|
homepage: https://github.com/actions/toolkit/tree/main/packages/http-client
|
||||||
license: other
|
license: other
|
||||||
licenses:
|
licenses:
|
||||||
- sources: LICENSE
|
- sources: LICENSE
|
||||||
text: |
|
text: |
|
||||||
Actions Http Client for Node.js
|
Actions Http Client for Node.js
|
||||||
|
|
||||||
Copyright (c) GitHub, Inc.
|
Copyright (c) GitHub, Inc.
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
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,
|
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,
|
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,
|
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:
|
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 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
|
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
|
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,
|
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
|
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.
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
notices: []
|
notices: []
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
---
|
---
|
||||||
name: "@actions/io"
|
name: "@actions/io"
|
||||||
version: 1.1.3
|
version: 3.0.2
|
||||||
type: npm
|
type: npm
|
||||||
summary: Actions io lib
|
summary: Actions io lib
|
||||||
homepage: https://github.com/actions/toolkit/tree/main/packages/io
|
homepage: https://github.com/actions/toolkit/tree/main/packages/io
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: LICENSE.md
|
- sources: LICENSE.md
|
||||||
text: |-
|
text: |-
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright 2019 GitHub
|
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:
|
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 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.
|
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: []
|
notices: []
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
---
|
---
|
||||||
name: "@actions/tool-cache"
|
name: "@actions/tool-cache"
|
||||||
version: 2.0.2
|
version: 4.0.0
|
||||||
type: npm
|
type: npm
|
||||||
summary: Actions tool-cache lib
|
summary: Actions tool-cache lib
|
||||||
homepage: https://github.com/actions/toolkit/tree/main/packages/tool-cache
|
homepage: https://github.com/actions/toolkit/tree/main/packages/tool-cache
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: LICENSE.md
|
- sources: LICENSE.md
|
||||||
text: |-
|
text: |-
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright 2019 GitHub
|
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:
|
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 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.
|
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: []
|
notices: []
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
---
|
|
||||||
name: "@fastify/busboy"
|
|
||||||
version: 2.1.1
|
|
||||||
type: npm
|
|
||||||
summary: A streaming parser for HTML form data for node.js
|
|
||||||
homepage:
|
|
||||||
license: mit
|
|
||||||
licenses:
|
|
||||||
- sources: LICENSE
|
|
||||||
text: |-
|
|
||||||
Copyright Brian White. All rights reserved.
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to
|
|
||||||
deal in the Software without restriction, including without limitation the
|
|
||||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
IN THE SOFTWARE.
|
|
||||||
notices: []
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
---
|
|
||||||
name: semver
|
|
||||||
version: 6.3.1
|
|
||||||
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: []
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
---
|
|
||||||
name: semver
|
|
||||||
version: 7.7.2
|
|
||||||
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: []
|
|
||||||
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: []
|
||||||
@@ -6,30 +6,30 @@ summary: Node HTTP/HTTPS Agents for tunneling proxies
|
|||||||
homepage: https://github.com/koichik/node-tunnel/
|
homepage: https://github.com/koichik/node-tunnel/
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: LICENSE
|
- sources: LICENSE
|
||||||
text: |
|
text: |
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2012 Koichi Kobayashi
|
Copyright (c) 2012 Koichi Kobayashi
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
The above copyright notice and this permission notice shall be included in
|
||||||
all copies or substantial portions of the Software.
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
- sources: README.md
|
- sources: README.md
|
||||||
text: Licensed under the [MIT](https://github.com/koichik/node-tunnel/blob/master/LICENSE)
|
text: Licensed under the [MIT](https://github.com/koichik/node-tunnel/blob/master/LICENSE)
|
||||||
license.
|
license.
|
||||||
notices: []
|
notices: []
|
||||||
|
|||||||
@@ -1,34 +1,34 @@
|
|||||||
---
|
---
|
||||||
name: undici
|
name: undici
|
||||||
version: 5.29.0
|
version: 6.24.1
|
||||||
type: npm
|
type: npm
|
||||||
summary: An HTTP/1.1 client, written from scratch for Node.js
|
summary: An HTTP/1.1 client, written from scratch for Node.js
|
||||||
homepage: https://undici.nodejs.org
|
homepage: https://undici.nodejs.org
|
||||||
license: mit
|
license: mit
|
||||||
licenses:
|
licenses:
|
||||||
- sources: LICENSE
|
- sources: LICENSE
|
||||||
text: |
|
text: |
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) Matteo Collina and Undici contributors
|
Copyright (c) Matteo Collina and Undici contributors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
- sources: README.md
|
- sources: README.md
|
||||||
text: MIT
|
text: MIT
|
||||||
notices: []
|
notices: []
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
# See: https://github.com/DavidAnson/markdownlint
|
|
||||||
|
|
||||||
# Unordered list style
|
|
||||||
MD004:
|
|
||||||
style: dash
|
|
||||||
|
|
||||||
# Disable line length for tables
|
|
||||||
MD013:
|
|
||||||
tables: false
|
|
||||||
|
|
||||||
# Ordered list item prefix
|
|
||||||
MD029:
|
|
||||||
style: one
|
|
||||||
|
|
||||||
# Spaces after list markers
|
|
||||||
MD030:
|
|
||||||
ul_single: 1
|
|
||||||
ol_single: 1
|
|
||||||
ul_multi: 1
|
|
||||||
ol_multi: 1
|
|
||||||
|
|
||||||
# Code block style
|
|
||||||
MD046:
|
|
||||||
style: fenced
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
20.19.4
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
.DS_Store
|
|
||||||
.licenses/
|
|
||||||
dist/
|
|
||||||
node_modules/
|
|
||||||
coverage/
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# See: https://prettier.io/docs/en/configuration
|
|
||||||
|
|
||||||
printWidth: 80
|
|
||||||
tabWidth: 2
|
|
||||||
useTabs: false
|
|
||||||
semi: false
|
|
||||||
singleQuote: true
|
|
||||||
quoteProps: as-needed
|
|
||||||
jsxSingleQuote: false
|
|
||||||
trailingComma: none
|
|
||||||
bracketSpacing: true
|
|
||||||
bracketSameLine: true
|
|
||||||
arrowParens: always
|
|
||||||
proseWrap: always
|
|
||||||
htmlWhitespaceSensitivity: css
|
|
||||||
endOfLine: lf
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
# See: https://yamllint.readthedocs.io/en/stable/
|
|
||||||
|
|
||||||
rules:
|
|
||||||
document-end: disable
|
|
||||||
document-start:
|
|
||||||
level: warning
|
|
||||||
present: false
|
|
||||||
line-length:
|
|
||||||
level: warning
|
|
||||||
max: 80
|
|
||||||
allow-non-breakable-words: true
|
|
||||||
allow-non-breakable-inline-mappings: true
|
|
||||||
ignore:
|
|
||||||
- .licenses/
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
* @sweatybridge
|
|
||||||
160
README.md
160
README.md
@@ -1,13 +1,12 @@
|
|||||||
# :gear: Supabase CLI Action
|
# :gear: Supabase CLI Action
|
||||||
|
|
||||||
[](https://github.com/supabase/setup-cli/actions/workflows/start.yml)
|
[](https://github.com/supabase/setup-cli/actions/workflows/ci.yml)
|
||||||
[](https://github.com/supabase/setup-cli/actions/workflows/linter.yml)
|
[](https://github.com/supabase/setup-cli/actions/workflows/e2e.yml)
|
||||||
[](https://github.com/supabase/setup-cli/actions/workflows/codeql-analysis.yml)
|
[](https://github.com/supabase/setup-cli/actions/workflows/codeql-analysis.yml)
|
||||||
[](https://github.com/supabase/setup-cli/actions/workflows/test.yml)
|
|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
This action sets up the Supabase CLI,
|
This composite action sets up the Supabase CLI,
|
||||||
[`supabase`](https://github.com/supabase/cli), on GitHub's hosted Actions
|
[`supabase`](https://github.com/supabase/cli), on GitHub's hosted Actions
|
||||||
runners. Other CI runners like
|
runners. Other CI runners like
|
||||||
[Bitbucket](https://bitbucket.org/supabase-cli/setup-cli/src/master/bitbucket-pipelines.yml)
|
[Bitbucket](https://bitbucket.org/supabase-cli/setup-cli/src/master/bitbucket-pipelines.yml)
|
||||||
@@ -25,23 +24,43 @@ Setup the `supabase` CLI:
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
steps:
|
steps:
|
||||||
- uses: supabase/setup-cli@v1
|
- uses: supabase/setup-cli@v2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If `version` is omitted, the action checks the repository root for `bun.lock`,
|
||||||
|
`pnpm-lock.yaml`, or `package-lock.json` and uses the declared `supabase`
|
||||||
|
version. If no supported lockfile is present, it falls back to `latest`.
|
||||||
|
|
||||||
A specific version of the `supabase` CLI can be installed:
|
A specific version of the `supabase` CLI can be installed:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
steps:
|
steps:
|
||||||
- uses: supabase/setup-cli@v1
|
- uses: supabase/setup-cli@v2
|
||||||
with:
|
with:
|
||||||
version: 2.20.3
|
version: 2.84.2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Cache Docker images used by `supabase start` across workflow runs:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
- uses: supabase/setup-cli@v2
|
||||||
|
with:
|
||||||
|
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@v1
|
- uses: supabase/setup-cli@v2
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
- run: supabase init
|
- run: supabase init
|
||||||
@@ -53,11 +72,20 @@ on Windows and macOS runners.
|
|||||||
|
|
||||||
## Inputs
|
## Inputs
|
||||||
|
|
||||||
The actions supports the following inputs:
|
The action supports the following inputs:
|
||||||
|
|
||||||
| Name | Type | Description | Default | Required |
|
| Name | Type | Description | Default | Required |
|
||||||
| --------- | ------ | ---------------------------------- | -------- | -------- |
|
| ----------- | ------- | ------------------------------------------------------ | --------------------------------- | -------- |
|
||||||
| `version` | String | Supabase CLI version (or `latest`) | `2.20.3` | 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
|
||||||
|
|
||||||
@@ -65,7 +93,7 @@ Check generated TypeScript types are up-to-date with Postgres schema:
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
steps:
|
steps:
|
||||||
- uses: supabase/setup-cli@v1
|
- 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
|
||||||
@@ -87,59 +115,86 @@ env:
|
|||||||
# Retrieve <project-id> from dashboard url: https://app.supabase.com/project/<project-id>
|
# Retrieve <project-id> from dashboard url: https://app.supabase.com/project/<project-id>
|
||||||
PROJECT_ID: <project-id>
|
PROJECT_ID: <project-id>
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: supabase/setup-cli@v1
|
- 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
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Export local Supabase env vars for app tests:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
steps:
|
||||||
|
- uses: supabase/setup-cli@v2
|
||||||
|
with:
|
||||||
|
cache: true
|
||||||
|
- run: supabase init
|
||||||
|
- run: supabase start
|
||||||
|
- name: Export local Supabase env vars
|
||||||
|
run: |
|
||||||
|
# Customize the variable names as needed for your app.
|
||||||
|
supabase status -o env \
|
||||||
|
--override-name api.url=SUPABASE_URL \
|
||||||
|
--override-name auth.service_role_key=SUPABASE_SERVICE_ROLE_KEY \
|
||||||
|
>> .env.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
|
||||||
need to perform some initial setup steps before you can develop your action.
|
need to perform a few setup steps before you can work on the action.
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
>
|
>
|
||||||
> You'll need to have a reasonably modern version of
|
> You'll need a recent version of [Bun](https://bun.sh) for local development.
|
||||||
> [Node.js](https://nodejs.org) handy (20.x or later should work!). If you are
|
> This repository includes a `.bun-version` file for tools that can auto-switch
|
||||||
> using a version manager like [`nodenv`](https://github.com/nodenv/nodenv) or
|
> Bun versions.
|
||||||
> [`fnm`](https://github.com/Schniz/fnm), this template has a `.node-version`
|
|
||||||
> file at the root of the repository that can be used to automatically switch to
|
|
||||||
> the correct version when you `cd` into the repository. Additionally, this
|
|
||||||
> `.node-version` file is used by GitHub Actions in any `actions/setup-node`
|
|
||||||
> actions.
|
|
||||||
|
|
||||||
1. :hammer_and_wrench: Install the dependencies
|
1. :hammer_and_wrench: Install the dependencies
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm ci
|
bun install
|
||||||
```
|
|
||||||
|
|
||||||
1. :building_construction: Package the TypeScript for distribution
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run bundle
|
|
||||||
```
|
```
|
||||||
|
|
||||||
1. :white_check_mark: Run the tests
|
1. :white_check_mark: Run the tests
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ npm test
|
bun test
|
||||||
|
|
||||||
PASS ./index.test.js
|
|
||||||
✓ gets download url to binary (3 ms)
|
|
||||||
✓ runs main action (891 ms)
|
|
||||||
|
|
||||||
...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Publish to a distribution branch
|
1. :package: Build the bundled action entrypoints
|
||||||
|
|
||||||
Actions are run from this GitHub repository so we will checkin the packed `dist`
|
```bash
|
||||||
folder.
|
bun run build
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :mag: Run the full local CI suite
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun run ci
|
||||||
|
```
|
||||||
|
|
||||||
|
## Publish
|
||||||
|
|
||||||
1. Create a new GitHub release
|
1. Create a new GitHub release
|
||||||
2. Rebase `v1` branch on `main`
|
2. Rebase `v2` branch on `main`
|
||||||
|
|
||||||
Your action is now published! :rocket:
|
Your action is now published! :rocket:
|
||||||
|
|
||||||
@@ -148,14 +203,17 @@ See the
|
|||||||
|
|
||||||
## Validate
|
## Validate
|
||||||
|
|
||||||
You can now validate the action by referencing `./` in a workflow in your
|
Validate changes by exercising the action from a workflow in this repository
|
||||||
repository (see [test.yml](.github/workflows/test.yml))
|
(see [ci.yml](.github/workflows/ci.yml) and [e2e.yml](.github/workflows/e2e.yml)).
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
uses: ./
|
steps:
|
||||||
with:
|
- uses: ./
|
||||||
version: latest
|
with:
|
||||||
|
version: latest
|
||||||
```
|
```
|
||||||
|
|
||||||
See the [actions tab](https://github.com/supabase/setup-cli/actions) for runs of
|
The CI workflow provides fast smoke coverage across GitHub-hosted runners, and
|
||||||
this action! :rocket:
|
the E2E workflow verifies `supabase init` and `supabase start` against supported
|
||||||
|
Postgres versions. See the [actions tab](https://github.com/supabase/setup-cli/actions)
|
||||||
|
for recent runs.
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
import { getDownloadUrl } from '../src/utils'
|
|
||||||
import { CLI_CONFIG_REGISTRY } from '../src/main'
|
|
||||||
import * as os from 'os'
|
|
||||||
import * as process from 'process'
|
|
||||||
import * as cp from 'child_process'
|
|
||||||
import * as path from 'path'
|
|
||||||
import * as fs from 'fs'
|
|
||||||
import * as yaml from 'js-yaml'
|
|
||||||
import * as url from 'url'
|
|
||||||
import { expect, test } from '@jest/globals'
|
|
||||||
|
|
||||||
test('gets download url to binary', async () => {
|
|
||||||
const url = await getDownloadUrl('1.28.0')
|
|
||||||
expect(
|
|
||||||
url.startsWith(
|
|
||||||
'https://github.com/supabase/cli/releases/download/v1.28.0/supabase_'
|
|
||||||
)
|
|
||||||
).toBeTruthy()
|
|
||||||
expect(url.endsWith('.tar.gz')).toBeTruthy()
|
|
||||||
expect(url).not.toContain('_1.28.0_')
|
|
||||||
})
|
|
||||||
|
|
||||||
test('gets legacy download url to binary', async () => {
|
|
||||||
const url = await getDownloadUrl('0.1.0')
|
|
||||||
expect(
|
|
||||||
url.startsWith(
|
|
||||||
`https://github.com/supabase/cli/releases/download/v0.1.0/supabase_0.1.0_`
|
|
||||||
)
|
|
||||||
).toBeTruthy()
|
|
||||||
expect(url.endsWith('.tar.gz')).toBeTruthy()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('gets download url to latest version', async () => {
|
|
||||||
const url = await getDownloadUrl('latest')
|
|
||||||
expect(url).toMatch(
|
|
||||||
'https://github.com/supabase/cli/releases/latest/download/'
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
// shows how the runner will run a javascript action with env / stdout protocol
|
|
||||||
test('runs main action', () => {
|
|
||||||
const { env, execPath } = process
|
|
||||||
const repo = path.dirname(path.dirname(url.fileURLToPath(import.meta.url)))
|
|
||||||
const config = path.join(repo, 'action.yml')
|
|
||||||
const action = yaml.load(fs.readFileSync(config, 'utf8')) as {
|
|
||||||
inputs: { version: { default: string } }
|
|
||||||
}
|
|
||||||
const ip = path.join(repo, 'dist', 'index.js')
|
|
||||||
const stdout = cp
|
|
||||||
.execFileSync(execPath, [ip], {
|
|
||||||
env: {
|
|
||||||
...env,
|
|
||||||
RUNNER_TEMP: os.tmpdir(),
|
|
||||||
INPUT_VERSION: action.inputs.version.default
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.toString()
|
|
||||||
expect
|
|
||||||
.stringContaining(`::set-env name=${CLI_CONFIG_REGISTRY}::`)
|
|
||||||
.asymmetricMatch(stdout)
|
|
||||||
})
|
|
||||||
18
action.yml
18
action.yml
@@ -3,12 +3,22 @@ description: Setup Supabase CLI, supabase, on GitHub Actions runners
|
|||||||
author: Supabase
|
author: Supabase
|
||||||
inputs:
|
inputs:
|
||||||
version:
|
version:
|
||||||
description: Version of Supabase CLI to install
|
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
|
||||||
default: 2.20.3
|
|
||||||
outputs:
|
outputs:
|
||||||
version:
|
version:
|
||||||
description: Version of installed Supabase CLI
|
description: Version of installed Supabase CLI
|
||||||
|
cache-hit:
|
||||||
|
description: Whether an exact Supabase Docker image cache was restored.
|
||||||
runs:
|
runs:
|
||||||
using: node20
|
using: node24
|
||||||
main: dist/index.js
|
main: dist/main.js
|
||||||
|
post: dist/post.js
|
||||||
|
post-if: success()
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="116" height="20" role="img" aria-label="Coverage: 51.42%"><title>Coverage: 51.42%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="116" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="53" height="20" fill="#e05d44"/><rect width="116" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Coverage</text><text x="325" y="140" transform="scale(.1)" fill="#fff" textLength="530">Coverage</text><text aria-hidden="true" x="885" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">51.42%</text><text x="885" y="140" transform="scale(.1)" fill="#fff" textLength="430">51.42%</text></g></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB |
244
bun.lock
Normal file
244
bun.lock
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
{
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"configVersion": 1,
|
||||||
|
"workspaces": {
|
||||||
|
"": {
|
||||||
|
"name": "setup-cli",
|
||||||
|
"dependencies": {
|
||||||
|
"@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": {
|
||||||
|
"@tsconfig/bun": "^1.0.10",
|
||||||
|
"@types/bun": "^1.3.11",
|
||||||
|
"@types/js-yaml": "^4.0.9",
|
||||||
|
"@types/node": "^24",
|
||||||
|
"@types/semver": "^7.7.1",
|
||||||
|
"@typescript/native-preview": "^7.0.0-dev.20260409.1",
|
||||||
|
"oxfmt": "^0.44.0",
|
||||||
|
"oxlint": "^1.59.0",
|
||||||
|
"oxlint-tsgolint": "^0.20.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"@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/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/io": ["@actions/io@3.0.2", "", {}, "sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw=="],
|
||||||
|
|
||||||
|
"@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=="],
|
||||||
|
|
||||||
|
"@azure/abort-controller": ["@azure/abort-controller@2.1.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA=="],
|
||||||
|
|
||||||
|
"@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=="],
|
||||||
|
|
||||||
|
"@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=="],
|
||||||
|
|
||||||
|
"@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=="],
|
||||||
|
|
||||||
|
"@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=="],
|
||||||
|
|
||||||
|
"@azure/core-paging": ["@azure/core-paging@1.6.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA=="],
|
||||||
|
|
||||||
|
"@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=="],
|
||||||
|
|
||||||
|
"@azure/core-tracing": ["@azure/core-tracing@1.3.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ=="],
|
||||||
|
|
||||||
|
"@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=="],
|
||||||
|
|
||||||
|
"@azure/core-xml": ["@azure/core-xml@1.5.1", "", { "dependencies": { "fast-xml-parser": "^5.5.9", "tslib": "^2.8.1" } }, "sha512-xcNRHqCoSp4AunOALEae6A8f3qATb83gSrm31Iqb01OzblvC3/W/bfXozcq78EzIdzZzuH1bZ2NvRR0TdX709w=="],
|
||||||
|
|
||||||
|
"@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=="],
|
||||||
|
|
||||||
|
"@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=="],
|
||||||
|
|
||||||
|
"@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-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.44.0", "", { "os": "android", "cpu": "arm" }, "sha512-5UvghMd9SA/yvKTWCAxMAPXS1d2i054UeOf4iFjZjfayTwCINcC3oaSXjtbZfCaEpxgJod7XiOjTtby5yEv/BQ=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.44.0", "", { "os": "android", "cpu": "arm64" }, "sha512-IVudM1BWfvrYO++Khtzr8q9n5Rxu7msUvoFMqzGJVdX7HfUXUDHwaH2zHZNB58svx2J56pmCUzophyaPFkcG/A=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.44.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-eWCLAIKAHfx88EqEP1Ga2yz7qVcqDU5lemn4xck+07bH182hDdprOHjbogyk0In1Djys3T0/pO2JepFnRJ41Mg=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.44.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-eHTBznHLM49++dwz07MblQ2cOXyIgeedmE3Wgy4ptUESj38/qYZyRi1MPwC9olQJWssMeY6WI3UZ7YmU5ggvyQ=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.44.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jLMmbj0u0Ft43QpkUVr/0v1ZfQCGWAvU+WznEHcN3wZC/q6ox7XeSJtk9P36CCpiDSUf3sGnzbIuG1KdEMEDJQ=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.44.0", "", { "os": "linux", "cpu": "arm" }, "sha512-n+A/u/ByK1qV8FVGOwyaSpw5NPNl0qlZfgTBqHeGIqr8Qzq1tyWZ4lAaxPoe5mZqE3w88vn3+jZtMxriHPE7tg=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/binding-linux-arm-musleabihf@0.44.0", "", { "os": "linux", "cpu": "arm" }, "sha512-5eax+FkxyCqAi3Rw0mrZFr7+KTt/XweFsbALR+B5ljWBLBl8nHe4ADrUnb1gLEfQCJLl+Ca5FIVD4xEt95AwIw=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.44.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-58l8JaHxSGOmOMOG2CIrNsnkRJAj0YcHQCmvNACniOa/vd1iRHhlPajczegzS5jwMENlqgreyiTR9iNlke8qCw=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.44.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-AlObQIXyVRZ96LbtVljtFq0JqH5B92NU+BQeDFrXWBUWlCKAM0wF5GLfIhCLT5kQ3Sl+U0YjRJ7Alqj5hGQaCg=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.44.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-YcFE8/q/BbrCiIiM5piwbkA6GwJc5QqhMQp2yDrqQ2fuVkZ7CInb1aIijZ/k8EXc72qXMSwKpVlBv1w/MsGO/A=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.44.0", "", { "os": "linux", "cpu": "none" }, "sha512-eOdzs6RqkRzuqNHUX5C8ISN5xfGh4xDww8OEd9YAmc3OWN8oAe5bmlIqQ+rrHLpv58/0BuU48bxkhnIGjA/ATQ=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.44.0", "", { "os": "linux", "cpu": "none" }, "sha512-YBgNTxntD/QvlFUfgvh8bEdwOhXiquX8gaofZJAwYa/Xp1S1DQrFVZEeck7GFktr24DztsSp8N8WtWCBwxs0Hw=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.44.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-GLIh1R6WHWshl/i4QQDNgj0WtT25aRO4HNUWEoitxiywyRdhTFmFEYT2rXlcl9U6/26vhmOqG5cRlMLG3ocaIA=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.44.0", "", { "os": "linux", "cpu": "x64" }, "sha512-gZOpgTlOsLcLfAF9qgpTr7FIIFSKnQN3hDf/0JvQ4CIwMY7h+eilNjxq/CorqvYcEOu+LRt1W4ZS7KccEHLOdA=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.44.0", "", { "os": "linux", "cpu": "x64" }, "sha512-1CyS9JTB+pCUFYFI6pkQGGZaT/AY5gnhHVrQQLhFba6idP9AzVYm1xbdWfywoldTYvjxQJV6x4SuduCIfP3W+A=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.44.0", "", { "os": "none", "cpu": "arm64" }, "sha512-bmEv70Ak6jLr1xotCbF5TxIKjsmQaiX+jFRtnGtfA03tJPf6VG3cKh96S21boAt3JZc+Vjx8PYcDuLj39vM2Pw=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.44.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-yWzB+oCpSnP/dmw85eFLAT5o35Ve5pkGS2uF/UCISpIwDqf1xa7OpmtomiqY/Vzg8VyvMbuf6vroF2khF/+1Vg=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.44.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-TcWpo18xEIE3AmIG2kpr3kz5IEhQgnx0lazl2+8L+3eTopOAUevQcmlr4nhguImNWz0OMeOZrYZOhJNCf16nlQ=="],
|
||||||
|
|
||||||
|
"@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.44.0", "", { "os": "win32", "cpu": "x64" }, "sha512-oj8aLkPJZppIM4CMQNsyir9ybM1Xw/CfGPTSsTnzpVGyljgfbdP0EVUlURiGM0BDrmw5psQ6ArmGCcUY/yABaQ=="],
|
||||||
|
|
||||||
|
"@oxlint-tsgolint/darwin-arm64": ["@oxlint-tsgolint/darwin-arm64@0.20.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-KKQcIHZHMxqpHUA1VXIbOG6chNCFkUWbQy6M+AFVtPKkA/3xAeJkJ3njoV66bfzwPHRcWQO+kcj5XqtbkjakoA=="],
|
||||||
|
|
||||||
|
"@oxlint-tsgolint/darwin-x64": ["@oxlint-tsgolint/darwin-x64@0.20.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-7HeVMuclGfG+NLZi2ybY0T4fMI7/XxO/208rJk+zEIloKkVnlh11Wd241JMGwgNFXn+MLJbOqOfojDb2Dt4L1g=="],
|
||||||
|
|
||||||
|
"@oxlint-tsgolint/linux-arm64": ["@oxlint-tsgolint/linux-arm64@0.20.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-zxhUwz+WSxE6oWlZLK2z2ps9yC6ebmgoYmjAl0Oa48+GqkZ56NVgo+wb8DURNv6xrggzHStQxqQxe3mK51HZag=="],
|
||||||
|
|
||||||
|
"@oxlint-tsgolint/linux-x64": ["@oxlint-tsgolint/linux-x64@0.20.0", "", { "os": "linux", "cpu": "x64" }, "sha512-/1l6FnahC9im8PK+Ekkx/V3yetO/PzZnJegE2FXcv/iXEhbeVxP/ouiTYcUQu9shT1FWJCSNti1VJHH+21Y1dg=="],
|
||||||
|
|
||||||
|
"@oxlint-tsgolint/win32-arm64": ["@oxlint-tsgolint/win32-arm64@0.20.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-oPZ5Yz8sVdo7P/5q+i3IKeix31eFZ55JAPa1+RGPoe9PoaYVsdMvR6Jvib6YtrqoJnFPlg3fjEjlEPL8VBKYJA=="],
|
||||||
|
|
||||||
|
"@oxlint-tsgolint/win32-x64": ["@oxlint-tsgolint/win32-x64@0.20.0", "", { "os": "win32", "cpu": "x64" }, "sha512-4stx8RHj3SP9vQyRF/yZbz5igtPvYMEUR8CUoha4BVNZihi39DpCR8qkU7lpjB5Ga1DRMo2pHaA4bdTOMaY4mw=="],
|
||||||
|
|
||||||
|
"@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-android-arm64": ["@oxlint/binding-android-arm64@1.59.0", "", { "os": "android", "cpu": "arm64" }, "sha512-TgLc7XVLKH2a4h8j3vn1MDjfK33i9MY60f/bKhRGWyVzbk5LCZ4X01VZG7iHrMmi5vYbAp8//Ponigx03CLsdw=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.59.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DXyFPf5ZKldMLloRHx/B9fsxsiTQomaw7cmEW3YIJko2HgCh+GUhp9gGYwHrqlLJPsEe3dYj9JebjX92D3j3AA=="],
|
||||||
|
|
||||||
|
"@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-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=="],
|
||||||
|
|
||||||
|
"@types/bun": ["@types/bun@1.3.11", "", { "dependencies": { "bun-types": "1.3.11" } }, "sha512-5vPne5QvtpjGpsGYXiFyycfpDF2ECyPcTSsFBMa0fraoxiQyMJ3SmuQIGhzPg2WJuWxVBoxWJ2kClYTcw/4fAg=="],
|
||||||
|
|
||||||
|
"@types/js-yaml": ["@types/js-yaml@4.0.9", "", {}, "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg=="],
|
||||||
|
|
||||||
|
"@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="],
|
||||||
|
|
||||||
|
"@types/semver": ["@types/semver@7.7.1", "", {}, "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA=="],
|
||||||
|
|
||||||
|
"@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-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260409.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-GcRRnaoeZVrbC47woQ/2t3vPoQcTSjsWPEAQGtwNSdw7Z9TKxG4ES22ghJIQXd3ncTRCMJ+XELnnuqxVutkJ9w=="],
|
||||||
|
|
||||||
|
"@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-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20260409.1", "", { "os": "linux", "cpu": "arm" }, "sha512-fOa07JBUXQpEPq+024g346inYZ2xp63ELuoRq6J0jwDWQ/ftCCuvdQNMncwFhsm1qlMdKT3S68NrnSxX16hiaw=="],
|
||||||
|
|
||||||
|
"@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-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20260409.1", "", { "os": "linux", "cpu": "x64" }, "sha512-lQrbc/BJKBxQrR1ttBDU5sYY1Hb2moFQgHL20T6nbapNqGpK4pzy64p+NK39O93D4omiCSk04pkchBCVrMPSAg=="],
|
||||||
|
|
||||||
|
"@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20260409.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-kmCafMo1xZlYx+9WnfpeZJ2tnB/CcJdR8QPX7j9vqcpe51D7b7Intmr921dD48KGpVh5YgjQ1MEFE5mjGqGMaA=="],
|
||||||
|
|
||||||
|
"@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20260409.1", "", { "os": "win32", "cpu": "x64" }, "sha512-WRd+JpQipTsE15QgYr3w7J0f1NKvGcq2QEgmcq8hB0WZA1X2WhQopNu+MpPQ3tdDD42VjMhm8ZoB8HpuOoXK5w=="],
|
||||||
|
|
||||||
|
"@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=="],
|
||||||
|
|
||||||
|
"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=="],
|
||||||
|
|
||||||
|
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
|
|
||||||
|
"tunnel": ["tunnel@0.0.6", "", {}, "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="],
|
||||||
|
|
||||||
|
"undici": ["undici@6.24.1", "", {}, "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA=="],
|
||||||
|
|
||||||
|
"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=="],
|
||||||
|
}
|
||||||
|
}
|
||||||
32595
dist/index.js
vendored
32595
dist/index.js
vendored
File diff suppressed because one or more lines are too long
1
dist/index.js.map
vendored
1
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
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
@@ -1,42 +1,58 @@
|
|||||||
# `supabase-github-action`
|
# `supabase/setup-cli`
|
||||||
|
|
||||||
The Supabase GitHub Action provides an easy way to use the Supabase CLI on
|
The Supabase CLI Action provides an easy way to install the
|
||||||
GitHub's hosted Actions runners.
|
[Supabase CLI](https://github.com/supabase/cli) on GitHub Actions runners.
|
||||||
|
|
||||||
The action can be run on `ubuntu-latest`, `windows-latest`, and `macos-latest`
|
The action supports `ubuntu-latest`, `windows-latest`, and `macos-latest`, and
|
||||||
GitHub Actions runners, and will install and expose a specified version of the
|
adds the requested `supabase` version to `PATH` for the rest of the job.
|
||||||
Supabase CLI on the runner environment.
|
|
||||||
|
|
||||||
## Quick start
|
If `version` is omitted, the action checks the repository root for `bun.lock`,
|
||||||
|
`pnpm-lock.yaml`, or `package-lock.json` and otherwise falls back to `latest`.
|
||||||
|
|
||||||
This example shows how you can use the Supabase GitHub Action to test your
|
## Quick Start
|
||||||
migrations on every Pull Request.
|
|
||||||
|
|
||||||
Inside your repository, create a new file inside the `.github/workflows` folder
|
This example runs Supabase migrations on every pull request:
|
||||||
called `test-migrations.yml`.
|
|
||||||
|
|
||||||
Copy this snippet inside the file, and the action will run whenever a new PR is
|
|
||||||
created:
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
name: 'test-migrations'
|
name: test-migrations
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
test-migrations:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: supabase/setup-cli@v1
|
- uses: actions/checkout@v6
|
||||||
with:
|
- uses: supabase/setup-cli@v2
|
||||||
version: latest
|
- run: supabase init
|
||||||
- run: supabase init
|
- run: supabase db start
|
||||||
- run: supabase db start
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
To pin a specific CLI version:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: supabase/setup-cli@v2
|
||||||
|
with:
|
||||||
|
version: 2.84.2
|
||||||
|
```
|
||||||
|
|
||||||
|
To cache the Docker images pulled by `supabase start`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: supabase/setup-cli@v2
|
||||||
|
with:
|
||||||
|
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**:
|
- **Source Code**: <https://github.com/supabase/setup-cli>
|
||||||
<a href="https://github.com/supabase/supabase-github-action" target="_blank">github.com/supabase/supabase-github-action</a>
|
- **CLI Documentation**: <https://supabase.com/docs/guides/cli>
|
||||||
- **CLI Documentation**:
|
|
||||||
<a href="https://supabase.com/docs/guides/cli" target="_blank">supabase.com/docs/guides/cli</a>
|
|
||||||
|
|||||||
@@ -1,81 +0,0 @@
|
|||||||
// See: https://eslint.org/docs/latest/use/configure/configuration-files
|
|
||||||
|
|
||||||
import { fixupPluginRules } from '@eslint/compat'
|
|
||||||
import { FlatCompat } from '@eslint/eslintrc'
|
|
||||||
import js from '@eslint/js'
|
|
||||||
import typescriptEslint from '@typescript-eslint/eslint-plugin'
|
|
||||||
import tsParser from '@typescript-eslint/parser'
|
|
||||||
import _import from 'eslint-plugin-import'
|
|
||||||
import jest from 'eslint-plugin-jest'
|
|
||||||
import prettier from 'eslint-plugin-prettier'
|
|
||||||
import globals from 'globals'
|
|
||||||
import path from 'node:path'
|
|
||||||
import { fileURLToPath } from 'node:url'
|
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url)
|
|
||||||
const __dirname = path.dirname(__filename)
|
|
||||||
const compat = new FlatCompat({
|
|
||||||
baseDirectory: __dirname,
|
|
||||||
recommendedConfig: js.configs.recommended,
|
|
||||||
allConfig: js.configs.all
|
|
||||||
})
|
|
||||||
|
|
||||||
export default [
|
|
||||||
{
|
|
||||||
ignores: ['**/coverage', '**/dist', '**/linter', '**/node_modules']
|
|
||||||
},
|
|
||||||
...compat.extends(
|
|
||||||
'eslint:recommended',
|
|
||||||
'plugin:@typescript-eslint/eslint-recommended',
|
|
||||||
'plugin:@typescript-eslint/recommended',
|
|
||||||
'plugin:jest/recommended',
|
|
||||||
'plugin:prettier/recommended'
|
|
||||||
),
|
|
||||||
{
|
|
||||||
plugins: {
|
|
||||||
import: fixupPluginRules(_import),
|
|
||||||
jest,
|
|
||||||
prettier,
|
|
||||||
'@typescript-eslint': typescriptEslint
|
|
||||||
},
|
|
||||||
|
|
||||||
languageOptions: {
|
|
||||||
globals: {
|
|
||||||
...globals.node,
|
|
||||||
...globals.jest,
|
|
||||||
Atomics: 'readonly',
|
|
||||||
SharedArrayBuffer: 'readonly'
|
|
||||||
},
|
|
||||||
|
|
||||||
parser: tsParser,
|
|
||||||
ecmaVersion: 2023,
|
|
||||||
sourceType: 'module',
|
|
||||||
|
|
||||||
parserOptions: {
|
|
||||||
project: ['tsconfig.eslint.json'],
|
|
||||||
tsconfigRootDir: '.'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
settings: {
|
|
||||||
'import/resolver': {
|
|
||||||
typescript: {
|
|
||||||
alwaysTryTypes: true,
|
|
||||||
project: 'tsconfig.eslint.json'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
rules: {
|
|
||||||
camelcase: 'off',
|
|
||||||
'eslint-comments/no-use': 'off',
|
|
||||||
'eslint-comments/no-unused-disable': 'off',
|
|
||||||
'i18n-text/no-en': 'off',
|
|
||||||
'import/no-namespace': 'off',
|
|
||||||
'no-console': 'off',
|
|
||||||
'no-shadow': 'off',
|
|
||||||
'no-unused-vars': 'off',
|
|
||||||
'prettier/prettier': 'error'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
// See: https://jestjs.io/docs/configuration
|
|
||||||
|
|
||||||
/** @type {import('ts-jest').JestConfigWithTsJest} **/
|
|
||||||
export default {
|
|
||||||
clearMocks: true,
|
|
||||||
collectCoverage: true,
|
|
||||||
collectCoverageFrom: ['./src/**'],
|
|
||||||
coverageDirectory: './coverage',
|
|
||||||
coveragePathIgnorePatterns: ['/node_modules/', '/dist/'],
|
|
||||||
coverageReporters: ['json-summary', 'text', 'lcov'],
|
|
||||||
// Uncomment the below lines if you would like to enforce a coverage threshold
|
|
||||||
// for your action. This will fail the build if the coverage is below the
|
|
||||||
// specified thresholds.
|
|
||||||
// coverageThreshold: {
|
|
||||||
// global: {
|
|
||||||
// branches: 100,
|
|
||||||
// functions: 100,
|
|
||||||
// lines: 100,
|
|
||||||
// statements: 100
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
extensionsToTreatAsEsm: ['.ts'],
|
|
||||||
moduleFileExtensions: ['ts', 'js'],
|
|
||||||
preset: 'ts-jest',
|
|
||||||
reporters: ['default'],
|
|
||||||
resolver: 'ts-jest-resolver',
|
|
||||||
testEnvironment: 'node',
|
|
||||||
testMatch: ['**/*.test.ts'],
|
|
||||||
testPathIgnorePatterns: ['/dist/', '/node_modules/'],
|
|
||||||
transform: {
|
|
||||||
'^.+\\.ts$': [
|
|
||||||
'ts-jest',
|
|
||||||
{
|
|
||||||
tsconfig: 'tsconfig.eslint.json',
|
|
||||||
useESM: true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
verbose: true
|
|
||||||
}
|
|
||||||
13198
package-lock.json
generated
13198
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
88
package.json
88
package.json
@@ -1,72 +1,48 @@
|
|||||||
{
|
{
|
||||||
"name": "setup-cli",
|
"name": "setup-cli",
|
||||||
"description": "Supabase CLI GitHub Action",
|
"version": "2.0.0",
|
||||||
"version": "1.6.0",
|
|
||||||
"author": "",
|
|
||||||
"type": "module",
|
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"description": "Supabase CLI GitHub Action",
|
||||||
|
"keywords": [
|
||||||
|
"actions"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"author": "",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/supabase/setup-cli.git"
|
"url": "git+https://github.com/supabase/setup-cli.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"type": "module",
|
||||||
"actions"
|
|
||||||
],
|
|
||||||
"exports": {
|
|
||||||
".": "./dist/index.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"bundle": "npm run format:write && npm run package",
|
"all": "bun run format && bun run lint && bun run coverage && bun run build",
|
||||||
"ci-test": "NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 npx jest",
|
"build": "bun build src/main.ts src/post.ts --target=node --format=esm --outdir=dist",
|
||||||
"coverage": "npx make-coverage-badge --output-path ./badges/coverage.svg",
|
"ci": "bun run format:check && bun run lint && bun run coverage && bun run build",
|
||||||
"format:write": "npx prettier --write .",
|
"coverage": "bun test --coverage --coverage-reporter=text --coverage-reporter=lcov",
|
||||||
"format:check": "npx prettier --check .",
|
"format": "bun x oxfmt --write . '!coverage/**' '!dist/**'",
|
||||||
"lint": "npx eslint .",
|
"format:check": "bun x oxfmt --check . '!coverage/**' '!dist/**'",
|
||||||
"local-action": "npx @github/local-action . src/main.ts .env",
|
"lint": "bun x oxlint --deny-warnings --type-aware --type-check --tsconfig tsconfig.json src",
|
||||||
"package": "npx rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",
|
"test": "bun test",
|
||||||
"package:watch": "npm run package -- --watch",
|
"typecheck": "bun x tsgo -p tsconfig.json --noEmit"
|
||||||
"test": "NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 npx jest",
|
|
||||||
"all": "npm run format:write && npm run lint && npm run package && npm run test && npm run coverage"
|
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.11.1",
|
"@actions/cache": "^6.0.0",
|
||||||
"@actions/tool-cache": "^2.0.2",
|
"@actions/core": "^3.0.0",
|
||||||
"semver": "^7.7.2"
|
"@actions/tool-cache": "^4.0.0",
|
||||||
|
"js-yaml": "^4.1.1",
|
||||||
|
"semver": "^7.7.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/compat": "^1.3.1",
|
"@tsconfig/bun": "^1.0.10",
|
||||||
"@github/local-action": "^5.1.0",
|
"@types/bun": "^1.3.11",
|
||||||
"@jest/globals": "^30.0.5",
|
|
||||||
"@rollup/plugin-commonjs": "^28.0.6",
|
|
||||||
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
||||||
"@rollup/plugin-typescript": "^12.1.4",
|
|
||||||
"@types/jest": "^30.0.0",
|
|
||||||
"@types/js-yaml": "^4.0.9",
|
"@types/js-yaml": "^4.0.9",
|
||||||
"@types/node": "^20.19.9",
|
"@types/node": "^24",
|
||||||
"@types/semver": "^7.7.0",
|
"@types/semver": "^7.7.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
"@typescript/native-preview": "^7.0.0-dev.20260409.1",
|
||||||
"@typescript-eslint/parser": "^8.38.0",
|
"oxfmt": "^0.44.0",
|
||||||
"eslint": "^9.31.0",
|
"oxlint": "^1.59.0",
|
||||||
"eslint-config-prettier": "^10.1.8",
|
"oxlint-tsgolint": "^0.20.0"
|
||||||
"eslint-import-resolver-typescript": "^4.4.4",
|
|
||||||
"eslint-plugin-import": "^2.32.0",
|
|
||||||
"eslint-plugin-jest": "^29.0.1",
|
|
||||||
"eslint-plugin-prettier": "^5.5.3",
|
|
||||||
"jest": "^30.0.5",
|
|
||||||
"js-yaml": "^4.1.0",
|
|
||||||
"make-coverage-badge": "^1.2.0",
|
|
||||||
"prettier": "^3.6.2",
|
|
||||||
"prettier-eslint": "^16.4.2",
|
|
||||||
"rollup": "^4.45.1",
|
|
||||||
"ts-jest": "^29.4.0",
|
|
||||||
"ts-jest-resolver": "^2.0.1",
|
|
||||||
"typescript": "^5.8.3"
|
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"engines": {
|
||||||
"@rollup/rollup-linux-x64-gnu": "*"
|
"bun": ">=1.3.10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
// See: https://rollupjs.org/introduction/
|
|
||||||
|
|
||||||
import commonjs from '@rollup/plugin-commonjs'
|
|
||||||
import nodeResolve from '@rollup/plugin-node-resolve'
|
|
||||||
import typescript from '@rollup/plugin-typescript'
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
input: 'src/index.ts',
|
|
||||||
output: {
|
|
||||||
esModule: true,
|
|
||||||
file: 'dist/index.js',
|
|
||||||
format: 'es',
|
|
||||||
sourcemap: true
|
|
||||||
},
|
|
||||||
plugins: [typescript(), nodeResolve({ preferBuiltins: true }), commonjs()]
|
|
||||||
}
|
|
||||||
|
|
||||||
export default config
|
|
||||||
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)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
/**
|
|
||||||
* The entrypoint for the action. This file simply imports and runs the action's
|
|
||||||
* main logic.
|
|
||||||
*/
|
|
||||||
import { run } from './main.js'
|
|
||||||
|
|
||||||
/* istanbul ignore next */
|
|
||||||
run()
|
|
||||||
432
src/main.test.ts
Normal file
432
src/main.test.ts
Normal file
@@ -0,0 +1,432 @@
|
|||||||
|
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||||
|
import os from "node:os";
|
||||||
|
import path from "node:path";
|
||||||
|
import process from "node:process";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
import { afterEach, expect, mock, spyOn, test } from "bun:test";
|
||||||
|
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 originalWorkspace = process.env.GITHUB_WORKSPACE;
|
||||||
|
const tempDirs = new Set<string>();
|
||||||
|
let mainModule: typeof import("./main.ts") | null = null;
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
mock.restore();
|
||||||
|
process.env.GITHUB_WORKSPACE = originalWorkspace;
|
||||||
|
|
||||||
|
for (const dir of tempDirs) {
|
||||||
|
rmSync(dir, { force: true, recursive: true });
|
||||||
|
}
|
||||||
|
tempDirs.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
function createFakeCli(versionOutput: string): string {
|
||||||
|
const dir = mkdtempSync(path.join(os.tmpdir(), "setup-cli-"));
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createWorkspace(files: Record<string, string>): string {
|
||||||
|
const dir = mkdtempSync(path.join(os.tmpdir(), "setup-cli-workspace-"));
|
||||||
|
tempDirs.add(dir);
|
||||||
|
|
||||||
|
for (const [relativePath, content] of Object.entries(files)) {
|
||||||
|
const filePath = path.join(dir, relativePath);
|
||||||
|
mkdirSync(path.dirname(filePath), { recursive: true });
|
||||||
|
writeFileSync(filePath, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createBunLock(
|
||||||
|
version: string,
|
||||||
|
options: {
|
||||||
|
includeDependency?: boolean;
|
||||||
|
includePackageEntry?: boolean;
|
||||||
|
useDevDependency?: boolean;
|
||||||
|
} = {},
|
||||||
|
): string {
|
||||||
|
const includeDependency = options.includeDependency ?? true;
|
||||||
|
const includePackageEntry = options.includePackageEntry ?? true;
|
||||||
|
const dependencyKey = options.useDevDependency ? "devDependencies" : "dependencies";
|
||||||
|
|
||||||
|
return `{
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"configVersion": 1,
|
||||||
|
"workspaces": {
|
||||||
|
"": {
|
||||||
|
"name": "app",
|
||||||
|
"${dependencyKey}": {
|
||||||
|
${includeDependency ? ` "supabase": "^${version}"` : ""}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
${
|
||||||
|
includePackageEntry
|
||||||
|
? ` "supabase": [
|
||||||
|
"supabase@${version}",
|
||||||
|
"",
|
||||||
|
{},
|
||||||
|
"sha512-test"
|
||||||
|
]`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createPnpmLock(
|
||||||
|
version: string,
|
||||||
|
options: { asString?: boolean; includeVersion?: boolean; useDevDependency?: boolean } = {},
|
||||||
|
): string {
|
||||||
|
const dependencyKey = options.useDevDependency ? "devDependencies" : "dependencies";
|
||||||
|
|
||||||
|
return `lockfileVersion: "9.0"
|
||||||
|
importers:
|
||||||
|
.:
|
||||||
|
${dependencyKey}:
|
||||||
|
${
|
||||||
|
options.asString
|
||||||
|
? ` supabase: ${version}`
|
||||||
|
: ` supabase:
|
||||||
|
specifier: ^${version}
|
||||||
|
${options.includeVersion === false ? "" : ` version: ${version}`}`
|
||||||
|
}
|
||||||
|
packages:
|
||||||
|
supabase@${version}:
|
||||||
|
resolution:
|
||||||
|
integrity: sha512-test
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createPackageLock(version: string): string {
|
||||||
|
return JSON.stringify(
|
||||||
|
{
|
||||||
|
name: "app",
|
||||||
|
lockfileVersion: 3,
|
||||||
|
packages: {
|
||||||
|
"": {
|
||||||
|
dependencies: {
|
||||||
|
supabase: `^${version}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"node_modules/supabase": {
|
||||||
|
version,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createActionSpies(inputVersion: string, cliDir: string, expectedUrlFragment: string) {
|
||||||
|
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(() => {}),
|
||||||
|
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(expectedUrlFragment);
|
||||||
|
return path.join(os.tmpdir(), "supabase-cli.tar.gz");
|
||||||
|
}),
|
||||||
|
extractTar: spyOn(tc, "extractTar").mockImplementation(async () => cliDir),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getMainModule(): Promise<typeof import("./main.ts")> {
|
||||||
|
if (!mainModule) {
|
||||||
|
mainModule = await import("./main.ts");
|
||||||
|
}
|
||||||
|
|
||||||
|
return mainModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
test("awaits the action entrypoint with omitted version and latest fallback", async () => {
|
||||||
|
process.env.GITHUB_WORKSPACE = repo;
|
||||||
|
const cliDir = createFakeCli("supabase 2.84.2");
|
||||||
|
let startDownload!: () => void;
|
||||||
|
let finishDownload!: () => void;
|
||||||
|
const downloadStarted = new Promise<void>((resolve) => {
|
||||||
|
startDownload = resolve;
|
||||||
|
});
|
||||||
|
const downloadFinished = new Promise<string>((resolve) => {
|
||||||
|
finishDownload = () => resolve(path.join(os.tmpdir(), "supabase-cli.tar.gz"));
|
||||||
|
});
|
||||||
|
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("uses the root bun.lock version when version is omitted", async () => {
|
||||||
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
|
"bun.lock": createBunLock("2.41.0"),
|
||||||
|
});
|
||||||
|
const cliDir = createFakeCli("supabase 2.41.0");
|
||||||
|
const spies = createActionSpies("", cliDir, "/download/v2.41.0/supabase_");
|
||||||
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(spies.downloadTool).not.toHaveBeenCalledWith(expect.stringContaining("/latest/download/"));
|
||||||
|
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 version when version is omitted", async () => {
|
||||||
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
|
"pnpm-lock.yaml": createPnpmLock("2.42.0"),
|
||||||
|
});
|
||||||
|
const cliDir = createFakeCli("supabase 2.42.0");
|
||||||
|
const spies = createActionSpies("", cliDir, "/download/v2.42.0/supabase_");
|
||||||
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 2.42.0");
|
||||||
|
expect(spies.exportVariable).toHaveBeenCalledWith(CLI_CONFIG_REGISTRY, "ghcr.io");
|
||||||
|
expect(spies.setFailed).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("uses the root package-lock.json version when version is omitted", async () => {
|
||||||
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
|
"package-lock.json": createPackageLock("2.43.0"),
|
||||||
|
});
|
||||||
|
const cliDir = createFakeCli("supabase 2.43.0");
|
||||||
|
const spies = createActionSpies("", cliDir, "/download/v2.43.0/supabase_");
|
||||||
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 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 () => {
|
||||||
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
|
"bun.lock": "{ not valid",
|
||||||
|
"package-lock.json": createPackageLock("2.44.0"),
|
||||||
|
});
|
||||||
|
const cliDir = createFakeCli("supabase 2.44.0");
|
||||||
|
const spies = createActionSpies("", cliDir, "/download/v2.44.0/supabase_");
|
||||||
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 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 () => {
|
||||||
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
|
"README.md": "# app\n",
|
||||||
|
});
|
||||||
|
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 version is omitted and no workspace is available", async () => {
|
||||||
|
delete process.env.GITHUB_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("uses the declared bun.lock version when the resolved package entry is missing", async () => {
|
||||||
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
|
"bun.lock": createBunLock("2.44.1", { includePackageEntry: false, useDevDependency: true }),
|
||||||
|
});
|
||||||
|
const cliDir = createFakeCli("supabase 2.44.1");
|
||||||
|
const spies = createActionSpies("", cliDir, "/download/v2.44.1/supabase_");
|
||||||
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
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 () => {
|
||||||
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
|
"bun.lock": createBunLock("2.47.0", { includeDependency: false }),
|
||||||
|
"pnpm-lock.yaml": createPnpmLock("2.47.0", { asString: true }),
|
||||||
|
});
|
||||||
|
const cliDir = createFakeCli("supabase 2.47.0");
|
||||||
|
const spies = createActionSpies("", cliDir, "/download/v2.47.0/supabase_");
|
||||||
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 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 () => {
|
||||||
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
|
"pnpm-lock.yaml": createPnpmLock("2.49.0", { includeVersion: false }),
|
||||||
|
});
|
||||||
|
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("explicit version overrides detected root lockfiles", async () => {
|
||||||
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
|
"bun.lock": createBunLock("2.45.0"),
|
||||||
|
});
|
||||||
|
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();
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 1.0.0");
|
||||||
|
expect(spies.exportVariable).not.toHaveBeenCalled();
|
||||||
|
expect(spies.setFailed).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("fails when the installed CLI does not report a version", async () => {
|
||||||
|
process.env.GITHUB_WORKSPACE = createWorkspace({
|
||||||
|
"package-lock.json": createPackageLock("2.46.0"),
|
||||||
|
});
|
||||||
|
const cliDir = createFakeCli("");
|
||||||
|
const spies = createActionSpies("", cliDir, "/download/v2.46.0/supabase_");
|
||||||
|
const { run } = await getMainModule();
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(spies.setFailed).toHaveBeenCalledWith(
|
||||||
|
"Could not determine installed Supabase CLI version",
|
||||||
|
);
|
||||||
|
expect(spies.setOutput).not.toHaveBeenCalled();
|
||||||
|
expect(spies.addPath).not.toHaveBeenCalled();
|
||||||
|
expect(spies.exportVariable).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
259
src/main.ts
259
src/main.ts
@@ -1,39 +1,230 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from "@actions/core";
|
||||||
import * as tc from '@actions/tool-cache'
|
import * as tc from "@actions/tool-cache";
|
||||||
import { gte } from 'semver'
|
import { load as loadYaml } from "js-yaml";
|
||||||
import { getDownloadUrl, determineInstalledVersion } from './utils.js'
|
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 { 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 DEFAULT_VERSION = "latest";
|
||||||
|
const execFile = promisify(execFileCallback);
|
||||||
|
|
||||||
|
type BunLock = {
|
||||||
|
workspaces?: {
|
||||||
|
"": {
|
||||||
|
dependencies?: Record<string, string>;
|
||||||
|
devDependencies?: Record<string, string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
packages?: Record<string, unknown>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PnpmDependency =
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
version?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PnpmLock = {
|
||||||
|
importers?: {
|
||||||
|
".": {
|
||||||
|
dependencies?: Record<string, PnpmDependency>;
|
||||||
|
devDependencies?: Record<string, PnpmDependency>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type PackageLock = {
|
||||||
|
packages?: Record<string, { version?: string }>;
|
||||||
|
dependencies?: Record<string, { version?: string }>;
|
||||||
|
};
|
||||||
|
|
||||||
|
function getArchivePlatform(platform: NodeJS.Platform): string {
|
||||||
|
return platform === "win32" ? "windows" : platform;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getArchiveArch(arch: NodeJS.Architecture): string {
|
||||||
|
return arch === "x64" ? "amd64" : arch;
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractConcreteVersion(raw: string | undefined): string | null {
|
||||||
|
if (!raw) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const match = raw.match(/\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?/);
|
||||||
|
return match?.[0] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readWorkspaceLockfile(workspaceRoot: string, filename: string): string | null {
|
||||||
|
const filePath = path.join(workspaceRoot, filename);
|
||||||
|
|
||||||
|
if (!existsSync(filePath)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The main function for the action.
|
|
||||||
*
|
|
||||||
* @returns Resolves when the action is complete.
|
|
||||||
*/
|
|
||||||
export async function run(): Promise<void> {
|
|
||||||
try {
|
try {
|
||||||
// Get version of tool to be installed
|
return readFileSync(filePath, "utf8");
|
||||||
const version = core.getInput('version')
|
} catch {
|
||||||
|
return null;
|
||||||
// Download the specific version of the tool, e.g. as a tarball/zipball
|
|
||||||
const download = await getDownloadUrl(version)
|
|
||||||
const pathToTarball = await tc.downloadTool(download)
|
|
||||||
|
|
||||||
// Extract the tarball/zipball onto host runner
|
|
||||||
const pathToCLI = await tc.extractTar(pathToTarball)
|
|
||||||
|
|
||||||
// Expose the tool by adding it to the PATH
|
|
||||||
core.addPath(pathToCLI)
|
|
||||||
|
|
||||||
// Expose installed tool version
|
|
||||||
const determinedVersion = await determineInstalledVersion()
|
|
||||||
core.setOutput('version', determinedVersion)
|
|
||||||
|
|
||||||
// Use GHCR mirror by default
|
|
||||||
if (version.toLowerCase() === 'latest' || gte(version, '1.28.0')) {
|
|
||||||
core.exportVariable(CLI_CONFIG_REGISTRY, 'ghcr.io')
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof Error) core.setFailed(error.message)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function detectVersionFromBunLock(workspaceRoot: string): string | null {
|
||||||
|
const text = readWorkspaceLockfile(workspaceRoot, "bun.lock");
|
||||||
|
|
||||||
|
if (!text) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const lockfile = JSON.parse(text.replace(/,\s*([}\]])/g, "$1")) as BunLock;
|
||||||
|
const rootWorkspace = lockfile.workspaces?.[""];
|
||||||
|
const declaredVersion =
|
||||||
|
rootWorkspace?.dependencies?.supabase ?? rootWorkspace?.devDependencies?.supabase;
|
||||||
|
|
||||||
|
if (!declaredVersion) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolvedPackage = lockfile.packages?.supabase;
|
||||||
|
if (Array.isArray(resolvedPackage) && typeof resolvedPackage[0] === "string") {
|
||||||
|
return extractConcreteVersion(resolvedPackage[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return extractConcreteVersion(declaredVersion);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function detectVersionFromPnpmLock(workspaceRoot: string): string | null {
|
||||||
|
const text = readWorkspaceLockfile(workspaceRoot, "pnpm-lock.yaml");
|
||||||
|
|
||||||
|
if (!text) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const lockfile = loadYaml(text) as PnpmLock;
|
||||||
|
const rootImporter = lockfile.importers?.["."];
|
||||||
|
const dependency =
|
||||||
|
rootImporter?.dependencies?.supabase ?? rootImporter?.devDependencies?.supabase;
|
||||||
|
|
||||||
|
if (typeof dependency === "string") {
|
||||||
|
return extractConcreteVersion(dependency);
|
||||||
|
}
|
||||||
|
|
||||||
|
return extractConcreteVersion(dependency?.version);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function detectVersionFromPackageLock(workspaceRoot: string): string | null {
|
||||||
|
const text = readWorkspaceLockfile(workspaceRoot, "package-lock.json");
|
||||||
|
|
||||||
|
if (!text) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const lockfile = JSON.parse(text) as PackageLock;
|
||||||
|
|
||||||
|
return (
|
||||||
|
extractConcreteVersion(lockfile.packages?.["node_modules/supabase"]?.version) ??
|
||||||
|
extractConcreteVersion(lockfile.dependencies?.supabase?.version)
|
||||||
|
);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveVersion(inputVersion: string): string {
|
||||||
|
const requestedVersion = inputVersion.trim();
|
||||||
|
|
||||||
|
if (requestedVersion) {
|
||||||
|
return requestedVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
const workspaceRoot = process.env.GITHUB_WORKSPACE?.trim();
|
||||||
|
|
||||||
|
if (!workspaceRoot) {
|
||||||
|
return DEFAULT_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
detectVersionFromBunLock(workspaceRoot) ??
|
||||||
|
detectVersionFromPnpmLock(workspaceRoot) ??
|
||||||
|
detectVersionFromPackageLock(workspaceRoot) ??
|
||||||
|
DEFAULT_VERSION
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDownloadUrl(version: string): string {
|
||||||
|
const platform = getArchivePlatform(process.platform);
|
||||||
|
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}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (semver.compare(version, REGISTRY_VERSION) === -1) {
|
||||||
|
return `https://github.com/supabase/cli/releases/download/v${version}/supabase_${version}_${platform}_${arch}.tar.gz`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `https://github.com/supabase/cli/releases/download/v${version}/${filename}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSupabaseExecutable(cliPath: string): string {
|
||||||
|
const names =
|
||||||
|
process.platform === "win32" ? ["supabase.exe", "supabase.cmd", "supabase"] : ["supabase"];
|
||||||
|
|
||||||
|
for (const name of names) {
|
||||||
|
const executable = path.join(cliPath, name);
|
||||||
|
if (existsSync(executable)) {
|
||||||
|
return executable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return path.join(cliPath, "supabase");
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function determineInstalledVersion(cliPath: string): Promise<string> {
|
||||||
|
const { stdout } = await execFile(getSupabaseExecutable(cliPath), ["--version"]);
|
||||||
|
const version = stdout.trim();
|
||||||
|
if (!version) {
|
||||||
|
throw new Error("Could not determine installed Supabase CLI version");
|
||||||
|
}
|
||||||
|
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function run(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const version = resolveVersion(core.getInput("version"));
|
||||||
|
const tarball = await tc.downloadTool(getDownloadUrl(version));
|
||||||
|
const cliPath = await tc.extractTar(tarball);
|
||||||
|
const installedVersion = await determineInstalledVersion(cliPath);
|
||||||
|
core.setOutput("version", installedVersion);
|
||||||
|
core.addPath(cliPath);
|
||||||
|
|
||||||
|
if (version.toLowerCase() === "latest" || semver.compare(version, REGISTRY_VERSION) >= 0) {
|
||||||
|
core.exportVariable(CLI_CONFIG_REGISTRY, getGhcrImageRegistry());
|
||||||
|
}
|
||||||
|
|
||||||
|
await restoreDockerImageCache(installedVersion, getImageRegistry());
|
||||||
|
} catch (error) {
|
||||||
|
core.setFailed(error instanceof Error ? error.message : String(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
||||||
|
await run();
|
||||||
|
}
|
||||||
|
|||||||
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();
|
||||||
|
}
|
||||||
48
src/utils.ts
48
src/utils.ts
@@ -1,48 +0,0 @@
|
|||||||
import { exec } from 'child_process'
|
|
||||||
import os from 'os'
|
|
||||||
import { lt } from 'semver'
|
|
||||||
import { promisify } from 'util'
|
|
||||||
|
|
||||||
const doExec = promisify(exec)
|
|
||||||
|
|
||||||
// arch in [arm, arm64, x64...] (https://nodejs.org/docs/latest-v16.x/api/os.html#osarch)
|
|
||||||
// return value in [amd64, arm64, arm]
|
|
||||||
const mapArch = (arch: string): string => {
|
|
||||||
const mappings: Record<string, string> = {
|
|
||||||
x64: 'amd64'
|
|
||||||
}
|
|
||||||
return mappings[arch] || arch
|
|
||||||
}
|
|
||||||
|
|
||||||
// os in [darwin, linux, win32...] (https://nodejs.org/docs/latest-v16.x/api/os.html#osplatform)
|
|
||||||
// return value in [darwin, linux, windows]
|
|
||||||
const mapOS = (platform: string): string => {
|
|
||||||
const mappings: Record<string, string> = {
|
|
||||||
win32: 'windows'
|
|
||||||
}
|
|
||||||
return mappings[platform] || platform
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getDownloadUrl = async (version: string): Promise<string> => {
|
|
||||||
const platform = mapOS(os.platform())
|
|
||||||
const arch = mapArch(os.arch())
|
|
||||||
const filename = `supabase_${platform}_${arch}.tar.gz`
|
|
||||||
if (version.toLowerCase() === 'latest') {
|
|
||||||
return `https://github.com/supabase/cli/releases/latest/download/${filename}`
|
|
||||||
}
|
|
||||||
if (lt(version, '1.28.0')) {
|
|
||||||
return `https://github.com/supabase/cli/releases/download/v${version}/supabase_${version}_${platform}_${arch}.tar.gz`
|
|
||||||
}
|
|
||||||
return `https://github.com/supabase/cli/releases/download/v${version}/${filename}`
|
|
||||||
}
|
|
||||||
|
|
||||||
export const determineInstalledVersion = async (): Promise<string> => {
|
|
||||||
const { stdout } = await doExec('supabase --version')
|
|
||||||
|
|
||||||
const version = stdout.trim()
|
|
||||||
if (!version) {
|
|
||||||
throw new Error('Could not determine installed Supabase CLI version')
|
|
||||||
}
|
|
||||||
|
|
||||||
return version
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/tsconfig",
|
|
||||||
"compilerOptions": {
|
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"declaration": false,
|
|
||||||
"declarationMap": false,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"lib": ["ES2022"],
|
|
||||||
"module": "NodeNext",
|
|
||||||
"moduleResolution": "NodeNext",
|
|
||||||
"newLine": "lf",
|
|
||||||
"noImplicitAny": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"noUnusedParameters": false,
|
|
||||||
"pretty": true,
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"strict": true,
|
|
||||||
"strictNullChecks": true,
|
|
||||||
"target": "ES2022"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/tsconfig",
|
|
||||||
"extends": "./tsconfig.base.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"allowJs": true,
|
|
||||||
"noEmit": true
|
|
||||||
},
|
|
||||||
"exclude": ["dist", "node_modules"],
|
|
||||||
"include": [
|
|
||||||
"__fixtures__",
|
|
||||||
"__tests__",
|
|
||||||
"src",
|
|
||||||
"eslint.config.mjs",
|
|
||||||
"jest.config.js",
|
|
||||||
"rollup.config.ts"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/tsconfig",
|
"extends": "@tsconfig/bun/tsconfig.json",
|
||||||
"extends": "./tsconfig.base.json",
|
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "NodeNext",
|
"types": ["bun", "node"]
|
||||||
"moduleResolution": "NodeNext",
|
|
||||||
"outDir": "./dist"
|
|
||||||
},
|
},
|
||||||
"exclude": ["__fixtures__", "__tests__", "coverage", "dist", "node_modules"],
|
|
||||||
"include": ["src"]
|
"include": ["src"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user