Compare commits
10 Commits
storage@0.
...
storage@0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
438355bff0 | ||
|
|
62b97838fe | ||
|
|
d287191f7a | ||
|
|
b8d2127b06 | ||
|
|
28cec232c8 | ||
|
|
fe853da133 | ||
|
|
c4445135bf | ||
|
|
db7366dfc7 | ||
|
|
31c503e458 | ||
|
|
187d35412e |
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -22,7 +22,6 @@ Where `TYPE` is:
|
||||
|
||||
Where `PKG` is:
|
||||
|
||||
- `auth`: For changes to the Nhost Auth service
|
||||
- `ci`: For general changes to the build and/or CI/CD pipeline
|
||||
- `cli`: For changes to the Nhost CLI
|
||||
- `codegen`: For changes to the code generator
|
||||
@@ -33,7 +32,7 @@ Where `PKG` is:
|
||||
- `mintlify-openapi`: For changes to the Mintlify OpenAPI tool
|
||||
- `nhost-js`: For changes to the Nhost JavaScript SDK
|
||||
- `nixops`: For changes to the NixOps
|
||||
- `storage`: For changes to the Nhost Storage service
|
||||
- `storage`: For changes to the Nhost Storage
|
||||
|
||||
Where `SUMMARY` is a short description of what the PR does.
|
||||
|
||||
|
||||
41
.github/actions/validate-pr-title/action.yaml
vendored
41
.github/actions/validate-pr-title/action.yaml
vendored
@@ -1,41 +0,0 @@
|
||||
---
|
||||
name: "Validate PR Title"
|
||||
description: "Validates that PR title follows the required format: TYPE(PKG): SUMMARY"
|
||||
inputs:
|
||||
pr_title:
|
||||
description: "The PR title to validate"
|
||||
required: true
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: "Validate PR title format"
|
||||
shell: bash
|
||||
run: |
|
||||
PR_TITLE="${{ inputs.pr_title }}"
|
||||
|
||||
echo "Validating PR title: $PR_TITLE"
|
||||
|
||||
# Define valid types and packages
|
||||
VALID_TYPES="feat|fix|chore"
|
||||
VALID_PKGS="auth|ci|cli|codegen|dashboard|deps|docs|examples|mintlify-openapi|nhost-js|nixops|storage"
|
||||
|
||||
# Check if title matches the pattern TYPE(PKG): SUMMARY
|
||||
if [[ ! "$PR_TITLE" =~ ^(${VALID_TYPES})\((${VALID_PKGS})\):\ .+ ]]; then
|
||||
echo "❌ PR title does not follow the required format!"
|
||||
echo ""
|
||||
echo "Expected format: TYPE(PKG): SUMMARY"
|
||||
echo ""
|
||||
echo "Valid TYPEs:"
|
||||
echo " - feat: mark this pull request as a feature"
|
||||
echo " - fix: mark this pull request as a bug fix"
|
||||
echo " - chore: mark this pull request as a maintenance item"
|
||||
echo ""
|
||||
echo "Valid PKGs:"
|
||||
echo " - auth, ci, cli, codegen, dashboard, deps, docs, examples,"
|
||||
echo " - mintlify-openapi, nhost-js, nixops, storage"
|
||||
echo ""
|
||||
echo "Example: feat(cli): add new command for database migrations"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ PR title is valid!"
|
||||
84
.github/workflows/auth_checks.yaml
vendored
84
.github/workflows/auth_checks.yaml
vendored
@@ -1,84 +0,0 @@
|
||||
---
|
||||
name: "auth: check and build"
|
||||
on:
|
||||
# pull_request_target:
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/auth_checks.yaml'
|
||||
- '.github/workflows/wf_check.yaml'
|
||||
- '.github/workflows/wf_build_artifacts.yaml'
|
||||
|
||||
# common build
|
||||
- 'flake.nix'
|
||||
- 'flake.lock'
|
||||
- 'nixops/**'
|
||||
- 'build/**'
|
||||
|
||||
# common go
|
||||
- '.golangci.yaml'
|
||||
- 'go.mod'
|
||||
- 'go.sum'
|
||||
- 'vendor/**'
|
||||
|
||||
# auth
|
||||
- 'services/auth/**'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('push-{0}', github.sha) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
check-permissions:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: |
|
||||
echo "github.event_name: ${{ github.event_name }}"
|
||||
echo "github.event.pull_request.author_association: ${{ github.event.pull_request.author_association }}"
|
||||
- name: "This task will run and fail if user has no permissions and label safe_to_test isn't present"
|
||||
if: "github.event_name == 'pull_request_target' && ! ( contains(github.event.pull_request.labels.*.name, 'safe_to_test') || contains(fromJson('[\"OWNER\", \"MEMBER\", \"COLLABORATOR\"]'), github.event.pull_request.author_association) )"
|
||||
run: |
|
||||
exit 1
|
||||
|
||||
tests:
|
||||
uses: ./.github/workflows/wf_check.yaml
|
||||
needs:
|
||||
- check-permissions
|
||||
with:
|
||||
NAME: auth
|
||||
PATH: services/auth
|
||||
GIT_REF: ${{ github.sha }}
|
||||
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
NHOST_PAT: ${{ secrets.NHOST_PAT }}
|
||||
|
||||
build_artifacts:
|
||||
uses: ./.github/workflows/wf_build_artifacts.yaml
|
||||
needs:
|
||||
- check-permissions
|
||||
with:
|
||||
NAME: auth
|
||||
PATH: services/auth
|
||||
GIT_REF: ${{ github.sha }}
|
||||
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
|
||||
DOCKER: true
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
|
||||
remove_label:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- check-permissions
|
||||
steps:
|
||||
- uses: actions-ecosystem/action-remove-labels@v1
|
||||
with:
|
||||
labels: |
|
||||
safe_to_test
|
||||
if: contains(github.event.pull_request.labels.*.name, 'safe_to_test')
|
||||
60
.github/workflows/auth_wf_release.yaml
vendored
60
.github/workflows/auth_wf_release.yaml
vendored
@@ -1,60 +0,0 @@
|
||||
---
|
||||
name: "auth: release"
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
GIT_REF:
|
||||
required: true
|
||||
type: string
|
||||
VERSION:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID:
|
||||
required: true
|
||||
NIX_CACHE_PUB_KEY:
|
||||
required: true
|
||||
NIX_CACHE_PRIV_KEY:
|
||||
required: true
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build_artifacts:
|
||||
uses: ./.github/workflows/wf_build_artifacts.yaml
|
||||
with:
|
||||
NAME: auth
|
||||
PATH: services/auth
|
||||
GIT_REF: ${{ inputs.GIT_REF }}
|
||||
VERSION: ${{ inputs.VERSION }}
|
||||
DOCKER: true
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
|
||||
push-docker-hub:
|
||||
uses: ./.github/workflows/wf_docker_push_image.yaml
|
||||
needs:
|
||||
- build_artifacts
|
||||
with:
|
||||
NAME: auth
|
||||
PATH: services/auth
|
||||
VERSION: ${{ inputs.VERSION }}
|
||||
secrets:
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
push-docker-ecr:
|
||||
uses: ./.github/workflows/wf_docker_push_image_ecr.yaml
|
||||
needs:
|
||||
- build_artifacts
|
||||
with:
|
||||
NAME: auth
|
||||
PATH: services/auth
|
||||
VERSION: ${{ inputs.VERSION }}
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
|
||||
CONTAINER_REGISTRY: ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.eu-central-1.amazonaws.com
|
||||
20
.github/workflows/ci_release.yaml
vendored
20
.github/workflows/ci_release.yaml
vendored
@@ -33,24 +33,10 @@ jobs:
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "Extracted project: $PROJECT, version: $VERSION"
|
||||
|
||||
auth:
|
||||
needs: extract-project
|
||||
if: needs.extract-project.outputs.project == 'auth'
|
||||
uses: ./.github/workflows/auth_wf_release.yaml
|
||||
with:
|
||||
GIT_REF: ${{ github.sha }}
|
||||
VERSION: ${{ needs.extract-project.outputs.version }}
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
cli:
|
||||
needs: extract-project
|
||||
if: needs.extract-project.outputs.project == 'cli'
|
||||
uses: ./.github/workflows/cli_wf_release.yaml
|
||||
uses: ./.github/workflows/cli_release.yaml
|
||||
with:
|
||||
GIT_REF: ${{ github.sha }}
|
||||
VERSION: ${{ needs.extract-project.outputs.version }}
|
||||
@@ -65,7 +51,7 @@ jobs:
|
||||
dashboard:
|
||||
needs: extract-project
|
||||
if: needs.extract-project.outputs.project == '@nhost/dashboard'
|
||||
uses: ./.github/workflows/dashboard_wf_release.yaml
|
||||
uses: ./.github/workflows/dashboard_release.yaml
|
||||
with:
|
||||
GIT_REF: ${{ github.sha }}
|
||||
VERSION: ${{ needs.extract-project.outputs.version }}
|
||||
@@ -99,7 +85,7 @@ jobs:
|
||||
storage:
|
||||
needs: extract-project
|
||||
if: needs.extract-project.outputs.project == 'storage'
|
||||
uses: ./.github/workflows/storage_wf_release.yaml
|
||||
uses: ./.github/workflows/storage_release.yaml
|
||||
with:
|
||||
GIT_REF: ${{ github.sha }}
|
||||
VERSION: ${{ needs.extract-project.outputs.version }}
|
||||
|
||||
2
.github/workflows/ci_update_changelog.yaml
vendored
2
.github/workflows/ci_update_changelog.yaml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
project: [cli, dashboard, packages/nhost-js, services/auth, services/storage]
|
||||
project: [cli, dashboard, packages/nhost-js, services/storage]
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
|
||||
6
.github/workflows/cli_checks.yaml
vendored
6
.github/workflows/cli_checks.yaml
vendored
@@ -27,10 +27,6 @@ on:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('push-{0}', github.sha) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
check-permissions:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -74,7 +70,7 @@ jobs:
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
|
||||
test_cli_build:
|
||||
uses: ./.github/workflows/cli_wf_test_new_project.yaml
|
||||
uses: ./.github/workflows/cli_test_new_project.yaml
|
||||
needs:
|
||||
- check-permissions
|
||||
- build_artifacts
|
||||
|
||||
122
.github/workflows/cli_release.yaml
vendored
Normal file
122
.github/workflows/cli_release.yaml
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
---
|
||||
name: "cli: release"
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
GIT_REF:
|
||||
required: true
|
||||
type: string
|
||||
VERSION:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID:
|
||||
required: true
|
||||
NIX_CACHE_PUB_KEY:
|
||||
required: true
|
||||
NIX_CACHE_PRIV_KEY:
|
||||
required: true
|
||||
GH_PAT:
|
||||
required: true
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build_artifacts:
|
||||
uses: ./.github/workflows/wf_build_artifacts.yaml
|
||||
with:
|
||||
NAME: cli
|
||||
PATH: cli
|
||||
GIT_REF: ${{ inputs.GIT_REF }}
|
||||
VERSION: ${{ inputs.VERSION }}
|
||||
DOCKER: true
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
|
||||
push-docker:
|
||||
uses: ./.github/workflows/wf_docker_push_image.yaml
|
||||
needs:
|
||||
- build_artifacts
|
||||
with:
|
||||
NAME: cli
|
||||
PATH: cli
|
||||
VERSION: ${{ inputs.VERSION }}
|
||||
secrets:
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
build-multiplatform:
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: cli
|
||||
|
||||
runs-on: blacksmith-2vcpu-ubuntu-2404
|
||||
timeout-minutes: 180
|
||||
|
||||
steps:
|
||||
- name: "Check out repository"
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
ref: ${{ inputs.GIT_REF }}
|
||||
|
||||
- name: Configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions-nhost-${{ github.event.repository.name }}
|
||||
aws-region: eu-central-1
|
||||
|
||||
- name: Setup Nix with Cache
|
||||
uses: ./.github/actions/setup-nix
|
||||
with:
|
||||
NAME: cli
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Compute common env vars
|
||||
id: vars
|
||||
run: |
|
||||
echo "VERSION=$(make get-version VER=${{ inputs.VERSION }})" >> $GITHUB_OUTPUT
|
||||
ARCH=$([ "${{ runner.arch }}" == "X64" ] && echo "x86_64" || echo "aarch64")
|
||||
echo "ARCH=${ARCH}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: "Build artifact"
|
||||
run: |
|
||||
make build-multiplatform
|
||||
|
||||
- name: "Upload assets"
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
|
||||
run: |
|
||||
export VERSION=${{ steps.vars.outputs.VERSION }}
|
||||
|
||||
mkdir upload
|
||||
|
||||
tar cvzf upload/cli-$VERSION-darwin-amd64.tar.gz -C result/darwin/amd64 cli
|
||||
tar cvzf upload/cli-$VERSION-darwin-arm64.tar.gz -C result/darwin/arm64 cli
|
||||
tar cvzf upload/cli-$VERSION-linux-amd64.tar.gz -C result/linux/amd64 cli
|
||||
tar cvzf upload/cli-$VERSION-linux-arm64.tar.gz -C result/linux/arm64 cli
|
||||
|
||||
cd upload
|
||||
find . -type f -exec sha256sum {} + > ../checksums.txt
|
||||
cd ..
|
||||
|
||||
cat checksums.txt
|
||||
|
||||
gh release upload \
|
||||
--clobber "${{ github.ref_name }}" \
|
||||
./upload/* checksums.txt
|
||||
|
||||
- name: "Store Nix cache"
|
||||
uses: ./.github/actions/cache-nix
|
||||
with:
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
if: always()
|
||||
97
.github/workflows/cli_test_new_project.yaml
vendored
Normal file
97
.github/workflows/cli_test_new_project.yaml
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
---
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
NAME:
|
||||
type: string
|
||||
required: true
|
||||
PATH:
|
||||
type: string
|
||||
required: true
|
||||
GIT_REF:
|
||||
type: string
|
||||
required: false
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID:
|
||||
required: true
|
||||
NIX_CACHE_PUB_KEY:
|
||||
required: true
|
||||
NIX_CACHE_PRIV_KEY:
|
||||
required: true
|
||||
NHOST_PAT:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: blacksmith-2vcpu-ubuntu-2404
|
||||
timeout-minutes: 30
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ inputs.PATH }}
|
||||
|
||||
env:
|
||||
NHOST_PAT: ${{ secrets.NHOST_PAT }}
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
actions: read
|
||||
|
||||
steps:
|
||||
- name: "Check out repository"
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
ref: ${{ inputs.GIT_REF }}
|
||||
|
||||
- name: Collect Workflow Telemetry
|
||||
uses: catchpoint/workflow-telemetry-action@v2
|
||||
with:
|
||||
comment_on_pr: false
|
||||
|
||||
- name: Configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions-nhost-${{ github.event.repository.name }}
|
||||
aws-region: eu-central-1
|
||||
|
||||
- name: Setup Nix with Cache
|
||||
uses: ./.github/actions/setup-nix
|
||||
with:
|
||||
NAME: ${{ inputs.NAME }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: "Get artifacts"
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
path: ~/artifacts
|
||||
|
||||
- name: "Inspect artifacts"
|
||||
run: find ~/artifacts
|
||||
|
||||
- name: Load docker image
|
||||
run: |
|
||||
skopeo copy --insecure-policy \
|
||||
dir:/home/runner/artifacts/cli-docker-image-x86_64-0.0.0-dev \
|
||||
docker-daemon:cli:0.0.0-dev
|
||||
|
||||
- name: "Create a new project"
|
||||
run: |
|
||||
export NHOST_DOMAIN=staging.nhost.run
|
||||
export NHOST_CONFIGSERVER_IMAGE=cli:0.0.0-dev
|
||||
|
||||
unzip /home/runner/artifacts/cli-artifact-x86_64-0.0.0-dev/result.zip
|
||||
|
||||
mkdir new-project
|
||||
cd new-project
|
||||
/home/runner/_work/nhost/nhost/cli/result/bin/cli login --pat ${{ secrets.NHOST_PAT }}
|
||||
/home/runner/_work/nhost/nhost/cli/result/bin/cli init
|
||||
/home/runner/_work/nhost/nhost/cli/result/bin/cli up --down-on-error
|
||||
/home/runner/_work/nhost/nhost/cli/result/bin/cli down --volumes
|
||||
|
||||
- name: "Store Nix cache"
|
||||
uses: ./.github/actions/cache-nix
|
||||
with:
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
if: always()
|
||||
122
.github/workflows/cli_wf_release.yaml
vendored
122
.github/workflows/cli_wf_release.yaml
vendored
@@ -1,122 +0,0 @@
|
||||
---
|
||||
name: "cli: release"
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
GIT_REF:
|
||||
required: true
|
||||
type: string
|
||||
VERSION:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID:
|
||||
required: true
|
||||
NIX_CACHE_PUB_KEY:
|
||||
required: true
|
||||
NIX_CACHE_PRIV_KEY:
|
||||
required: true
|
||||
GH_PAT:
|
||||
required: true
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build_artifacts:
|
||||
uses: ./.github/workflows/wf_build_artifacts.yaml
|
||||
with:
|
||||
NAME: cli
|
||||
PATH: cli
|
||||
GIT_REF: ${{ inputs.GIT_REF }}
|
||||
VERSION: ${{ inputs.VERSION }}
|
||||
DOCKER: true
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
|
||||
push-docker:
|
||||
uses: ./.github/workflows/wf_docker_push_image.yaml
|
||||
needs:
|
||||
- build_artifacts
|
||||
with:
|
||||
NAME: cli
|
||||
PATH: cli
|
||||
VERSION: ${{ inputs.VERSION }}
|
||||
secrets:
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
build-multiplatform:
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: cli
|
||||
|
||||
runs-on: blacksmith-2vcpu-ubuntu-2404
|
||||
timeout-minutes: 180
|
||||
|
||||
steps:
|
||||
- name: "Check out repository"
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
ref: ${{ inputs.GIT_REF }}
|
||||
|
||||
- name: Configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions-nhost-${{ github.event.repository.name }}
|
||||
aws-region: eu-central-1
|
||||
|
||||
- name: Setup Nix with Cache
|
||||
uses: ./.github/actions/setup-nix
|
||||
with:
|
||||
NAME: cli
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Compute common env vars
|
||||
id: vars
|
||||
run: |
|
||||
echo "VERSION=$(make get-version VER=${{ inputs.VERSION }})" >> $GITHUB_OUTPUT
|
||||
ARCH=$([ "${{ runner.arch }}" == "X64" ] && echo "x86_64" || echo "aarch64")
|
||||
echo "ARCH=${ARCH}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: "Build artifact"
|
||||
run: |
|
||||
make build-multiplatform
|
||||
|
||||
- name: "Upload assets"
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
|
||||
run: |
|
||||
export VERSION=${{ steps.vars.outputs.VERSION }}
|
||||
|
||||
mkdir upload
|
||||
|
||||
tar cvzf upload/cli-$VERSION-darwin-amd64.tar.gz -C result/darwin/amd64 cli
|
||||
tar cvzf upload/cli-$VERSION-darwin-arm64.tar.gz -C result/darwin/arm64 cli
|
||||
tar cvzf upload/cli-$VERSION-linux-amd64.tar.gz -C result/linux/amd64 cli
|
||||
tar cvzf upload/cli-$VERSION-linux-arm64.tar.gz -C result/linux/arm64 cli
|
||||
|
||||
cd upload
|
||||
find . -type f -exec sha256sum {} + > ../checksums.txt
|
||||
cd ..
|
||||
|
||||
cat checksums.txt
|
||||
|
||||
gh release upload \
|
||||
--clobber "${{ github.ref_name }}" \
|
||||
./upload/* checksums.txt
|
||||
|
||||
- name: "Store Nix cache"
|
||||
uses: ./.github/actions/cache-nix
|
||||
with:
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
if: always()
|
||||
97
.github/workflows/cli_wf_test_new_project.yaml
vendored
97
.github/workflows/cli_wf_test_new_project.yaml
vendored
@@ -1,97 +0,0 @@
|
||||
---
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
NAME:
|
||||
type: string
|
||||
required: true
|
||||
PATH:
|
||||
type: string
|
||||
required: true
|
||||
GIT_REF:
|
||||
type: string
|
||||
required: false
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID:
|
||||
required: true
|
||||
NIX_CACHE_PUB_KEY:
|
||||
required: true
|
||||
NIX_CACHE_PRIV_KEY:
|
||||
required: true
|
||||
NHOST_PAT:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: blacksmith-2vcpu-ubuntu-2404
|
||||
timeout-minutes: 30
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ inputs.PATH }}
|
||||
|
||||
env:
|
||||
NHOST_PAT: ${{ secrets.NHOST_PAT }}
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
actions: read
|
||||
|
||||
steps:
|
||||
- name: "Check out repository"
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
ref: ${{ inputs.GIT_REF }}
|
||||
|
||||
- name: Collect Workflow Telemetry
|
||||
uses: catchpoint/workflow-telemetry-action@v2
|
||||
with:
|
||||
comment_on_pr: false
|
||||
|
||||
- name: Configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions-nhost-${{ github.event.repository.name }}
|
||||
aws-region: eu-central-1
|
||||
|
||||
- name: Setup Nix with Cache
|
||||
uses: ./.github/actions/setup-nix
|
||||
with:
|
||||
NAME: ${{ inputs.NAME }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: "Get artifacts"
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
path: ~/artifacts
|
||||
|
||||
- name: "Inspect artifacts"
|
||||
run: find ~/artifacts
|
||||
|
||||
- name: Load docker image
|
||||
run: |
|
||||
skopeo copy --insecure-policy \
|
||||
dir:/home/runner/artifacts/cli-docker-image-x86_64-0.0.0-dev \
|
||||
docker-daemon:cli:0.0.0-dev
|
||||
|
||||
- name: "Create a new project"
|
||||
run: |
|
||||
export NHOST_DOMAIN=staging.nhost.run
|
||||
export NHOST_CONFIGSERVER_IMAGE=cli:0.0.0-dev
|
||||
|
||||
unzip /home/runner/artifacts/cli-artifact-x86_64-0.0.0-dev/result.zip
|
||||
|
||||
mkdir new-project
|
||||
cd new-project
|
||||
/home/runner/_work/nhost/nhost/cli/result/bin/cli login --pat ${{ secrets.NHOST_PAT }}
|
||||
/home/runner/_work/nhost/nhost/cli/result/bin/cli init
|
||||
/home/runner/_work/nhost/nhost/cli/result/bin/cli up --down-on-error
|
||||
/home/runner/_work/nhost/nhost/cli/result/bin/cli down --volumes
|
||||
|
||||
- name: "Store Nix cache"
|
||||
uses: ./.github/actions/cache-nix
|
||||
with:
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
if: always()
|
||||
4
.github/workflows/codegen_checks.yaml
vendored
4
.github/workflows/codegen_checks.yaml
vendored
@@ -25,10 +25,6 @@ on:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('push-{0}', github.sha) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
check-permissions:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
12
.github/workflows/dashboard_checks.yaml
vendored
12
.github/workflows/dashboard_checks.yaml
vendored
@@ -32,10 +32,6 @@ on:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('push-{0}', github.sha) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
check-permissions:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -63,7 +59,6 @@ jobs:
|
||||
VERCEL_TEAM_ID: ${{ secrets.DASHBOARD_VERCEL_TEAM_ID }}
|
||||
VERCEL_PROJECT_ID: ${{ secrets.DASHBOARD_STAGING_VERCEL_PROJECT_ID }}
|
||||
VERCEL_DEPLOY_TOKEN: ${{ secrets.DASHBOARD_VERCEL_DEPLOY_TOKEN }}
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
|
||||
|
||||
build_artifacts:
|
||||
@@ -76,7 +71,6 @@ jobs:
|
||||
GIT_REF: ${{ github.sha }}
|
||||
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
|
||||
DOCKER: true
|
||||
OS_MATRIX: '["blacksmith-2vcpu-ubuntu-2404"]'
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
@@ -99,7 +93,7 @@ jobs:
|
||||
|
||||
|
||||
e2e_staging:
|
||||
uses: ./.github/workflows/dashboard_wf_e2e_staging.yaml
|
||||
uses: ./.github/workflows/wf_dashboard_e2e_staging.yaml
|
||||
needs:
|
||||
- check-permissions
|
||||
- deploy-vercel
|
||||
@@ -126,10 +120,8 @@ jobs:
|
||||
NHOST_TEST_USER_EMAIL: ${{ secrets.NHOST_TEST_USER_EMAIL }}
|
||||
NHOST_TEST_USER_PASSWORD: ${{ secrets.NHOST_TEST_USER_PASSWORD }}
|
||||
NHOST_TEST_PROJECT_ADMIN_SECRET: ${{ secrets.NHOST_TEST_PROJECT_ADMIN_SECRET }}
|
||||
NHOST_TEST_ONBOARDING_USER: ${{ secrets.NHOST_TEST_ONBOARDING_USER }}
|
||||
NHOST_TEST_FREE_USER_EMAILS: ${{ secrets.NHOST_TEST_FREE_USER_EMAILS }}
|
||||
PLAYWRIGHT_REPORT_ENCRYPTION_KEY: ${{ secrets.PLAYWRIGHT_REPORT_ENCRYPTION_KEY }}
|
||||
NHOST_TEST_STAGING_SUBDOMAIN: ${{ secrets.NHOST_TEST_STAGING_SUBDOMAIN }}
|
||||
NHOST_TEST_STAGING_REGION: ${{ secrets.NHOST_TEST_STAGING_REGION }}
|
||||
|
||||
remove_label:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
102
.github/workflows/dashboard_release.yaml
vendored
Normal file
102
.github/workflows/dashboard_release.yaml
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
---
|
||||
name: 'dashboard: release'
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
GIT_REF:
|
||||
required: true
|
||||
type: string
|
||||
VERSION:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID:
|
||||
required: true
|
||||
NIX_CACHE_PUB_KEY:
|
||||
required: true
|
||||
NIX_CACHE_PRIV_KEY:
|
||||
required: true
|
||||
VERCEL_TEAM_ID:
|
||||
required: true
|
||||
VERCEL_PROJECT_ID:
|
||||
required: true
|
||||
VERCEL_DEPLOY_TOKEN:
|
||||
required: true
|
||||
DISCORD_WEBHOOK:
|
||||
required: false
|
||||
GH_PAT:
|
||||
required: true
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
deploy-vercel:
|
||||
uses: ./.github/workflows/wf_deploy_vercel.yaml
|
||||
with:
|
||||
NAME: dashboard
|
||||
GIT_REF: ${{ inputs.GIT_REF }}
|
||||
ENVIRONMENT: production
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
VERCEL_TEAM_ID: ${{ secrets.VERCEL_TEAM_ID }}
|
||||
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
|
||||
VERCEL_DEPLOY_TOKEN: ${{ secrets.VERCEL_DEPLOY_TOKEN }}
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
|
||||
build_artifacts:
|
||||
uses: ./.github/workflows/wf_build_artifacts.yaml
|
||||
with:
|
||||
NAME: dashboard
|
||||
PATH: dashboard
|
||||
GIT_REF: ${{ inputs.GIT_REF }}
|
||||
VERSION: ${{ inputs.VERSION }}
|
||||
DOCKER: true
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
|
||||
push-docker:
|
||||
uses: ./.github/workflows/wf_docker_push_image.yaml
|
||||
needs:
|
||||
- build_artifacts
|
||||
with:
|
||||
NAME: dashboard
|
||||
PATH: dashboard
|
||||
VERSION: ${{ inputs.VERSION }}
|
||||
secrets:
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
bump-cli:
|
||||
name: Bump Dashboard version in the Nhost CLI
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- push-docker
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
token: ${{ secrets.GH_PAT }}
|
||||
|
||||
- name: Bump version in source code
|
||||
run: |
|
||||
find cli -type f -exec sed -i 's/"nhost\/dashboard:[^"]*"/"nhost\/dashboard:${{ inputs.VERSION }}"/g' {} +
|
||||
|
||||
- name: "Create Pull Request"
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
token: ${{ secrets.GH_PAT }}
|
||||
title: "chore(cli): bump nhost/dashboard to ${{ inputs.VERSION }}"
|
||||
commit-message: "chore: bump nhost/dashboard to ${{ inputs.VERSION }}"
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||
body: |
|
||||
This PR bumps the Nhost Dashboard Docker image to version ${{ needs.version.outputs.dashboardVersion }}.
|
||||
branch: bump-dashboard-version
|
||||
delete-branch: true
|
||||
27
.github/workflows/dashboard_release_staging.yaml
vendored
27
.github/workflows/dashboard_release_staging.yaml
vendored
@@ -4,32 +4,6 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- '.github/workflows/wf_build_artifacts.yaml'
|
||||
- '.github/workflows/wf_check.yaml'
|
||||
- '.github/workflows/dashboard_checks.yaml'
|
||||
|
||||
# common build
|
||||
- 'flake.nix'
|
||||
- 'flake.lock'
|
||||
- 'nixops/**'
|
||||
- 'build/**'
|
||||
|
||||
# common javascript
|
||||
- ".npmrc"
|
||||
- ".prettierignore"
|
||||
- ".prettierrc.js"
|
||||
- "audit-ci.jsonc"
|
||||
- "package.json"
|
||||
- "pnpm-workspace.yaml"
|
||||
- "pnpm-lock.yaml"
|
||||
- "turbo.json"
|
||||
|
||||
# dashboard
|
||||
- "dashboard/**"
|
||||
|
||||
# nhost-js
|
||||
- packages/nhost-js/**
|
||||
|
||||
jobs:
|
||||
deploy-vercel:
|
||||
@@ -45,5 +19,4 @@ jobs:
|
||||
VERCEL_TEAM_ID: ${{ secrets.DASHBOARD_VERCEL_TEAM_ID }}
|
||||
VERCEL_PROJECT_ID: ${{ secrets.DASHBOARD_STAGING_VERCEL_PROJECT_ID }}
|
||||
VERCEL_DEPLOY_TOKEN: ${{ secrets.DASHBOARD_VERCEL_DEPLOY_TOKEN }}
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_STAGING }}
|
||||
|
||||
162
.github/workflows/dashboard_wf_e2e_staging.yaml
vendored
162
.github/workflows/dashboard_wf_e2e_staging.yaml
vendored
@@ -1,162 +0,0 @@
|
||||
---
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
NAME:
|
||||
type: string
|
||||
required: true
|
||||
PATH:
|
||||
type: string
|
||||
required: true
|
||||
GIT_REF:
|
||||
type: string
|
||||
required: false
|
||||
NHOST_TEST_DASHBOARD_URL:
|
||||
type: string
|
||||
required: true
|
||||
NHOST_TEST_PROJECT_NAME:
|
||||
type: string
|
||||
required: true
|
||||
NHOST_TEST_ORGANIZATION_NAME:
|
||||
type: string
|
||||
required: true
|
||||
NHOST_TEST_ORGANIZATION_SLUG:
|
||||
type: string
|
||||
required: true
|
||||
NHOST_TEST_PERSONAL_ORG_SLUG:
|
||||
type: string
|
||||
required: true
|
||||
NHOST_TEST_PROJECT_SUBDOMAIN:
|
||||
type: string
|
||||
required: true
|
||||
NHOST_TEST_PROJECT_REMOTE_SCHEMA_NAME:
|
||||
type: string
|
||||
required: true
|
||||
NHOST_PRO_TEST_PROJECT_NAME:
|
||||
type: string
|
||||
required: true
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID:
|
||||
required: true
|
||||
NIX_CACHE_PUB_KEY:
|
||||
required: true
|
||||
NIX_CACHE_PRIV_KEY:
|
||||
required: true
|
||||
DASHBOARD_VERCEL_DEPLOY_TOKEN:
|
||||
required: true
|
||||
DASHBOARD_VERCEL_TEAM_ID:
|
||||
required: true
|
||||
DASHBOARD_STAGING_VERCEL_PROJECT_ID:
|
||||
required: true
|
||||
NHOST_TEST_USER_EMAIL:
|
||||
required: true
|
||||
NHOST_TEST_USER_PASSWORD:
|
||||
required: true
|
||||
NHOST_TEST_ONBOARDING_USER:
|
||||
required: true
|
||||
NHOST_TEST_PROJECT_ADMIN_SECRET:
|
||||
required: true
|
||||
PLAYWRIGHT_REPORT_ENCRYPTION_KEY:
|
||||
required: true
|
||||
NHOST_TEST_STAGING_SUBDOMAIN:
|
||||
required: true
|
||||
NHOST_TEST_STAGING_REGION:
|
||||
required: true
|
||||
|
||||
concurrency:
|
||||
group: dashboard-e2e-staging
|
||||
cancel-in-progress: false
|
||||
|
||||
env:
|
||||
NEXT_PUBLIC_ENV: dev
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
NHOST_TEST_DASHBOARD_URL: ${{ inputs.NHOST_TEST_DASHBOARD_URL }}
|
||||
NHOST_TEST_PROJECT_NAME: ${{ inputs.NHOST_TEST_PROJECT_NAME }}
|
||||
NHOST_TEST_ORGANIZATION_NAME: ${{ inputs.NHOST_TEST_ORGANIZATION_NAME }}
|
||||
NHOST_TEST_ORGANIZATION_SLUG: ${{ inputs.NHOST_TEST_ORGANIZATION_SLUG }}
|
||||
NHOST_TEST_PERSONAL_ORG_SLUG: ${{ inputs.NHOST_TEST_PERSONAL_ORG_SLUG }}
|
||||
NHOST_TEST_PROJECT_SUBDOMAIN: ${{ inputs.NHOST_TEST_PROJECT_SUBDOMAIN }}
|
||||
NHOST_TEST_PROJECT_REMOTE_SCHEMA_NAME: ${{ inputs.NHOST_TEST_PROJECT_REMOTE_SCHEMA_NAME }}
|
||||
NHOST_PRO_TEST_PROJECT_NAME: ${{ inputs.NHOST_PRO_TEST_PROJECT_NAME }}
|
||||
NHOST_TEST_USER_EMAIL: ${{ secrets.NHOST_TEST_USER_EMAIL }}
|
||||
NHOST_TEST_USER_PASSWORD: ${{ secrets.NHOST_TEST_USER_PASSWORD }}
|
||||
NHOST_TEST_PROJECT_ADMIN_SECRET: ${{ secrets.NHOST_TEST_PROJECT_ADMIN_SECRET }}
|
||||
NHOST_TEST_ONBOARDING_USER: ${{ secrets.NHOST_TEST_ONBOARDING_USER }}
|
||||
NHOST_TEST_STAGING_SUBDOMAIN: ${{ secrets.NHOST_TEST_STAGING_SUBDOMAIN }}
|
||||
NHOST_TEST_STAGING_REGION: ${{ secrets.NHOST_TEST_STAGING_REGION }}
|
||||
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: blacksmith-2vcpu-ubuntu-2404
|
||||
timeout-minutes: 30
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ inputs.PATH }}
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
actions: read
|
||||
|
||||
steps:
|
||||
- name: "Check out repository"
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
ref: ${{ inputs.GIT_REF }}
|
||||
|
||||
- name: Collect Workflow Telemetry
|
||||
uses: catchpoint/workflow-telemetry-action@v2
|
||||
with:
|
||||
comment_on_pr: false
|
||||
|
||||
- name: Configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions-nhost-${{ github.event.repository.name }}
|
||||
aws-region: eu-central-1
|
||||
|
||||
- name: Setup Nix with Cache
|
||||
uses: ./.github/actions/setup-nix
|
||||
with:
|
||||
NAME: ${{ inputs.NAME }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Start CLI
|
||||
run: |
|
||||
nix develop .\#dashboard -c make dev-env-cli-up
|
||||
|
||||
- name: Run e2e tests
|
||||
run: nix develop .\#dashboard -c pnpm e2e
|
||||
|
||||
- name: Run e2e onboarding tests
|
||||
run: nix develop .\#dashboard -c pnpm e2e:onboarding
|
||||
|
||||
- name: Run e2e local tests
|
||||
run: nix develop .\#dashboard -c pnpm e2e:local
|
||||
|
||||
- name: Encrypt Playwright report
|
||||
if: failure()
|
||||
run: |
|
||||
tar -czf playwright-report.tar.gz playwright-report/
|
||||
openssl enc -aes-256-cbc -salt -pbkdf2 -iter 100000 \
|
||||
-in playwright-report.tar.gz \
|
||||
-out playwright-report.tar.gz.enc \
|
||||
-k "${{ secrets.PLAYWRIGHT_REPORT_ENCRYPTION_KEY }}"
|
||||
rm playwright-report.tar.gz
|
||||
|
||||
- name: Upload encrypted Playwright report
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: encrypted-playwright-report-${{ github.run_id }}
|
||||
path: dashboard/playwright-report.tar.gz.enc
|
||||
retention-days: 1
|
||||
|
||||
- name: "Store Nix cache"
|
||||
uses: ./.github/actions/cache-nix
|
||||
with:
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
if: always()
|
||||
105
.github/workflows/dashboard_wf_release.yaml
vendored
105
.github/workflows/dashboard_wf_release.yaml
vendored
@@ -1,105 +0,0 @@
|
||||
---
|
||||
name: 'dashboard: release'
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
GIT_REF:
|
||||
required: true
|
||||
type: string
|
||||
VERSION:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID:
|
||||
required: true
|
||||
NIX_CACHE_PUB_KEY:
|
||||
required: true
|
||||
NIX_CACHE_PRIV_KEY:
|
||||
required: true
|
||||
VERCEL_TEAM_ID:
|
||||
required: true
|
||||
VERCEL_PROJECT_ID:
|
||||
required: true
|
||||
VERCEL_DEPLOY_TOKEN:
|
||||
required: true
|
||||
DISCORD_WEBHOOK:
|
||||
required: false
|
||||
GH_PAT:
|
||||
required: true
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
deploy-vercel:
|
||||
uses: ./.github/workflows/wf_deploy_vercel.yaml
|
||||
with:
|
||||
NAME: dashboard
|
||||
GIT_REF: ${{ inputs.GIT_REF }}
|
||||
ENVIRONMENT: production
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
VERCEL_TEAM_ID: ${{ secrets.VERCEL_TEAM_ID }}
|
||||
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
|
||||
VERCEL_DEPLOY_TOKEN: ${{ secrets.VERCEL_DEPLOY_TOKEN }}
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
|
||||
build_artifacts:
|
||||
uses: ./.github/workflows/wf_build_artifacts.yaml
|
||||
with:
|
||||
NAME: dashboard
|
||||
PATH: dashboard
|
||||
GIT_REF: ${{ inputs.GIT_REF }}
|
||||
VERSION: ${{ inputs.VERSION }}
|
||||
DOCKER: true
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
|
||||
push-docker:
|
||||
uses: ./.github/workflows/wf_docker_push_image.yaml
|
||||
needs:
|
||||
- build_artifacts
|
||||
with:
|
||||
NAME: dashboard
|
||||
PATH: dashboard
|
||||
VERSION: ${{ inputs.VERSION }}
|
||||
secrets:
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
bump-cli:
|
||||
name: Bump Dashboard version in the Nhost CLI
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- push-docker
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
token: ${{ secrets.GH_PAT }}
|
||||
|
||||
- name: Bump version in source code
|
||||
run: |
|
||||
find cli -type f -exec sed -i 's/"nhost\/dashboard:[^"]*"/"nhost\/dashboard:${{ inputs.VERSION }}"/g' {} +
|
||||
sed -i 's/"nhost\/dashboard:[^"]*"/"nhost\/dashboard:${{ inputs.VERSION }}"/g' docs/reference/cli/commands.mdx
|
||||
|
||||
- name: "Create Pull Request"
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
token: ${{ secrets.GH_PAT }}
|
||||
title: "chore(cli): bump nhost/dashboard to ${{ inputs.VERSION }}"
|
||||
commit-message: "chore: bump nhost/dashboard to ${{ inputs.VERSION }}"
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||
body: |
|
||||
This PR bumps the Nhost Dashboard Docker image to version ${{ inputs.VERSION }}.
|
||||
branch: bump-dashboard-version
|
||||
base: main
|
||||
delete-branch: true
|
||||
11
.github/workflows/docs_checks.yaml
vendored
11
.github/workflows/docs_checks.yaml
vendored
@@ -27,21 +27,10 @@ on:
|
||||
|
||||
# nhost-js
|
||||
- packages/nhost-js/**
|
||||
|
||||
# apis
|
||||
- 'services/auth/docs/openapi.yaml'
|
||||
- 'services/storage/controller/openapi.yaml'
|
||||
|
||||
# cli
|
||||
- cli/**
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('push-{0}', github.sha) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
check-permissions:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
5
.github/workflows/examples_demos_checks.yaml
vendored
5
.github/workflows/examples_demos_checks.yaml
vendored
@@ -41,10 +41,6 @@ on:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('push-{0}', github.sha) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
check-permissions:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -81,7 +77,6 @@ jobs:
|
||||
GIT_REF: ${{ github.sha }}
|
||||
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
|
||||
DOCKER: false
|
||||
OS_MATRIX: '["blacksmith-2vcpu-ubuntu-2404"]'
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
|
||||
@@ -41,10 +41,6 @@ on:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('push-{0}', github.sha) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
check-permissions:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -81,7 +77,6 @@ jobs:
|
||||
GIT_REF: ${{ github.sha }}
|
||||
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
|
||||
DOCKER: false
|
||||
OS_MATRIX: '["blacksmith-2vcpu-ubuntu-2404"]'
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
|
||||
@@ -41,10 +41,6 @@ on:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('push-{0}', github.sha) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
check-permissions:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -81,7 +77,6 @@ jobs:
|
||||
GIT_REF: ${{ github.sha }}
|
||||
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
|
||||
DOCKER: false
|
||||
OS_MATRIX: '["blacksmith-2vcpu-ubuntu-2404"]'
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
|
||||
6
.github/workflows/gen_ai_review.yaml
vendored
6
.github/workflows/gen_ai_review.yaml
vendored
@@ -21,8 +21,6 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
OPENAI_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
config.model: ${{ vars.GEN_AI_MODEL }}
|
||||
config.model_turbo: $${{ vars.GEN_AI_MODEL_TURBO }}
|
||||
config.max_model_tokens: 200000
|
||||
config.custom_model_max_tokens: 200000
|
||||
config.model: "anthropic/claude-sonnet-4-20250514"
|
||||
config.model_turbo: "anthropic/claude-sonnet-4-20250514"
|
||||
ignore.glob: "['pnpm-lock.yaml','**/pnpm-lock.yaml', 'vendor/**','**/client_gen.go','**/models_gen.go','**/generated.go','**/*.gen.go']"
|
||||
|
||||
10
.github/workflows/gen_codeql-analysis.yml
vendored
10
.github/workflows/gen_codeql-analysis.yml
vendored
@@ -1,6 +1,8 @@
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push: {}
|
||||
pull_request: {}
|
||||
schedule:
|
||||
- cron: '20 23 * * 3'
|
||||
|
||||
@@ -16,7 +18,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'javascript', 'go' ]
|
||||
language: [ 'javascript' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||
|
||||
@@ -26,7 +28,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v4
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -37,7 +39,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v4
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -51,4 +53,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v4
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
@@ -18,12 +18,12 @@ jobs:
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}:role/github-actions-nhost-${{ github.event.repository.name }}
|
||||
aws-region: eu-central-1
|
||||
|
||||
- uses: nixbuild/nix-quick-install-action@v34
|
||||
- uses: nixbuild/nix-quick-install-action@v26
|
||||
with:
|
||||
nix_version: 2.16.2
|
||||
nix_conf: |
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
"
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: Update dependencies
|
||||
|
||||
8
.github/workflows/nhost-js_checks.yaml
vendored
8
.github/workflows/nhost-js_checks.yaml
vendored
@@ -34,18 +34,10 @@ on:
|
||||
|
||||
# nhost-js
|
||||
- 'packages/nhost-js/**'
|
||||
|
||||
# apis
|
||||
- 'services/auth/docs/openapi.yaml'
|
||||
- 'services/storage/controller/openapi.yaml'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('push-{0}', github.sha) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
check-permissions:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
6
.github/workflows/nixops_checks.yaml
vendored
6
.github/workflows/nixops_checks.yaml
vendored
@@ -17,10 +17,6 @@ on:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('push-{0}', github.sha) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
check-permissions:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -56,7 +52,7 @@ jobs:
|
||||
PATH: nixops
|
||||
GIT_REF: ${{ github.sha }}
|
||||
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
|
||||
DOCKER: true
|
||||
DOCKER: false
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
|
||||
35
.github/workflows/nixops_wf_release.yaml
vendored
35
.github/workflows/nixops_wf_release.yaml
vendored
@@ -1,35 +0,0 @@
|
||||
---
|
||||
name: "nixops: release"
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'flake.lock'
|
||||
- 'nixops/project.nix'
|
||||
|
||||
jobs:
|
||||
build_artifacts:
|
||||
uses: ./.github/workflows/wf_build_artifacts.yaml
|
||||
with:
|
||||
NAME: nixops
|
||||
PATH: nixops
|
||||
GIT_REF: ${{ inputs.GIT_REF }}
|
||||
VERSION: latest
|
||||
DOCKER: true
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
|
||||
push-docker:
|
||||
uses: ./.github/workflows/wf_docker_push_image.yaml
|
||||
needs:
|
||||
- build_artifacts
|
||||
with:
|
||||
NAME: nixops
|
||||
PATH: nixops
|
||||
VERSION: latest
|
||||
secrets:
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
6
.github/workflows/storage_checks.yaml
vendored
6
.github/workflows/storage_checks.yaml
vendored
@@ -21,15 +21,11 @@ on:
|
||||
- 'vendor/**'
|
||||
|
||||
# storage
|
||||
- 'services/storage/**'
|
||||
- 'storage/**'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('push-{0}', github.sha) }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
check-permissions:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
14
.github/workflows/wf_build_artifacts.yaml
vendored
14
.github/workflows/wf_build_artifacts.yaml
vendored
@@ -17,10 +17,6 @@ on:
|
||||
DOCKER:
|
||||
type: boolean
|
||||
required: true
|
||||
OS_MATRIX:
|
||||
type: string
|
||||
required: false
|
||||
default: '["blacksmith-4vcpu-ubuntu-2404-arm", "blacksmith-2vcpu-ubuntu-2404"]'
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID:
|
||||
required: true
|
||||
@@ -41,7 +37,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: ${{ fromJSON(inputs.OS_MATRIX) }}
|
||||
os: [blacksmith-4vcpu-ubuntu-2404-arm, blacksmith-2vcpu-ubuntu-2404]
|
||||
fail-fast: true
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
@@ -53,14 +49,8 @@ jobs:
|
||||
with:
|
||||
ref: ${{ inputs.GIT_REF }}
|
||||
|
||||
- name: "Validate PR title"
|
||||
uses: ./.github/actions/validate-pr-title
|
||||
with:
|
||||
pr_title: ${{ github.event.pull_request.title }}
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
- name: Configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions-nhost-${{ github.event.repository.name }}
|
||||
aws-region: eu-central-1
|
||||
|
||||
8
.github/workflows/wf_check.yaml
vendored
8
.github/workflows/wf_check.yaml
vendored
@@ -44,19 +44,13 @@ jobs:
|
||||
with:
|
||||
ref: ${{ inputs.GIT_REF }}
|
||||
|
||||
- name: "Validate PR title"
|
||||
uses: ./.github/actions/validate-pr-title
|
||||
with:
|
||||
pr_title: ${{ github.event.pull_request.title }}
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
- name: Collect Workflow Telemetry
|
||||
uses: catchpoint/workflow-telemetry-action@v2
|
||||
with:
|
||||
comment_on_pr: false
|
||||
|
||||
- name: Configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions-nhost-${{ github.event.repository.name }}
|
||||
aws-region: eu-central-1
|
||||
|
||||
151
.github/workflows/wf_dashboard_e2e_staging.yaml
vendored
Normal file
151
.github/workflows/wf_dashboard_e2e_staging.yaml
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
---
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
NAME:
|
||||
type: string
|
||||
required: true
|
||||
PATH:
|
||||
type: string
|
||||
required: true
|
||||
GIT_REF:
|
||||
type: string
|
||||
required: false
|
||||
NHOST_TEST_DASHBOARD_URL:
|
||||
type: string
|
||||
required: true
|
||||
NHOST_TEST_PROJECT_NAME:
|
||||
type: string
|
||||
required: true
|
||||
NHOST_TEST_ORGANIZATION_NAME:
|
||||
type: string
|
||||
required: true
|
||||
NHOST_TEST_ORGANIZATION_SLUG:
|
||||
type: string
|
||||
required: true
|
||||
NHOST_TEST_PERSONAL_ORG_SLUG:
|
||||
type: string
|
||||
required: true
|
||||
NHOST_TEST_PROJECT_SUBDOMAIN:
|
||||
type: string
|
||||
required: true
|
||||
NHOST_TEST_PROJECT_REMOTE_SCHEMA_NAME:
|
||||
type: string
|
||||
required: true
|
||||
NHOST_PRO_TEST_PROJECT_NAME:
|
||||
type: string
|
||||
required: true
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID:
|
||||
required: true
|
||||
NIX_CACHE_PUB_KEY:
|
||||
required: true
|
||||
NIX_CACHE_PRIV_KEY:
|
||||
required: true
|
||||
DASHBOARD_VERCEL_DEPLOY_TOKEN:
|
||||
required: true
|
||||
DASHBOARD_VERCEL_TEAM_ID:
|
||||
required: true
|
||||
DASHBOARD_STAGING_VERCEL_PROJECT_ID:
|
||||
required: true
|
||||
NHOST_TEST_USER_EMAIL:
|
||||
required: true
|
||||
NHOST_TEST_USER_PASSWORD:
|
||||
required: true
|
||||
NHOST_TEST_PROJECT_ADMIN_SECRET:
|
||||
required: true
|
||||
NHOST_TEST_FREE_USER_EMAILS:
|
||||
required: true
|
||||
PLAYWRIGHT_REPORT_ENCRYPTION_KEY:
|
||||
required: true
|
||||
|
||||
env:
|
||||
NEXT_PUBLIC_ENV: dev
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
NHOST_TEST_DASHBOARD_URL: ${{ inputs.NHOST_TEST_DASHBOARD_URL }}
|
||||
NHOST_TEST_PROJECT_NAME: ${{ inputs.NHOST_TEST_PROJECT_NAME }}
|
||||
NHOST_TEST_ORGANIZATION_NAME: ${{ inputs.NHOST_TEST_ORGANIZATION_NAME }}
|
||||
NHOST_TEST_ORGANIZATION_SLUG: ${{ inputs.NHOST_TEST_ORGANIZATION_SLUG }}
|
||||
NHOST_TEST_PERSONAL_ORG_SLUG: ${{ inputs.NHOST_TEST_PERSONAL_ORG_SLUG }}
|
||||
NHOST_TEST_PROJECT_SUBDOMAIN: ${{ inputs.NHOST_TEST_PROJECT_SUBDOMAIN }}
|
||||
NHOST_TEST_PROJECT_REMOTE_SCHEMA_NAME: ${{ inputs.NHOST_TEST_PROJECT_REMOTE_SCHEMA_NAME }}
|
||||
NHOST_PRO_TEST_PROJECT_NAME: ${{ inputs.NHOST_PRO_TEST_PROJECT_NAME }}
|
||||
NHOST_TEST_USER_EMAIL: ${{ secrets.NHOST_TEST_USER_EMAIL }}
|
||||
NHOST_TEST_USER_PASSWORD: ${{ secrets.NHOST_TEST_USER_PASSWORD }}
|
||||
NHOST_TEST_PROJECT_ADMIN_SECRET: ${{ secrets.NHOST_TEST_PROJECT_ADMIN_SECRET }}
|
||||
NHOST_TEST_FREE_USER_EMAILS: ${{ secrets.NHOST_TEST_FREE_USER_EMAILS }}
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: blacksmith-2vcpu-ubuntu-2404
|
||||
timeout-minutes: 30
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ inputs.PATH }}
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
actions: read
|
||||
|
||||
steps:
|
||||
- name: "Check out repository"
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
ref: ${{ inputs.GIT_REF }}
|
||||
|
||||
- name: Collect Workflow Telemetry
|
||||
uses: catchpoint/workflow-telemetry-action@v2
|
||||
with:
|
||||
comment_on_pr: false
|
||||
|
||||
- name: Configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions-nhost-${{ github.event.repository.name }}
|
||||
aws-region: eu-central-1
|
||||
|
||||
- name: Setup Nix with Cache
|
||||
uses: ./.github/actions/setup-nix
|
||||
with:
|
||||
NAME: ${{ inputs.NAME }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Start CLI
|
||||
run: |
|
||||
nix develop .\#dashboard -c make dev-env-cli-up
|
||||
|
||||
- name: Run e2e tests
|
||||
run: nix develop .\#dashboard -c pnpm e2e
|
||||
|
||||
- name: Run e2e onboarding tests
|
||||
run: nix develop .\#dashboard -c pnpm e2e:onboarding
|
||||
|
||||
- name: Run e2e local tests
|
||||
run: nix develop .\#dashboard -c pnpm e2e:local
|
||||
|
||||
- name: Encrypt Playwright report
|
||||
if: failure()
|
||||
run: |
|
||||
tar -czf playwright-report.tar.gz playwright-report/
|
||||
openssl enc -aes-256-cbc -salt -pbkdf2 -iter 100000 \
|
||||
-in playwright-report.tar.gz \
|
||||
-out playwright-report.tar.gz.enc \
|
||||
-k "${{ secrets.PLAYWRIGHT_REPORT_ENCRYPTION_KEY }}"
|
||||
rm playwright-report.tar.gz
|
||||
|
||||
- name: Upload encrypted Playwright report
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: encrypted-playwright-report-${{ github.run_id }}
|
||||
path: dashboard/playwright-report.tar.gz.enc
|
||||
retention-days: 1
|
||||
|
||||
- name: "Store Nix cache"
|
||||
uses: ./.github/actions/cache-nix
|
||||
with:
|
||||
NIX_CACHE_PRIV_KEY: ${{ secrets.NIX_CACHE_PRIV_KEY }}
|
||||
if: always()
|
||||
6
.github/workflows/wf_deploy_vercel.yaml
vendored
6
.github/workflows/wf_deploy_vercel.yaml
vendored
@@ -27,8 +27,6 @@ on:
|
||||
required: true
|
||||
DISCORD_WEBHOOK:
|
||||
required: false
|
||||
TURBO_TOKEN:
|
||||
required: true
|
||||
|
||||
outputs:
|
||||
preview-url:
|
||||
@@ -54,7 +52,7 @@ jobs:
|
||||
ref: ${{ inputs.GIT_REF }}
|
||||
|
||||
- name: Configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions-nhost-${{ github.event.repository.name }}
|
||||
aws-region: eu-central-1
|
||||
@@ -71,8 +69,6 @@ jobs:
|
||||
env:
|
||||
VERCEL_ORG_ID: ${{ secrets.VERCEL_TEAM_ID }}
|
||||
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: nhost
|
||||
run: |
|
||||
TARGET_OPTS="--target=${{ inputs.ENVIRONMENT }}"
|
||||
echo "Deploying to: ${{ inputs.ENVIRONMENT }}..."
|
||||
|
||||
2
.github/workflows/wf_docker_push_image.yaml
vendored
2
.github/workflows/wf_docker_push_image.yaml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: "Check out repository"
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
@@ -33,13 +33,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: "Check out repository"
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- name: Configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions-nhost-${{ github.event.repository.name }}
|
||||
aws-region: eu-central-1
|
||||
|
||||
2
.github/workflows/wf_release_npm.yaml
vendored
2
.github/workflows/wf_release_npm.yaml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions-nhost-${{ github.event.repository.name }}
|
||||
aws-region: eu-central-1
|
||||
|
||||
@@ -7,8 +7,6 @@ linters:
|
||||
settings:
|
||||
funlen:
|
||||
lines: 65
|
||||
wsl_v5:
|
||||
allow-whole-block: true
|
||||
disable:
|
||||
- canonicalheader
|
||||
- depguard
|
||||
@@ -32,7 +30,6 @@ linters:
|
||||
- linters:
|
||||
- funlen
|
||||
- ireturn
|
||||
- goconst
|
||||
path: _test\.go
|
||||
- linters:
|
||||
- lll
|
||||
|
||||
@@ -24,20 +24,28 @@ If you find an Issue that addresses the problem you're having, please add your r
|
||||
|
||||
### Pull Requests
|
||||
|
||||
Please have a look at our [developers guide](https://github.com/nhost/nhost/blob/main/DEVELOPERS.md) to start coding!
|
||||
|
||||
PRs to our libraries are always welcome and can be a quick way to get your fix or improvement slated for the next release. In general, PRs should:
|
||||
|
||||
## Monorepo Structure
|
||||
- Only fix/add the functionality in question **OR** address wide-spread whitespace/style issues, not both.
|
||||
- Add unit or integration tests for fixed or changed functionality (if a test suite exists).
|
||||
- Address a single concern in the least number of changed lines as possible.
|
||||
- Include documentation in the repo or on our [docs site](https://docs.nhost.io).
|
||||
- Be accompanied by a complete Pull Request template (loaded automatically when a PR is created).
|
||||
|
||||
This repository is a monorepo that contains multiple packages and applications. The structure is as follows:
|
||||
For changes that address core functionality or require breaking changes (e.g., a major release), it's best to open an Issue to discuss your proposal first. This is not required but can save time creating and reviewing changes.
|
||||
|
||||
- `cli` - The Nhost CLI
|
||||
- `dashboard` - The Nhost Dashboard
|
||||
- `docs` - Documentation
|
||||
- `examples` - Various example projects
|
||||
- `packages/nhost-js` - The Nhost JavaScript/TypeScript SDK
|
||||
- `services/auth` - Nhost Authentication service
|
||||
- `services/storage` - Nhost Storage service
|
||||
- `tools/codegen` - Internal code generation tool to build the SDK
|
||||
- `tools/mintlify-openapi` - Internal tool to generate reference documentation for Mintlify from an OpenAPI spec.
|
||||
In general, we follow the ["fork-and-pull" Git workflow](https://github.com/susam/gitpr)
|
||||
|
||||
For details about those projects and how to contribure, please refer to their respective `README.md` and `CONTRIBUTING.md` files.
|
||||
1. Fork the repository to your own Github account
|
||||
2. Clone the project to your machine
|
||||
3. Create a branch locally with a succinct but descriptive name. All changes should be part of a branch and submitted as a pull request - your branches should be prefixed with one of:
|
||||
- `bug/` for bug fixes
|
||||
- `feat/` for features
|
||||
- `chore/` for configuration changes
|
||||
- `docs/` for documentation changes
|
||||
4. Commit changes to the branch
|
||||
5. Following any formatting and testing guidelines specific to this repo
|
||||
6. Push changes to your fork
|
||||
7. Open a PR in our repository and follow the PR template to review the changes efficiently.
|
||||
|
||||
100
DEVELOPERS.md
Normal file
100
DEVELOPERS.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Developer Guide
|
||||
|
||||
## Requirements
|
||||
|
||||
### Node.js v20 or later
|
||||
|
||||
### [pnpm](https://pnpm.io/) package manager
|
||||
|
||||
The easiest way to install `pnpm` if it's not installed on your machine yet is to use `npm`:
|
||||
|
||||
```sh
|
||||
$ npm install -g pnpm
|
||||
```
|
||||
|
||||
### [Nhost CLI](https://docs.nhost.io/platform/cli/local-development)
|
||||
|
||||
- The CLI is primarily used for running the E2E tests
|
||||
- Please refer to the [installation guide](https://docs.nhost.io/platform/cli/local-development) if you have not installed it yet
|
||||
|
||||
## File Structure
|
||||
|
||||
The repository is organized as a monorepo, with the following structure (only relevant folders are shown):
|
||||
|
||||
```
|
||||
assets/ # Assets used in the README
|
||||
config/ # Configuration files for the monorepo
|
||||
dashboard/ # Dashboard
|
||||
docs/ # Documentation website
|
||||
examples/ # Example projects
|
||||
packages/ # Core packages
|
||||
integrations/ # These are packages that rely on the core packages
|
||||
```
|
||||
|
||||
## Get started
|
||||
|
||||
### Installation
|
||||
|
||||
First, clone this repository:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/nhost/nhost
|
||||
```
|
||||
|
||||
Then, install the dependencies with `pnpm`:
|
||||
|
||||
```sh
|
||||
$ cd nhost
|
||||
$ pnpm install
|
||||
```
|
||||
|
||||
### Development
|
||||
|
||||
Although package references are correctly updated on the fly for TypeScript, example projects and the dashboard won't see the changes because they are depending on the build output. To fix this, you can run packages in development mode.
|
||||
|
||||
Running packages in development mode from the root folder is as simple as:
|
||||
|
||||
```sh
|
||||
$ pnpm dev
|
||||
```
|
||||
|
||||
Our packages are linked together using [PNPM's workspace](https://pnpm.io/workspaces) feature. Next.js and Vite automatically detect changes in the dependencies and rebuild everything, so the changes will be reflected in the examples and the dashboard.
|
||||
|
||||
**Note:** It's possible that Next.js or Vite throw an error when you run `pnpm dev`. Restarting the process should fix it.
|
||||
|
||||
### Use Examples
|
||||
|
||||
Examples are a great way to test your changes in practice. Make sure you've `pnpm dev` running in your terminal and then run an example.
|
||||
|
||||
Let's follow the instructions to run [react-apollo example](https://github.com/nhost/nhost/blob/main/examples/react-apollo/README.md).
|
||||
|
||||
## Edit Documentation
|
||||
|
||||
The easier way to contribute to our documentation is to go to the `docs` folder and follow the [instructions to start local development](https://github.com/nhost/nhost/blob/main/docs/README.md):
|
||||
|
||||
```sh
|
||||
$ cd docs
|
||||
# not necessary if you've already done this step somewhere in the repository
|
||||
$ pnpm install
|
||||
$ pnpm start
|
||||
```
|
||||
|
||||
## Run Test Suites
|
||||
|
||||
### Unit Tests
|
||||
|
||||
You can run the unit tests with the following command from the repository root:
|
||||
|
||||
```sh
|
||||
$ pnpm test
|
||||
```
|
||||
|
||||
### E2E Tests
|
||||
|
||||
Each package that defines end-to-end tests embeds their own Nhost configuration, that will be automatically when running the tests. As a result, you must make sure you are not running the Nhost CLI before running the tests.
|
||||
|
||||
You can run the e2e tests with the following command from the repository root:
|
||||
|
||||
```sh
|
||||
$ pnpm e2e
|
||||
```
|
||||
16
Makefile
16
Makefile
@@ -1,16 +0,0 @@
|
||||
.PHONY: envrc-install
|
||||
envrc-install: ## Copy envrc.sample to all project folders
|
||||
@for f in $$(find . -name "project.nix"); do \
|
||||
echo "Copying envrc.sample to $$(dirname $$f)/.envrc"; \
|
||||
cp ./envrc.sample $$(dirname $$f)/.envrc; \
|
||||
done
|
||||
|
||||
.PHONY: nixops-container-env
|
||||
nixops-container-env: ## Enter a NixOS container environment
|
||||
docker run \
|
||||
-it \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v ./:/build \
|
||||
-w /build \
|
||||
nixops:0.0.0-dev \
|
||||
bash
|
||||
@@ -12,7 +12,7 @@
|
||||
<span> • </span>
|
||||
<a href="https://nhost.io/blog">Blog</a>
|
||||
<span> • </span>
|
||||
<a href="https://x.com/nhost">X</a>
|
||||
<a href="https://twitter.com/nhost">Twitter</a>
|
||||
<span> • </span>
|
||||
<a href="https://nhost.io/discord">Discord</a>
|
||||
<span> • </span>
|
||||
@@ -33,10 +33,10 @@ Nhost consists of open source software:
|
||||
|
||||
- Database: [PostgreSQL](https://www.postgresql.org/)
|
||||
- Instant GraphQL API: [Hasura](https://hasura.io/)
|
||||
- Authentication: [Auth](https://github.com/nhost/nhost/tree/main/services/auth)
|
||||
- Storage: [Storage](https://github.com/nhost/nhost/tree/main/services/storage)
|
||||
- Authentication: [Hasura Auth](https://github.com/nhost/hasura-auth/)
|
||||
- Storage: [Hasura Storage](https://github.com/nhost/hasura-storage)
|
||||
- Serverless Functions: Node.js (JavaScript and TypeScript)
|
||||
- [Nhost CLI](https://github.com/nhost/nhost/tree/main/cli) for local development
|
||||
- [Nhost CLI](https://docs.nhost.io/platform/cli/local-development) for local development
|
||||
|
||||
## Architecture of Nhost
|
||||
|
||||
@@ -107,6 +107,7 @@ Nhost is frontend agnostic, which means Nhost works with all frontend frameworks
|
||||
# Resources
|
||||
|
||||
- Start developing locally with the [Nhost CLI](https://docs.nhost.io/platform/cli/local-development)
|
||||
|
||||
## Nhost Clients
|
||||
|
||||
- [JavaScript/TypeScript](https://docs.nhost.io/reference/javascript/nhost-js/main)
|
||||
|
||||
@@ -2,7 +2,5 @@
|
||||
// $schema provides code completion hints to IDEs.
|
||||
"$schema": "https://github.com/IBM/audit-ci/raw/main/docs/schema.json",
|
||||
"moderate": true,
|
||||
"allowlist": [
|
||||
"GHSA-9965-vmph-33xx" // https://github.com/advisories/GHSA-9965-vmph-33xx Update package once have a fix
|
||||
]
|
||||
"allowlist": ["vue-template-compiler", { "id": "CVE-2025-48068", "path": "next" }]
|
||||
}
|
||||
|
||||
@@ -54,11 +54,6 @@ get-version: ## Return version
|
||||
@echo $(VERSION)
|
||||
|
||||
|
||||
.PHONY: develop
|
||||
develop: ## Start a nix develop shell
|
||||
nix develop .\#$(NAME)
|
||||
|
||||
|
||||
.PHONY: _check-pre
|
||||
_check-pre: ## Pre-checks before running nix flake check
|
||||
|
||||
@@ -110,11 +105,6 @@ build-docker-image: ## Build docker container for native architecture
|
||||
skopeo copy --insecure-policy dir:./result docker-daemon:$(NAME):$(VERSION)
|
||||
|
||||
|
||||
.PHONY: build-docker-image-import-bare
|
||||
build-docker-image-import-bare:
|
||||
skopeo copy --insecure-policy dir:./result docker-daemon:$(NAME):$(VERSION)
|
||||
|
||||
|
||||
.PHONY: dev-env-up
|
||||
dev-env-up: _dev-env-build _dev-env-up ## Starts development environment
|
||||
|
||||
|
||||
20
cli/.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
20
cli/.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
## Description
|
||||
<!--
|
||||
Use one of the following title prefix to categorize the pull request:
|
||||
feat: mark this pull request as a feature
|
||||
fix: mark this pull request as a bug fix
|
||||
chore: mark this pull request as a maintenance item
|
||||
|
||||
To auto merge this pull request when it was approved
|
||||
by another member of the organization: set the label `auto-merge`
|
||||
-->
|
||||
## Problem
|
||||
A short description of the problem this PR is addressing.
|
||||
|
||||
## Solution
|
||||
A short description of the chosen method to resolve the problem
|
||||
with an overview of the logic and implementation details when needed.
|
||||
|
||||
## Notes
|
||||
Other notes that you want to share but do not fit into _Problem_ or _Solution_.
|
||||
|
||||
36
cli/.github/cert.sh
vendored
Executable file
36
cli/.github/cert.sh
vendored
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
mkdir -p /tmp/letsencrypt
|
||||
|
||||
echo "Generating SSL certificate for hostnames: local.nhost.run, local.graphql.nhost.run, local.auth.nhost.run, local.storage.nhost.run, local.functions.nhost.run, local.mail.nhost.run"
|
||||
docker run --rm \
|
||||
--name certbot \
|
||||
-e AWS_ACCESS_KEY_ID \
|
||||
-e AWS_SECRET_ACCESS_KEY \
|
||||
-e AWS_SESSION_TOKEN \
|
||||
-e AWS_REGION \
|
||||
-v /tmp/letsencrypt:/etc/letsencrypt \
|
||||
-v /tmp/letsencrypt:/var/lib/letsencrypt \
|
||||
certbot/dns-route53 certonly --dns-route53 --dns-route53-propagation-seconds 60 \
|
||||
-d local.auth.nhost.run \
|
||||
-d local.dashboard.nhost.run \
|
||||
-d local.db.nhost.run \
|
||||
-d local.functions.nhost.run \
|
||||
-d local.graphql.nhost.run \
|
||||
-d local.hasura.nhost.run \
|
||||
-d local.mailhog.nhost.run \
|
||||
-d local.storage.nhost.run \
|
||||
-d *.auth.local.nhost.run \
|
||||
-d *.dashboard.local.nhost.run \
|
||||
-d *.db.local.nhost.run \
|
||||
-d *.functions.local.nhost.run \
|
||||
-d *.graphql.local.nhost.run \
|
||||
-d *.hasura.local.nhost.run \
|
||||
-d *.mailhog.local.nhost.run \
|
||||
-d *.storage.local.nhost.run \
|
||||
-m 'admin@nhost.io' --non-interactive --agree-tos --server https://acme-v02.api.letsencrypt.org/directory
|
||||
|
||||
sudo cp /tmp/letsencrypt/live/local.db.nhost.run/fullchain.pem ssl/.ssl/
|
||||
sudo cp /tmp/letsencrypt/live/local.db.nhost.run/privkey.pem ssl/.ssl/
|
||||
8
cli/.github/labeler.yml
vendored
Normal file
8
cli/.github/labeler.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
labels:
|
||||
'feature':
|
||||
- '^(?i:feat)'
|
||||
- '^(?i:feature)'
|
||||
'fix':
|
||||
- '^(?i:fix)'
|
||||
'chore':
|
||||
- '^(?i:chore)'
|
||||
39
cli/.github/release-drafter.yml
vendored
Normal file
39
cli/.github/release-drafter.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
name-template: 'v$RESOLVED_VERSION'
|
||||
tag-template: 'v$RESOLVED_VERSION'
|
||||
categories:
|
||||
- title: '🚀 Features'
|
||||
label: 'feature'
|
||||
- title: '🐛 Bug Fixes'
|
||||
label: 'fix'
|
||||
- title: '🧰 Maintenance'
|
||||
label: 'chore'
|
||||
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
|
||||
change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
|
||||
version-resolver:
|
||||
major:
|
||||
labels:
|
||||
- 'major'
|
||||
minor:
|
||||
labels:
|
||||
- 'minor'
|
||||
patch:
|
||||
labels:
|
||||
- 'patch'
|
||||
default: patch
|
||||
autolabeler:
|
||||
- label: 'feature'
|
||||
title:
|
||||
- '/^feat/i'
|
||||
- '/^feature/i'
|
||||
- label: 'fix'
|
||||
title:
|
||||
- '/^fix/i'
|
||||
- label: 'chore'
|
||||
title:
|
||||
- '/^chore/i'
|
||||
prerelease: true
|
||||
template: |
|
||||
## Changes
|
||||
|
||||
$CHANGES
|
||||
|
||||
16
cli/.github/stale.yml
vendored
Normal file
16
cli/.github/stale.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
|
||||
daysUntilStale: 180
|
||||
daysUntilClose: 7
|
||||
limitPerRun: 30
|
||||
onlyLabels: []
|
||||
exemptLabels: []
|
||||
|
||||
exemptProjects: false
|
||||
exemptMilestones: false
|
||||
exemptAssignees: false
|
||||
staleLabel: stale
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
17
cli/.github/workflows/assign_labels.yml
vendored
Normal file
17
cli/.github/workflows/assign_labels.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
# this workflow will run on all pull requests opened but in the context of the base of the pull request.
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened]
|
||||
|
||||
name: "assign labels"
|
||||
jobs:
|
||||
# labeler will label pull requests based on their title.
|
||||
# the configuration is at .github/labeler.yml.
|
||||
label_pull_request:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Label Pull Request
|
||||
uses: jimschubert/labeler-action@v2
|
||||
with:
|
||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
53
cli/.github/workflows/build-cert-weekly.yaml.disabled
vendored
Normal file
53
cli/.github/workflows/build-cert-weekly.yaml.disabled
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
---
|
||||
name: "build certificate weekly"
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * 1'
|
||||
|
||||
jobs:
|
||||
run:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v2
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::796351718684:role/github-actions-nhost-cli
|
||||
aws-region: eu-central-1
|
||||
|
||||
- name: fetch let's encrypt cert
|
||||
id: certs
|
||||
run: |
|
||||
.github/cert.sh
|
||||
|
||||
echo "CERT_FULL_CHAIN<<EOF" >> $GITHUB_OUTPUT
|
||||
sudo cat /tmp/letsencrypt/live/local.db.nhost.run/fullchain.pem >> "$GITHUB_OUTPUT"
|
||||
echo EOF >> $GITHUB_OUTPUT
|
||||
|
||||
echo "CERT_PRIV_KEY<<EOF" >> $GITHUB_OUTPUT
|
||||
sudo cat /tmp/letsencrypt/live/local.db.nhost.run/privkey.pem >> "$GITHUB_OUTPUT"
|
||||
echo EOF >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- uses: hmanzur/actions-set-secret@v2.0.0
|
||||
with:
|
||||
name: 'CERT_FULL_CHAIN'
|
||||
value: "${{ steps.certs.outputs.CERT_FULL_CHAIN }}"
|
||||
repository: nhost/cli
|
||||
token: ${{ secrets.GH_PAT }}
|
||||
|
||||
- uses: hmanzur/actions-set-secret@v2.0.0
|
||||
with:
|
||||
name: 'CERT_PRIV_KEY'
|
||||
value: "${{ steps.certs.outputs.CERT_PRIV_KEY }}"
|
||||
repository: nhost/cli
|
||||
token: ${{ secrets.GH_PAT }}
|
||||
27
cli/.github/workflows/checks.yaml
vendored
Normal file
27
cli/.github/workflows/checks.yaml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
name: "check and build"
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
uses: ./.github/workflows/wf_check.yaml
|
||||
secrets:
|
||||
NHOST_PAT: ${{ secrets.NHOST_PAT }}
|
||||
|
||||
build_artifacts:
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
GOOS: ["darwin", "linux"]
|
||||
GOARCH: ["amd64", "arm64"]
|
||||
uses: ./.github/workflows/wf_build_artifacts.yaml
|
||||
with:
|
||||
GOOS: ${{ matrix.GOOS }}
|
||||
GOARCH: ${{ matrix.GOARCH }}
|
||||
VERSION: ${{ github.sha }}
|
||||
secrets:
|
||||
NHOST_PAT: ${{ secrets.NHOST_PAT }}
|
||||
56
cli/.github/workflows/codeql-analysis.yml
vendored
Normal file
56
cli/.github/workflows/codeql-analysis.yml
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push: {}
|
||||
pull_request: {}
|
||||
schedule:
|
||||
- cron: '20 23 * * 3'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'go' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
27
cli/.github/workflows/gen_ai_review.yaml
vendored
Normal file
27
cli/.github/workflows/gen_ai_review.yaml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
name: "gen: AI review"
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened, ready_for_review]
|
||||
issue_comment:
|
||||
jobs:
|
||||
pr_agent_job:
|
||||
if: ${{ github.event.sender.type != 'Bot' }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
name: Run pr agent on every pull request, respond to user comments
|
||||
steps:
|
||||
- name: PR Agent action step
|
||||
id: pragent
|
||||
uses: Codium-ai/pr-agent@v0.29
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
OPENAI_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
config.max_model_tokens: 100000
|
||||
config.model: "anthropic/claude-sonnet-4-20250514"
|
||||
config.model_turbo: "anthropic/claude-sonnet-4-20250514"
|
||||
ignore.glob: "['vendor/**','**/client_gen.go','**/models_gen.go','**/generated.go','**/*.gen.go']"
|
||||
91
cli/.github/workflows/gen_schedule_update_deps.yaml
vendored
Normal file
91
cli/.github/workflows/gen_schedule_update_deps.yaml
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
---
|
||||
name: "gen: update depenendencies"
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 2 1 2,5,8,11 *'
|
||||
|
||||
jobs:
|
||||
run:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}:role/github-actions-nhost-${{ github.event.repository.name }}
|
||||
aws-region: eu-central-1
|
||||
|
||||
- uses: nixbuild/nix-quick-install-action@v26
|
||||
with:
|
||||
nix_version: 2.16.2
|
||||
nix_conf: |
|
||||
experimental-features = nix-command flakes
|
||||
sandbox = false
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
substituters = https://cache.nixos.org/?priority=40 s3://nhost-nix-cache?region=eu-central-1&priority=50
|
||||
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
|
||||
- name: Cache nix store
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: /nix
|
||||
key: nix-update-deps-${{ hashFiles('flakes.nix', 'flake.lock') }}
|
||||
|
||||
- name: Update nix flakes
|
||||
run: nix flake update
|
||||
|
||||
- uses: shaunco/ssh-agent@git-repo-mapping
|
||||
with:
|
||||
ssh-private-key: |
|
||||
${{ secrets.NHOST_BE_DEPLOY_SSH_PRIVATE_KEY}}
|
||||
repo-mappings: |
|
||||
github.com/nhost/be
|
||||
|
||||
- name: Update golang dependencies
|
||||
run: |
|
||||
export GOPRIVATE=github.com/nhost/be
|
||||
nix develop -c bash -c "
|
||||
go mod tidy
|
||||
go get -u $(cat go.mod | grep nhost\/be | tr ' ' '@') ./...
|
||||
go mod tidy
|
||||
go mod vendor
|
||||
"
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: Update dependencies
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||
signoff: false
|
||||
branch: automated/update-deps
|
||||
delete-branch: true
|
||||
title: '[Scheduled] Update dependencies'
|
||||
body: |
|
||||
Dependencies updated
|
||||
|
||||
Note - If you see this PR and the checks haven't run, close and reopen the PR. See https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.md#triggering-further-workflow-runs
|
||||
labels: |
|
||||
dependencies
|
||||
draft: false
|
||||
|
||||
- name: "Cache nix store on s3"
|
||||
run: |
|
||||
echo ${{ secrets.NIX_CACHE_PRIV_KEY }} > cache-priv-key.pem
|
||||
nix build .\#devShells.x86_64-linux.default
|
||||
nix store sign --key-file cache-priv-key.pem --all
|
||||
nix copy --to s3://nhost-nix-cache\?region=eu-central-1 .\#devShells.x86_64-linux.default
|
||||
|
||||
- run: rm cache-priv-key.pem
|
||||
if: always()
|
||||
35
cli/.github/workflows/release.yaml
vendored
Normal file
35
cli/.github/workflows/release.yaml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
name: "release"
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
uses: ./.github/workflows/wf_check.yaml
|
||||
secrets:
|
||||
NHOST_PAT: ${{ secrets.NHOST_PAT }}
|
||||
|
||||
build_artifacts:
|
||||
strategy:
|
||||
matrix:
|
||||
GOOS: ["darwin", "linux"]
|
||||
GOARCH: ["amd64", "arm64"]
|
||||
uses: ./.github/workflows/wf_build_artifacts.yaml
|
||||
with:
|
||||
GOOS: ${{ matrix.GOOS }}
|
||||
GOARCH: ${{ matrix.GOARCH }}
|
||||
VERSION: ${{ github.ref_name }}
|
||||
secrets:
|
||||
NHOST_PAT: ${{ secrets.NHOST_PAT }}
|
||||
|
||||
publish:
|
||||
uses: ./.github/workflows/wf_publish.yaml
|
||||
needs:
|
||||
- tests
|
||||
- build_artifacts
|
||||
with:
|
||||
VERSION: ${{ github.ref_name }}
|
||||
secrets:
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
17
cli/.github/workflows/release_drafter.yml
vendored
Normal file
17
cli/.github/workflows/release_drafter.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
name: "release drafter"
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
# draft your next release notes as pull requests are merged into "master"
|
||||
# the configuration is at /.github/release-drafter.yml.
|
||||
update_release_draft:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: release-drafter/release-drafter@v5
|
||||
with:
|
||||
config-name: release-drafter.yml
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
89
cli/.github/workflows/wf_build_artifacts.yaml
vendored
Normal file
89
cli/.github/workflows/wf_build_artifacts.yaml
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
---
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
GIT_REF:
|
||||
type: string
|
||||
required: false
|
||||
VERSION:
|
||||
type: string
|
||||
required: true
|
||||
GOOS:
|
||||
type: string
|
||||
required: true
|
||||
GOARCH:
|
||||
type: string
|
||||
required: true
|
||||
secrets:
|
||||
NHOST_PAT:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
artifacts:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: "Check out repository"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ inputs.GIT_REF }}
|
||||
submodules: true
|
||||
|
||||
- uses: cachix/install-nix-action@v27
|
||||
with:
|
||||
install_url: "https://releases.nixos.org/nix/nix-2.22.3/install"
|
||||
install_options: "--no-daemon"
|
||||
extra_nix_config: |
|
||||
experimental-features = nix-command flakes
|
||||
sandbox = false
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
substituters = https://cache.nixos.org/?priority=40
|
||||
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
|
||||
|
||||
- name: Compute common env vars
|
||||
id: vars
|
||||
run: |
|
||||
echo "VERSION=$(make get-version VERSION=${{ inputs.VERSION }})" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: "Build artifact"
|
||||
run: |
|
||||
make build ARCH=${{ inputs.GOARCH }} OS=${{ inputs.GOOS }}
|
||||
find -L result -type f -exec cp {} nhost-cli \;
|
||||
|
||||
- name: "Push artifact to artifact repository"
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cli-${{ steps.vars.outputs.VERSION }}-${{ inputs.GOOS }}-${{ inputs.GOARCH }}
|
||||
path: nhost-cli
|
||||
retention-days: 7
|
||||
|
||||
- name: "Build docker-image"
|
||||
run: |
|
||||
make build-docker-image ARCH=${{ inputs.GOARCH }}
|
||||
if: ${{ ( inputs.GOOS == 'linux' ) }}
|
||||
|
||||
- name: "Create a new project"
|
||||
run: |
|
||||
export NHOST_DOMAIN=staging.nhost.run
|
||||
export NHOST_CONFIGSERVER_IMAGE=nhost/cli:${{ steps.vars.outputs.VERSION }}
|
||||
|
||||
mkdir new-project
|
||||
cd new-project
|
||||
../nhost-cli login --pat ${{ secrets.NHOST_PAT }}
|
||||
../nhost-cli init
|
||||
../nhost-cli up --down-on-error
|
||||
../nhost-cli down
|
||||
if: ${{ ( inputs.GOOS == 'linux' && inputs.GOARCH == 'amd64' ) }}
|
||||
|
||||
- name: "Push docker-image to artifact repository"
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cli-docker-image-${{ steps.vars.outputs.VERSION }}-${{ inputs.GOOS }}-${{ inputs.GOARCH }}
|
||||
path: result
|
||||
retention-days: 7
|
||||
if: ${{ ( inputs.GOOS == 'linux' ) }}
|
||||
42
cli/.github/workflows/wf_check.yaml
vendored
Normal file
42
cli/.github/workflows/wf_check.yaml
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
---
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
GIT_REF:
|
||||
type: string
|
||||
required: false
|
||||
secrets:
|
||||
NHOST_PAT:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: "Check out repository"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ inputs.GIT_REF }}
|
||||
submodules: true
|
||||
|
||||
- uses: cachix/install-nix-action@v27
|
||||
with:
|
||||
install_url: "https://releases.nixos.org/nix/nix-2.22.3/install"
|
||||
install_options: "--no-daemon"
|
||||
extra_nix_config: |
|
||||
experimental-features = nix-command flakes
|
||||
sandbox = false
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
substituters = https://cache.nixos.org/?priority=40
|
||||
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
|
||||
|
||||
- name: "Run checks"
|
||||
run: |
|
||||
export NHOST_PAT=${{ secrets.NHOST_PAT }}
|
||||
make check
|
||||
93
cli/.github/workflows/wf_publish.yaml
vendored
Normal file
93
cli/.github/workflows/wf_publish.yaml
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
---
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
VERSION:
|
||||
type: string
|
||||
required: true
|
||||
secrets:
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
|
||||
name: release
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: "Check out repository"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ inputs.GIT_REF }}
|
||||
submodules: true
|
||||
|
||||
- name: Compute common env vars
|
||||
id: vars
|
||||
run: |
|
||||
echo "VERSION=$(make get-version VERSION=${{ inputs.VERSION }})" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: "Get artifacts"
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ~/artifacts
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Upload docker images
|
||||
shell: bash
|
||||
run: |
|
||||
export VERSION=${{ steps.vars.outputs.VERSION }}
|
||||
export CONTAINER_NAME=nhost/cli
|
||||
|
||||
skopeo copy --insecure-policy \
|
||||
dir:/home/runner/artifacts/cli-docker-image-$VERSION-linux-amd64 \
|
||||
docker-daemon:$CONTAINER_NAME:$VERSION-amd64
|
||||
docker push $CONTAINER_NAME:$VERSION-amd64
|
||||
|
||||
skopeo copy --insecure-policy \
|
||||
dir:/home/runner/artifacts/cli-docker-image-$VERSION-linux-arm64 \
|
||||
docker-daemon:$CONTAINER_NAME:$VERSION-arm64
|
||||
docker push $CONTAINER_NAME:$VERSION-arm64
|
||||
|
||||
docker manifest create \
|
||||
$CONTAINER_NAME:$VERSION \
|
||||
--amend $CONTAINER_NAME:$VERSION-amd64 \
|
||||
--amend $CONTAINER_NAME:$VERSION-arm64
|
||||
docker manifest push $CONTAINER_NAME:$VERSION
|
||||
|
||||
- name: Upload assets
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
export VERSION=${{ steps.vars.outputs.VERSION }}
|
||||
|
||||
mkdir upload
|
||||
|
||||
find ~/artifacts -type f -name "nhost-cli" -exec bash -c 'chmod +x "$0" && mv "$0" "${0//nhost-cli/cli}"' {} \;
|
||||
|
||||
tar cvzf upload/cli-$VERSION-darwin-amd64.tar.gz -C ~/artifacts/cli-$VERSION-darwin-amd64 cli
|
||||
tar cvzf upload/cli-$VERSION-darwin-arm64.tar.gz -C ~/artifacts/cli-$VERSION-darwin-arm64 cli
|
||||
tar cvzf upload/cli-$VERSION-linux-amd64.tar.gz -C ~/artifacts/cli-$VERSION-linux-amd64 cli
|
||||
tar cvzf upload/cli-$VERSION-linux-arm64.tar.gz -C ~/artifacts/cli-$VERSION-linux-arm64 cli
|
||||
|
||||
cd upload
|
||||
find . -type f -exec sha256sum {} + > ../checksums.txt
|
||||
cd ..
|
||||
|
||||
cat checksums.txt
|
||||
|
||||
gh release upload \
|
||||
--clobber "${{ github.ref_name }}" \
|
||||
./upload/* checksums.txt
|
||||
@@ -1,67 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [cli@1.34.1] - 2025-10-13
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- *(cli)* Remove references to mcp-nhost (#3575)
|
||||
- *(cli)* Workaround os.Rename issues when src and dst are on different partitions (#3599)
|
||||
|
||||
|
||||
### ⚙️ Miscellaneous Tasks
|
||||
|
||||
- *(auth)* Change some references to deprecated hasura-auth (#3584)
|
||||
- *(docs)* Udpated README.md and CONTRIBUTING.md (#3587)
|
||||
|
||||
## [cli@1.34.0] - 2025-10-09
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- *(cli)* Added mcp server functionality from mcp-nhost (#3550)
|
||||
- *(cli)* Mcp: move configuration to .nhost folder and integrate cloud credentials (#3555)
|
||||
- *(cli)* Mcp: added support for environment variables in the configuration (#3556)
|
||||
- *(cli)* MCP refactor and documentation prior to official release (#3571)
|
||||
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- *(dashboard)* Remove NODE_ENV from restricted env vars (#3573)
|
||||
|
||||
|
||||
### ⚙️ Miscellaneous Tasks
|
||||
|
||||
- *(nixops)* Update nhost-cli (#3554)
|
||||
- *(cli)* Bump nhost/dashboard to 2.38.4 (#3539)
|
||||
|
||||
## [cli@1.33.0] - 2025-10-02
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- *(cli)* Migrate from urfave/v2 to urfave/v3 (#3545)
|
||||
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- *(cli)* Disable tls on AUTH_SERVER_URL when auth uses custom port (#3549)
|
||||
- *(cli)* Fix breaking change in go-getter dependency (#3551)
|
||||
|
||||
|
||||
### ⚙️ Miscellaneous Tasks
|
||||
|
||||
- *(cli)* Update certs (#3552)
|
||||
|
||||
## [cli@1.32.2] - 2025-10-01
|
||||
|
||||
### ⚙️ Miscellaneous Tasks
|
||||
|
||||
- *(cli)* Remove hasura- prefix from auth/storage images (#3538)
|
||||
|
||||
## [cli@1.32.1] - 2025-09-29
|
||||
|
||||
### ⚙️ Miscellaneous Tasks
|
||||
|
||||
- *(ci)* Minor improvements to the ci (#3527)
|
||||
- *(cli)* Update schema (#3529)
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
# Developer Guide
|
||||
|
||||
## Requirements
|
||||
|
||||
We use nix to manage the development environment, the build process and for running tests.
|
||||
|
||||
### With Nix (Recommended)
|
||||
|
||||
Run `nix develop \#cli` to get a complete development environment.
|
||||
|
||||
### Without Nix
|
||||
|
||||
Check `project.nix` (checkDeps, buildInputs, buildNativeInputs) for manual dependency installation. Alternatively, you can run `make nixops-container-env` in the root of the repository to enter a Docker container with nix and all dependencies pre-installed (note it is a large image).
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Running Tests
|
||||
|
||||
**With Nix:**
|
||||
```bash
|
||||
make dev-env-up
|
||||
make check
|
||||
```
|
||||
|
||||
**Without Nix:**
|
||||
```bash
|
||||
# Start development environment
|
||||
make dev-env-up
|
||||
|
||||
# Lint Go code
|
||||
golangci-lint run ./...
|
||||
|
||||
# Run tests
|
||||
go test -v ./...
|
||||
```
|
||||
|
||||
### Formatting
|
||||
|
||||
Format code before committing:
|
||||
```bash
|
||||
golines -w --base-formatter=gofumpt .
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
### Local Build
|
||||
|
||||
Build the project (output in `./result`):
|
||||
```bash
|
||||
make build
|
||||
```
|
||||
|
||||
### Docker Image
|
||||
|
||||
Build and import Docker image with skopeo:
|
||||
```bash
|
||||
make build-docker-image
|
||||
```
|
||||
|
||||
If you run the command above inside the dockerized nixops-container-env and you get an error like:
|
||||
|
||||
```
|
||||
FATA[0000] writing blob: io: read/write on closed pipe
|
||||
```
|
||||
|
||||
then you need to run the following command outside of the container (needs skopeo installed on the host):
|
||||
|
||||
```bash
|
||||
cd cli
|
||||
make build-docker-image-import-bare
|
||||
```
|
||||
|
||||
### Multi-Platform Builds
|
||||
|
||||
Build for multiple platforms (Darwin/Linux, ARM64/AMD64):
|
||||
```bash
|
||||
make build-multiplatform
|
||||
```
|
||||
|
||||
This produces binaries for:
|
||||
- darwin/arm64
|
||||
- darwin/amd64
|
||||
- linux/arm64
|
||||
- linux/amd64
|
||||
@@ -12,9 +12,9 @@ It's recommended to use the Nhost CLI and the [Nhost GitHub Integration](https:/
|
||||
|
||||
- [Nhost Dashboard](https://github.com/nhost/nhost/tree/main/dashboard)
|
||||
- [Postgres Database](https://www.postgresql.org/)
|
||||
- [GraphQL Engine](https://github.com/hasura/graphql-engine)
|
||||
- [Auth](https://github.com/nhost/nhost/main/auth)
|
||||
- [Storage](https://github.com/nhost/nhost/main/storage)
|
||||
- [Hasura's GraphQL Engine](https://github.com/hasura/graphql-engine)
|
||||
- [Hasura Auth](https://github.com/nhost/hasura-auth)
|
||||
- [Hasura Storage](https://github.com/nhost/hasura-storage)
|
||||
- [Nhost Serverless Functions](https://github.com/nhost/functions)
|
||||
- [Minio S3](https://github.com/minio/minio)
|
||||
- [Mailhog](https://github.com/mailhog/MailHog)
|
||||
@@ -51,18 +51,11 @@ nhost up
|
||||
nhost up --ui nhost
|
||||
```
|
||||
|
||||
## MCP Server
|
||||
|
||||
The Nhost cli ships with an MCP server that lets you interact with your Nhost projects through AI assistants using the Model Context Protocol. It provides secure, controlled access to your GraphQL data, project configuration, and documentation—with granular permissions that let you specify exactly which queries and mutations an LLM can execute. For development, it streamlines your workflow by enabling AI-assisted schema management, metadata changes, and migrations, while providing direct access to your GraphQL schema for intelligent query building.
|
||||
|
||||
You can read more about the MCP server in the [MCP Server documentation](https://docs.nhost.io/platform/cli/mcp/overview).
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Get started with Nhost CLI (longer version)](https://docs.nhost.io/platform/overview/get-started-with-nhost-cli)
|
||||
- [Nhost CLI](https://docs.nhost.io/platform/cli)
|
||||
- [Reference](https://docs.nhost.io/reference/cli)
|
||||
- [MCP Server](https://docs.nhost.io/platform/cli/mcp/overview)
|
||||
|
||||
## Build from Source
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
"github.com/nhost/nhost/cli/nhostclient"
|
||||
"github.com/nhost/nhost/cli/nhostclient/graphql"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func sanitizeName(name string) string {
|
||||
@@ -55,28 +55,28 @@ func New(
|
||||
}
|
||||
}
|
||||
|
||||
func FromCLI(cmd *cli.Command) *CliEnv {
|
||||
func FromCLI(cCtx *cli.Context) *CliEnv {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &CliEnv{
|
||||
stdout: cmd.Writer,
|
||||
stderr: cmd.ErrWriter,
|
||||
stdout: cCtx.App.Writer,
|
||||
stderr: cCtx.App.ErrWriter,
|
||||
Path: NewPathStructure(
|
||||
cwd,
|
||||
cmd.String(flagRootFolder),
|
||||
cmd.String(flagDotNhostFolder),
|
||||
cmd.String(flagNhostFolder),
|
||||
cCtx.String(flagRootFolder),
|
||||
cCtx.String(flagDotNhostFolder),
|
||||
cCtx.String(flagNhostFolder),
|
||||
),
|
||||
authURL: cmd.String(flagAuthURL),
|
||||
graphqlURL: cmd.String(flagGraphqlURL),
|
||||
branch: cmd.String(flagBranch),
|
||||
projectName: sanitizeName(cmd.String(flagProjectName)),
|
||||
authURL: cCtx.String(flagAuthURL),
|
||||
graphqlURL: cCtx.String(flagGraphqlURL),
|
||||
branch: cCtx.String(flagBranch),
|
||||
projectName: sanitizeName(cCtx.String(flagProjectName)),
|
||||
nhclient: nil,
|
||||
nhpublicclient: nil,
|
||||
localSubdomain: cmd.String(flagLocalSubdomain),
|
||||
localSubdomain: cCtx.String(flagLocalSubdomain),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -53,42 +53,42 @@ func Flags() ([]cli.Flag, error) {
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagAuthURL,
|
||||
Usage: "Nhost auth URL",
|
||||
Sources: cli.EnvVars("NHOST_CLI_AUTH_URL"),
|
||||
EnvVars: []string{"NHOST_CLI_AUTH_URL"},
|
||||
Value: "https://otsispdzcwxyqzbfntmj.auth.eu-central-1.nhost.run/v1",
|
||||
Hidden: true,
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagGraphqlURL,
|
||||
Usage: "Nhost GraphQL URL",
|
||||
Sources: cli.EnvVars("NHOST_CLI_GRAPHQL_URL"),
|
||||
EnvVars: []string{"NHOST_CLI_GRAPHQL_URL"},
|
||||
Value: "https://otsispdzcwxyqzbfntmj.graphql.eu-central-1.nhost.run/v1",
|
||||
Hidden: true,
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagBranch,
|
||||
Usage: "Git branch name. If not set, it will be detected from the current git repository. This flag is used to dynamically create docker volumes for each branch. If you want to have a static volume name or if you are not using git, set this flag to a static value.", //nolint:lll
|
||||
Sources: cli.EnvVars("BRANCH"),
|
||||
EnvVars: []string{"BRANCH"},
|
||||
Value: branch,
|
||||
Hidden: false,
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagRootFolder,
|
||||
Usage: "Root folder of project\n\t",
|
||||
Sources: cli.EnvVars("NHOST_ROOT_FOLDER"),
|
||||
EnvVars: []string{"NHOST_ROOT_FOLDER"},
|
||||
Value: workingDir,
|
||||
Category: "Project structure",
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagDotNhostFolder,
|
||||
Usage: "Path to .nhost folder\n\t",
|
||||
Sources: cli.EnvVars("NHOST_DOT_NHOST_FOLDER"),
|
||||
EnvVars: []string{"NHOST_DOT_NHOST_FOLDER"},
|
||||
Value: dotNhostFolder,
|
||||
Category: "Project structure",
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagNhostFolder,
|
||||
Usage: "Path to nhost folder\n\t",
|
||||
Sources: cli.EnvVars("NHOST_NHOST_FOLDER"),
|
||||
EnvVars: []string{"NHOST_NHOST_FOLDER"},
|
||||
Value: nhostFolder,
|
||||
Category: "Project structure",
|
||||
},
|
||||
@@ -96,13 +96,13 @@ func Flags() ([]cli.Flag, error) {
|
||||
Name: flagProjectName,
|
||||
Usage: "Project name",
|
||||
Value: filepath.Base(fullWorkingDir),
|
||||
Sources: cli.EnvVars("NHOST_PROJECT_NAME"),
|
||||
EnvVars: []string{"NHOST_PROJECT_NAME"},
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagLocalSubdomain,
|
||||
Usage: "Local subdomain to reach the development environment",
|
||||
Value: "local",
|
||||
Sources: cli.EnvVars("NHOST_LOCAL_SUBDOMAIN"),
|
||||
EnvVars: []string{"NHOST_LOCAL_SUBDOMAIN"},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -29,12 +29,3 @@ func (ce *CliEnv) LoadSession(
|
||||
|
||||
return session, nil
|
||||
}
|
||||
|
||||
func (ce *CliEnv) Credentials() (credentials.Credentials, error) {
|
||||
var creds credentials.Credentials
|
||||
if err := UnmarshalFile(ce.Path.AuthFile(), &creds, json.Unmarshal); err != nil {
|
||||
return credentials.Credentials{}, err
|
||||
}
|
||||
|
||||
return creds, nil
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/nhost/be/services/mimir/model"
|
||||
"github.com/nhost/nhost/cli/clienv"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func CommandApply() *cli.Command {
|
||||
@@ -22,42 +22,38 @@ func CommandApply() *cli.Command {
|
||||
Name: flagSubdomain,
|
||||
Usage: "Subdomain of the Nhost project to apply configuration to. Defaults to linked project",
|
||||
Required: true,
|
||||
Sources: cli.EnvVars("NHOST_SUBDOMAIN"),
|
||||
EnvVars: []string{"NHOST_SUBDOMAIN"},
|
||||
},
|
||||
&cli.BoolFlag{ //nolint:exhaustruct
|
||||
Name: flagYes,
|
||||
Usage: "Skip confirmation",
|
||||
Sources: cli.EnvVars("NHOST_YES"),
|
||||
EnvVars: []string{"NHOST_YES"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func commandApply(ctx context.Context, cmd *cli.Command) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func commandApply(cCtx *cli.Context) error {
|
||||
ce := clienv.FromCLI(cCtx)
|
||||
|
||||
proj, err := ce.GetAppInfo(ctx, cmd.String(flagSubdomain))
|
||||
proj, err := ce.GetAppInfo(cCtx.Context, cCtx.String(flagSubdomain))
|
||||
if err != nil {
|
||||
return cli.Exit(fmt.Sprintf("Failed to get app info: %v", err), 1)
|
||||
return fmt.Errorf("failed to get app info: %w", err)
|
||||
}
|
||||
|
||||
ce.Infoln("Validating configuration...")
|
||||
|
||||
cfg, _, err := ValidateRemote(
|
||||
ctx,
|
||||
cCtx.Context,
|
||||
ce,
|
||||
proj.GetSubdomain(),
|
||||
proj.GetID(),
|
||||
)
|
||||
if err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := Apply(ctx, ce, proj.ID, cfg, cmd.Bool(flagYes)); err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
|
||||
return nil
|
||||
return Apply(cCtx.Context, ce, proj.ID, cfg, cCtx.Bool(flagYes))
|
||||
}
|
||||
|
||||
func Apply(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package config
|
||||
|
||||
import "github.com/urfave/cli/v3"
|
||||
import "github.com/urfave/cli/v2"
|
||||
|
||||
const flagSubdomain = "subdomain"
|
||||
|
||||
@@ -9,7 +9,7 @@ func Command() *cli.Command {
|
||||
Name: "config",
|
||||
Aliases: []string{},
|
||||
Usage: "Perform config operations",
|
||||
Commands: []*cli.Command{
|
||||
Subcommands: []*cli.Command{
|
||||
CommandDefault(),
|
||||
CommandExample(),
|
||||
CommandApply(),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
@@ -9,7 +8,7 @@ import (
|
||||
"github.com/nhost/nhost/cli/project"
|
||||
"github.com/nhost/nhost/cli/project/env"
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func CommandDefault() *cli.Command {
|
||||
@@ -22,8 +21,8 @@ func CommandDefault() *cli.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func commandDefault(_ context.Context, cmd *cli.Command) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func commandDefault(cCtx *cli.Context) error {
|
||||
ce := clienv.FromCLI(cCtx)
|
||||
|
||||
if err := os.MkdirAll(ce.Path.NhostFolder(), 0o755); err != nil { //nolint:mnd
|
||||
return fmt.Errorf("failed to create nhost folder: %w", err)
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"github.com/nhost/be/services/mimir/model"
|
||||
"github.com/nhost/nhost/cli/clienv"
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/wI2L/jsondiff"
|
||||
)
|
||||
|
||||
@@ -31,13 +31,13 @@ func CommandEdit() *cli.Command {
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagSubdomain,
|
||||
Usage: "If specified, edit this subdomain's overlay, otherwise edit base configuation",
|
||||
Sources: cli.EnvVars("NHOST_SUBDOMAIN"),
|
||||
EnvVars: []string{"NHOST_SUBDOMAIN"},
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagEditor,
|
||||
Usage: "Editor to use",
|
||||
Value: "vim",
|
||||
Sources: cli.EnvVars("EDITOR"),
|
||||
EnvVars: []string{"EDITOR"},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -139,11 +139,11 @@ func GenerateJSONPatch(origfilepath, newfilepath, dst string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func edit(ctx context.Context, cmd *cli.Command) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func edit(cCtx *cli.Context) error {
|
||||
ce := clienv.FromCLI(cCtx)
|
||||
|
||||
if cmd.String(flagSubdomain) == "" {
|
||||
if err := EditFile(ctx, cmd.String(flagEditor), ce.Path.NhostToml()); err != nil {
|
||||
if cCtx.String(flagSubdomain) == "" {
|
||||
if err := EditFile(cCtx.Context, cCtx.String(flagEditor), ce.Path.NhostToml()); err != nil {
|
||||
return fmt.Errorf("failed to edit config: %w", err)
|
||||
}
|
||||
|
||||
@@ -163,17 +163,17 @@ func edit(ctx context.Context, cmd *cli.Command) error {
|
||||
tmpfileName := filepath.Join(tmpdir, "nhost.toml")
|
||||
|
||||
if err := CopyConfig[model.ConfigConfig](
|
||||
ce.Path.NhostToml(), tmpfileName, ce.Path.Overlay(cmd.String(flagSubdomain)),
|
||||
ce.Path.NhostToml(), tmpfileName, ce.Path.Overlay(cCtx.String(flagSubdomain)),
|
||||
); err != nil {
|
||||
return fmt.Errorf("failed to copy config: %w", err)
|
||||
}
|
||||
|
||||
if err := EditFile(ctx, cmd.String(flagEditor), tmpfileName); err != nil {
|
||||
if err := EditFile(cCtx.Context, cCtx.String(flagEditor), tmpfileName); err != nil {
|
||||
return fmt.Errorf("failed to edit config: %w", err)
|
||||
}
|
||||
|
||||
if err := GenerateJSONPatch(
|
||||
ce.Path.NhostToml(), tmpfileName, ce.Path.Overlay(cmd.String(flagSubdomain)),
|
||||
ce.Path.NhostToml(), tmpfileName, ce.Path.Overlay(cCtx.String(flagSubdomain)),
|
||||
); err != nil {
|
||||
return fmt.Errorf("failed to generate json patch: %w", err)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/nhost/be/services/mimir/model"
|
||||
"github.com/nhost/be/services/mimir/schema"
|
||||
"github.com/nhost/nhost/cli/clienv"
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func CommandExample() *cli.Command {
|
||||
@@ -23,8 +22,8 @@ func CommandExample() *cli.Command {
|
||||
|
||||
func ptr[T any](v T) *T { return &v }
|
||||
|
||||
func commandExample(_ context.Context, cmd *cli.Command) error { //nolint:funlen,maintidx
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func commandExample(cCtx *cli.Context) error { //nolint:funlen,maintidx
|
||||
ce := clienv.FromCLI(cCtx)
|
||||
|
||||
//nolint:mnd
|
||||
cfg := model.ConfigConfig{
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"github.com/nhost/nhost/cli/project/env"
|
||||
"github.com/nhost/nhost/cli/system"
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -36,21 +36,21 @@ func CommandPull() *cli.Command {
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagSubdomain,
|
||||
Usage: "Pull this subdomain's configuration. Defaults to linked project",
|
||||
Sources: cli.EnvVars("NHOST_SUBDOMAIN"),
|
||||
EnvVars: []string{"NHOST_SUBDOMAIN"},
|
||||
},
|
||||
&cli.BoolFlag{ //nolint:exhaustruct
|
||||
Name: flagYes,
|
||||
Usage: "Skip confirmation",
|
||||
Sources: cli.EnvVars("NHOST_YES"),
|
||||
EnvVars: []string{"NHOST_YES"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func commandPull(ctx context.Context, cmd *cli.Command) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func commandPull(cCtx *cli.Context) error {
|
||||
ce := clienv.FromCLI(cCtx)
|
||||
|
||||
skipConfirmation := cmd.Bool(flagYes)
|
||||
skipConfirmation := cCtx.Bool(flagYes)
|
||||
|
||||
if !skipConfirmation {
|
||||
if err := verifyFile(ce, ce.Path.NhostToml()); err != nil {
|
||||
@@ -66,12 +66,12 @@ func commandPull(ctx context.Context, cmd *cli.Command) error {
|
||||
}
|
||||
}
|
||||
|
||||
proj, err := ce.GetAppInfo(ctx, cmd.String(flagSubdomain))
|
||||
proj, err := ce.GetAppInfo(cCtx.Context, cCtx.String(flagSubdomain))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get app info: %w", err)
|
||||
}
|
||||
|
||||
_, err = Pull(ctx, ce, proj, writeSecrets)
|
||||
_, err = Pull(cCtx.Context, ce, proj, writeSecrets)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/nhost/be/services/mimir/model"
|
||||
"github.com/nhost/nhost/cli/clienv"
|
||||
"github.com/nhost/nhost/cli/project/env"
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func CommandShow() *cli.Command {
|
||||
@@ -22,14 +21,14 @@ func CommandShow() *cli.Command {
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagSubdomain,
|
||||
Usage: "Show this subdomain's rendered configuration. Defaults to base configuration",
|
||||
Sources: cli.EnvVars("NHOST_SUBDOMAIN"),
|
||||
EnvVars: []string{"NHOST_SUBDOMAIN"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func commandShow(_ context.Context, cmd *cli.Command) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func commandShow(c *cli.Context) error {
|
||||
ce := clienv.FromCLI(c)
|
||||
|
||||
var secrets model.Secrets
|
||||
if err := clienv.UnmarshalFile(ce.Path.Secrets(), &secrets, env.Unmarshal); err != nil {
|
||||
@@ -39,7 +38,7 @@ func commandShow(_ context.Context, cmd *cli.Command) error {
|
||||
)
|
||||
}
|
||||
|
||||
cfg, err := Validate(ce, cmd.String(flagSubdomain), secrets)
|
||||
cfg, err := Validate(ce, c.String(flagSubdomain), secrets)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"github.com/nhost/nhost/cli/clienv"
|
||||
"github.com/nhost/nhost/cli/project/env"
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
jsonpatch "gopkg.in/evanphx/json-patch.v5"
|
||||
)
|
||||
|
||||
@@ -27,24 +27,24 @@ func CommandValidate() *cli.Command {
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagSubdomain,
|
||||
Usage: "Validate this subdomain's configuration. Defaults to linked project",
|
||||
Sources: cli.EnvVars("NHOST_SUBDOMAIN"),
|
||||
EnvVars: []string{"NHOST_SUBDOMAIN"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func commandValidate(ctx context.Context, cmd *cli.Command) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func commandValidate(cCtx *cli.Context) error {
|
||||
ce := clienv.FromCLI(cCtx)
|
||||
|
||||
subdomain := cmd.String(flagSubdomain)
|
||||
subdomain := cCtx.String(flagSubdomain)
|
||||
if subdomain != "" && subdomain != "local" {
|
||||
proj, err := ce.GetAppInfo(ctx, cmd.String(flagSubdomain))
|
||||
proj, err := ce.GetAppInfo(cCtx.Context, cCtx.String(flagSubdomain))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get app info: %w", err)
|
||||
}
|
||||
|
||||
_, _, err = ValidateRemote(
|
||||
ctx,
|
||||
cCtx.Context,
|
||||
ce,
|
||||
proj.GetSubdomain(),
|
||||
proj.GetID(),
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/nhost/be/services/mimir/graph"
|
||||
cors "github.com/rs/cors/wrapper/gin"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -48,27 +48,27 @@ func Command() *cli.Command {
|
||||
Name: enablePlaygroundFlag,
|
||||
Usage: "enable graphql playground (under /v1)",
|
||||
Category: "server",
|
||||
Sources: cli.EnvVars("ENABLE_PLAYGROUND"),
|
||||
EnvVars: []string{"ENABLE_PLAYGROUND"},
|
||||
},
|
||||
&cli.StringFlag{ //nolint: exhaustruct
|
||||
Name: storageLocalConfigPath,
|
||||
Usage: "Path to the local mimir config file",
|
||||
Value: "/tmp/root/nhost/nhost.toml",
|
||||
Category: "plugins",
|
||||
Sources: cli.EnvVars("STORAGE_LOCAL_CONFIG_PATH"),
|
||||
EnvVars: []string{"STORAGE_LOCAL_CONFIG_PATH"},
|
||||
},
|
||||
&cli.StringFlag{ //nolint: exhaustruct
|
||||
Name: storageLocalSecretsPath,
|
||||
Usage: "Path to the local mimir secrets file",
|
||||
Value: "/tmp/root/.secrets",
|
||||
Category: "plugins",
|
||||
Sources: cli.EnvVars("STORAGE_LOCAL_SECRETS_PATH"),
|
||||
EnvVars: []string{"STORAGE_LOCAL_SECRETS_PATH"},
|
||||
},
|
||||
&cli.StringSliceFlag{ //nolint: exhaustruct
|
||||
Name: storageLocalRunServicesPath,
|
||||
Usage: "Path to the local mimir run services files",
|
||||
Category: "plugins",
|
||||
Sources: cli.EnvVars("STORAGE_LOCAL_RUN_SERVICES_PATH"),
|
||||
EnvVars: []string{"STORAGE_LOCAL_RUN_SERVICES_PATH"},
|
||||
},
|
||||
},
|
||||
Action: serve,
|
||||
@@ -103,14 +103,14 @@ func runServicesFiles(runServices ...string) map[string]string {
|
||||
return m
|
||||
}
|
||||
|
||||
func serve(_ context.Context, cmd *cli.Command) error {
|
||||
logger := getLogger(cmd.Bool(debugFlag), cmd.Bool(logFormatJSONFlag))
|
||||
logger.Info(cmd.Root().Name + " v" + cmd.Root().Version)
|
||||
logFlags(logger, cmd)
|
||||
func serve(cCtx *cli.Context) error {
|
||||
logger := getLogger(cCtx.Bool(debugFlag), cCtx.Bool(logFormatJSONFlag))
|
||||
logger.Info(cCtx.App.Name + " v" + cCtx.App.Version)
|
||||
logFlags(logger, cCtx)
|
||||
|
||||
configFile := cmd.String(storageLocalConfigPath)
|
||||
secretsFile := cmd.String(storageLocalSecretsPath)
|
||||
runServices := runServicesFiles(cmd.StringSlice(storageLocalRunServicesPath)...)
|
||||
configFile := cCtx.String(storageLocalConfigPath)
|
||||
secretsFile := cCtx.String(storageLocalSecretsPath)
|
||||
runServices := runServicesFiles(cCtx.StringSlice(storageLocalRunServicesPath)...)
|
||||
|
||||
st := NewLocal(configFile, secretsFile, runServices)
|
||||
|
||||
@@ -131,13 +131,13 @@ func serve(_ context.Context, cmd *cli.Command) error {
|
||||
resolver,
|
||||
dummyMiddleware,
|
||||
dummyMiddleware2,
|
||||
cmd.Bool(enablePlaygroundFlag),
|
||||
cmd.Root().Version,
|
||||
cCtx.Bool(enablePlaygroundFlag),
|
||||
cCtx.App.Version,
|
||||
[]graphql.FieldMiddleware{},
|
||||
gin.Recovery(),
|
||||
cors.Default(),
|
||||
)
|
||||
if err := r.Run(cmd.String(bindFlag)); err != nil {
|
||||
if err := r.Run(cCtx.String(bindFlag)); err != nil {
|
||||
return fmt.Errorf("failed to run gin: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func getLogger(debug bool, formatJSON bool) *logrus.Logger {
|
||||
@@ -29,15 +29,15 @@ func getLogger(debug bool, formatJSON bool) *logrus.Logger {
|
||||
return logger
|
||||
}
|
||||
|
||||
func logFlags(logger logrus.FieldLogger, cmd *cli.Command) {
|
||||
func logFlags(logger logrus.FieldLogger, cCtx *cli.Context) {
|
||||
fields := logrus.Fields{}
|
||||
|
||||
for _, flag := range cmd.Root().Flags {
|
||||
for _, flag := range cCtx.App.Flags {
|
||||
name := flag.Names()[0]
|
||||
fields[name] = cmd.Value(name)
|
||||
fields[name] = cCtx.Generic(name)
|
||||
}
|
||||
|
||||
for _, flag := range cmd.Flags {
|
||||
for _, flag := range cCtx.Command.Flags {
|
||||
name := flag.Names()[0]
|
||||
if strings.Contains(name, "pass") ||
|
||||
strings.Contains(name, "token") ||
|
||||
@@ -47,7 +47,7 @@ func logFlags(logger logrus.FieldLogger, cmd *cli.Command) {
|
||||
continue
|
||||
}
|
||||
|
||||
fields[name] = cmd.Value(name)
|
||||
fields[name] = cCtx.Generic(name)
|
||||
}
|
||||
|
||||
logger.WithFields(fields).Info("started with settings")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package deployments
|
||||
|
||||
import "github.com/urfave/cli/v3"
|
||||
import "github.com/urfave/cli/v2"
|
||||
|
||||
const flagSubdomain = "subdomain"
|
||||
|
||||
@@ -9,7 +9,7 @@ func commonFlags() []cli.Flag {
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagSubdomain,
|
||||
Usage: "Project's subdomain to operate on, defaults to linked project",
|
||||
Sources: cli.EnvVars("NHOST_SUBDOMAIN"),
|
||||
EnvVars: []string{"NHOST_SUBDOMAIN"},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ func Command() *cli.Command {
|
||||
Name: "deployments",
|
||||
Aliases: []string{},
|
||||
Usage: "Manage deployments",
|
||||
Commands: []*cli.Command{
|
||||
Subcommands: []*cli.Command{
|
||||
CommandList(),
|
||||
CommandLogs(),
|
||||
CommandNew(),
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package deployments
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/nhost/nhost/cli/clienv"
|
||||
"github.com/nhost/nhost/cli/nhostclient/graphql"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func CommandList() *cli.Command {
|
||||
@@ -78,21 +77,21 @@ func printDeployments(ce *clienv.CliEnv, deployments []*graphql.ListDeployments_
|
||||
ce.Println("%s", clienv.Table(id, date, duration, status, user, ref, message))
|
||||
}
|
||||
|
||||
func commandList(ctx context.Context, cmd *cli.Command) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func commandList(cCtx *cli.Context) error {
|
||||
ce := clienv.FromCLI(cCtx)
|
||||
|
||||
proj, err := ce.GetAppInfo(ctx, cmd.String(flagSubdomain))
|
||||
proj, err := ce.GetAppInfo(cCtx.Context, cCtx.String(flagSubdomain))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get app info: %w", err)
|
||||
}
|
||||
|
||||
cl, err := ce.GetNhostClient(ctx)
|
||||
cl, err := ce.GetNhostClient(cCtx.Context)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get nhost client: %w", err)
|
||||
}
|
||||
|
||||
deployments, err := cl.ListDeployments(
|
||||
ctx,
|
||||
cCtx.Context,
|
||||
proj.ID,
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/nhost/nhost/cli/clienv"
|
||||
"github.com/nhost/nhost/cli/nhostclient"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -101,28 +101,28 @@ func showLogsFollow(
|
||||
}
|
||||
}
|
||||
|
||||
func commandLogs(ctx context.Context, cmd *cli.Command) error {
|
||||
deploymentID := cmd.Args().First()
|
||||
func commandLogs(cCtx *cli.Context) error {
|
||||
deploymentID := cCtx.Args().First()
|
||||
if deploymentID == "" {
|
||||
return errors.New("deployment_id is required") //nolint:err113
|
||||
}
|
||||
|
||||
ce := clienv.FromCLI(cmd)
|
||||
ce := clienv.FromCLI(cCtx)
|
||||
|
||||
cl, err := ce.GetNhostClient(ctx)
|
||||
cl, err := ce.GetNhostClient(cCtx.Context)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get nhost client: %w", err)
|
||||
}
|
||||
|
||||
if cmd.Bool(flagFollow) {
|
||||
ctxWithTimeout, cancel := context.WithTimeout(ctx, cmd.Duration(flagTimeout))
|
||||
if cCtx.Bool(flagFollow) {
|
||||
ctx, cancel := context.WithTimeout(cCtx.Context, cCtx.Duration(flagTimeout))
|
||||
defer cancel()
|
||||
|
||||
if _, err := showLogsFollow(ctxWithTimeout, ce, cl, deploymentID); err != nil {
|
||||
if _, err := showLogsFollow(ctx, ce, cl, deploymentID); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := showLogsSimple(ctx, ce, cl, deploymentID); err != nil {
|
||||
if err := showLogsSimple(cCtx.Context, ce, cl, deploymentID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"github.com/nhost/nhost/cli/clienv"
|
||||
"github.com/nhost/nhost/cli/nhostclient/graphql"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -40,7 +40,7 @@ func CommandNew() *cli.Command {
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagRef,
|
||||
Usage: "Git reference",
|
||||
Sources: cli.EnvVars("GITHUB_SHA"),
|
||||
EnvVars: []string{"GITHUB_SHA"},
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
@@ -51,7 +51,7 @@ func CommandNew() *cli.Command {
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagUser,
|
||||
Usage: "Commit user name",
|
||||
Sources: cli.EnvVars("GITHUB_ACTOR"),
|
||||
EnvVars: []string{"GITHUB_ACTOR"},
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
@@ -67,28 +67,28 @@ func ptr[i any](v i) *i {
|
||||
return &v
|
||||
}
|
||||
|
||||
func commandNew(ctx context.Context, cmd *cli.Command) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func commandNew(cCtx *cli.Context) error {
|
||||
ce := clienv.FromCLI(cCtx)
|
||||
|
||||
cl, err := ce.GetNhostClient(ctx)
|
||||
cl, err := ce.GetNhostClient(cCtx.Context)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get nhost client: %w", err)
|
||||
}
|
||||
|
||||
proj, err := ce.GetAppInfo(ctx, cmd.String(flagSubdomain))
|
||||
proj, err := ce.GetAppInfo(cCtx.Context, cCtx.String(flagSubdomain))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get app info: %w", err)
|
||||
}
|
||||
|
||||
resp, err := cl.InsertDeployment(
|
||||
ctx,
|
||||
cCtx.Context,
|
||||
graphql.DeploymentsInsertInput{
|
||||
App: nil,
|
||||
AppID: ptr(proj.ID),
|
||||
CommitMessage: ptr(cmd.String(flagMessage)),
|
||||
CommitSha: ptr(cmd.String(flagRef)),
|
||||
CommitUserAvatarURL: ptr(cmd.String(flagUserAvatarURL)),
|
||||
CommitUserName: ptr(cmd.String(flagUser)),
|
||||
CommitMessage: ptr(cCtx.String(flagMessage)),
|
||||
CommitSha: ptr(cCtx.String(flagRef)),
|
||||
CommitUserAvatarURL: ptr(cCtx.String(flagUserAvatarURL)),
|
||||
CommitUserName: ptr(cCtx.String(flagUser)),
|
||||
DeploymentStatus: ptr("SCHEDULED"),
|
||||
},
|
||||
)
|
||||
@@ -98,13 +98,13 @@ func commandNew(ctx context.Context, cmd *cli.Command) error {
|
||||
|
||||
ce.Println("Deployment created: %s", resp.InsertDeployment.ID)
|
||||
|
||||
if cmd.Bool(flagFollow) {
|
||||
if cCtx.Bool(flagFollow) {
|
||||
ce.Println("")
|
||||
|
||||
ctxWithTimeout, cancel := context.WithTimeout(ctx, cmd.Duration(flagTimeout))
|
||||
ctx, cancel := context.WithTimeout(cCtx.Context, cCtx.Duration(flagTimeout))
|
||||
defer cancel()
|
||||
|
||||
status, err := showLogsFollow(ctxWithTimeout, ce, cl, resp.InsertDeployment.ID)
|
||||
status, err := showLogsFollow(ctx, ce, cl, resp.InsertDeployment.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error streaming logs: %w", err)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
"github.com/nhost/nhost/cli/cmd/software"
|
||||
"github.com/nhost/nhost/cli/dockercompose"
|
||||
"github.com/nhost/nhost/cli/nhostclient/graphql"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -34,19 +34,19 @@ func CommandCloud() *cli.Command {
|
||||
Name: flagHTTPPort,
|
||||
Usage: "HTTP port to listen on",
|
||||
Value: defaultHTTPPort,
|
||||
Sources: cli.EnvVars("NHOST_HTTP_PORT"),
|
||||
EnvVars: []string{"NHOST_HTTP_PORT"},
|
||||
},
|
||||
&cli.BoolFlag{ //nolint:exhaustruct
|
||||
Name: flagDisableTLS,
|
||||
Usage: "Disable TLS",
|
||||
Value: false,
|
||||
Sources: cli.EnvVars("NHOST_DISABLE_TLS"),
|
||||
EnvVars: []string{"NHOST_DISABLE_TLS"},
|
||||
},
|
||||
&cli.BoolFlag{ //nolint:exhaustruct
|
||||
Name: flagApplySeeds,
|
||||
Usage: "Apply seeds. If the .nhost folder does not exist, seeds will be applied regardless of this flag",
|
||||
Value: false,
|
||||
Sources: cli.EnvVars("NHOST_APPLY_SEEDS"),
|
||||
EnvVars: []string{"NHOST_APPLY_SEEDS"},
|
||||
},
|
||||
&cli.UintFlag{ //nolint:exhaustruct
|
||||
Name: flagsHasuraConsolePort,
|
||||
@@ -56,42 +56,42 @@ func CommandCloud() *cli.Command {
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagDashboardVersion,
|
||||
Usage: "Dashboard version to use",
|
||||
Value: "nhost/dashboard:2.38.4",
|
||||
Sources: cli.EnvVars("NHOST_DASHBOARD_VERSION"),
|
||||
Value: "nhost/dashboard:2.33.0",
|
||||
EnvVars: []string{"NHOST_DASHBOARD_VERSION"},
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagConfigserverImage,
|
||||
Hidden: true,
|
||||
Value: "",
|
||||
Sources: cli.EnvVars("NHOST_CONFIGSERVER_IMAGE"),
|
||||
EnvVars: []string{"NHOST_CONFIGSERVER_IMAGE"},
|
||||
},
|
||||
&cli.BoolFlag{ //nolint:exhaustruct
|
||||
Name: flagDownOnError,
|
||||
Usage: "Skip confirmation",
|
||||
Sources: cli.EnvVars("NHOST_YES"),
|
||||
EnvVars: []string{"NHOST_YES"},
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagCACertificates,
|
||||
Usage: "Mounts and everrides path to CA certificates in the containers",
|
||||
Sources: cli.EnvVars("NHOST_CA_CERTIFICATES"),
|
||||
EnvVars: []string{"NHOST_CA_CERTIFICATES"},
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagSubdomain,
|
||||
Usage: "Project's subdomain to operate on, defaults to linked project",
|
||||
Sources: cli.EnvVars("NHOST_SUBDOMAIN"),
|
||||
EnvVars: []string{"NHOST_SUBDOMAIN"},
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagPostgresURL,
|
||||
Usage: "Postgres URL",
|
||||
Required: true,
|
||||
Sources: cli.EnvVars("NHOST_POSTGRES_URL"),
|
||||
EnvVars: []string{"NHOST_POSTGRES_URL"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func commandCloud(ctx context.Context, cmd *cli.Command) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func commandCloud(cCtx *cli.Context) error {
|
||||
ce := clienv.FromCLI(cCtx)
|
||||
|
||||
if !clienv.PathExists(ce.Path.NhostToml()) {
|
||||
return errors.New( //nolint:err113
|
||||
@@ -105,38 +105,38 @@ func commandCloud(ctx context.Context, cmd *cli.Command) error {
|
||||
)
|
||||
}
|
||||
|
||||
proj, err := ce.GetAppInfo(ctx, cmd.String(flagSubdomain))
|
||||
proj, err := ce.GetAppInfo(cCtx.Context, cCtx.String(flagSubdomain))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get app info: %w", err)
|
||||
}
|
||||
|
||||
configserverImage := cmd.String(flagConfigserverImage)
|
||||
configserverImage := cCtx.String(flagConfigserverImage)
|
||||
if configserverImage == "" {
|
||||
configserverImage = "nhost/cli:" + cmd.Root().Version
|
||||
configserverImage = "nhost/cli:" + cCtx.App.Version
|
||||
}
|
||||
|
||||
applySeeds := cmd.Bool(flagApplySeeds)
|
||||
applySeeds := cCtx.Bool(flagApplySeeds)
|
||||
|
||||
return Cloud(
|
||||
ctx,
|
||||
cCtx.Context,
|
||||
ce,
|
||||
cmd.Root().Version,
|
||||
cmd.Uint(flagHTTPPort),
|
||||
!cmd.Bool(flagDisableTLS),
|
||||
cCtx.App.Version,
|
||||
cCtx.Uint(flagHTTPPort),
|
||||
!cCtx.Bool(flagDisableTLS),
|
||||
applySeeds,
|
||||
dockercompose.ExposePorts{
|
||||
Auth: cmd.Uint(flagAuthPort),
|
||||
Storage: cmd.Uint(flagStoragePort),
|
||||
Graphql: cmd.Uint(flagsHasuraPort),
|
||||
Console: cmd.Uint(flagsHasuraConsolePort),
|
||||
Functions: cmd.Uint(flagsFunctionsPort),
|
||||
Auth: cCtx.Uint(flagAuthPort),
|
||||
Storage: cCtx.Uint(flagStoragePort),
|
||||
Graphql: cCtx.Uint(flagsHasuraPort),
|
||||
Console: cCtx.Uint(flagsHasuraConsolePort),
|
||||
Functions: cCtx.Uint(flagsFunctionsPort),
|
||||
},
|
||||
cmd.String(flagDashboardVersion),
|
||||
cCtx.String(flagDashboardVersion),
|
||||
configserverImage,
|
||||
cmd.String(flagCACertificates),
|
||||
cmd.Bool(flagDownOnError),
|
||||
cCtx.String(flagCACertificates),
|
||||
cCtx.Bool(flagDownOnError),
|
||||
proj,
|
||||
cmd.String(flagPostgresURL),
|
||||
cCtx.String(flagPostgresURL),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package dev
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/nhost/nhost/cli/clienv"
|
||||
"github.com/nhost/nhost/cli/dockercompose"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func CommandCompose() *cli.Command {
|
||||
@@ -19,9 +17,9 @@ func CommandCompose() *cli.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func commandCompose(ctx context.Context, cmd *cli.Command) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func commandCompose(cCtx *cli.Context) error {
|
||||
ce := clienv.FromCLI(cCtx)
|
||||
dc := dockercompose.New(ce.Path.WorkingDir(), ce.Path.DockerCompose(), ce.ProjectName())
|
||||
|
||||
return dc.Wrapper(ctx, cmd.Args().Slice()...) //nolint:wrapcheck
|
||||
return dc.Wrapper(cCtx.Context, cCtx.Args().Slice()...) //nolint:wrapcheck
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package dev
|
||||
|
||||
import "github.com/urfave/cli/v3"
|
||||
import "github.com/urfave/cli/v2"
|
||||
|
||||
func Command() *cli.Command {
|
||||
return &cli.Command{ //nolint:exhaustruct
|
||||
Name: "dev",
|
||||
Aliases: []string{},
|
||||
Usage: "Operate local development environment",
|
||||
Commands: []*cli.Command{
|
||||
Subcommands: []*cli.Command{
|
||||
CommandCompose(),
|
||||
CommandHasura(),
|
||||
},
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package dev
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/nhost/nhost/cli/clienv"
|
||||
"github.com/nhost/nhost/cli/dockercompose"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -28,12 +26,12 @@ func CommandDown() *cli.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func commandDown(ctx context.Context, cmd *cli.Command) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func commandDown(cCtx *cli.Context) error {
|
||||
ce := clienv.FromCLI(cCtx)
|
||||
|
||||
dc := dockercompose.New(ce.Path.WorkingDir(), ce.Path.DockerCompose(), ce.ProjectName())
|
||||
|
||||
if err := dc.Stop(ctx, cmd.Bool(flagVolumes)); err != nil {
|
||||
if err := dc.Stop(cCtx.Context, cCtx.Bool(flagVolumes)); err != nil {
|
||||
ce.Warnln("failed to stop Nhost development environment: %s", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package dev
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/nhost/be/services/mimir/model"
|
||||
"github.com/nhost/nhost/cli/clienv"
|
||||
"github.com/nhost/nhost/cli/dockercompose"
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func CommandHasura() *cli.Command {
|
||||
@@ -22,8 +21,8 @@ func CommandHasura() *cli.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func commandHasura(ctx context.Context, cmd *cli.Command) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func commandHasura(cCtx *cli.Context) error {
|
||||
ce := clienv.FromCLI(cCtx)
|
||||
|
||||
cfg := &model.ConfigConfig{} //nolint:exhaustruct
|
||||
if err := clienv.UnmarshalFile(ce.Path.NhostToml(), cfg, toml.Unmarshal); err != nil {
|
||||
@@ -33,10 +32,10 @@ func commandHasura(ctx context.Context, cmd *cli.Command) error {
|
||||
docker := dockercompose.NewDocker()
|
||||
|
||||
return docker.HasuraWrapper( //nolint:wrapcheck
|
||||
ctx,
|
||||
cCtx.Context,
|
||||
ce.LocalSubdomain(),
|
||||
ce.Path.NhostFolder(),
|
||||
*cfg.Hasura.Version,
|
||||
cmd.Args().Slice()...,
|
||||
cCtx.Args().Slice()...,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package dev
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/nhost/nhost/cli/clienv"
|
||||
"github.com/nhost/nhost/cli/dockercompose"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func CommandLogs() *cli.Command {
|
||||
@@ -19,12 +17,12 @@ func CommandLogs() *cli.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func commandLogs(ctx context.Context, cmd *cli.Command) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func commandLogs(cCtx *cli.Context) error {
|
||||
ce := clienv.FromCLI(cCtx)
|
||||
|
||||
dc := dockercompose.New(ce.Path.WorkingDir(), ce.Path.DockerCompose(), ce.ProjectName())
|
||||
|
||||
if err := dc.Logs(ctx, cmd.Args().Slice()...); err != nil {
|
||||
if err := dc.Logs(cCtx.Context, cCtx.Args().Slice()...); err != nil {
|
||||
ce.Warnln("%s", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
"github.com/nhost/nhost/cli/cmd/software"
|
||||
"github.com/nhost/nhost/cli/dockercompose"
|
||||
"github.com/nhost/nhost/cli/project/env"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func deptr[T any](t *T) T { //nolint:ireturn
|
||||
@@ -63,25 +63,25 @@ func CommandUp() *cli.Command { //nolint:funlen
|
||||
Name: flagHTTPPort,
|
||||
Usage: "HTTP port to listen on",
|
||||
Value: defaultHTTPPort,
|
||||
Sources: cli.EnvVars("NHOST_HTTP_PORT"),
|
||||
EnvVars: []string{"NHOST_HTTP_PORT"},
|
||||
},
|
||||
&cli.BoolFlag{ //nolint:exhaustruct
|
||||
Name: flagDisableTLS,
|
||||
Usage: "Disable TLS",
|
||||
Value: false,
|
||||
Sources: cli.EnvVars("NHOST_DISABLE_TLS"),
|
||||
EnvVars: []string{"NHOST_DISABLE_TLS"},
|
||||
},
|
||||
&cli.UintFlag{ //nolint:exhaustruct
|
||||
Name: flagPostgresPort,
|
||||
Usage: "Postgres port to listen on",
|
||||
Value: defaultPostgresPort,
|
||||
Sources: cli.EnvVars("NHOST_POSTGRES_PORT"),
|
||||
EnvVars: []string{"NHOST_POSTGRES_PORT"},
|
||||
},
|
||||
&cli.BoolFlag{ //nolint:exhaustruct
|
||||
Name: flagApplySeeds,
|
||||
Usage: "Apply seeds. If the .nhost folder does not exist, seeds will be applied regardless of this flag",
|
||||
Value: false,
|
||||
Sources: cli.EnvVars("NHOST_APPLY_SEEDS"),
|
||||
EnvVars: []string{"NHOST_APPLY_SEEDS"},
|
||||
},
|
||||
&cli.UintFlag{ //nolint:exhaustruct
|
||||
Name: flagAuthPort,
|
||||
@@ -111,39 +111,39 @@ func CommandUp() *cli.Command { //nolint:funlen
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagDashboardVersion,
|
||||
Usage: "Dashboard version to use",
|
||||
Value: "nhost/dashboard:2.38.4",
|
||||
Sources: cli.EnvVars("NHOST_DASHBOARD_VERSION"),
|
||||
Value: "nhost/dashboard:2.33.0",
|
||||
EnvVars: []string{"NHOST_DASHBOARD_VERSION"},
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagConfigserverImage,
|
||||
Hidden: true,
|
||||
Value: "",
|
||||
Sources: cli.EnvVars("NHOST_CONFIGSERVER_IMAGE"),
|
||||
EnvVars: []string{"NHOST_CONFIGSERVER_IMAGE"},
|
||||
},
|
||||
&cli.StringSliceFlag{ //nolint:exhaustruct
|
||||
Name: flagRunService,
|
||||
Usage: "Run service to add to the development environment. Can be passed multiple times. Comma-separated values are also accepted. Format: /path/to/run-service.toml[:overlay_name]", //nolint:lll
|
||||
Sources: cli.EnvVars("NHOST_RUN_SERVICE"),
|
||||
EnvVars: []string{"NHOST_RUN_SERVICE"},
|
||||
},
|
||||
&cli.BoolFlag{ //nolint:exhaustruct
|
||||
Name: flagDownOnError,
|
||||
Usage: "Skip confirmation",
|
||||
Sources: cli.EnvVars("NHOST_YES"),
|
||||
EnvVars: []string{"NHOST_YES"},
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagCACertificates,
|
||||
Usage: "Mounts and everrides path to CA certificates in the containers",
|
||||
Sources: cli.EnvVars("NHOST_CA_CERTIFICATES"),
|
||||
EnvVars: []string{"NHOST_CA_CERTIFICATES"},
|
||||
},
|
||||
},
|
||||
Commands: []*cli.Command{
|
||||
Subcommands: []*cli.Command{
|
||||
CommandCloud(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func commandUp(ctx context.Context, cmd *cli.Command) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func commandUp(cCtx *cli.Context) error {
|
||||
ce := clienv.FromCLI(cCtx)
|
||||
|
||||
// projname to be root directory
|
||||
|
||||
@@ -159,33 +159,33 @@ func commandUp(ctx context.Context, cmd *cli.Command) error {
|
||||
)
|
||||
}
|
||||
|
||||
configserverImage := cmd.String(flagConfigserverImage)
|
||||
configserverImage := cCtx.String(flagConfigserverImage)
|
||||
if configserverImage == "" {
|
||||
configserverImage = "nhost/cli:" + cmd.Root().Version
|
||||
configserverImage = "nhost/cli:" + cCtx.App.Version
|
||||
}
|
||||
|
||||
applySeeds := cmd.Bool(flagApplySeeds) || !clienv.PathExists(ce.Path.DotNhostFolder())
|
||||
applySeeds := cCtx.Bool(flagApplySeeds) || !clienv.PathExists(ce.Path.DotNhostFolder())
|
||||
|
||||
return Up(
|
||||
ctx,
|
||||
cCtx.Context,
|
||||
ce,
|
||||
cmd.Root().Version,
|
||||
cmd.Uint(flagHTTPPort),
|
||||
!cmd.Bool(flagDisableTLS),
|
||||
cmd.Uint(flagPostgresPort),
|
||||
cCtx.App.Version,
|
||||
cCtx.Uint(flagHTTPPort),
|
||||
!cCtx.Bool(flagDisableTLS),
|
||||
cCtx.Uint(flagPostgresPort),
|
||||
applySeeds,
|
||||
dockercompose.ExposePorts{
|
||||
Auth: cmd.Uint(flagAuthPort),
|
||||
Storage: cmd.Uint(flagStoragePort),
|
||||
Graphql: cmd.Uint(flagsHasuraPort),
|
||||
Console: cmd.Uint(flagsHasuraConsolePort),
|
||||
Functions: cmd.Uint(flagsFunctionsPort),
|
||||
Auth: cCtx.Uint(flagAuthPort),
|
||||
Storage: cCtx.Uint(flagStoragePort),
|
||||
Graphql: cCtx.Uint(flagsHasuraPort),
|
||||
Console: cCtx.Uint(flagsHasuraConsolePort),
|
||||
Functions: cCtx.Uint(flagsFunctionsPort),
|
||||
},
|
||||
cmd.String(flagDashboardVersion),
|
||||
cCtx.String(flagDashboardVersion),
|
||||
configserverImage,
|
||||
cmd.String(flagCACertificates),
|
||||
cmd.StringSlice(flagRunService),
|
||||
cmd.Bool(flagDownOnError),
|
||||
cCtx.String(flagCACertificates),
|
||||
cCtx.StringSlice(flagRunService),
|
||||
cCtx.Bool(flagDownOnError),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"os/exec"
|
||||
|
||||
"github.com/nhost/nhost/cli/clienv"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -35,13 +35,13 @@ func CommandConfigure() *cli.Command {
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagDockerConfig,
|
||||
Usage: "Path to docker config file",
|
||||
Sources: cli.EnvVars("DOCKER_CONFIG"),
|
||||
EnvVars: []string{"DOCKER_CONFIG"},
|
||||
Value: home + "/.docker/config.json",
|
||||
},
|
||||
&cli.BoolFlag{ //nolint:exhaustruct
|
||||
Name: flagNoInteractive,
|
||||
Usage: "Do not prompt for confirmation",
|
||||
Sources: cli.EnvVars("NO_INTERACTIVE"),
|
||||
EnvVars: []string{"NO_INTERACTIVE"},
|
||||
Value: false,
|
||||
},
|
||||
},
|
||||
@@ -140,21 +140,21 @@ func configureDocker(dockerConfig string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func actionConfigure(ctx context.Context, cmd *cli.Command) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func actionConfigure(c *cli.Context) error {
|
||||
ce := clienv.FromCLI(c)
|
||||
|
||||
if err := writeScript(ctx, ce); err != nil {
|
||||
if err := writeScript(c.Context, ce); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.Bool(flagNoInteractive) {
|
||||
return configureDocker(cmd.String(flagDockerConfig))
|
||||
if c.Bool(flagNoInteractive) {
|
||||
return configureDocker(c.String(flagDockerConfig))
|
||||
}
|
||||
|
||||
//nolint:lll
|
||||
ce.PromptMessage(
|
||||
"I am about to configure docker to authenticate with Nhost's registry. This will modify your docker config file on %s. Should I continue? [y/N] ",
|
||||
cmd.String(flagDockerConfig),
|
||||
c.String(flagDockerConfig),
|
||||
)
|
||||
|
||||
v, err := ce.PromptInput(false)
|
||||
@@ -163,7 +163,7 @@ func actionConfigure(ctx context.Context, cmd *cli.Command) error {
|
||||
}
|
||||
|
||||
if v == "y" || v == "Y" {
|
||||
return configureDocker(cmd.String(flagDockerConfig))
|
||||
return configureDocker(c.String(flagDockerConfig))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package dockercredentials
|
||||
|
||||
import "github.com/urfave/cli/v3"
|
||||
import "github.com/urfave/cli/v2"
|
||||
|
||||
func Command() *cli.Command {
|
||||
return &cli.Command{ //nolint:exhaustruct
|
||||
Name: "docker-credentials",
|
||||
Aliases: []string{},
|
||||
Usage: "Perform docker-credentials operations",
|
||||
Commands: []*cli.Command{
|
||||
Subcommands: []*cli.Command{
|
||||
CommandGet(),
|
||||
CommandErase(),
|
||||
CommandStore(),
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package dockercredentials
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func CommandErase() *cli.Command {
|
||||
@@ -16,7 +14,7 @@ func CommandErase() *cli.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func actionErase(_ context.Context, cmd *cli.Command) error {
|
||||
_, _ = cmd.Root().Writer.Write([]byte("Please, use the nhost CLI to logout\n"))
|
||||
func actionErase(c *cli.Context) error {
|
||||
_, _ = c.App.Writer.Write([]byte("Please, use the nhost CLI to logout\n"))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/nhost/nhost/cli/clienv"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -26,14 +26,14 @@ func CommandGet() *cli.Command {
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagAuthURL,
|
||||
Usage: "Nhost auth URL",
|
||||
Sources: cli.EnvVars("NHOST_CLI_AUTH_URL"),
|
||||
EnvVars: []string{"NHOST_CLI_AUTH_URL"},
|
||||
Value: "https://otsispdzcwxyqzbfntmj.auth.eu-central-1.nhost.run/v1",
|
||||
Hidden: true,
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagGraphqlURL,
|
||||
Usage: "Nhost GraphQL URL",
|
||||
Sources: cli.EnvVars("NHOST_CLI_GRAPHQL_URL"),
|
||||
EnvVars: []string{"NHOST_CLI_GRAPHQL_URL"},
|
||||
Value: "https://otsispdzcwxyqzbfntmj.graphql.eu-central-1.nhost.run/v1",
|
||||
Hidden: true,
|
||||
},
|
||||
@@ -69,15 +69,15 @@ type response struct {
|
||||
Secret string `json:"Secret"`
|
||||
}
|
||||
|
||||
func actionGet(ctx context.Context, cmd *cli.Command) error {
|
||||
scanner := bufio.NewScanner(cmd.Root().Reader)
|
||||
func actionGet(c *cli.Context) error {
|
||||
scanner := bufio.NewScanner(c.App.Reader)
|
||||
|
||||
var input string
|
||||
for scanner.Scan() {
|
||||
input += scanner.Text()
|
||||
}
|
||||
|
||||
token, err := getToken(ctx, cmd.String(flagAuthURL), cmd.String(flagGraphqlURL))
|
||||
token, err := getToken(c.Context, c.String(flagAuthURL), c.String(flagGraphqlURL))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func actionGet(ctx context.Context, cmd *cli.Command) error {
|
||||
return fmt.Errorf("failed to marshal response: %w", err)
|
||||
}
|
||||
|
||||
if _, err = cmd.Root().Writer.Write(b); err != nil {
|
||||
if _, err = c.App.Writer.Write(b); err != nil {
|
||||
return fmt.Errorf("failed to write response: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package dockercredentials
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func CommandStore() *cli.Command {
|
||||
@@ -16,7 +14,7 @@ func CommandStore() *cli.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func actionStore(_ context.Context, cmd *cli.Command) error {
|
||||
_, _ = cmd.Root().Writer.Write([]byte("Please, use the nhost CLI to login\n"))
|
||||
func actionStore(c *cli.Context) error {
|
||||
_, _ = c.App.Writer.Write([]byte("Please, use the nhost CLI to login\n"))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/nhost/nhost/cli/mcp/config"
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
flagConfirm = "confirm"
|
||||
)
|
||||
|
||||
func Command() *cli.Command {
|
||||
return &cli.Command{ //nolint:exhaustruct
|
||||
Name: "config",
|
||||
Usage: "Generate and save configuration file",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{ //nolint:exhaustruct
|
||||
Name: flagConfirm,
|
||||
Usage: "Skip confirmation prompt",
|
||||
Value: false,
|
||||
Sources: cli.EnvVars("CONFIRM"),
|
||||
},
|
||||
},
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "dump",
|
||||
Usage: "Dump the configuration to stdout for verification",
|
||||
Flags: []cli.Flag{},
|
||||
Action: actionDump,
|
||||
},
|
||||
},
|
||||
Action: action,
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:forbidigo
|
||||
func action(_ context.Context, cmd *cli.Command) error {
|
||||
cfg, err := config.RunWizard()
|
||||
if err != nil {
|
||||
return cli.Exit(fmt.Sprintf("failed to run wizard: %s", err), 1)
|
||||
}
|
||||
|
||||
tomlData, err := toml.Marshal(cfg)
|
||||
if err != nil {
|
||||
return cli.Exit(fmt.Sprintf("failed to marshal config: %s", err), 1)
|
||||
}
|
||||
|
||||
fmt.Println("Configuration Preview:")
|
||||
fmt.Println("---------------------")
|
||||
fmt.Println(string(tomlData))
|
||||
fmt.Println()
|
||||
|
||||
filePath := config.GetConfigPath(cmd)
|
||||
fmt.Printf("Save configuration to %s?\n", filePath)
|
||||
fmt.Print("Proceed? (y/N): ")
|
||||
|
||||
var confirm string
|
||||
if _, err := fmt.Scanln(&confirm); err != nil {
|
||||
return cli.Exit(fmt.Sprintf("failed to read input: %s", err), 1)
|
||||
}
|
||||
|
||||
if confirm != "y" && confirm != "Y" {
|
||||
fmt.Println("Operation cancelled.")
|
||||
return nil
|
||||
}
|
||||
|
||||
dir := filepath.Dir(filePath)
|
||||
if err := os.MkdirAll(dir, 0o755); err != nil { //nolint:mnd
|
||||
return fmt.Errorf("failed to create config directory: %w", err)
|
||||
}
|
||||
|
||||
data, err := toml.Marshal(cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal config: %w", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(filePath, data, 0o600); err != nil { //nolint:mnd
|
||||
return fmt.Errorf("failed to write config file: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("\nConfiguration saved successfully!")
|
||||
fmt.Println("Note: Review the documentation for additional configuration options,")
|
||||
fmt.Println(" especially for fine-tuning LLM access permissions.")
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/nhost/nhost/cli/mcp/config"
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
func actionDump(_ context.Context, cmd *cli.Command) error {
|
||||
configPath := config.GetConfigPath(cmd)
|
||||
if configPath == "" {
|
||||
return cli.Exit("config file path is required", 1)
|
||||
}
|
||||
|
||||
cfg, err := config.Load(configPath)
|
||||
if err != nil {
|
||||
fmt.Println("Please, run `nhost mcp config` to configure the service.") //nolint:forbidigo
|
||||
return cli.Exit("failed to load config file "+err.Error(), 1)
|
||||
}
|
||||
|
||||
b, err := toml.Marshal(cfg)
|
||||
if err != nil {
|
||||
return cli.Exit("failed to marshal config file "+err.Error(), 1)
|
||||
}
|
||||
|
||||
fmt.Println("Configuration Preview:") //nolint:forbidigo
|
||||
fmt.Println("---------------------") //nolint:forbidigo
|
||||
fmt.Println(string(b)) //nolint:forbidigo
|
||||
fmt.Println() //nolint:forbidigo
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/nhost/nhost/cli/mcp/graphql"
|
||||
"github.com/nhost/nhost/cli/mcp/nhost/auth"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
flagNhostAuthURL = "nhost-auth-url"
|
||||
flagNhostGraphqlURL = "nhost-graphql-url"
|
||||
flagNhostPAT = "nhost-pat"
|
||||
flagWithMutations = "with-mutations"
|
||||
)
|
||||
|
||||
func Command() *cli.Command {
|
||||
return &cli.Command{ //nolint:exhaustruct
|
||||
Name: "gen",
|
||||
Usage: "Generate GraphQL schema for Nhost Cloud",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagNhostAuthURL,
|
||||
Usage: "Nhost auth URL",
|
||||
Hidden: true,
|
||||
Value: "https://otsispdzcwxyqzbfntmj.auth.eu-central-1.nhost.run/v1",
|
||||
Sources: cli.EnvVars("NHOST_AUTH_URL"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagNhostGraphqlURL,
|
||||
Usage: "Nhost GraphQL URL",
|
||||
Hidden: true,
|
||||
Value: "https://otsispdzcwxyqzbfntmj.graphql.eu-central-1.nhost.run/v1",
|
||||
Sources: cli.EnvVars("NHOST_GRAPHQL_URL"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagNhostPAT,
|
||||
Usage: "Personal Access Token",
|
||||
Required: true,
|
||||
Sources: cli.EnvVars("NHOST_PAT"),
|
||||
},
|
||||
&cli.BoolFlag{ //nolint:exhaustruct
|
||||
Name: flagWithMutations,
|
||||
Usage: "Include mutations in the generated schema",
|
||||
Value: false,
|
||||
Sources: cli.EnvVars("WITH_MUTATIONS"),
|
||||
},
|
||||
},
|
||||
Action: action,
|
||||
}
|
||||
}
|
||||
|
||||
func action(ctx context.Context, cmd *cli.Command) error {
|
||||
interceptor, err := auth.WithPAT(
|
||||
cmd.String(flagNhostAuthURL), cmd.String(flagNhostPAT),
|
||||
)
|
||||
if err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
|
||||
var introspection graphql.ResponseIntrospection
|
||||
if err := graphql.Query(
|
||||
ctx,
|
||||
cmd.String(flagNhostGraphqlURL),
|
||||
graphql.IntrospectionQuery,
|
||||
nil,
|
||||
&introspection,
|
||||
nil,
|
||||
nil,
|
||||
interceptor,
|
||||
); err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
|
||||
filter := graphql.Filter{
|
||||
AllowQueries: []graphql.Queries{
|
||||
{
|
||||
Name: "organizations",
|
||||
DisableNesting: true,
|
||||
},
|
||||
{
|
||||
Name: "organization",
|
||||
DisableNesting: true,
|
||||
},
|
||||
{
|
||||
Name: "app",
|
||||
DisableNesting: true,
|
||||
},
|
||||
{
|
||||
Name: "apps",
|
||||
DisableNesting: true,
|
||||
},
|
||||
{
|
||||
Name: "config",
|
||||
DisableNesting: false,
|
||||
},
|
||||
},
|
||||
AllowMutations: []graphql.Queries{},
|
||||
}
|
||||
|
||||
if cmd.Bool(flagWithMutations) {
|
||||
filter.AllowMutations = []graphql.Queries{
|
||||
{
|
||||
Name: "updateConfig",
|
||||
DisableNesting: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
schema := graphql.ParseSchema(introspection, filter)
|
||||
|
||||
fmt.Print(schema) //nolint:forbidigo
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package mcp
|
||||
|
||||
import (
|
||||
"github.com/nhost/nhost/cli/cmd/mcp/config"
|
||||
"github.com/nhost/nhost/cli/cmd/mcp/gen"
|
||||
"github.com/nhost/nhost/cli/cmd/mcp/start"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
flagConfigFile = "config-file"
|
||||
)
|
||||
|
||||
func Command() *cli.Command {
|
||||
return &cli.Command{ //nolint:exhaustruct
|
||||
Name: "mcp",
|
||||
Aliases: []string{},
|
||||
Usage: "Model Context Protocol (MCP) related commands",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagConfigFile,
|
||||
Usage: "Configuration file path. Defaults to $NHOST_DOT_NHOST_FOLDER/nhost-mcp.toml",
|
||||
Value: "",
|
||||
Sources: cli.EnvVars("NHOST_MCP_CONFIG_FILE"),
|
||||
},
|
||||
},
|
||||
Commands: []*cli.Command{
|
||||
config.Command(),
|
||||
start.Command(),
|
||||
gen.Command(),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,401 +0,0 @@
|
||||
package mcp_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/mark3labs/mcp-go/client"
|
||||
"github.com/mark3labs/mcp-go/client/transport"
|
||||
"github.com/mark3labs/mcp-go/mcp"
|
||||
nhostmcp "github.com/nhost/nhost/cli/cmd/mcp"
|
||||
"github.com/nhost/nhost/cli/cmd/mcp/start"
|
||||
"github.com/nhost/nhost/cli/cmd/user"
|
||||
"github.com/nhost/nhost/cli/mcp/resources"
|
||||
"github.com/nhost/nhost/cli/mcp/tools/cloud"
|
||||
"github.com/nhost/nhost/cli/mcp/tools/docs"
|
||||
"github.com/nhost/nhost/cli/mcp/tools/project"
|
||||
"github.com/nhost/nhost/cli/mcp/tools/schemas"
|
||||
)
|
||||
|
||||
func ptr[T any](v T) *T {
|
||||
return &v
|
||||
}
|
||||
|
||||
func TestStart(t *testing.T) { //nolint:cyclop,maintidx,paralleltest
|
||||
loginCmd := user.CommandLogin()
|
||||
mcpCmd := nhostmcp.Command()
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
mcpCmd.Writer = buf
|
||||
|
||||
go func() {
|
||||
t.Setenv("HOME", t.TempDir())
|
||||
|
||||
if err := loginCmd.Run(
|
||||
context.Background(),
|
||||
[]string{
|
||||
"main",
|
||||
"--pat=user-pat",
|
||||
},
|
||||
); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := mcpCmd.Run(
|
||||
context.Background(),
|
||||
[]string{
|
||||
"main",
|
||||
"start",
|
||||
"--bind=:9000",
|
||||
"--config-file=testdata/sample.toml",
|
||||
},
|
||||
); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
|
||||
transportClient, err := transport.NewSSE("http://localhost:9000/sse")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create transport client: %v", err)
|
||||
}
|
||||
|
||||
mcpClient := client.NewClient(transportClient)
|
||||
|
||||
if err := mcpClient.Start(t.Context()); err != nil {
|
||||
t.Fatalf("failed to start mcp client: %v", err)
|
||||
}
|
||||
defer mcpClient.Close()
|
||||
|
||||
initRequest := mcp.InitializeRequest{} //nolint:exhaustruct
|
||||
initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION
|
||||
initRequest.Params.ClientInfo = mcp.Implementation{
|
||||
Name: "example-client",
|
||||
Version: "1.0.0",
|
||||
}
|
||||
|
||||
res, err := mcpClient.Initialize(
|
||||
context.Background(),
|
||||
initRequest,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to initialize mcp client: %v", err)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(
|
||||
res,
|
||||
//nolint:tagalign
|
||||
&mcp.InitializeResult{
|
||||
ProtocolVersion: "2025-06-18",
|
||||
Capabilities: mcp.ServerCapabilities{
|
||||
Elicitation: nil,
|
||||
Experimental: nil,
|
||||
Logging: nil,
|
||||
Prompts: nil,
|
||||
Resources: &struct {
|
||||
Subscribe bool "json:\"subscribe,omitempty\""
|
||||
ListChanged bool "json:\"listChanged,omitempty\""
|
||||
}{
|
||||
Subscribe: false,
|
||||
ListChanged: false,
|
||||
},
|
||||
Sampling: nil,
|
||||
Tools: &struct {
|
||||
ListChanged bool "json:\"listChanged,omitempty\""
|
||||
}{
|
||||
ListChanged: true,
|
||||
},
|
||||
},
|
||||
ServerInfo: mcp.Implementation{
|
||||
Name: "mcp",
|
||||
Version: "",
|
||||
},
|
||||
Instructions: start.ServerInstructions + `
|
||||
|
||||
Configured projects:
|
||||
- local (local): Local development project running via the Nhost CLI
|
||||
- asdasdasdasdasd (eu-central-1): Staging project for my awesome app
|
||||
- qweqweqweqweqwe (us-east-1): Production project for my awesome app
|
||||
|
||||
The following resources are available:
|
||||
|
||||
- schema://nhost-cloud: Schema to interact with the Nhost Cloud. Projects are equivalent
|
||||
to apps in the schema. IDs are typically uuids.
|
||||
- schema://graphql-management: GraphQL's management schema for an Nhost project.
|
||||
This tool is useful to properly understand how manage hasura metadata, migrations,
|
||||
permissions, remote schemas, etc.
|
||||
- schema://nhost.toml: Cuelang schema for the nhost.toml configuration file. Run nhost
|
||||
config validate after making changes to your nhost.toml file to ensure it is valid.
|
||||
`,
|
||||
Result: mcp.Result{
|
||||
Meta: nil,
|
||||
},
|
||||
},
|
||||
); diff != "" {
|
||||
t.Errorf("ServerInfo mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
|
||||
tools, err := mcpClient.ListTools(
|
||||
context.Background(),
|
||||
mcp.ListToolsRequest{}, //nolint:exhaustruct
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to list tools: %v", err)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(
|
||||
tools,
|
||||
//nolint:exhaustruct,lll
|
||||
&mcp.ListToolsResult{
|
||||
Tools: []mcp.Tool{
|
||||
{
|
||||
Name: "cloud-graphql-query",
|
||||
Description: cloud.ToolGraphqlQueryInstructions,
|
||||
InputSchema: mcp.ToolInputSchema{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"query": map[string]any{
|
||||
"description": "graphql query to perform",
|
||||
"type": "string",
|
||||
},
|
||||
"variables": map[string]any{
|
||||
"description": "variables to use in the query",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
Required: []string{"query"},
|
||||
},
|
||||
Annotations: mcp.ToolAnnotation{
|
||||
Title: "Perform GraphQL Query on Nhost Cloud Platform",
|
||||
ReadOnlyHint: ptr(false),
|
||||
DestructiveHint: ptr(true),
|
||||
IdempotentHint: ptr(false),
|
||||
OpenWorldHint: ptr(true),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "get-schema",
|
||||
Description: schemas.ToolGetGraphqlSchemaInstructions,
|
||||
InputSchema: mcp.ToolInputSchema{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"role": map[string]any{
|
||||
"description": string("role to use when executing queries. Keep in mind the schema depends on the role so if you retrieved the schema for a different role previously retrieve it for this role beforehand as it might differ"),
|
||||
"type": string("string"),
|
||||
},
|
||||
"subdomain": map[string]any{
|
||||
"description": string("Project to get the GraphQL schema for. Required when service is `project`"),
|
||||
"enum": []any{string("local"), string("asdasdasdasdasd"), string("qweqweqweqweqwe")},
|
||||
"type": string("string"),
|
||||
},
|
||||
"mutations": map[string]any{
|
||||
"description": string("list of mutations to fetch"),
|
||||
"type": string("array"),
|
||||
},
|
||||
"queries": map[string]any{
|
||||
"description": string("list of queries to fetch"),
|
||||
"type": string("array"),
|
||||
},
|
||||
"summary": map[string]any{
|
||||
"default": bool(true),
|
||||
"description": string("only return a summary of the schema"),
|
||||
"type": string("boolean"),
|
||||
},
|
||||
},
|
||||
Required: []string{"role", "subdomain"},
|
||||
},
|
||||
Annotations: mcp.ToolAnnotation{
|
||||
Title: "Get GraphQL/API schema for various services",
|
||||
ReadOnlyHint: ptr(true),
|
||||
DestructiveHint: ptr(false),
|
||||
IdempotentHint: ptr(true),
|
||||
OpenWorldHint: ptr(true),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "graphql-query",
|
||||
Description: project.ToolGraphqlQueryInstructions,
|
||||
InputSchema: mcp.ToolInputSchema{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"query": map[string]any{
|
||||
"description": "graphql query to perform",
|
||||
"type": "string",
|
||||
},
|
||||
"subdomain": map[string]any{
|
||||
"description": "Project to perform the GraphQL query against",
|
||||
"type": "string",
|
||||
"enum": []any{
|
||||
string("local"),
|
||||
string("asdasdasdasdasd"),
|
||||
string("qweqweqweqweqwe"),
|
||||
},
|
||||
},
|
||||
"role": map[string]any{
|
||||
"description": "role to use when executing queries. Keep in mind the schema depends on the role so if you retrieved the schema for a different role previously retrieve it for this role beforehand as it might differ",
|
||||
"type": "string",
|
||||
},
|
||||
"userId": map[string]any{
|
||||
"description": string("Overrides X-Hasura-User-Id in the GraphQL query/mutation. Credentials must allow it (i.e. admin secret must be in use)"),
|
||||
"type": string("string"),
|
||||
},
|
||||
"variables": map[string]any{
|
||||
"description": "variables to use in the query",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
Required: []string{"query", "subdomain", "role"},
|
||||
},
|
||||
Annotations: mcp.ToolAnnotation{
|
||||
Title: "Perform GraphQL Query on Nhost Project running on Nhost Cloud",
|
||||
ReadOnlyHint: ptr(false),
|
||||
DestructiveHint: ptr(true),
|
||||
IdempotentHint: ptr(false),
|
||||
OpenWorldHint: ptr(true),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "manage-graphql",
|
||||
Description: project.ToolManageGraphqlInstructions,
|
||||
InputSchema: mcp.ToolInputSchema{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"body": map[string]any{
|
||||
"description": "The body for the HTTP request",
|
||||
"type": "string",
|
||||
},
|
||||
"path": map[string]any{
|
||||
"description": "The path for the HTTP request",
|
||||
"type": "string",
|
||||
},
|
||||
"subdomain": map[string]any{
|
||||
"description": "Project to perform the GraphQL management operation against",
|
||||
"type": "string",
|
||||
"enum": []any{
|
||||
string("local"),
|
||||
string("asdasdasdasdasd"),
|
||||
string("qweqweqweqweqwe"),
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"subdomain", "path", "body"},
|
||||
},
|
||||
Annotations: mcp.ToolAnnotation{
|
||||
Title: "Manage GraphQL's Metadata on an Nhost Development Project",
|
||||
ReadOnlyHint: ptr(false),
|
||||
DestructiveHint: ptr(true),
|
||||
IdempotentHint: ptr(true),
|
||||
OpenWorldHint: ptr(true),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "search",
|
||||
Description: docs.ToolSearchInstructions,
|
||||
InputSchema: mcp.ToolInputSchema{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"query": map[string]any{
|
||||
"description": string("The search query"),
|
||||
"type": string("string"),
|
||||
},
|
||||
},
|
||||
Required: []string{"query"},
|
||||
},
|
||||
Annotations: mcp.ToolAnnotation{
|
||||
Title: "Search Nhost Docs",
|
||||
ReadOnlyHint: ptr(true),
|
||||
IdempotentHint: ptr(true),
|
||||
DestructiveHint: ptr(false),
|
||||
OpenWorldHint: ptr(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
cmpopts.SortSlices(func(a, b mcp.Tool) bool {
|
||||
return a.Name < b.Name
|
||||
}),
|
||||
); diff != "" {
|
||||
t.Errorf("ListToolsResult mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
|
||||
resourceList, err := mcpClient.ListResources(
|
||||
context.Background(),
|
||||
mcp.ListResourcesRequest{}, //nolint:exhaustruct
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to list resources: %v", err)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(
|
||||
resourceList,
|
||||
//nolint:exhaustruct
|
||||
&mcp.ListResourcesResult{
|
||||
Resources: []mcp.Resource{
|
||||
{
|
||||
Annotated: mcp.Annotated{
|
||||
Annotations: &mcp.Annotations{
|
||||
Audience: []mcp.Role{"agent"},
|
||||
Priority: 9,
|
||||
},
|
||||
},
|
||||
URI: "schema://graphql-management",
|
||||
Name: "graphql-management",
|
||||
Description: resources.GraphqlManagementDescription,
|
||||
MIMEType: "text/plain",
|
||||
},
|
||||
|
||||
{
|
||||
Annotated: mcp.Annotated{
|
||||
Annotations: &mcp.Annotations{
|
||||
Audience: []mcp.Role{"agent"},
|
||||
Priority: 9,
|
||||
},
|
||||
},
|
||||
URI: "schema://nhost-cloud",
|
||||
Name: "nhost-cloud",
|
||||
Description: resources.CloudDescription,
|
||||
MIMEType: "text/plain",
|
||||
},
|
||||
{
|
||||
Annotated: mcp.Annotated{
|
||||
Annotations: &mcp.Annotations{
|
||||
Audience: []mcp.Role{"agent"},
|
||||
Priority: 9,
|
||||
},
|
||||
},
|
||||
URI: "schema://nhost.toml",
|
||||
Name: "nhost.toml",
|
||||
Description: resources.NhostTomlResourceDescription,
|
||||
MIMEType: "text/plain",
|
||||
},
|
||||
},
|
||||
},
|
||||
); diff != "" {
|
||||
t.Errorf("ListResourcesResult mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
|
||||
if res.Capabilities.Prompts != nil {
|
||||
prompts, err := mcpClient.ListPrompts(
|
||||
context.Background(),
|
||||
mcp.ListPromptsRequest{}, //nolint:exhaustruct
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to list prompts: %v", err)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(
|
||||
prompts,
|
||||
//nolint:exhaustruct
|
||||
&mcp.ListPromptsResult{
|
||||
Prompts: []mcp.Prompt{},
|
||||
},
|
||||
); diff != "" {
|
||||
t.Errorf("ListPromptsResult mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,208 +0,0 @@
|
||||
package start
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/mark3labs/mcp-go/server"
|
||||
"github.com/nhost/nhost/cli/clienv"
|
||||
"github.com/nhost/nhost/cli/mcp/config"
|
||||
"github.com/nhost/nhost/cli/mcp/nhost/auth"
|
||||
"github.com/nhost/nhost/cli/mcp/resources"
|
||||
"github.com/nhost/nhost/cli/mcp/tools/cloud"
|
||||
"github.com/nhost/nhost/cli/mcp/tools/docs"
|
||||
"github.com/nhost/nhost/cli/mcp/tools/project"
|
||||
"github.com/nhost/nhost/cli/mcp/tools/schemas"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
flagNhostAuthURL = "nhost-auth-url"
|
||||
flagNhostGraphqlURL = "nhost-graphql-url"
|
||||
flagBind = "bind"
|
||||
)
|
||||
|
||||
const (
|
||||
// this seems to be largely ignored by clients, or at least by cursor.
|
||||
// we also need to look into roots and resources as those might be helpful.
|
||||
ServerInstructions = `
|
||||
This is an MCP server to interact with the Nhost Cloud and with Nhost projects.
|
||||
|
||||
Important notes to anyone using this MCP server. Do not use this MCP server without
|
||||
following these instructions:
|
||||
|
||||
1. Make sure you are clear on which environment the user wants to operate against.
|
||||
2. Before attempting to call any tool, always make sure you list resources, roots, and
|
||||
resource templates to understand what is available.
|
||||
3. Apps and projects are the same and while users may talk about projects in Nhost's GraphQL
|
||||
api those are referred as apps.
|
||||
4. If you have an error querying the GraphQL API, please check the schema again. The schema may
|
||||
have changed and the query you are using may be invalid.
|
||||
5. Always follow the instructions provided by each tool. If you need to deviate from these
|
||||
instructions, please, confirm with the user before doing so.
|
||||
`
|
||||
)
|
||||
|
||||
func Command() *cli.Command {
|
||||
return &cli.Command{ //nolint:exhaustruct
|
||||
Name: "start",
|
||||
Usage: "Starts the MCP server",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagNhostAuthURL,
|
||||
Usage: "Nhost auth URL",
|
||||
Hidden: true,
|
||||
Value: "https://otsispdzcwxyqzbfntmj.auth.eu-central-1.nhost.run/v1",
|
||||
Category: "Cloud Platform",
|
||||
Sources: cli.EnvVars("NHOST_AUTH_URL"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagNhostGraphqlURL,
|
||||
Usage: "Nhost GraphQL URL",
|
||||
Hidden: true,
|
||||
Value: "https://otsispdzcwxyqzbfntmj.graphql.eu-central-1.nhost.run/v1",
|
||||
Category: "Cloud Platform",
|
||||
Sources: cli.EnvVars("NHOST_GRAPHQL_URL"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagBind,
|
||||
Usage: "Bind address in the form $host:$port. If omitted use stdio",
|
||||
Required: false,
|
||||
Category: "General",
|
||||
Sources: cli.EnvVars("BIND"),
|
||||
},
|
||||
},
|
||||
Action: action,
|
||||
}
|
||||
}
|
||||
|
||||
func action(ctx context.Context, cmd *cli.Command) error {
|
||||
cfg, err := getConfig(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ServerInstructions := ServerInstructions
|
||||
ServerInstructions += "\n\n"
|
||||
ServerInstructions += cfg.Projects.Instructions()
|
||||
ServerInstructions += "\n"
|
||||
ServerInstructions += resources.Instructions()
|
||||
|
||||
mcpServer := server.NewMCPServer(
|
||||
cmd.Root().Name,
|
||||
cmd.Root().Version,
|
||||
server.WithInstructions(ServerInstructions),
|
||||
)
|
||||
|
||||
if err := resources.Register(cfg, mcpServer); err != nil {
|
||||
return cli.Exit(fmt.Sprintf("failed to register resources: %s", err), 1)
|
||||
}
|
||||
|
||||
if cfg.Cloud != nil {
|
||||
if err := registerCloud(
|
||||
cmd,
|
||||
mcpServer,
|
||||
cfg,
|
||||
cmd.String(flagNhostAuthURL),
|
||||
cmd.String(flagNhostGraphqlURL),
|
||||
); err != nil {
|
||||
return cli.Exit(fmt.Sprintf("failed to register cloud tools: %s", err), 1)
|
||||
}
|
||||
}
|
||||
|
||||
if len(cfg.Projects) > 0 {
|
||||
if err := registerProjectTool(mcpServer, cfg); err != nil {
|
||||
return cli.Exit(fmt.Sprintf("failed to register project tools: %s", err), 1)
|
||||
}
|
||||
}
|
||||
|
||||
resources := schemas.NewTool(cfg)
|
||||
resources.Register(mcpServer)
|
||||
|
||||
d, err := docs.NewTool(ctx)
|
||||
if err != nil {
|
||||
return cli.Exit(fmt.Sprintf("failed to initialize docs tools: %s", err), 1)
|
||||
}
|
||||
|
||||
d.Register(mcpServer)
|
||||
|
||||
return start(mcpServer, cmd.String(flagBind))
|
||||
}
|
||||
|
||||
func getConfig(cmd *cli.Command) (*config.Config, error) {
|
||||
configPath := config.GetConfigPath(cmd)
|
||||
if configPath == "" {
|
||||
return nil, cli.Exit("config file path is required", 1)
|
||||
}
|
||||
|
||||
cfg, err := config.Load(configPath)
|
||||
if err != nil {
|
||||
fmt.Println("Please, run `nhost mcp config` to configure the service.") //nolint:forbidigo
|
||||
return nil, cli.Exit("failed to load config file "+err.Error(), 1)
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func registerCloud(
|
||||
cmd *cli.Command,
|
||||
mcpServer *server.MCPServer,
|
||||
cfg *config.Config,
|
||||
authURL string,
|
||||
graphqlURL string,
|
||||
) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
|
||||
creds, err := ce.Credentials()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load credentials: %w", err)
|
||||
}
|
||||
|
||||
interceptor, err := auth.WithPAT(
|
||||
authURL,
|
||||
creds.PersonalAccessToken,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create PAT interceptor: %w", err)
|
||||
}
|
||||
|
||||
cloudTool := cloud.NewTool(
|
||||
graphqlURL, cfg.Cloud.EnableMutations, interceptor,
|
||||
)
|
||||
|
||||
if err := cloudTool.Register(mcpServer); err != nil {
|
||||
return fmt.Errorf("failed to register tools: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func registerProjectTool(
|
||||
mcpServer *server.MCPServer,
|
||||
cfg *config.Config,
|
||||
) error {
|
||||
projectTool := project.NewTool(cfg)
|
||||
if err := projectTool.Register(mcpServer); err != nil {
|
||||
return fmt.Errorf("failed to register tool: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func start(
|
||||
mcpServer *server.MCPServer,
|
||||
bind string,
|
||||
) error {
|
||||
if bind != "" {
|
||||
sseServer := server.NewSSEServer(mcpServer, server.WithBaseURL(bind))
|
||||
if err := sseServer.Start(bind); err != nil {
|
||||
return cli.Exit(fmt.Sprintf("failed to serve tcp: %v", err), 1)
|
||||
}
|
||||
} else {
|
||||
if err := server.ServeStdio(mcpServer); err != nil {
|
||||
return cli.Exit(fmt.Sprintf("failed to serve stdio: %v", err), 1)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
29
cli/cmd/mcp/testdata/sample.toml
vendored
29
cli/cmd/mcp/testdata/sample.toml
vendored
@@ -1,29 +0,0 @@
|
||||
[cloud]
|
||||
enable_mutations = true
|
||||
|
||||
[[projects]]
|
||||
subdomain = 'local'
|
||||
region = 'local'
|
||||
description = 'Local development project running via the Nhost CLI'
|
||||
admin_secret = 'nhost-admin-secret'
|
||||
manage_metadata = true
|
||||
allow_queries = ['*']
|
||||
allow_mutations = ['*']
|
||||
|
||||
[[projects]]
|
||||
subdomain = 'asdasdasdasdasd'
|
||||
region = 'eu-central-1'
|
||||
description = 'Staging project for my awesome app'
|
||||
manage_metadata = false
|
||||
admin_secret = 'your-admin-secret-1'
|
||||
allow_queries = ['*']
|
||||
allow_mutations = ['*']
|
||||
|
||||
[[projects]]
|
||||
subdomain = 'qweqweqweqweqwe'
|
||||
region = 'us-east-1'
|
||||
description = 'Production project for my awesome app'
|
||||
manage_metadata = false
|
||||
pat = 'pat-for-qweqweqweqweqwe'
|
||||
allow_queries = ['getComments']
|
||||
allow_mutations = ['insertComment', 'updateComment', 'deleteComment']
|
||||
@@ -9,12 +9,12 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/hashicorp/go-getter/v2"
|
||||
"github.com/hashicorp/go-getter"
|
||||
"github.com/nhost/be/services/mimir/model"
|
||||
"github.com/nhost/nhost/cli/clienv"
|
||||
"github.com/nhost/nhost/cli/cmd/config"
|
||||
"github.com/nhost/nhost/cli/dockercompose"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -75,14 +75,14 @@ func CommandInit() *cli.Command {
|
||||
Name: flagRemote,
|
||||
Usage: "Initialize pulling configuration, migrations and metadata from the linked project",
|
||||
Value: false,
|
||||
Sources: cli.EnvVars("NHOST_REMOTE"),
|
||||
EnvVars: []string{"NHOST_REMOTE"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func commandInit(ctx context.Context, cmd *cli.Command) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func commandInit(cCtx *cli.Context) error {
|
||||
ce := clienv.FromCLI(cCtx)
|
||||
|
||||
if clienv.PathExists(ce.Path.NhostFolder()) {
|
||||
return errors.New("nhost folder already exists") //nolint:err113
|
||||
@@ -98,12 +98,12 @@ func commandInit(ctx context.Context, cmd *cli.Command) error {
|
||||
return fmt.Errorf("failed to initialize configuration: %w", err)
|
||||
}
|
||||
|
||||
if cmd.Bool(flagRemote) {
|
||||
if err := InitRemote(ctx, ce); err != nil {
|
||||
if cCtx.Bool(flagRemote) {
|
||||
if err := InitRemote(cCtx.Context, ce); err != nil {
|
||||
return fmt.Errorf("failed to initialize remote project: %w", err)
|
||||
}
|
||||
} else {
|
||||
if err := initInit(ctx, ce.Path); err != nil {
|
||||
if err := initInit(cCtx.Context, ce.Path); err != nil {
|
||||
return fmt.Errorf("failed to initialize project: %w", err)
|
||||
}
|
||||
}
|
||||
@@ -129,12 +129,17 @@ func initInit(
|
||||
return err
|
||||
}
|
||||
|
||||
getclient := &getter.Client{} //nolint:exhaustruct
|
||||
if _, err := getclient.Get(ctx, &getter.Request{ //nolint:exhaustruct
|
||||
Src: "git::https://github.com/nhost/nhost.git//services/auth/email-templates",
|
||||
Dst: "nhost/emails",
|
||||
DisableSymlinks: true,
|
||||
}); err != nil {
|
||||
getclient := &getter.Client{ //nolint:exhaustruct
|
||||
Ctx: ctx,
|
||||
Src: "github.com/nhost/hasura-auth/email-templates",
|
||||
Dst: "nhost/emails",
|
||||
Mode: getter.ClientModeAny,
|
||||
Detectors: []getter.Detector{
|
||||
&getter.GitHubDetector{},
|
||||
},
|
||||
}
|
||||
|
||||
if err := getclient.Get(); err != nil {
|
||||
return fmt.Errorf("failed to download email templates: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package project
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/nhost/nhost/cli/clienv"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func CommandLink() *cli.Command {
|
||||
@@ -19,14 +18,14 @@ func CommandLink() *cli.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func commandLink(ctx context.Context, cmd *cli.Command) error {
|
||||
ce := clienv.FromCLI(cmd)
|
||||
func commandLink(cCtx *cli.Context) error {
|
||||
ce := clienv.FromCLI(cCtx)
|
||||
|
||||
if err := os.MkdirAll(ce.Path.DotNhostFolder(), 0o755); err != nil { //nolint:mnd
|
||||
return fmt.Errorf("failed to create .nhost folder: %w", err)
|
||||
}
|
||||
|
||||
_, err := ce.Link(ctx)
|
||||
_, err := ce.Link(cCtx.Context)
|
||||
|
||||
return err //nolint:wrapcheck
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user