CI/CD
A useful Apso pipeline validates the schema, regenerates code, fails on an uncommitted generated diff, runs the framework test suite, and deploys only after those checks pass.
Repository requirements
Commit the files another machine needs to reproduce the service:
.apsorc- Generated framework source
extensions/- Migrations
- Dependency manifests and lockfiles
- Tests
.env.examplewithout secrets
Keep .env, service API keys, database credentials, and platform tokens in the CI secret store.
Validation job
This GitHub Actions example validates a TypeScript service:
name: Validate backend
on:
pull_request:
push:
branches: [main]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm install -g @apso/cli
- run: npm ci
- run: apso schema validate
- run: apso generate
- name: Require generated code to be committed
run: git diff --exit-code
- run: apso migrate
- run: npm test
- run: npm run buildapso migrate uses a local PGlite sandbox, so the validation job does not need production database credentials.
Framework checks
TypeScript
npm ci
npm test
npm run buildDeploy to Apso Cloud
Connect GitHub and the service once from an interactive environment before enabling automated deployment:
apso github connect
apso link --workspace your-team --service project-apiThe automation token is a platform credential, not a generated service API key. Store it as APSO_TOKEN in the repository or environment secret store.
name: Deploy backend
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm install -g @apso/cli
- name: Authenticate
run: apso login --token "$APSO_TOKEN"
env:
APSO_TOKEN: ${{ secrets.APSO_TOKEN }}
- name: Link service
run: apso link --workspace your-team --service project-api
- name: Deploy committed source
run: apso deploy --skip-push --yes--skip-push is appropriate here because the workflow is already running the commit from the connected repository. Remove it when the job must synchronize a different local source tree.
Do not pass --token to apso deploy. Authentication is a separate apso login --token step.
Self-hosted image
Generated services can use a normal container pipeline. This example publishes an existing project Dockerfile to GitHub Container Registry:
name: Publish backend image
on:
push:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ghcr.io/${{ env.IMAGE_NAME }}:${{ github.sha }}Deployment verification
After either deployment path:
- Request
/healthfrom the deployed endpoint. - Exercise one authenticated read request.
- Exercise one write in a non-production smoke-test resource when available.
- Record the deployed commit SHA in the release system.
- Stop the pipeline when migration, health, or authentication checks fail.