Skip to main content

CI/CD for Serverless with GitHub Actions

Automate your serverless deployments using GitHub Actions. This guide covers setting up continuous integration and deployment pipelines for staging, production, and preview environments.

Prerequisites

Before setting up CI/CD, you'll need:

  1. Personal Access Token (PAT) from Boltic Console
  2. Account ID from your Boltic account settings
  3. A GitHub repository with your serverless code
  4. A working serverless function (see Build an API with Boltic Tables)

Step 1: Generate a Personal Access Token

  1. Go to Boltic Console > Settings > Access Tokens
  2. Click Generate New Token
  3. Give it a descriptive name (e.g., github-actions-deploy)
  4. Set appropriate expiration
  5. Copy the token (you won't see it again)

Step 2: Configure GitHub Secrets

Add the following secrets to your GitHub repository:

  1. Go to Repository > Settings > Secrets and variables > Actions
  2. Click New repository secret
  3. Add these secrets:
Secret NameDescription
BOLTIC_TOKENYour Personal Access Token
BOLTIC_ACCOUNT_IDYour Boltic Account ID
DATABASE_URLPostgreSQL connection string (optional)

Step 3: Basic Deployment Workflow

Create .github/workflows/deploy.yml in your repository:

name: Deploy Serverless

on:
push:
branches:
- main
workflow_dispatch: # Allow manual triggers

env:
NODE_VERSION: '20'
SERVERLESS_NAME: 'tasks-api'

jobs:
deploy:
name: Deploy to Boltic
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Install Boltic CLI
run: npm install -g @boltic/cli

- name: Authenticate with Boltic
run: boltic login --token ${{ secrets.BOLTIC_TOKEN }} --account-id ${{ secrets.BOLTIC_ACCOUNT_ID }}

- name: Deploy serverless function
run: boltic serverless publish

- name: Verify deployment
run: |
echo "Waiting for deployment to be ready..."
sleep 10
boltic serverless status --name ${{ env.SERVERLESS_NAME }} --watch

Step 4: Multi-Environment Workflow

For teams with staging and production environments, use this comprehensive workflow.

Create .github/workflows/deploy-environments.yml:

name: Deploy Serverless (Multi-Environment)

on:
push:
branches:
- main # Deploy to production
- develop # Deploy to staging
pull_request:
branches:
- main
types: [opened, synchronize]

env:
NODE_VERSION: '20'

jobs:
# ============================================================================
# Lint and Test
# ============================================================================
test:
name: Lint & Test
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run linter
run: npm run lint --if-present

- name: Run tests
run: npm test --if-present

# ============================================================================
# Deploy to Staging
# ============================================================================
deploy-staging:
name: Deploy to Staging
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/develop' && github.event_name == 'push'
environment:
name: staging
url: https://tasks-api-staging.boltic.app

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Install Boltic CLI
run: npm install -g @boltic/cli

- name: Authenticate with Boltic
run: boltic login --token ${{ secrets.BOLTIC_TOKEN }} --account-id ${{ secrets.BOLTIC_ACCOUNT_ID }}

- name: Update config for staging
run: |
# Update serverless name for staging
sed -i 's/Name: "tasks-api"/Name: "tasks-api-staging"/' boltic.yaml
sed -i 's/app: "tasks-api"/app: "tasks-api-staging"/' boltic.yaml

- name: Deploy to staging
run: boltic serverless publish

- name: Wait for deployment
run: |
echo "Waiting for staging deployment..."
for i in {1..30}; do
STATUS=$(boltic serverless status --name tasks-api-staging 2>/dev/null | grep -i "status" | head -1 || echo "pending")
if echo "$STATUS" | grep -qi "running"; then
echo "✓ Staging deployment successful!"
exit 0
fi
echo "Attempt $i/30: $STATUS"
sleep 10
done
echo "Deployment did not reach running state"
exit 1

- name: Health check
run: |
HEALTH_URL="https://tasks-api-staging.boltic.app/health"
echo "Checking health at $HEALTH_URL"
curl -sf "$HEALTH_URL" || (echo "Health check failed" && exit 1)
echo "✓ Health check passed!"

# ============================================================================
# Deploy to Production
# ============================================================================
deploy-production:
name: Deploy to Production
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
environment:
name: production
url: https://tasks-api.boltic.app

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Install Boltic CLI
run: npm install -g @boltic/cli

- name: Authenticate with Boltic
run: boltic login --token ${{ secrets.BOLTIC_TOKEN }} --account-id ${{ secrets.BOLTIC_ACCOUNT_ID }}

- name: Deploy to production
run: boltic serverless publish

- name: Wait for deployment
run: |
echo "Waiting for production deployment..."
for i in {1..30}; do
STATUS=$(boltic serverless status --name tasks-api 2>/dev/null | grep -i "status" | head -1 || echo "pending")
if echo "$STATUS" | grep -qi "running"; then
echo "✓ Production deployment successful!"
exit 0
fi
echo "Attempt $i/30: $STATUS"
sleep 10
done
echo "Deployment did not reach running state"
exit 1

- name: Health check
run: |
HEALTH_URL="https://tasks-api.boltic.app/health"
echo "Checking health at $HEALTH_URL"
curl -sf "$HEALTH_URL" || (echo "Health check failed" && exit 1)
echo "✓ Health check passed!"

- name: Notify on success
if: success()
run: echo "🚀 Production deployment completed successfully!"

- name: Notify on failure
if: failure()
run: echo "❌ Production deployment failed!"

Step 5: Pull Request Preview Deployments

Deploy preview environments for each pull request.

Create .github/workflows/preview.yml:

name: Preview Deployment

on:
pull_request:
types: [opened, synchronize, reopened]

env:
NODE_VERSION: '20'

jobs:
deploy-preview:
name: Deploy Preview
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Install Boltic CLI
run: npm install -g @boltic/cli

- name: Authenticate with Boltic
run: boltic login --token ${{ secrets.BOLTIC_TOKEN }} --account-id ${{ secrets.BOLTIC_ACCOUNT_ID }}

- name: Create preview deployment
id: preview
run: |
PREVIEW_NAME="tasks-api-pr-${{ github.event.pull_request.number }}"
echo "preview_name=$PREVIEW_NAME" >> $GITHUB_OUTPUT

# Update config for preview
sed -i "s/Name: \"tasks-api\"/Name: \"$PREVIEW_NAME\"/" boltic.yaml
sed -i "s/app: \"tasks-api\"/app: \"$PREVIEW_NAME\"/" boltic.yaml

# Deploy preview
boltic serverless publish

echo "preview_url=https://$PREVIEW_NAME.boltic.app" >> $GITHUB_OUTPUT

- name: Comment on PR
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## 🚀 Preview Deployment Ready!

| Environment | URL |
|-------------|-----|
| Preview | [${{ steps.preview.outputs.preview_name }}](${{ steps.preview.outputs.preview_url }}) |

### Test endpoints:
- Health: \`${{ steps.preview.outputs.preview_url }}/health\`
- Tasks: \`${{ steps.preview.outputs.preview_url }}/tasks\`

_This preview will be automatically cleaned up when the PR is closed._`
})

# Cleanup preview on PR close
cleanup-preview:
name: Cleanup Preview
runs-on: ubuntu-latest
if: github.event.action == 'closed'

steps:
- name: Install Boltic CLI
run: npm install -g @boltic/cli

- name: Authenticate with Boltic
run: boltic login --token ${{ secrets.BOLTIC_TOKEN }} --account-id ${{ secrets.BOLTIC_ACCOUNT_ID }}

- name: Delete preview deployment
run: |
PREVIEW_NAME="tasks-api-pr-${{ github.event.pull_request.number }}"
echo "Cleaning up preview: $PREVIEW_NAME"
# Note: Add delete command when available
# boltic serverless delete --name $PREVIEW_NAME

Step 6: Scheduled Deployments

For scheduled deployments (e.g., nightly builds).

Create .github/workflows/scheduled-deploy.yml:

name: Scheduled Deployment

on:
schedule:
# Run at 2 AM UTC every day
- cron: '0 2 * * *'
workflow_dispatch:

jobs:
scheduled-deploy:
name: Nightly Deploy
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: main

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Install Boltic CLI
run: npm install -g @boltic/cli

- name: Authenticate with Boltic
run: boltic login --token ${{ secrets.BOLTIC_TOKEN }} --account-id ${{ secrets.BOLTIC_ACCOUNT_ID }}

- name: Deploy
run: boltic serverless publish

- name: Verify deployment
run: boltic serverless status --name tasks-api

Workflow Triggers Summary

TriggerWorkflowEnvironment
Push to maindeploy-environments.ymlProduction
Push to developdeploy-environments.ymlStaging
Pull Requestpreview.ymlPreview (ephemeral)
Manualdeploy.ymlConfigurable
Scheduled (cron)scheduled-deploy.ymlProduction

Best Practices

1. Use GitHub Environments

  • Configure environment protection rules
  • Require approvals for production deployments
  • Set environment-specific secrets

2. Implement Health Checks

  • Always verify deployments with health endpoints
  • Fail the pipeline if health checks don't pass

3. Version Your Deployments

  • Tag releases with semantic versioning
  • Include commit SHA in deployment metadata

4. Monitor Build Logs

# View build logs in case of failures
boltic serverless builds --name tasks-api
boltic serverless build logs --name tasks-api --build <BUILD_ID>

5. Rollback Strategy

  • Keep previous deployments available
  • Document rollback procedures
  • Consider blue-green deployments for zero-downtime

Troubleshooting

Authentication Failures

Error: Authentication failed

Solutions:

  • Verify BOLTIC_TOKEN secret is correct and not expired
  • Check BOLTIC_ACCOUNT_ID matches your account
  • Regenerate PAT if needed

Deployment Timeouts

Error: Deployment did not reach running state

Solutions:

  • Check build logs: boltic serverless builds --name <name>
  • Increase wait time in workflow
  • Verify boltic.yaml configuration

Permission Errors

Error: Insufficient permissions

Solutions:

  • Verify PAT has deployment permissions
  • Check account access levels
  • Contact your Boltic administrator

CLI Commands Reference

# Authentication (for CI/CD)
boltic login --token <PAT> --account-id <ACCOUNT_ID>

# Deploy
boltic serverless publish

# Check status
boltic serverless status --name <name>

# View logs
boltic serverless logs --name <name>

# View builds
boltic serverless builds --name <name>
boltic serverless build logs --name <name> --build <BUILD_ID>