mirror of
https://github.com/supabase/setup-cli.git
synced 2026-06-28 09:57:03 +00:00
Compare commits
2 Commits
julien/cli
...
v1.7.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad077b4817 | ||
|
|
cd9b0fd6c9 |
@@ -1 +0,0 @@
|
|||||||
1.3.10
|
|
||||||
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
* text=auto eol=lf
|
||||||
|
|
||||||
|
dist/** -diff linguist-generated=true
|
||||||
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -1 +1 @@
|
|||||||
* @supabase/cli
|
* @supabase/dev-workflows
|
||||||
|
|||||||
5
.github/codeql/codeql-config.yml
vendored
Normal file
5
.github/codeql/codeql-config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
name: JavaScript CodeQL Configuration
|
||||||
|
|
||||||
|
paths-ignore:
|
||||||
|
- node_modules
|
||||||
|
- dist
|
||||||
33
.github/dependabot.yml
vendored
33
.github/dependabot.yml
vendored
@@ -4,33 +4,28 @@ 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-patch:
|
actions-minor:
|
||||||
patterns:
|
|
||||||
- "*"
|
|
||||||
update-types:
|
update-types:
|
||||||
- minor
|
- minor
|
||||||
- patch
|
- patch
|
||||||
|
|
||||||
- package-ecosystem: bun
|
- package-ecosystem: npm
|
||||||
directory: /
|
directory: /
|
||||||
schedule:
|
schedule:
|
||||||
interval: weekly
|
interval: daily
|
||||||
day: tuesday
|
|
||||||
time: "09:00"
|
|
||||||
timezone: Europe/Paris
|
|
||||||
open-pull-requests-limit: 1
|
|
||||||
cooldown:
|
|
||||||
semver-minor-days: 7
|
|
||||||
semver-patch-days: 2
|
|
||||||
groups:
|
groups:
|
||||||
bun-minor-patch:
|
npm-development:
|
||||||
patterns:
|
dependency-type: development
|
||||||
- "*"
|
|
||||||
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
68
.github/workflows/ci.yml
vendored
@@ -1,68 +0,0 @@
|
|||||||
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.178.2, latest, beta]
|
|
||||||
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" ]]
|
|
||||||
46
.github/workflows/codeql-analysis.yml
vendored
Normal file
46
.github/workflows/codeql-analysis.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
name: CodeQL
|
||||||
|
|
||||||
|
on:
|
||||||
|
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,10 +3,6 @@ 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
|
||||||
@@ -14,33 +10,29 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
dependabot:
|
dependabot:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 10
|
# Checking the actor will prevent your Action run failing on non-Dependabot
|
||||||
# Only act on PRs opened by Dependabot from branches in this repository.
|
# PRs but also ensures that it only does work for Dependabot PRs.
|
||||||
if: github.actor == 'dependabot[bot]' && github.repository == github.event.pull_request.head.repo.full_name
|
if: ${{ github.actor == 'dependabot[bot]' }}
|
||||||
steps:
|
steps:
|
||||||
# Metadata drives the non-major gating used for approval and auto-merge.
|
# This first step will fail if there's no metadata and so the approval
|
||||||
|
# will not occur.
|
||||||
- id: meta
|
- id: meta
|
||||||
uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0
|
uses: dependabot/fetch-metadata@v2
|
||||||
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@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.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 == null || steps.meta.outputs.update-type == 'version-update:semver-patch' || steps.meta.outputs.update-type == 'version-update:semver-minor' }}
|
if: ${{steps.meta.outputs.update-type != 'version-update:semver-major'}}
|
||||||
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: ${{ steps.app-token.outputs.token }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_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 == null || steps.meta.outputs.update-type == 'version-update:semver-patch' || steps.meta.outputs.update-type == 'version-update:semver-minor' }}
|
if: ${{steps.meta.outputs.update-type != 'version-update:semver-major'}}
|
||||||
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
71
.github/workflows/e2e.yml
vendored
@@ -1,71 +0,0 @@
|
|||||||
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" ]]
|
|
||||||
136
.github/workflows/licensed.yml
vendored
136
.github/workflows/licensed.yml
vendored
@@ -1,6 +1,6 @@
|
|||||||
# This workflow refreshes and checks dependency license records used in this
|
# This workflow checks the statuses of cached dependencies used in this action
|
||||||
# action with the help of the Licensed tool. If any licenses are invalid or
|
# with the help of the Licensed tool. If any licenses are invalid or missing,
|
||||||
# missing, this workflow will fail. See: https://github.com/licensee/licensed
|
# this workflow will fail. See: https://github.com/licensee/licensed
|
||||||
|
|
||||||
name: Licensed
|
name: Licensed
|
||||||
|
|
||||||
@@ -9,139 +9,61 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
paths:
|
|
||||||
- .github/workflows/licensed.yml
|
|
||||||
- .licensed.yml
|
|
||||||
- .licenses/**
|
|
||||||
- bun.lock
|
|
||||||
- package.json
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
concurrency:
|
permissions:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
contents: write
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-licenses:
|
licensed:
|
||||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
name: Check Licenses
|
||||||
name: Licensed
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 15
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: read
|
|
||||||
|
|
||||||
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
|
|
||||||
id: checkout
|
|
||||||
if: steps.license-inputs.outputs.changed == 'true'
|
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
||||||
|
|
||||||
- name: Setup Bun
|
|
||||||
id: setup-bun
|
|
||||||
if: steps.license-inputs.outputs.changed == 'true'
|
|
||||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
|
||||||
with:
|
|
||||||
bun-version-file: .bun-version
|
|
||||||
|
|
||||||
- name: Install Dependencies
|
|
||||||
id: bun-install
|
|
||||||
if: steps.license-inputs.outputs.changed == 'true'
|
|
||||||
run: bun install --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Setup Ruby
|
|
||||||
id: setup-ruby
|
|
||||||
if: steps.license-inputs.outputs.changed == 'true'
|
|
||||||
uses: ruby/setup-ruby@97ecb7b512899eb71ab1bf2310a624c6f1589ac6 # v1.308.0
|
|
||||||
with:
|
|
||||||
ruby-version: ruby
|
|
||||||
|
|
||||||
- uses: licensee/setup-licensed@0d52e575b3258417672be0dff2f115d7db8771d8 # v1.3.2
|
|
||||||
if: steps.license-inputs.outputs.changed == 'true'
|
|
||||||
with:
|
|
||||||
version: 4.x
|
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Refresh License Cache
|
|
||||||
id: refresh-license-cache
|
|
||||||
if: steps.license-inputs.outputs.changed == 'true'
|
|
||||||
run: licensed cache
|
|
||||||
|
|
||||||
- name: Check Licenses
|
|
||||||
id: check-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:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
id: checkout
|
id: checkout
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Bun
|
- name: Setup Node.js
|
||||||
id: setup-bun
|
id: setup-node
|
||||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
bun-version-file: .bun-version
|
node-version-file: .node-version
|
||||||
|
cache: npm
|
||||||
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
id: bun-install
|
id: npm-ci
|
||||||
run: bun install --frozen-lockfile
|
run: npm ci
|
||||||
|
|
||||||
- name: Setup Ruby
|
- name: Setup Ruby
|
||||||
id: setup-ruby
|
id: setup-ruby
|
||||||
uses: ruby/setup-ruby@97ecb7b512899eb71ab1bf2310a624c6f1589ac6 # v1.308.0
|
uses: ruby/setup-ruby@v1
|
||||||
with:
|
with:
|
||||||
ruby-version: ruby
|
ruby-version: ruby
|
||||||
|
|
||||||
- uses: licensee/setup-licensed@0d52e575b3258417672be0dff2f115d7db8771d8 # v1.3.2
|
- uses: licensee/setup-licensed@v1.3.2
|
||||||
with:
|
with:
|
||||||
version: 4.x
|
version: 4.x
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Update License Cache
|
# If this is a workflow_dispatch event, update the cached licenses.
|
||||||
|
- if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||||
|
name: Update Licenses
|
||||||
id: update-licenses
|
id: update-licenses
|
||||||
run: licensed cache
|
run: licensed cache
|
||||||
|
|
||||||
- name: Format License Files
|
# Then, commit the updated licenses to the repository.
|
||||||
id: format-licenses
|
- if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||||
run: bun x oxfmt --write .licensed.yml .licenses
|
name: Commit 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 .licenses .licensed.yml
|
git add .
|
||||||
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
|
||||||
|
|||||||
58
.github/workflows/linter.yml
vendored
Normal file
58
.github/workflows/linter.yml
vendored
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# 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_BIOME_FORMAT: false
|
||||||
|
VALIDATE_JAVASCRIPT_ES: false
|
||||||
|
VALIDATE_JAVASCRIPT_STANDARD: false
|
||||||
|
VALIDATE_JSCPD: false
|
||||||
|
VALIDATE_TYPESCRIPT_ES: false
|
||||||
|
VALIDATE_JSON: false
|
||||||
|
VALIDATE_GITHUB_ACTIONS_ZIZMOR: false
|
||||||
|
VALIDATE_TYPESCRIPT_STANDARD: false
|
||||||
46
.github/workflows/start.yml
vendored
Normal file
46
.github/workflows/start.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
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 }}
|
||||||
|
github-token: ${{ github.token }}
|
||||||
|
- run: supabase init
|
||||||
|
- run:
|
||||||
|
sed -i -E "s|^(major_version) .*|\1 = ${{ matrix.pg_major }}|"
|
||||||
|
supabase/config.toml
|
||||||
|
- run: supabase start
|
||||||
69
.github/workflows/test.yml
vendored
Normal file
69
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
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 }}
|
||||||
|
github-token: ${{ github.token }}
|
||||||
|
- 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,6 +1,7 @@
|
|||||||
# 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,4 +13,6 @@ 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: 3.0.0
|
version: 3.0.1
|
||||||
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: []
|
||||||
|
|||||||
@@ -6,15 +6,15 @@ 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: 4.0.0
|
version: 4.0.1
|
||||||
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: []
|
||||||
|
|||||||
@@ -6,15 +6,15 @@ 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: []
|
||||||
|
|||||||
20
.licenses/npm/@actions/tool-cache.dep.yml
Normal file
20
.licenses/npm/@actions/tool-cache.dep.yml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: "@actions/tool-cache"
|
||||||
|
version: 4.0.0
|
||||||
|
type: npm
|
||||||
|
summary: Actions tool-cache lib
|
||||||
|
homepage: https://github.com/actions/toolkit/tree/main/packages/tool-cache
|
||||||
|
license: mit
|
||||||
|
licenses:
|
||||||
|
- sources: LICENSE.md
|
||||||
|
text: |-
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright 2019 GitHub
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
notices: []
|
||||||
26
.licenses/npm/semver.dep.yml
Normal file
26
.licenses/npm/semver.dep.yml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
name: semver
|
||||||
|
version: 7.8.0
|
||||||
|
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: 6.24.1
|
version: 6.25.0
|
||||||
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: []
|
||||||
|
|||||||
24
.markdown-lint.yml
Normal file
24
.markdown-lint.yml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# 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
.node-version
Normal file
1
.node-version
Normal file
@@ -0,0 +1 @@
|
|||||||
|
20.19.4
|
||||||
5
.prettierignore
Normal file
5
.prettierignore
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.DS_Store
|
||||||
|
.licenses/
|
||||||
|
dist/
|
||||||
|
node_modules/
|
||||||
|
coverage/
|
||||||
16
.prettierrc.yml
Normal file
16
.prettierrc.yml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# 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
|
||||||
14
.yaml-lint.yml
Normal file
14
.yaml-lint.yml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# 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
CODEOWNERS
Normal file
1
CODEOWNERS
Normal file
@@ -0,0 +1 @@
|
|||||||
|
* @sweatybridge
|
||||||
130
README.md
130
README.md
@@ -1,12 +1,13 @@
|
|||||||
# :gear: Supabase CLI Action
|
# :gear: Supabase CLI Action
|
||||||
|
|
||||||
[](https://github.com/supabase/setup-cli/actions/workflows/ci.yml)
|
[](https://github.com/supabase/setup-cli/actions/workflows/start.yml)
|
||||||
[](https://github.com/supabase/setup-cli/actions/workflows/e2e.yml)
|
[](https://github.com/supabase/setup-cli/actions/workflows/linter.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 composite action sets up the Supabase CLI,
|
This 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)
|
||||||
@@ -24,43 +25,26 @@ Setup the `supabase` CLI:
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
steps:
|
steps:
|
||||||
- uses: supabase/setup-cli@v3
|
- uses: supabase/setup-cli@v1
|
||||||
```
|
```
|
||||||
|
|
||||||
If `version` is omitted, the action checks the repository root for `bun.lock`,
|
A specific version of the `supabase` CLI can be installed:
|
||||||
`pnpm-lock.yaml`, or `package-lock.json` and installs the declared `supabase`
|
|
||||||
package version through npm. If the lockfile includes package integrity
|
|
||||||
metadata, the action verifies it against the npm registry before installing. If
|
|
||||||
no supported lockfile is present, it falls back to `latest`.
|
|
||||||
|
|
||||||
The action provisions Node.js and npm internally, so runners do not need npm
|
|
||||||
preinstalled. Runners must be able to reach the npm registry to install the CLI
|
|
||||||
package.
|
|
||||||
|
|
||||||
A fixed npm-published version, `latest`, or `beta` of the `supabase` CLI can be
|
|
||||||
installed:
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
steps:
|
steps:
|
||||||
- uses: supabase/setup-cli@v3
|
- uses: supabase/setup-cli@v1
|
||||||
with:
|
with:
|
||||||
version: 2.84.2
|
version: 2.20.3
|
||||||
```
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
steps:
|
|
||||||
- uses: supabase/setup-cli@v3
|
|
||||||
with:
|
|
||||||
version: beta
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Run `supabase db start` to execute all migrations on a fresh database:
|
Run `supabase db start` to execute all migrations on a fresh database:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
steps:
|
steps:
|
||||||
- uses: supabase/setup-cli@v3
|
- uses: supabase/setup-cli@v1
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
|
github-token: ${{ github.token }}
|
||||||
- run: supabase init
|
- run: supabase init
|
||||||
- run: supabase db start
|
- run: supabase db start
|
||||||
```
|
```
|
||||||
@@ -70,11 +54,12 @@ on Windows and macOS runners.
|
|||||||
|
|
||||||
## Inputs
|
## Inputs
|
||||||
|
|
||||||
The action supports the following inputs:
|
The actions supports the following inputs:
|
||||||
|
|
||||||
| Name | Type | Description | Default | Required |
|
| Name | Type | Description | Default | Required |
|
||||||
| --------- | ------ | ---------------------------------------------------------------- | --------------------------------- | -------- |
|
| -------------- | ------ | -------------------------------------------------------------------------- | -------- | -------- |
|
||||||
| `version` | String | Supabase CLI `latest`, `beta`, or fixed version published to npm | Root lockfile version or `latest` | false |
|
| `version` | String | Supabase CLI version (or `latest`) | `2.20.3` | false |
|
||||||
|
| `github-token` | String | GitHub token used to resolve `latest` without unauthenticated API limiting | | false |
|
||||||
|
|
||||||
## Advanced Usage
|
## Advanced Usage
|
||||||
|
|
||||||
@@ -82,7 +67,7 @@ Check generated TypeScript types are up-to-date with Postgres schema:
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
steps:
|
steps:
|
||||||
- uses: supabase/setup-cli@v3
|
- uses: supabase/setup-cli@v1
|
||||||
- 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
|
||||||
@@ -104,62 +89,59 @@ 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@v3
|
- uses: supabase/setup-cli@v1
|
||||||
- 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@v3
|
|
||||||
- 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
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 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 a few setup steps before you can work on the action.
|
need to perform some initial setup steps before you can develop your action.
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
>
|
>
|
||||||
> You'll need a recent version of [Bun](https://bun.sh) for local development.
|
> You'll need to have a reasonably modern version of
|
||||||
> This repository includes a `.bun-version` file for tools that can auto-switch
|
> [Node.js](https://nodejs.org) handy (20.x or later should work!). If you are
|
||||||
> Bun versions.
|
> using a version manager like [`nodenv`](https://github.com/nodenv/nodenv) or
|
||||||
|
> [`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
|
||||||
bun install
|
npm ci
|
||||||
|
```
|
||||||
|
|
||||||
|
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
|
||||||
bun test
|
$ npm test
|
||||||
|
|
||||||
|
PASS ./index.test.js
|
||||||
|
✓ gets download url to binary (3 ms)
|
||||||
|
✓ runs main action (891 ms)
|
||||||
|
|
||||||
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
1. :mag: Run the full local CI suite
|
## Publish to a distribution branch
|
||||||
|
|
||||||
```bash
|
Actions are run from this GitHub repository so we will check in the packed
|
||||||
bun run ci
|
`dist` folder.
|
||||||
```
|
|
||||||
|
|
||||||
## Publish
|
|
||||||
|
|
||||||
1. Create a new GitHub release
|
1. Create a new GitHub release
|
||||||
2. Rebase `v3` branch on `main`
|
2. Rebase `v1` branch on `main`
|
||||||
|
|
||||||
Your action is now published! :rocket:
|
Your action is now published! :rocket:
|
||||||
|
|
||||||
@@ -168,17 +150,15 @@ See the
|
|||||||
|
|
||||||
## Validate
|
## Validate
|
||||||
|
|
||||||
Validate changes by exercising the action from a workflow in this repository
|
You can now validate the action by referencing `./` in a workflow in your
|
||||||
(see [ci.yml](.github/workflows/ci.yml) and [e2e.yml](.github/workflows/e2e.yml)).
|
repository (see [test.yml](.github/workflows/test.yml))
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
steps:
|
uses: ./
|
||||||
- uses: ./
|
with:
|
||||||
with:
|
version: latest
|
||||||
version: latest
|
github-token: ${{ github.token }}
|
||||||
```
|
```
|
||||||
|
|
||||||
The CI workflow provides fast smoke coverage across GitHub-hosted runners, and
|
See the [actions tab](https://github.com/supabase/setup-cli/actions) for runs of
|
||||||
the E2E workflow verifies `supabase init` and `supabase start` against supported
|
this action! :rocket:
|
||||||
Postgres versions. See the [actions tab](https://github.com/supabase/setup-cli/actions)
|
|
||||||
for recent runs.
|
|
||||||
|
|||||||
163
__tests__/main.test.ts
Normal file
163
__tests__/main.test.ts
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
import { getCliPath, getDownloadArchive, 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 { afterEach, expect, jest, test } from '@jest/globals'
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.restoreAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
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 () => {
|
||||||
|
jest.spyOn(globalThis, 'fetch').mockResolvedValue(
|
||||||
|
new Response(JSON.stringify({ tag_name: 'v2.99.0' }), {
|
||||||
|
status: 200,
|
||||||
|
statusText: 'OK'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const url = await getDownloadUrl('latest')
|
||||||
|
expect(url).toContain('/download/v2.99.0/supabase_2.99.0_')
|
||||||
|
expect(url).toMatch(/\.tar\.gz$|\.zip$/)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('authenticates latest version lookup when a GitHub token is provided', async () => {
|
||||||
|
const fetchMock = jest.spyOn(globalThis, 'fetch').mockResolvedValue(
|
||||||
|
new Response(JSON.stringify({ tag_name: 'v2.99.0' }), {
|
||||||
|
status: 200,
|
||||||
|
statusText: 'OK'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
await getDownloadUrl('latest', 'github-token')
|
||||||
|
|
||||||
|
expect(fetchMock).toHaveBeenCalledWith(
|
||||||
|
'https://api.github.com/repos/supabase/cli/releases/latest',
|
||||||
|
expect.objectContaining({
|
||||||
|
headers: expect.objectContaining({
|
||||||
|
Accept: 'application/vnd.github+json',
|
||||||
|
Authorization: 'Bearer github-token',
|
||||||
|
'X-GitHub-Api-Version': '2022-11-28'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('omits authorization from latest version lookup without a GitHub token', async () => {
|
||||||
|
const fetchMock = jest.spyOn(globalThis, 'fetch').mockResolvedValue(
|
||||||
|
new Response(JSON.stringify({ tag_name: 'v2.99.0' }), {
|
||||||
|
status: 200,
|
||||||
|
statusText: 'OK'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
await getDownloadUrl('latest')
|
||||||
|
|
||||||
|
expect(fetchMock).toHaveBeenCalledWith(
|
||||||
|
'https://api.github.com/repos/supabase/cli/releases/latest',
|
||||||
|
expect.objectContaining({
|
||||||
|
headers: expect.not.objectContaining({
|
||||||
|
Authorization: expect.any(String)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('gets versioned archive url to binary from Supabase CLI v2.99.0', async () => {
|
||||||
|
const archive = await getDownloadArchive('2.99.0', 'linux', 'x64')
|
||||||
|
|
||||||
|
expect(archive).toEqual({
|
||||||
|
url: 'https://github.com/supabase/cli/releases/download/v2.99.0/supabase_2.99.0_linux_amd64.tar.gz',
|
||||||
|
format: 'tar'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('gets apk archive url on Linux musl from Supabase CLI v2.99.0', async () => {
|
||||||
|
const archive = await getDownloadArchive('2.99.0', 'linux', 'x64', true)
|
||||||
|
|
||||||
|
expect(archive).toEqual({
|
||||||
|
url: 'https://github.com/supabase/cli/releases/download/v2.99.0/supabase_2.99.0_linux_amd64.apk',
|
||||||
|
format: 'apk'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('keeps tar archives before Supabase CLI v2.99.0 on Linux musl', async () => {
|
||||||
|
const archive = await getDownloadArchive('2.98.2', 'linux', 'x64', true)
|
||||||
|
|
||||||
|
expect(archive).toEqual({
|
||||||
|
url: 'https://github.com/supabase/cli/releases/download/v2.98.2/supabase_linux_amd64.tar.gz',
|
||||||
|
format: 'tar'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('uses usr/bin as the CLI path for apk archives', () => {
|
||||||
|
expect(getCliPath('/tmp/extracted', 'apk')).toBe('/tmp/extracted/usr/bin')
|
||||||
|
expect(getCliPath('/tmp/extracted', 'tar')).toBe('/tmp/extracted')
|
||||||
|
expect(getCliPath('/tmp/extracted', 'zip')).toBe('/tmp/extracted')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('gets versioned zip archive url on Windows from Supabase CLI v2.99.0', async () => {
|
||||||
|
const archive = await getDownloadArchive('2.99.0', 'win32', 'x64')
|
||||||
|
|
||||||
|
expect(archive).toEqual({
|
||||||
|
url: 'https://github.com/supabase/cli/releases/download/v2.99.0/supabase_2.99.0_windows_amd64.zip',
|
||||||
|
format: 'zip'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('keeps unversioned archive url to binary before Supabase CLI v2.99.0', async () => {
|
||||||
|
const url = await getDownloadUrl('2.98.2')
|
||||||
|
|
||||||
|
expect(url).toContain('/download/v2.98.2/supabase_')
|
||||||
|
expect(url).not.toContain('supabase_2.98.2_')
|
||||||
|
expect(url).toMatch(/\.tar\.gz$/)
|
||||||
|
})
|
||||||
|
|
||||||
|
// shows how the runner will run a javascript action with env / stdout protocol
|
||||||
|
test('runs main action', () => {
|
||||||
|
const { env, execPath } = process
|
||||||
|
const repo = path.dirname(path.dirname(url.fileURLToPath(import.meta.url)))
|
||||||
|
const config = path.join(repo, 'action.yml')
|
||||||
|
const action = yaml.load(fs.readFileSync(config, 'utf8')) as {
|
||||||
|
inputs: { version: { default: string } }
|
||||||
|
}
|
||||||
|
const ip = path.join(repo, 'dist', 'index.js')
|
||||||
|
const stdout = cp
|
||||||
|
.execFileSync(execPath, [ip], {
|
||||||
|
env: {
|
||||||
|
...env,
|
||||||
|
RUNNER_TEMP: os.tmpdir(),
|
||||||
|
INPUT_VERSION: action.inputs.version.default
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.toString()
|
||||||
|
expect
|
||||||
|
.stringContaining(`::set-env name=${CLI_CONFIG_REGISTRY}::`)
|
||||||
|
.asymmetricMatch(stdout)
|
||||||
|
})
|
||||||
116
action.yml
116
action.yml
@@ -3,115 +3,17 @@ description: Setup Supabase CLI, supabase, on GitHub Actions runners
|
|||||||
author: Supabase
|
author: Supabase
|
||||||
inputs:
|
inputs:
|
||||||
version:
|
version:
|
||||||
description: Supabase CLI version to install. Supports latest, beta, or a fixed version published to npm. If omitted, detect from the root lockfile and otherwise use latest.
|
description: Version of Supabase CLI to install
|
||||||
|
required: false
|
||||||
|
default: 2.20.3
|
||||||
|
github-token:
|
||||||
|
description:
|
||||||
|
GitHub token used to resolve the latest Supabase CLI release without
|
||||||
|
hitting unauthenticated API limits.
|
||||||
required: false
|
required: false
|
||||||
outputs:
|
outputs:
|
||||||
version:
|
version:
|
||||||
description: Version of installed Supabase CLI
|
description: Version of installed Supabase CLI
|
||||||
value: ${{ steps.setup-cli.outputs.version }}
|
|
||||||
runs:
|
runs:
|
||||||
using: composite
|
using: node20
|
||||||
steps:
|
main: dist/index.js
|
||||||
- id: bun-download
|
|
||||||
name: Resolve Bun Download URL
|
|
||||||
shell: sh
|
|
||||||
working-directory: ${{ github.action_path }}
|
|
||||||
run: |
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
if [ "${RUNNER_OS}" != "Linux" ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# setup-bun does not detect Linux musl yet, so Alpine-like containers need the musl asset explicitly.
|
|
||||||
is_musl=false
|
|
||||||
if [ -f /etc/alpine-release ]; then
|
|
||||||
is_musl=true
|
|
||||||
elif command -v ldd >/dev/null 2>&1 && ldd --version 2>&1 | grep -qi musl; then
|
|
||||||
is_musl=true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${is_musl}" != "true" ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
version="$(cat .bun-version)"
|
|
||||||
case "$(uname -m)" in
|
|
||||||
x86_64) arch="x64" ;;
|
|
||||||
aarch64|arm64) arch="aarch64" ;;
|
|
||||||
*)
|
|
||||||
echo "Unsupported Linux musl architecture: $(uname -m)" >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo "url=https://github.com/oven-sh/bun/releases/download/bun-v${version}/bun-linux-${arch}-musl.zip" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Install Alpine Runtime Dependencies
|
|
||||||
shell: sh
|
|
||||||
run: |
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
if [ "${RUNNER_OS}" != "Linux" ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
is_musl=false
|
|
||||||
if [ -f /etc/alpine-release ]; then
|
|
||||||
is_musl=true
|
|
||||||
elif command -v ldd >/dev/null 2>&1 && ldd --version 2>&1 | grep -qi musl; then
|
|
||||||
is_musl=true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${is_musl}" != "true" ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Bun's musl binary and the Supabase CLI shim both dynamically link libstdc++ and libgcc.
|
|
||||||
if command -v apk >/dev/null 2>&1; then
|
|
||||||
missing_packages=""
|
|
||||||
for package in libstdc++ libgcc; do
|
|
||||||
if ! apk info -e "${package}" >/dev/null 2>&1; then
|
|
||||||
missing_packages="${missing_packages} ${package}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -z "${missing_packages}" ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$(id -u)" != "0" ]; then
|
|
||||||
echo "::error::Alpine/musl containers need${missing_packages} to run Supabase CLI. Add 'apk add --no-cache${missing_packages}' before supabase/setup-cli, or run this job container as root."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
apk add --no-cache ${missing_packages}
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "::error::Linux musl containers need libstdc++ and libgcc to run Supabase CLI. Install them before supabase/setup-cli."
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
- name: Setup Node
|
|
||||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
||||||
with:
|
|
||||||
node-version: 24
|
|
||||||
|
|
||||||
- name: Setup Bun
|
|
||||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
|
||||||
with:
|
|
||||||
bun-version-file: ${{ github.action_path }}/.bun-version
|
|
||||||
bun-download-url: ${{ steps.bun-download.outputs.url }}
|
|
||||||
|
|
||||||
- name: Install Action Dependencies
|
|
||||||
shell: sh
|
|
||||||
working-directory: ${{ github.action_path }}
|
|
||||||
run: bun install --frozen-lockfile --production
|
|
||||||
|
|
||||||
- id: setup-cli
|
|
||||||
name: Setup Supabase CLI
|
|
||||||
shell: sh
|
|
||||||
working-directory: ${{ github.action_path }}
|
|
||||||
env:
|
|
||||||
INPUT_VERSION: ${{ inputs.version }}
|
|
||||||
run: bun src/main.ts
|
|
||||||
|
|||||||
1
badges/coverage.svg
Normal file
1
badges/coverage.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<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>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
155
bun.lock
155
bun.lock
@@ -1,155 +0,0 @@
|
|||||||
{
|
|
||||||
"lockfileVersion": 1,
|
|
||||||
"configVersion": 1,
|
|
||||||
"workspaces": {
|
|
||||||
"": {
|
|
||||||
"name": "setup-cli",
|
|
||||||
"dependencies": {
|
|
||||||
"@actions/core": "^3.0.1",
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@tsconfig/bun": "^1.0.10",
|
|
||||||
"@types/bun": "^1.3.14",
|
|
||||||
"@typescript/native-preview": "^7.0.0-dev.20260410.1",
|
|
||||||
"oxfmt": "^0.49.0",
|
|
||||||
"oxlint": "^1.64.0",
|
|
||||||
"oxlint-tsgolint": "^0.22.1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"packages": {
|
|
||||||
"@actions/core": ["@actions/core@3.0.1", "", { "dependencies": { "@actions/exec": "^3.0.0", "@actions/http-client": "^4.0.0" } }, "sha512-a6d/Nwahm9fliVGRhdhofo40HjHQasUPusmc7vBfyky+7Z+P2A1J68zyFVaNcEclc/Se+eO595oAr5nwEIoIUA=="],
|
|
||||||
|
|
||||||
"@actions/exec": ["@actions/exec@3.0.0", "", { "dependencies": { "@actions/io": "^3.0.2" } }, "sha512-6xH/puSoNBXb72VPlZVm7vQ+svQpFyA96qdDBvhB8eNZOE8LtPf9L4oAsfzK/crCL8YZ+19fKYVnM63Sl+Xzlw=="],
|
|
||||||
|
|
||||||
"@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=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.49.0", "", { "os": "android", "cpu": "arm" }, "sha512-HbifJ84prIh9+55CTPAU35JdRQrwg47y16cGerCC+iejSKOuHXYo2WDql6l7cQlzrYVtc3f4UWY+dBj2lRmOeA=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.49.0", "", { "os": "android", "cpu": "arm64" }, "sha512-Ef7SKJqAaH2d7E6eXZZa2OffIShbhFMxnGK0zd93p4qiyTJr75B0qf7lrPD+qQOwcf04BrjYJ0JUxq8d5+yZwg=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.49.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-8x5DN9CsFfb432sHa9NyqX5XisGUdA53LPEGSdv/VniS+v4uEOR8Orv7A9QSB98Xxgp0t6r31DzQA/wpIobGqQ=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.49.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-e0+DSVzk4ewhMVKNYDaRTmP81jNMBWR1X9al0cVKWS+hDM/dElNqD5zjTOCuLOZc4oOdp2Gx2ldrVL+yYo9TZQ=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.49.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-W+mjtYtrQvFbXT/uNT+221OBhGRZ8UqNsLxjTWsjZ4GsQnRdvRC/N2NCK86BcamWr7lsTxwpwN3PULnr78sgcQ=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.49.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Rtv6UevV7czDlLqil+NZUe4d8gs8jQo/zScSpumwyf7I+fSdLc+hc8AF3MQC7ymxSMMD9+vfiqQlsIf7wOAzXA=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/binding-linux-arm-musleabihf@0.49.0", "", { "os": "linux", "cpu": "arm" }, "sha512-sBi+8C/Q/MdKa5FL8ibAUCdhFBGFH7HFN/Qoyd5xQbZ/0ky3NMPpKfIBpaH0lhK2dXkGLczVQUoZ+xuNSerCdQ=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.49.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-JIfWenFhlzx+O8YygyZhoHFzTsdgDhxhbDRnE2iJLnnM5pWKScFvPECO2vOlA7JqJ/9S1g3uzEKuRCkHFwTjvA=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.49.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-iNzkMPG18jPkwBOZ4/HEjwqfzAjq4RrUQ0CgId/fC1ENvYD5jLVAaU/gWgpiqP1ys07kxSsSggDd1fp3E7mQHw=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.49.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-BPHA/NN3LvoIXiid+iz3BHt5V0Rzx0tXAqRUovwE1NsbDaLG9e8mtv7evDGRIkVQacqTDBv0XL25THHsxSJosQ=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.49.0", "", { "os": "linux", "cpu": "none" }, "sha512-3Eroshe+s69htC9JIL0+zLGQczLtRKezkMhwqQC21VC5Z/fuLvzLfbAOLgJLUq601H8gDYjy7deYycfOBjCvWg=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.49.0", "", { "os": "linux", "cpu": "none" }, "sha512-fnaERGgsxGm0lKAmO72EYR4BA3qBnzBTJBTi6EtUMq1D4R7EexRBMU4voXnx4TXla3SEDl9x4uNp/18SbkPjGg=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.49.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-rBwasMl1Uul1MCCeTGEFKnOTL7VUxHf+634jWStrQAbzpBJgd5Yz5m4F7exVCsoI8PHn57dNjssXagXLCLB5yA=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.49.0", "", { "os": "linux", "cpu": "x64" }, "sha512-BoC/F9xHe2y/deuBGA5Aw7bes07OD2gcL2wlpzTrfImR92vPP7S/k3LBTyspQZCNIVNdagkELcqKELwMLGIfAg=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.49.0", "", { "os": "linux", "cpu": "x64" }, "sha512-umY6jFADAo/oztFKl8D/S6vSrG6oBpEskcentiRuz42kZVU2kfDXMWCYavxyZR2bwPjqkHpcHZ6EZFiH3Qj9ZA=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.49.0", "", { "os": "none", "cpu": "arm64" }, "sha512-J85zQMiw2pXiGPK+OusmDvSnJ/dgpgN7VgmB2zOBtgS8F+nsOUfSg9ZEBrwbQscjZ7tkPbm38CG4VF5f53MsiA=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.49.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-38K67XR++CoFFORDd4sMFwUVAnD6msYBdGTei+qvKGrRPO6S2PbrYPNL/eQQ1RgnnxOegNba0YQwg6uRkNcw6A=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.49.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-rXVe0HICwQF0dBgbQtBCoYf8x/SidPIdhyQl+iPuJlV7suV+qDv7yUEB3wQ4qC3nOeNxz287SwFXKzyr0kWgEg=="],
|
|
||||||
|
|
||||||
"@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.49.0", "", { "os": "win32", "cpu": "x64" }, "sha512-gwWLwSEmBBfIK/Wh7GGd658161o4RKAvHWRaRQbJm571iQXGKfyr7UKsI1vsWvDlNLc30CxJDc8mMmCvJ/kczQ=="],
|
|
||||||
|
|
||||||
"@oxlint-tsgolint/darwin-arm64": ["@oxlint-tsgolint/darwin-arm64@0.22.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4150Lpgc1YM09GcjA6GSrra1JoPjC7aOpfywLjWEY4vW0Sd1qKzqHF1WRaiw0/qUZ40OATYdv3aRd7ipPkWQbw=="],
|
|
||||||
|
|
||||||
"@oxlint-tsgolint/darwin-x64": ["@oxlint-tsgolint/darwin-x64@0.22.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-vFWcPWYOgZs4HWcgS1EjUZg33NLcNfEYU49KGImmCfZWkflENrmBYV4HN/C0YeAPum6ZZ/goPSvQrB/cOD+NfA=="],
|
|
||||||
|
|
||||||
"@oxlint-tsgolint/linux-arm64": ["@oxlint-tsgolint/linux-arm64@0.22.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-6LiUpP0Zir3+29FvBm7Y28q/dBjSHqTZ5MhG1Ckw4fGhI4cAvbcwXaKvbjx1TP7rRmBNOoq/M5xdpHjTb+GAew=="],
|
|
||||||
|
|
||||||
"@oxlint-tsgolint/linux-x64": ["@oxlint-tsgolint/linux-x64@0.22.1", "", { "os": "linux", "cpu": "x64" }, "sha512-fuX1hEQfpHauUbXADsfqVhRzrUrGabzGXbj5wsp2vKhV5uk/Rze8Mba9GdjFGECzvXudMGqHqxB4r6jGRdhxVA=="],
|
|
||||||
|
|
||||||
"@oxlint-tsgolint/win32-arm64": ["@oxlint-tsgolint/win32-arm64@0.22.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SZidAj+jrbZf9ZjBEYW0tiNZ+KasqB2zgW26qdiPpQSF/DzURnPmXz651IeA9YsmbVdHGIooEHUmev6QJdquA=="],
|
|
||||||
|
|
||||||
"@oxlint-tsgolint/win32-x64": ["@oxlint-tsgolint/win32-x64@0.22.1", "", { "os": "win32", "cpu": "x64" }, "sha512-QweSk9H5lFh5Y+WUf2Kq/OAN88V6+62ZwGhP38gqdRotI90luXSMkruFTj7Q2rYrzH4ZVNaSqx7NY8JpSfIzqg=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.64.0", "", { "os": "android", "cpu": "arm" }, "sha512-2r6Nq3XXGLHEXKkSj8JtmJ6N4gDw431DPFOg0ZoJHlNjnG6HVMm/ksQ10m0HJ8WBvwgMe1L50UHPaYZutCRPCw=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.64.0", "", { "os": "android", "cpu": "arm64" }, "sha512-ePJMpePgg7fBv+L/hVx1xXRU5/5gd5m0obLA6hPEfLXF3GjpR8idIDbY1dhQYhyz1ms2wdTccSboo6KEd2Oxtg=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.64.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-U4DMLQd10gJLuoSTLSGbfv3bGjTlUNsScm9Dgb8wwBqmCzidf1pE1pXV4doGNxqwH3KtVng1AGTINA0NvkGLvQ=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.64.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-GoRIL48QWm4/TAvjN8pB1nAG+1/uqc9EdnWT9zqHeb6wsmjZtywj8VRe5aGW47Fdb64YtLOsdLqVxOvQuz98Wg=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.64.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-5dFkv4tkg7PxJJGS9/OjrJwjhuHczrd3OQOkRE0wHcLM+ncUnULtzEPWjqGOxTXxZnLWcB91bGiIznx89TVXyQ=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.64.0", "", { "os": "linux", "cpu": "arm" }, "sha512-jsBqMLl/uOL5+Kq/+BtK9FrmiNGUbx8SiyZXv+WlUxA45KuwcLu9BfiSIL3I3DBDgWM3yZizDITnTK9BcqNBQg=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.64.0", "", { "os": "linux", "cpu": "arm" }, "sha512-1lrj8At/Uuc9GhjrVFBQo0NEjfBrTkzpmtHIGAhNnIXqn1CAyGL+qrztUsXb2GIluJrpl9Q7qRLJOb/NqydacQ=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.64.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-HpSQbubwh03mMhAdy2BYtad/fsY8vDFHDAb6bUwuCYg2VD3xCQgn6ArKcO0oZyLCheacKTv4PrF3Mfu5hgoE2g=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.64.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-00QQ0h0Y7u0G69BgiH3+ky2aaq/QvkDL6DYok8htIuJHxybiux5aQ8jwmg8qIk9wha6UagUP2BAwAzbemcJbpg=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.64.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-2GaimTV6EMW+s5HS0An3oGbQme3BgHswvfVdGk3EB57Xe9+/gyT+Qd7lNVzb3rtir52vbIPzXfaYArzs5b5zcw=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.64.0", "", { "os": "linux", "cpu": "none" }, "sha512-H46AtFb9wypjoVwGdlxrm0DsD809NGmtiK9HiyPKTxkSte2YjhC4S+00rOIrwCaxcyPiGid3Y3OMXp5KMAkGZw=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.64.0", "", { "os": "linux", "cpu": "none" }, "sha512-HEgsidjjvvyzdg82icYkuFCf7REDV7B9JFwbIMbVwrKLBY0MrXX+bku3POn/hduZ2yW91IyVDUMq0Bf02KwXQw=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.64.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-Axvm8qryotmKN00P5w4JapaSjvP2LOSbdbBJiX+2SuHd3QzhW7TUc8skqgw+ahQZ5DmzEYeHCqauvW8f32Ns6Q=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.64.0", "", { "os": "linux", "cpu": "x64" }, "sha512-cR60vSd7+m+KRZ3GQGfDxWwahW5RMXg0qlGvAluZr0fTUYvw0H9N9AXAF/M/PMqgytyqvVNmBAkJG9l7U30Y1g=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.64.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2u/aPZ9pEg7HnvZPDsHxUGNnrpr4qaHi+mCgLgpt+LYRzPrS4Px4wPfkIdRdr2GvKnaYyt+XSlto0Vm5sbStTg=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.64.0", "", { "os": "none", "cpu": "arm64" }, "sha512-kfhkGfCdoXLSxEkrhDlJrvBYajGmq+ma4EMc53dsOWTq+rIBOlI0vTBmpZNnM5oH2LY/K/w1HAK+UQEgjgpVUg=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.64.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-r/cNKBFieONoVu2bb1KkVouq9W+edDUgHumXJGphCRRj+U0xaD4nanrw8ZOqo0IsutPkEM4vCcGBpak6x5aXMg=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.64.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-tUw0xUUwEFVZbpJoeCblkv8SJA4Xz3CdXCJbAnBsiNLyxDrk2tLcxEAS6M73Q7hHHDg3OtwI8vZVK3t5RJt4Gw=="],
|
|
||||||
|
|
||||||
"@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.64.0", "", { "os": "win32", "cpu": "x64" }, "sha512-9CBR+LO0JVST87fNTzzNxS5I29jIUO5gxT9i9+M3SDHHALElj9sY1Prf12tad3vIRC6OD7Ehtvvh+sn13vSwHw=="],
|
|
||||||
|
|
||||||
"@tsconfig/bun": ["@tsconfig/bun@1.0.10", "", {}, "sha512-5AV5YknQjNyoYzZ/8NG0dawqew/wH+x7ANiCfCIn29qo0cdbd1EryvFD1k5NSZWLBMOI/fGqMIaxi58GPIP9Cg=="],
|
|
||||||
|
|
||||||
"@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="],
|
|
||||||
|
|
||||||
"@types/node": ["@types/node@20.19.37", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw=="],
|
|
||||||
|
|
||||||
"@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20260410.1", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260410.1", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260410.1", "@typescript/native-preview-linux-arm": "7.0.0-dev.20260410.1", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260410.1", "@typescript/native-preview-linux-x64": "7.0.0-dev.20260410.1", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260410.1", "@typescript/native-preview-win32-x64": "7.0.0-dev.20260410.1" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-K3TIwBw4XGQM33wW8KUqRU7r6ZY1IqB8chk1u1kT+CDj4iu+eQ6jCXgU7EDxmpJ++gbNcIf8iBYgWgYNssrhZQ=="],
|
|
||||||
|
|
||||||
"@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260410.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bpLYm6woXd8BECzV9AQvPqISVeohpekK1qwpRopvNIxydhRQ4fEjZsS7EtDYpqHAW4/u1uEv07P9/iS6TAL1fQ=="],
|
|
||||||
|
|
||||||
"@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20260410.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-V8bW8g5hgu+bAwGvTqF1kilkkoDgxhxi5egrdMUeWQkR+MIisoBQeaAupqMpLoSkqZsc/kKucM0zwBNC/KRU3Q=="],
|
|
||||||
|
|
||||||
"@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20260410.1", "", { "os": "linux", "cpu": "arm" }, "sha512-NO6Ci65ADadOCr2ycTxOyCgC5kyk+Ryjl8k5c78mz9sKDxYqwEtryFFjLqitAG+rejtJbnUq897WRICjAOwslA=="],
|
|
||||||
|
|
||||||
"@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20260410.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-MOluRRAhv46s9ScFmePa0InMHmpZ/z0Evc11RrTKsg+bN8BR7sWoAtFq6IujEDK9WVP7YmEYtBRgEfMLuqVojw=="],
|
|
||||||
|
|
||||||
"@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20260410.1", "", { "os": "linux", "cpu": "x64" }, "sha512-IofIUrMGjXmZKDEMaRgshzOne0EQZtx9vE/6URHfgmDnWLDKWzz9eQ2qWmvsFD2vOBbgc6GwVWEq6XTHMEfx2A=="],
|
|
||||||
|
|
||||||
"@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20260410.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-TXmE+wovQqRo+qAhaewB0MPB9esgayvSHr6vFlCpHykHqbDl3FUucuC4F8yU6zVOA3UqXTk4/GHeLsAvU7YEgQ=="],
|
|
||||||
|
|
||||||
"@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20260410.1", "", { "os": "win32", "cpu": "x64" }, "sha512-dMFT4tdHBe2vVA2WPQMjorT+fzCURRtillevQzz8/bwCEz2uXSnpu4oLRLS5045ppGE0wCFELE+Hq5z2oRddDw=="],
|
|
||||||
|
|
||||||
"bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
|
|
||||||
|
|
||||||
"oxfmt": ["oxfmt@0.49.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.49.0", "@oxfmt/binding-android-arm64": "0.49.0", "@oxfmt/binding-darwin-arm64": "0.49.0", "@oxfmt/binding-darwin-x64": "0.49.0", "@oxfmt/binding-freebsd-x64": "0.49.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.49.0", "@oxfmt/binding-linux-arm-musleabihf": "0.49.0", "@oxfmt/binding-linux-arm64-gnu": "0.49.0", "@oxfmt/binding-linux-arm64-musl": "0.49.0", "@oxfmt/binding-linux-ppc64-gnu": "0.49.0", "@oxfmt/binding-linux-riscv64-gnu": "0.49.0", "@oxfmt/binding-linux-riscv64-musl": "0.49.0", "@oxfmt/binding-linux-s390x-gnu": "0.49.0", "@oxfmt/binding-linux-x64-gnu": "0.49.0", "@oxfmt/binding-linux-x64-musl": "0.49.0", "@oxfmt/binding-openharmony-arm64": "0.49.0", "@oxfmt/binding-win32-arm64-msvc": "0.49.0", "@oxfmt/binding-win32-ia32-msvc": "0.49.0", "@oxfmt/binding-win32-x64-msvc": "0.49.0" }, "peerDependencies": { "svelte": "^5.0.0" }, "optionalPeers": ["svelte"], "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-IAHFMdlJSWe+oAr65dx22UvjCtV9DBMisAuLnKpDqMQrctzCkGnj3QRwNHm0d+uwSWPalsDF8ZYLz9rh6nH2IQ=="],
|
|
||||||
|
|
||||||
"oxlint": ["oxlint@1.64.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.64.0", "@oxlint/binding-android-arm64": "1.64.0", "@oxlint/binding-darwin-arm64": "1.64.0", "@oxlint/binding-darwin-x64": "1.64.0", "@oxlint/binding-freebsd-x64": "1.64.0", "@oxlint/binding-linux-arm-gnueabihf": "1.64.0", "@oxlint/binding-linux-arm-musleabihf": "1.64.0", "@oxlint/binding-linux-arm64-gnu": "1.64.0", "@oxlint/binding-linux-arm64-musl": "1.64.0", "@oxlint/binding-linux-ppc64-gnu": "1.64.0", "@oxlint/binding-linux-riscv64-gnu": "1.64.0", "@oxlint/binding-linux-riscv64-musl": "1.64.0", "@oxlint/binding-linux-s390x-gnu": "1.64.0", "@oxlint/binding-linux-x64-gnu": "1.64.0", "@oxlint/binding-linux-x64-musl": "1.64.0", "@oxlint/binding-openharmony-arm64": "1.64.0", "@oxlint/binding-win32-arm64-msvc": "1.64.0", "@oxlint/binding-win32-ia32-msvc": "1.64.0", "@oxlint/binding-win32-x64-msvc": "1.64.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.22.1" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-Star3SNpWPeWFPw7kRXIhXUSn6fdiAl25q15CQzH/9WaOtG6e9CWTc25vNZOCr4PE1yEP1GtKJKIKglhj3OmEQ=="],
|
|
||||||
|
|
||||||
"oxlint-tsgolint": ["oxlint-tsgolint@0.22.1", "", { "optionalDependencies": { "@oxlint-tsgolint/darwin-arm64": "0.22.1", "@oxlint-tsgolint/darwin-x64": "0.22.1", "@oxlint-tsgolint/linux-arm64": "0.22.1", "@oxlint-tsgolint/linux-x64": "0.22.1", "@oxlint-tsgolint/win32-arm64": "0.22.1", "@oxlint-tsgolint/win32-x64": "0.22.1" }, "bin": { "tsgolint": "bin/tsgolint.js" } }, "sha512-YUSGSLUnoolsu8gxISEDio3q1rtsCozwfOzASUn3DT2mR2EeQ93uEEnen7s+6LpF+lyTQFln1pQfqwBh/fsVEg=="],
|
|
||||||
|
|
||||||
"tinypool": ["tinypool@2.1.0", "", {}, "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw=="],
|
|
||||||
|
|
||||||
"tunnel": ["tunnel@0.0.6", "", {}, "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="],
|
|
||||||
|
|
||||||
"undici": ["undici@6.24.1", "", {}, "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA=="],
|
|
||||||
|
|
||||||
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
60587
dist/index.js
generated
vendored
Normal file
60587
dist/index.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/index.js.map
generated
vendored
Normal file
1
dist/index.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1,55 +1,42 @@
|
|||||||
# `supabase/setup-cli`
|
# `supabase-github-action`
|
||||||
|
|
||||||
The Supabase CLI Action provides an easy way to install the
|
The Supabase GitHub Action provides an easy way to use the Supabase CLI on
|
||||||
[Supabase CLI](https://github.com/supabase/cli) on GitHub Actions runners.
|
GitHub's hosted Actions runners.
|
||||||
|
|
||||||
The action supports `ubuntu-latest`, `windows-latest`, and `macos-latest`, and
|
The action can be run on `ubuntu-latest`, `windows-latest`, and `macos-latest`
|
||||||
adds the requested `supabase` version to `PATH` for the rest of the job.
|
GitHub Actions runners, and will install and expose a specified version of the
|
||||||
|
Supabase CLI on the runner environment.
|
||||||
|
|
||||||
If `version` is omitted, the action checks the repository root for `bun.lock`,
|
## Quick start
|
||||||
`pnpm-lock.yaml`, or `package-lock.json` and otherwise falls back to npm
|
|
||||||
`latest`.
|
|
||||||
|
|
||||||
The action provisions Node.js and npm internally; runners only need network
|
This example shows how you can use the Supabase GitHub Action to test your
|
||||||
access to the npm registry.
|
migrations on every Pull Request.
|
||||||
|
|
||||||
## Quick Start
|
Inside your repository, create a new file inside the `.github/workflows` folder
|
||||||
|
called `test-migrations.yml`.
|
||||||
|
|
||||||
This example runs Supabase migrations on every pull request:
|
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:
|
||||||
test-migrations:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: supabase/setup-cli@v1
|
||||||
- uses: supabase/setup-cli@v3
|
with:
|
||||||
- run: supabase init
|
version: latest
|
||||||
- run: supabase db start
|
- run: supabase init
|
||||||
```
|
- run: supabase db start
|
||||||
|
|
||||||
To pin a fixed npm-published CLI version:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- uses: supabase/setup-cli@v3
|
|
||||||
with:
|
|
||||||
version: 2.84.2
|
|
||||||
```
|
|
||||||
|
|
||||||
To test the current beta release:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- uses: supabase/setup-cli@v3
|
|
||||||
with:
|
|
||||||
version: beta
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
|
|
||||||
- **Source Code**: <https://github.com/supabase/setup-cli>
|
- **Source Code**:
|
||||||
- **CLI Documentation**: <https://supabase.com/docs/guides/cli>
|
<a href="https://github.com/supabase/supabase-github-action" target="_blank">github.com/supabase/supabase-github-action</a>
|
||||||
|
- **CLI Documentation**:
|
||||||
|
<a href="https://supabase.com/docs/guides/cli" target="_blank">supabase.com/docs/guides/cli</a>
|
||||||
|
|||||||
81
eslint.config.mjs
Normal file
81
eslint.config.mjs
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
// 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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
40
jest.config.js
Normal file
40
jest.config.js
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// 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
|
||||||
|
}
|
||||||
13284
package-lock.json
generated
Normal file
13284
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
88
package.json
88
package.json
@@ -1,40 +1,72 @@
|
|||||||
{
|
{
|
||||||
"name": "setup-cli",
|
"name": "setup-cli",
|
||||||
"version": "3.0.0",
|
|
||||||
"private": true,
|
|
||||||
"description": "Supabase CLI GitHub Action",
|
"description": "Supabase CLI GitHub Action",
|
||||||
"keywords": [
|
"version": "1.6.0",
|
||||||
"actions"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"author": "",
|
"author": "",
|
||||||
|
"type": "module",
|
||||||
|
"private": true,
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/supabase/setup-cli.git"
|
"url": "git+https://github.com/supabase/setup-cli.git"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"keywords": [
|
||||||
"scripts": {
|
"actions"
|
||||||
"all": "bun run format && bun run lint && bun run coverage",
|
],
|
||||||
"ci": "bun run format:check && bun run lint && bun run coverage",
|
"exports": {
|
||||||
"coverage": "bun test --coverage --coverage-reporter=text --coverage-reporter=lcov",
|
".": "./dist/index.js"
|
||||||
"format": "bun x oxfmt --write . '!coverage/**'",
|
|
||||||
"format:check": "bun x oxfmt --check . '!coverage/**'",
|
|
||||||
"lint": "bun x oxlint --deny-warnings --type-aware --type-check --tsconfig tsconfig.json src",
|
|
||||||
"test": "bun test",
|
|
||||||
"typecheck": "bun x tsgo -p tsconfig.json --noEmit"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@actions/core": "^3.0.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@tsconfig/bun": "^1.0.10",
|
|
||||||
"@types/bun": "^1.3.14",
|
|
||||||
"@typescript/native-preview": "^7.0.0-dev.20260410.1",
|
|
||||||
"oxfmt": "^0.49.0",
|
|
||||||
"oxlint": "^1.64.0",
|
|
||||||
"oxlint-tsgolint": "^0.22.1"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"bun": ">=1.3.10"
|
"node": ">=20"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"bundle": "npm run format:write && npm run package",
|
||||||
|
"ci-test": "NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 npx jest",
|
||||||
|
"coverage": "npx make-coverage-badge --output-path ./badges/coverage.svg",
|
||||||
|
"format:write": "npx prettier --write .",
|
||||||
|
"format:check": "npx prettier --check .",
|
||||||
|
"lint": "npx eslint .",
|
||||||
|
"local-action": "npx @github/local-action . src/main.ts .env",
|
||||||
|
"package": "npx rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",
|
||||||
|
"package:watch": "npm run package -- --watch",
|
||||||
|
"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": {
|
||||||
|
"@actions/core": "^3.0.1",
|
||||||
|
"@actions/tool-cache": "^4.0.0",
|
||||||
|
"semver": "^7.7.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@eslint/compat": "^1.3.1",
|
||||||
|
"@github/local-action": "^5.1.0",
|
||||||
|
"@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/node": "^20.19.9",
|
||||||
|
"@types/semver": "^7.7.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
||||||
|
"@typescript-eslint/parser": "^8.38.0",
|
||||||
|
"eslint": "^9.31.0",
|
||||||
|
"eslint-config-prettier": "^10.1.8",
|
||||||
|
"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": {
|
||||||
|
"@rollup/rollup-linux-x64-gnu": "*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
rollup.config.ts
Normal file
18
rollup.config.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// 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
|
||||||
8
src/index.ts
Normal file
8
src/index.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* 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()
|
||||||
592
src/main.test.ts
592
src/main.test.ts
@@ -1,592 +0,0 @@
|
|||||||
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
||||||
import os from "node:os";
|
|
||||||
import path from "node:path";
|
|
||||||
import process from "node:process";
|
|
||||||
import { afterEach, expect, mock, spyOn, test } from "bun:test";
|
|
||||||
import * as core from "@actions/core";
|
|
||||||
|
|
||||||
const CLI_CONFIG_REGISTRY = "SUPABASE_INTERNAL_IMAGE_REGISTRY";
|
|
||||||
const originalPath = process.env.PATH;
|
|
||||||
const originalRunnerTemp = process.env.RUNNER_TEMP;
|
|
||||||
const originalWorkspace = process.env.GITHUB_WORKSPACE;
|
|
||||||
const tempDirs = new Set<string>();
|
|
||||||
let mainModule: typeof import("./main.ts") | null = null;
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
mock.restore();
|
|
||||||
process.env.PATH = originalPath;
|
|
||||||
process.env.RUNNER_TEMP = originalRunnerTemp;
|
|
||||||
process.env.GITHUB_WORKSPACE = originalWorkspace;
|
|
||||||
delete process.env.FAKE_CLI_VERSION;
|
|
||||||
delete process.env.FAKE_NPM_BIN;
|
|
||||||
delete process.env.FAKE_NPM_INTEGRITY;
|
|
||||||
delete process.env.FAKE_NPM_LOG;
|
|
||||||
delete process.env.FAKE_NPM_PACKAGE_VERSION;
|
|
||||||
delete process.env.FAKE_NPM_POSTINSTALL;
|
|
||||||
delete process.env.SUPABASE_SETUP_CLI_NPM;
|
|
||||||
|
|
||||||
for (const dir of tempDirs) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createWorkspace(files: Record<string, string>): string {
|
|
||||||
const dir = createTempDir("setup-cli-workspace-");
|
|
||||||
|
|
||||||
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;
|
|
||||||
integrity?: string;
|
|
||||||
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}",
|
|
||||||
"",
|
|
||||||
{},
|
|
||||||
"${options.integrity ?? "sha512-bun"}"
|
|
||||||
]`
|
|
||||||
: ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createPnpmLock(
|
|
||||||
version: string,
|
|
||||||
options: {
|
|
||||||
asString?: boolean;
|
|
||||||
includeVersion?: boolean;
|
|
||||||
integrity?: string;
|
|
||||||
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: ${options.integrity ?? "sha512-pnpm"}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createPackageLock(version: string, integrity = "sha512-package-lock"): string {
|
|
||||||
return JSON.stringify(
|
|
||||||
{
|
|
||||||
name: "app",
|
|
||||||
lockfileVersion: 3,
|
|
||||||
packages: {
|
|
||||||
"": {
|
|
||||||
dependencies: {
|
|
||||||
supabase: `^${version}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"node_modules/supabase": {
|
|
||||||
integrity,
|
|
||||||
version,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
2,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createFakeNpm(): string {
|
|
||||||
const root = createTempDir("setup-cli-fake-npm-");
|
|
||||||
const binDir = path.join(root, "bin");
|
|
||||||
const scriptPath = path.join(root, "fake-npm.js");
|
|
||||||
mkdirSync(binDir, { recursive: true });
|
|
||||||
writeFileSync(
|
|
||||||
scriptPath,
|
|
||||||
`import { appendFileSync, mkdirSync, writeFileSync } from "node:fs";
|
|
||||||
import path from "node:path";
|
|
||||||
|
|
||||||
const args = process.argv.slice(2);
|
|
||||||
appendFileSync(process.env.FAKE_NPM_LOG, JSON.stringify(args) + "\\n");
|
|
||||||
|
|
||||||
if (args[0] === "view") {
|
|
||||||
const bin =
|
|
||||||
process.env.FAKE_NPM_BIN === "missing"
|
|
||||||
? undefined
|
|
||||||
: { supabase: process.env.FAKE_NPM_BIN ?? "dist/supabase.js" };
|
|
||||||
const scripts = process.env.FAKE_NPM_POSTINSTALL
|
|
||||||
? { postinstall: process.env.FAKE_NPM_POSTINSTALL }
|
|
||||||
: {};
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
JSON.stringify({
|
|
||||||
version: process.env.FAKE_NPM_PACKAGE_VERSION ?? "2.101.0",
|
|
||||||
bin,
|
|
||||||
scripts,
|
|
||||||
"dist.integrity": process.env.FAKE_NPM_INTEGRITY ?? "sha512-test",
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args[0] !== "install") {
|
|
||||||
console.error("Unexpected npm command: " + args.join(" "));
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const prefixIndex = args.indexOf("--prefix");
|
|
||||||
const prefix = prefixIndex === -1 ? undefined : args[prefixIndex + 1];
|
|
||||||
if (!prefix) {
|
|
||||||
console.error("Missing --prefix");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const binDir = path.join(prefix, "node_modules", ".bin");
|
|
||||||
mkdirSync(binDir, { recursive: true });
|
|
||||||
|
|
||||||
if (process.platform === "win32") {
|
|
||||||
writeFileSync(
|
|
||||||
path.join(binDir, "supabase.cmd"),
|
|
||||||
process.env.FAKE_CLI_VERSION ? "@echo off\\r\\necho " + process.env.FAKE_CLI_VERSION + "\\r\\n" : "@echo off\\r\\n",
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
writeFileSync(
|
|
||||||
path.join(binDir, "supabase"),
|
|
||||||
process.env.FAKE_CLI_VERSION
|
|
||||||
? "#!/usr/bin/env bash\\nprintf '%s\\\\n' '" + process.env.FAKE_CLI_VERSION.replaceAll("'", "'\\\\''") + "'\\n"
|
|
||||||
: "#!/usr/bin/env bash\\n",
|
|
||||||
{ mode: 0o755 },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (process.platform === "win32") {
|
|
||||||
writeFileSync(
|
|
||||||
path.join(binDir, "npm.cmd"),
|
|
||||||
`@echo off\r\n"${process.execPath}" "${scriptPath}" %*\r\n`,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
writeFileSync(
|
|
||||||
path.join(binDir, "npm"),
|
|
||||||
`#!/usr/bin/env bash\nexec "${process.execPath}" "${scriptPath}" "$@"\n`,
|
|
||||||
{ mode: 0o755 },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return binDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
function installFakeNpm(
|
|
||||||
versionOutput = "supabase 2.101.0",
|
|
||||||
options: {
|
|
||||||
bin?: string;
|
|
||||||
integrity?: string;
|
|
||||||
packageVersion?: string;
|
|
||||||
postinstall?: string;
|
|
||||||
} = {},
|
|
||||||
): string {
|
|
||||||
const binDir = createFakeNpm();
|
|
||||||
const logPath = path.join(createTempDir("setup-cli-fake-npm-log-"), "npm.log");
|
|
||||||
writeFileSync(logPath, "");
|
|
||||||
process.env.FAKE_CLI_VERSION = versionOutput;
|
|
||||||
process.env.FAKE_NPM_BIN = options.bin ?? "dist/supabase.js";
|
|
||||||
process.env.FAKE_NPM_INTEGRITY = options.integrity ?? "sha512-test";
|
|
||||||
process.env.FAKE_NPM_LOG = logPath;
|
|
||||||
process.env.FAKE_NPM_PACKAGE_VERSION =
|
|
||||||
options.packageVersion ??
|
|
||||||
versionOutput.match(/\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/)?.[0] ??
|
|
||||||
"2.101.0";
|
|
||||||
if (options.postinstall) {
|
|
||||||
process.env.FAKE_NPM_POSTINSTALL = options.postinstall;
|
|
||||||
}
|
|
||||||
process.env.PATH = `${binDir}${path.delimiter}${originalPath ?? ""}`;
|
|
||||||
process.env.RUNNER_TEMP = createTempDir("setup-cli-runner-temp-");
|
|
||||||
process.env.SUPABASE_SETUP_CLI_NPM = path.join(
|
|
||||||
binDir,
|
|
||||||
process.platform === "win32" ? "npm.cmd" : "npm",
|
|
||||||
);
|
|
||||||
|
|
||||||
return logPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
function readNpmCalls(logPath: string): string[][] {
|
|
||||||
return readFileSync(logPath, "utf8")
|
|
||||||
.trim()
|
|
||||||
.split("\n")
|
|
||||||
.filter(Boolean)
|
|
||||||
.map((line) => JSON.parse(line) as string[]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function viewMetadataCall(spec: string): string[] {
|
|
||||||
return ["view", spec, "version", "bin", "scripts", "dist.integrity", "--json"];
|
|
||||||
}
|
|
||||||
|
|
||||||
function createActionSpies(inputVersion: string) {
|
|
||||||
return {
|
|
||||||
addPath: spyOn(core, "addPath").mockImplementation(() => {}),
|
|
||||||
exportVariable: spyOn(core, "exportVariable").mockImplementation(() => {}),
|
|
||||||
getInput: spyOn(core, "getInput").mockReturnValue(inputVersion),
|
|
||||||
setFailed: spyOn(core, "setFailed").mockImplementation(() => {}),
|
|
||||||
setOutput: spyOn(core, "setOutput").mockImplementation(() => {}),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getMainModule(): Promise<typeof import("./main.ts")> {
|
|
||||||
if (!mainModule) {
|
|
||||||
mainModule = await import("./main.ts");
|
|
||||||
}
|
|
||||||
|
|
||||||
return mainModule;
|
|
||||||
}
|
|
||||||
|
|
||||||
test("uses an explicit npm package version when provided", async () => {
|
|
||||||
const { resolvePackage } = await getMainModule();
|
|
||||||
|
|
||||||
expect(resolvePackage("v2.101.0")).toEqual({
|
|
||||||
spec: "supabase@2.101.0",
|
|
||||||
version: "2.101.0",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("uses an explicit npm dist-tag when provided", async () => {
|
|
||||||
const { resolvePackage } = await getMainModule();
|
|
||||||
|
|
||||||
expect(resolvePackage("beta")).toEqual({
|
|
||||||
spec: "supabase@beta",
|
|
||||||
version: "beta",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("rejects unsupported npm package selectors", async () => {
|
|
||||||
const { resolvePackage } = await getMainModule();
|
|
||||||
|
|
||||||
expect(() => resolvePackage("hotfix")).toThrow(
|
|
||||||
'Unsupported Supabase CLI version "hotfix". Use latest, beta, or a fixed npm package version like 2.101.0.',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("uses the root bun.lock resolution when version is omitted", async () => {
|
|
||||||
process.env.GITHUB_WORKSPACE = createWorkspace({
|
|
||||||
"bun.lock": createBunLock("2.41.0", { integrity: "sha512-bun-lock" }),
|
|
||||||
});
|
|
||||||
const { resolvePackage } = await getMainModule();
|
|
||||||
|
|
||||||
expect(resolvePackage("")).toEqual({
|
|
||||||
integrity: "sha512-bun-lock",
|
|
||||||
spec: "supabase@2.41.0",
|
|
||||||
version: "2.41.0",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("uses the root pnpm-lock.yaml resolution when version is omitted", async () => {
|
|
||||||
process.env.GITHUB_WORKSPACE = createWorkspace({
|
|
||||||
"pnpm-lock.yaml": createPnpmLock("2.42.0", { integrity: "sha512-pnpm-lock" }),
|
|
||||||
});
|
|
||||||
const { resolvePackage } = await getMainModule();
|
|
||||||
|
|
||||||
expect(resolvePackage("")).toEqual({
|
|
||||||
integrity: "sha512-pnpm-lock",
|
|
||||||
spec: "supabase@2.42.0",
|
|
||||||
version: "2.42.0",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("uses the root package-lock.json resolution when version is omitted", async () => {
|
|
||||||
process.env.GITHUB_WORKSPACE = createWorkspace({
|
|
||||||
"package-lock.json": createPackageLock("2.43.0", "sha512-package-lock"),
|
|
||||||
});
|
|
||||||
const { resolvePackage } = await getMainModule();
|
|
||||||
|
|
||||||
expect(resolvePackage("")).toEqual({
|
|
||||||
integrity: "sha512-package-lock",
|
|
||||||
spec: "supabase@2.43.0",
|
|
||||||
version: "2.43.0",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
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 { resolvePackage } = await getMainModule();
|
|
||||||
|
|
||||||
expect(resolvePackage("")).toEqual({
|
|
||||||
integrity: "sha512-package-lock",
|
|
||||||
spec: "supabase@2.44.0",
|
|
||||||
version: "2.44.0",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
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 { resolvePackage } = await getMainModule();
|
|
||||||
|
|
||||||
expect(resolvePackage("")).toEqual({
|
|
||||||
spec: "supabase@latest",
|
|
||||||
version: "latest",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("falls back to latest when version is omitted and no workspace is available", async () => {
|
|
||||||
delete process.env.GITHUB_WORKSPACE;
|
|
||||||
const { resolvePackage } = await getMainModule();
|
|
||||||
|
|
||||||
expect(resolvePackage("")).toEqual({
|
|
||||||
spec: "supabase@latest",
|
|
||||||
version: "latest",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
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 { resolvePackage } = await getMainModule();
|
|
||||||
|
|
||||||
expect(resolvePackage("")).toEqual({
|
|
||||||
spec: "supabase@2.44.1",
|
|
||||||
version: "2.44.1",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
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 { resolvePackage } = await getMainModule();
|
|
||||||
|
|
||||||
expect(resolvePackage("")).toEqual({
|
|
||||||
integrity: "sha512-pnpm",
|
|
||||||
spec: "supabase@2.47.0",
|
|
||||||
version: "2.47.0",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
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 { resolvePackage } = await getMainModule();
|
|
||||||
|
|
||||||
expect(resolvePackage("")).toEqual({
|
|
||||||
spec: "supabase@latest",
|
|
||||||
version: "latest",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("installs the CLI with npm into an isolated prefix", async () => {
|
|
||||||
const logPath = installFakeNpm();
|
|
||||||
const { installCli } = await getMainModule();
|
|
||||||
|
|
||||||
const cliPath = await installCli({
|
|
||||||
spec: "supabase@2.101.0",
|
|
||||||
version: "2.101.0",
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(cliPath).toContain(`${path.sep}node_modules${path.sep}.bin`);
|
|
||||||
expect(readNpmCalls(logPath)).toEqual([
|
|
||||||
viewMetadataCall("supabase@2.101.0"),
|
|
||||||
[
|
|
||||||
"install",
|
|
||||||
"--prefix",
|
|
||||||
expect.any(String),
|
|
||||||
"--omit=dev",
|
|
||||||
"--include=optional",
|
|
||||||
"--no-audit",
|
|
||||||
"--no-fund",
|
|
||||||
"--no-package-lock",
|
|
||||||
"--ignore-scripts=true",
|
|
||||||
"supabase@2.101.0",
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("allows install scripts for legacy npm packages that declare a postinstall", async () => {
|
|
||||||
const logPath = installFakeNpm("supabase 1.178.2", {
|
|
||||||
bin: "bin/supabase",
|
|
||||||
postinstall: "node scripts/postinstall.js",
|
|
||||||
});
|
|
||||||
const { installCli } = await getMainModule();
|
|
||||||
|
|
||||||
await installCli({
|
|
||||||
spec: "supabase@1.178.2",
|
|
||||||
version: "1.178.2",
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(readNpmCalls(logPath)).toEqual([
|
|
||||||
viewMetadataCall("supabase@1.178.2"),
|
|
||||||
[
|
|
||||||
"install",
|
|
||||||
"--prefix",
|
|
||||||
expect.any(String),
|
|
||||||
"--omit=dev",
|
|
||||||
"--include=optional",
|
|
||||||
"--no-audit",
|
|
||||||
"--no-fund",
|
|
||||||
"--no-package-lock",
|
|
||||||
"--ignore-scripts=false",
|
|
||||||
"supabase@1.178.2",
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("verifies lockfile integrity before installing", async () => {
|
|
||||||
const logPath = installFakeNpm("supabase 2.101.0", { integrity: "sha512-lock" });
|
|
||||||
const { installCli } = await getMainModule();
|
|
||||||
|
|
||||||
await installCli({
|
|
||||||
integrity: "sha512-lock",
|
|
||||||
spec: "supabase@2.101.0",
|
|
||||||
version: "2.101.0",
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(readNpmCalls(logPath)).toEqual([
|
|
||||||
viewMetadataCall("supabase@2.101.0"),
|
|
||||||
[
|
|
||||||
"install",
|
|
||||||
"--prefix",
|
|
||||||
expect.any(String),
|
|
||||||
"--omit=dev",
|
|
||||||
"--include=optional",
|
|
||||||
"--no-audit",
|
|
||||||
"--no-fund",
|
|
||||||
"--no-package-lock",
|
|
||||||
"--ignore-scripts=true",
|
|
||||||
"supabase@2.101.0",
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("fails when lockfile integrity does not match the registry", async () => {
|
|
||||||
installFakeNpm("supabase 2.101.0", { integrity: "sha512-registry" });
|
|
||||||
const { installCli } = await getMainModule();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await installCli({
|
|
||||||
integrity: "sha512-lock",
|
|
||||||
spec: "supabase@2.101.0",
|
|
||||||
version: "2.101.0",
|
|
||||||
});
|
|
||||||
throw new Error("Expected installCli to reject");
|
|
||||||
} catch (error) {
|
|
||||||
expect(error).toEqual(
|
|
||||||
new Error("Lockfile integrity for supabase@2.101.0 does not match the npm registry"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test("fails when the npm package does not expose a Supabase CLI executable", async () => {
|
|
||||||
installFakeNpm("supabase 2.101.0", { bin: "missing" });
|
|
||||||
const { installCli } = await getMainModule();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await installCli({
|
|
||||||
spec: "supabase@2.101.0",
|
|
||||||
version: "2.101.0",
|
|
||||||
});
|
|
||||||
throw new Error("Expected installCli to reject");
|
|
||||||
} catch (error) {
|
|
||||||
expect(error).toEqual(
|
|
||||||
new Error("The npm package supabase@2.101.0 does not expose a supabase executable"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test("runs the action with a package-lock resolution", async () => {
|
|
||||||
const logPath = installFakeNpm("supabase 2.43.0", { integrity: "sha512-package-lock" });
|
|
||||||
process.env.GITHUB_WORKSPACE = createWorkspace({
|
|
||||||
"package-lock.json": createPackageLock("2.43.0", "sha512-package-lock"),
|
|
||||||
});
|
|
||||||
const spies = createActionSpies("");
|
|
||||||
const { run } = await getMainModule();
|
|
||||||
|
|
||||||
await run();
|
|
||||||
|
|
||||||
expect(readNpmCalls(logPath)[0]).toEqual(viewMetadataCall("supabase@2.43.0"));
|
|
||||||
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 2.43.0");
|
|
||||||
expect(spies.addPath).toHaveBeenCalledWith(expect.stringContaining("node_modules"));
|
|
||||||
expect(spies.exportVariable).toHaveBeenCalledWith(CLI_CONFIG_REGISTRY, "ghcr.io");
|
|
||||||
expect(spies.setFailed).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("explicit version overrides detected root lockfiles", async () => {
|
|
||||||
installFakeNpm("supabase 1.1.6");
|
|
||||||
process.env.GITHUB_WORKSPACE = createWorkspace({
|
|
||||||
"bun.lock": createBunLock("2.45.0"),
|
|
||||||
});
|
|
||||||
const spies = createActionSpies("1.1.6");
|
|
||||||
const { run } = await getMainModule();
|
|
||||||
|
|
||||||
await run();
|
|
||||||
|
|
||||||
expect(spies.setOutput).toHaveBeenCalledWith("version", "supabase 1.1.6");
|
|
||||||
expect(spies.exportVariable).not.toHaveBeenCalled();
|
|
||||||
expect(spies.setFailed).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("fails when the installed CLI does not report a version", async () => {
|
|
||||||
installFakeNpm("");
|
|
||||||
process.env.GITHUB_WORKSPACE = createWorkspace({
|
|
||||||
"package-lock.json": createPackageLock("2.46.0", "sha512-test"),
|
|
||||||
});
|
|
||||||
const spies = createActionSpies("");
|
|
||||||
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();
|
|
||||||
});
|
|
||||||
439
src/main.ts
439
src/main.ts
@@ -1,399 +1,54 @@
|
|||||||
import { semver } from "bun";
|
import * as core from '@actions/core'
|
||||||
import * as core from "@actions/core";
|
import * as tc from '@actions/tool-cache'
|
||||||
import { existsSync, mkdtempSync, readFileSync } from "node:fs";
|
import { gte } from 'semver'
|
||||||
import os from "node:os";
|
import {
|
||||||
import path from "node:path";
|
getDownloadArchive,
|
||||||
import { fileURLToPath } from "node:url";
|
determineInstalledVersion,
|
||||||
|
getCliPath
|
||||||
export const CLI_CONFIG_REGISTRY = "SUPABASE_INTERNAL_IMAGE_REGISTRY";
|
} from './utils.js'
|
||||||
const REGISTRY_VERSION = "1.28.0";
|
|
||||||
const DEFAULT_VERSION = "latest";
|
export const CLI_CONFIG_REGISTRY = 'SUPABASE_INTERNAL_IMAGE_REGISTRY'
|
||||||
const NPM_PACKAGE = "supabase";
|
|
||||||
const NPM_EXECUTABLE_ENV = "SUPABASE_SETUP_CLI_NPM";
|
/**
|
||||||
const SUPPORTED_DIST_TAGS = new Set([DEFAULT_VERSION, "beta"]);
|
* The main function for the action.
|
||||||
const CONCRETE_VERSION_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
*
|
||||||
const CONCRETE_VERSION_EXTRACT_PATTERN = /\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?/;
|
* @returns Resolves when the action is complete.
|
||||||
|
*/
|
||||||
type PackageResolution = {
|
|
||||||
spec: string;
|
|
||||||
version: string;
|
|
||||||
integrity?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type PackageMetadata = {
|
|
||||||
version?: unknown;
|
|
||||||
bin?: unknown;
|
|
||||||
scripts?: unknown;
|
|
||||||
"dist.integrity"?: unknown;
|
|
||||||
};
|
|
||||||
|
|
||||||
type BunLock = {
|
|
||||||
workspaces?: {
|
|
||||||
"": {
|
|
||||||
dependencies?: Record<string, string>;
|
|
||||||
devDependencies?: Record<string, string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
packages?: Record<string, unknown>;
|
|
||||||
};
|
|
||||||
|
|
||||||
type PnpmDependency =
|
|
||||||
| string
|
|
||||||
| {
|
|
||||||
version?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type PnpmPackage = {
|
|
||||||
resolution?: {
|
|
||||||
integrity?: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
type PnpmLock = {
|
|
||||||
importers?: {
|
|
||||||
".": {
|
|
||||||
dependencies?: Record<string, PnpmDependency>;
|
|
||||||
devDependencies?: Record<string, PnpmDependency>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
packages?: Record<string, PnpmPackage>;
|
|
||||||
};
|
|
||||||
|
|
||||||
type PackageLock = {
|
|
||||||
packages?: Record<string, { integrity?: string; version?: string }>;
|
|
||||||
dependencies?: Record<string, { integrity?: string; version?: string }>;
|
|
||||||
};
|
|
||||||
|
|
||||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
||||||
return typeof value === "object" && value !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractConcreteVersion(raw: string | undefined): string | null {
|
|
||||||
if (!raw) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const match = raw.match(CONCRETE_VERSION_EXTRACT_PATTERN);
|
|
||||||
return match?.[0] ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeVersion(version: string): string {
|
|
||||||
return version.replace(/^v/i, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeSupportedVersion(version: string): string {
|
|
||||||
const normalizedVersion = normalizeVersion(version.trim());
|
|
||||||
const distTag = normalizedVersion.toLowerCase();
|
|
||||||
|
|
||||||
if (SUPPORTED_DIST_TAGS.has(distTag)) {
|
|
||||||
return distTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CONCRETE_VERSION_PATTERN.test(normalizedVersion)) {
|
|
||||||
return normalizedVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(
|
|
||||||
`Unsupported Supabase CLI version "${version}". Use latest, beta, or a fixed npm package version like 2.101.0.`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function toPackageResolution(version: string, integrity?: string): PackageResolution {
|
|
||||||
const normalizedVersion = normalizeSupportedVersion(version);
|
|
||||||
|
|
||||||
return {
|
|
||||||
spec: `${NPM_PACKAGE}@${normalizedVersion}`,
|
|
||||||
version: normalizedVersion,
|
|
||||||
integrity,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function readWorkspaceLockfile(workspaceRoot: string, filename: string): string | null {
|
|
||||||
const filePath = path.join(workspaceRoot, filename);
|
|
||||||
|
|
||||||
if (!existsSync(filePath)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return readFileSync(filePath, "utf8");
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function detectResolutionFromBunLock(workspaceRoot: string): PackageResolution | 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?.[NPM_PACKAGE] ?? rootWorkspace?.devDependencies?.[NPM_PACKAGE];
|
|
||||||
|
|
||||||
if (!declaredVersion) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const resolvedPackage = lockfile.packages?.[NPM_PACKAGE];
|
|
||||||
if (Array.isArray(resolvedPackage) && typeof resolvedPackage[0] === "string") {
|
|
||||||
const version = extractConcreteVersion(resolvedPackage[0]);
|
|
||||||
const integrity = typeof resolvedPackage[3] === "string" ? resolvedPackage[3] : undefined;
|
|
||||||
|
|
||||||
return version ? toPackageResolution(version, integrity) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const version = extractConcreteVersion(declaredVersion);
|
|
||||||
return version ? toPackageResolution(version) : null;
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function detectResolutionFromPnpmLock(workspaceRoot: string): PackageResolution | null {
|
|
||||||
const text = readWorkspaceLockfile(workspaceRoot, "pnpm-lock.yaml");
|
|
||||||
|
|
||||||
if (!text) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const lockfile = Bun.YAML.parse(text) as PnpmLock;
|
|
||||||
const rootImporter = lockfile.importers?.["."];
|
|
||||||
const dependency =
|
|
||||||
rootImporter?.dependencies?.[NPM_PACKAGE] ?? rootImporter?.devDependencies?.[NPM_PACKAGE];
|
|
||||||
const version =
|
|
||||||
typeof dependency === "string"
|
|
||||||
? extractConcreteVersion(dependency)
|
|
||||||
: extractConcreteVersion(dependency?.version);
|
|
||||||
|
|
||||||
if (!version) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const integrity = Object.entries(lockfile.packages ?? {}).find(
|
|
||||||
([packageKey]) =>
|
|
||||||
packageKey === `${NPM_PACKAGE}@${version}` ||
|
|
||||||
packageKey.startsWith(`/${NPM_PACKAGE}@${version}`),
|
|
||||||
)?.[1].resolution?.integrity;
|
|
||||||
|
|
||||||
return toPackageResolution(version, integrity);
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function detectResolutionFromPackageLock(workspaceRoot: string): PackageResolution | null {
|
|
||||||
const text = readWorkspaceLockfile(workspaceRoot, "package-lock.json");
|
|
||||||
|
|
||||||
if (!text) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const lockfile = JSON.parse(text) as PackageLock;
|
|
||||||
const packageEntry = lockfile.packages?.[`node_modules/${NPM_PACKAGE}`];
|
|
||||||
const dependencyEntry = lockfile.dependencies?.[NPM_PACKAGE];
|
|
||||||
const version =
|
|
||||||
extractConcreteVersion(packageEntry?.version) ??
|
|
||||||
extractConcreteVersion(dependencyEntry?.version);
|
|
||||||
|
|
||||||
return version
|
|
||||||
? toPackageResolution(version, packageEntry?.integrity ?? dependencyEntry?.integrity)
|
|
||||||
: null;
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function resolvePackage(inputVersion: string): PackageResolution {
|
|
||||||
const requestedVersion = inputVersion.trim();
|
|
||||||
|
|
||||||
if (requestedVersion) {
|
|
||||||
return toPackageResolution(requestedVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
const workspaceRoot = process.env.GITHUB_WORKSPACE?.trim();
|
|
||||||
|
|
||||||
if (!workspaceRoot) {
|
|
||||||
return toPackageResolution(DEFAULT_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
detectResolutionFromBunLock(workspaceRoot) ??
|
|
||||||
detectResolutionFromPnpmLock(workspaceRoot) ??
|
|
||||||
detectResolutionFromPackageLock(workspaceRoot) ??
|
|
||||||
toPackageResolution(DEFAULT_VERSION)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function verifyPackageIntegrity(resolution: PackageResolution, metadata: PackageMetadata): void {
|
|
||||||
if (!resolution.integrity) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const registryIntegrity = metadata["dist.integrity"];
|
|
||||||
if (registryIntegrity !== resolution.integrity) {
|
|
||||||
throw new Error(`Lockfile integrity for ${resolution.spec} does not match the npm registry`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getPackageMetadata(resolution: PackageResolution): Promise<PackageMetadata> {
|
|
||||||
const output = await runNpm([
|
|
||||||
"view",
|
|
||||||
resolution.spec,
|
|
||||||
"version",
|
|
||||||
"bin",
|
|
||||||
"scripts",
|
|
||||||
"dist.integrity",
|
|
||||||
"--json",
|
|
||||||
]);
|
|
||||||
const metadata = JSON.parse(output) as unknown;
|
|
||||||
|
|
||||||
if (!isRecord(metadata)) {
|
|
||||||
throw new Error(`Could not read npm metadata for ${resolution.spec}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
function verifyPackageMetadata(resolution: PackageResolution, metadata: PackageMetadata): void {
|
|
||||||
if (typeof metadata.version !== "string" || !CONCRETE_VERSION_PATTERN.test(metadata.version)) {
|
|
||||||
throw new Error(`Could not resolve a fixed npm version for ${resolution.spec}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const bin = metadata.bin;
|
|
||||||
const hasSupabaseBin =
|
|
||||||
typeof bin === "string" || (isRecord(bin) && typeof bin[NPM_PACKAGE] === "string");
|
|
||||||
|
|
||||||
if (!hasSupabaseBin) {
|
|
||||||
throw new Error(`The npm package ${resolution.spec} does not expose a supabase executable`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function shouldIgnoreInstallScripts(metadata: PackageMetadata): boolean {
|
|
||||||
return !(isRecord(metadata.scripts) && typeof metadata.scripts.postinstall === "string");
|
|
||||||
}
|
|
||||||
|
|
||||||
function createInstallRoot(): string {
|
|
||||||
const tempRoot = process.env.RUNNER_TEMP?.trim() || os.tmpdir();
|
|
||||||
return mkdtempSync(path.join(tempRoot, "setup-cli-"));
|
|
||||||
}
|
|
||||||
|
|
||||||
async function runNpm(args: string[]): Promise<string> {
|
|
||||||
const executable = process.env[NPM_EXECUTABLE_ENV]?.trim() || "npm";
|
|
||||||
const proc = Bun.spawn([executable, ...args], {
|
|
||||||
env: process.env,
|
|
||||||
stderr: "pipe",
|
|
||||||
stdout: "pipe",
|
|
||||||
});
|
|
||||||
const [stdout, stderr, exitCode] = await Promise.all([
|
|
||||||
new Response(proc.stdout).text(),
|
|
||||||
new Response(proc.stderr).text(),
|
|
||||||
proc.exited,
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (exitCode !== 0) {
|
|
||||||
throw new Error(stderr.trim() || `npm ${args.join(" ")} failed`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return stdout;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function installCli(resolution: PackageResolution): Promise<string> {
|
|
||||||
const metadata = await getPackageMetadata(resolution);
|
|
||||||
verifyPackageMetadata(resolution, metadata);
|
|
||||||
verifyPackageIntegrity(resolution, metadata);
|
|
||||||
|
|
||||||
const installRoot = createInstallRoot();
|
|
||||||
|
|
||||||
await runNpm([
|
|
||||||
"install",
|
|
||||||
"--prefix",
|
|
||||||
installRoot,
|
|
||||||
"--omit=dev",
|
|
||||||
"--include=optional",
|
|
||||||
"--no-audit",
|
|
||||||
"--no-fund",
|
|
||||||
"--no-package-lock",
|
|
||||||
`--ignore-scripts=${shouldIgnoreInstallScripts(metadata)}`,
|
|
||||||
resolution.spec,
|
|
||||||
]);
|
|
||||||
|
|
||||||
return path.join(installRoot, "node_modules", ".bin");
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCliExecutablePath(cliPath: string): string {
|
|
||||||
if (process.platform !== "win32") {
|
|
||||||
return path.join(cliPath, "supabase");
|
|
||||||
}
|
|
||||||
|
|
||||||
const cmdPath = path.join(cliPath, "supabase.cmd");
|
|
||||||
if (existsSync(cmdPath)) {
|
|
||||||
return cmdPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
const exePath = path.join(cliPath, "supabase.exe");
|
|
||||||
if (existsSync(exePath)) {
|
|
||||||
return exePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
return path.join(cliPath, "supabase");
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function determineInstalledVersion(cliPath: string): Promise<string> {
|
|
||||||
const executable = getCliExecutablePath(cliPath);
|
|
||||||
const proc = Bun.spawn([executable, "--version"], {
|
|
||||||
stderr: "pipe",
|
|
||||||
stdout: "pipe",
|
|
||||||
});
|
|
||||||
const [stdout, stderr, exitCode] = await Promise.all([
|
|
||||||
new Response(proc.stdout).text(),
|
|
||||||
new Response(proc.stderr).text(),
|
|
||||||
proc.exited,
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (exitCode !== 0) {
|
|
||||||
throw new Error(stderr.trim() || "Could not determine installed Supabase CLI version");
|
|
||||||
}
|
|
||||||
|
|
||||||
const version = stdout.trim();
|
|
||||||
if (!version) {
|
|
||||||
throw new Error("Could not determine installed Supabase CLI version");
|
|
||||||
}
|
|
||||||
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|
||||||
function shouldUseGhcrRegistry(requestedVersion: string, installedVersion: string): boolean {
|
|
||||||
if (requestedVersion.toLowerCase() === DEFAULT_VERSION) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const concreteVersion = extractConcreteVersion(installedVersion);
|
|
||||||
return concreteVersion !== null && semver.order(concreteVersion, REGISTRY_VERSION) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function run(): Promise<void> {
|
export async function run(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const resolution = resolvePackage(core.getInput("version"));
|
// Get version of tool to be installed
|
||||||
const cliPath = await installCli(resolution);
|
const version = core.getInput('version')
|
||||||
const installedVersion = await determineInstalledVersion(cliPath);
|
const githubToken = core.getInput('github-token')
|
||||||
core.setOutput("version", installedVersion);
|
|
||||||
core.addPath(cliPath);
|
|
||||||
|
|
||||||
if (shouldUseGhcrRegistry(resolution.version, installedVersion)) {
|
// Download the specific version of the tool, e.g. as a tarball/zipball
|
||||||
core.exportVariable(CLI_CONFIG_REGISTRY, "ghcr.io");
|
const download = await getDownloadArchive(
|
||||||
|
version,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
githubToken
|
||||||
|
)
|
||||||
|
const pathToArchive = await tc.downloadTool(download.url)
|
||||||
|
|
||||||
|
// Extract the tarball/zipball onto host runner
|
||||||
|
const extractedPath =
|
||||||
|
download.format === 'zip'
|
||||||
|
? await tc.extractZip(pathToArchive)
|
||||||
|
: await tc.extractTar(pathToArchive)
|
||||||
|
const pathToCLI = getCliPath(extractedPath, download.format)
|
||||||
|
|
||||||
|
// 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) {
|
} catch (error) {
|
||||||
core.setFailed(error instanceof Error ? error.message : String(error));
|
if (error instanceof Error) core.setFailed(error.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
||||||
await run();
|
|
||||||
}
|
|
||||||
|
|||||||
183
src/utils.ts
Normal file
183
src/utils.ts
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
import { exec } from 'child_process'
|
||||||
|
import { existsSync } from 'fs'
|
||||||
|
import os from 'os'
|
||||||
|
import { gte, lt } from 'semver'
|
||||||
|
import { promisify } from 'util'
|
||||||
|
|
||||||
|
const doExec = promisify(exec)
|
||||||
|
const VERSIONED_ARCHIVE_VERSION = '2.99.0'
|
||||||
|
const LATEST_RELEASE_URL =
|
||||||
|
'https://api.github.com/repos/supabase/cli/releases/latest'
|
||||||
|
|
||||||
|
export type ArchiveFormat = 'apk' | 'tar' | 'zip'
|
||||||
|
|
||||||
|
export type DownloadArchive = {
|
||||||
|
url: string
|
||||||
|
format: ArchiveFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalizeVersion = (version: string): string => version.replace(/^v/i, '')
|
||||||
|
|
||||||
|
const resolveLatestVersion = async (githubToken?: string): Promise<string> => {
|
||||||
|
const headers: Record<string, string> = {
|
||||||
|
Accept: 'application/vnd.github+json',
|
||||||
|
'X-GitHub-Api-Version': '2022-11-28'
|
||||||
|
}
|
||||||
|
const token = githubToken?.trim()
|
||||||
|
|
||||||
|
if (token) {
|
||||||
|
headers.Authorization = `Bearer ${token}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(LATEST_RELEASE_URL, { headers })
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to resolve latest Supabase CLI release: ${response.statusText}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const release = (await response.json()) as { tag_name?: unknown }
|
||||||
|
if (typeof release.tag_name !== 'string') {
|
||||||
|
throw new Error(
|
||||||
|
'Failed to resolve latest Supabase CLI release: missing tag name'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalizeVersion(release.tag_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
const detectMuslLinux = async (platform = os.platform()): Promise<boolean> => {
|
||||||
|
if (platform !== 'linux') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existsSync('/etc/alpine-release')) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { stdout, stderr } = await doExec('ldd --version')
|
||||||
|
return `${stdout}\n${stderr}`.toLowerCase().includes('musl')
|
||||||
|
} catch (error) {
|
||||||
|
const output = error instanceof Error ? error.message : String(error)
|
||||||
|
return output.toLowerCase().includes('musl')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getArchiveFormat = (
|
||||||
|
version: string,
|
||||||
|
platform: string,
|
||||||
|
isMuslLinux: boolean
|
||||||
|
): ArchiveFormat => {
|
||||||
|
if (
|
||||||
|
platform === 'linux' &&
|
||||||
|
isMuslLinux &&
|
||||||
|
gte(version, VERSIONED_ARCHIVE_VERSION)
|
||||||
|
) {
|
||||||
|
return 'apk'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform === 'win32' && gte(version, VERSIONED_ARCHIVE_VERSION)) {
|
||||||
|
return 'zip'
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'tar'
|
||||||
|
}
|
||||||
|
|
||||||
|
const getArchiveFilename = (
|
||||||
|
version: string,
|
||||||
|
platform: string,
|
||||||
|
arch: string,
|
||||||
|
format: ArchiveFormat
|
||||||
|
): string => {
|
||||||
|
const archivePlatform = mapOS(platform)
|
||||||
|
const archiveArch = mapArch(arch)
|
||||||
|
if (lt(version, '1.28.0')) {
|
||||||
|
return `supabase_${version}_${archivePlatform}_${archiveArch}.tar.gz`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform === 'linux' && format === 'apk') {
|
||||||
|
return `supabase_${version}_${archivePlatform}_${archiveArch}.apk`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gte(version, VERSIONED_ARCHIVE_VERSION)) {
|
||||||
|
const extension = platform === 'win32' ? 'zip' : 'tar.gz'
|
||||||
|
return `supabase_${version}_${archivePlatform}_${archiveArch}.${extension}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return `supabase_${archivePlatform}_${archiveArch}.tar.gz`
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getDownloadArchive = async (
|
||||||
|
version: string,
|
||||||
|
platform = os.platform(),
|
||||||
|
arch = os.arch(),
|
||||||
|
isMuslLinux?: boolean,
|
||||||
|
githubToken?: string
|
||||||
|
): Promise<DownloadArchive> => {
|
||||||
|
const resolvedVersion =
|
||||||
|
version.toLowerCase() === 'latest'
|
||||||
|
? await resolveLatestVersion(githubToken)
|
||||||
|
: normalizeVersion(version)
|
||||||
|
const format = getArchiveFormat(
|
||||||
|
resolvedVersion,
|
||||||
|
platform,
|
||||||
|
isMuslLinux ?? (await detectMuslLinux(platform))
|
||||||
|
)
|
||||||
|
const filename = getArchiveFilename(resolvedVersion, platform, arch, format)
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: `https://github.com/supabase/cli/releases/download/v${resolvedVersion}/${filename}`,
|
||||||
|
format
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getCliPath = (
|
||||||
|
extractedPath: string,
|
||||||
|
archiveFormat: ArchiveFormat
|
||||||
|
): string => {
|
||||||
|
return archiveFormat === 'apk' ? `${extractedPath}/usr/bin` : extractedPath
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getDownloadUrl = async (
|
||||||
|
version: string,
|
||||||
|
githubToken?: string
|
||||||
|
): Promise<string> => {
|
||||||
|
const archive = await getDownloadArchive(
|
||||||
|
version,
|
||||||
|
os.platform(),
|
||||||
|
os.arch(),
|
||||||
|
undefined,
|
||||||
|
githubToken
|
||||||
|
)
|
||||||
|
return archive.url
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
23
tsconfig.base.json
Normal file
23
tsconfig.base.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"$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"
|
||||||
|
}
|
||||||
|
}
|
||||||
17
tsconfig.eslint.json
Normal file
17
tsconfig.eslint.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"$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,4 +1,11 @@
|
|||||||
{
|
{
|
||||||
"extends": "@tsconfig/bun/tsconfig.json",
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
|
"extends": "./tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "NodeNext",
|
||||||
|
"moduleResolution": "NodeNext",
|
||||||
|
"outDir": "./dist"
|
||||||
|
},
|
||||||
|
"exclude": ["__fixtures__", "__tests__", "coverage", "dist", "node_modules"],
|
||||||
"include": ["src"]
|
"include": ["src"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user