CI/CD Integration

GitHub Actions CI/CD

Automate deployments to Focal Deploy with every push to your repository

15-20 minutesIntermediate

Prerequisites

  • GitHub Repository

    Your application code hosted on GitHub

  • Focal Deploy Account & Project

    An existing project deployed at least once manually (follow this guide)

  • Focal Deploy API Key

    Generate from Dashboard → API Keys

Step 1: Generate a Focal Deploy API Key

  1. 1
  2. 2

    Click "Generate New API Key"

  3. 3

    Give it a descriptive name like "GitHub Actions - My Project"

  4. 4

    Copy the generated API key - you'll need it in the next step

    Important: The API key will only be shown once. Store it securely!

Step 2: Add Secrets to GitHub Repository

  1. 1

    Go to your GitHub repository → SettingsSecrets and variablesActions

  2. 2

    Click "New repository secret" and add:

    Secret #1:

    Name:

    FOCAL_DEPLOY_API_KEY

    Value:

    Your API key from Step 1

    Secret #2 (Optional):

    Name:

    FOCAL_DEPLOY_PROJECT_ID

    Value:

    Your project ID from Focal Deploy dashboard

Step 3: Create GitHub Actions Workflow

Choose between a simple workflow or an advanced one with testing and PR previews:

Option A: Simple Workflow

Perfect for getting started. Deploys on every push to main branch.

name: Deploy to Focal Deploy

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - run: npm ci
      - run: npm run build

      - name: Deploy
        env:
          FOCAL_DEPLOY_API_KEY: ${{ secrets.FOCAL_DEPLOY_API_KEY }}
        run: |
          curl -X POST https://api.focuswithfocal.io/api/deployments \
            -H "Authorization: Bearer $FOCAL_DEPLOY_API_KEY" \
            -H "Content-Type: application/json" \
            -d '{"projectName": "my-app"}'

Option B: Advanced Workflow

Includes testing, build steps, and PR preview deployments.

name: Deploy to Focal Deploy

on:
  push:
    branches: [ main, production ]
  pull_request:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest

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

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

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test

      - name: Build application
        run: npm run build

      - name: Deploy to Focal Deploy
        if: github.ref == 'refs/heads/main' && github.event_name == 'push'
        env:
          FOCAL_DEPLOY_API_KEY: ${{ secrets.FOCAL_DEPLOY_API_KEY }}
          FOCAL_DEPLOY_PROJECT_ID: ${{ secrets.FOCAL_DEPLOY_PROJECT_ID }}
        run: |
          curl -X POST https://api.focuswithfocal.io/api/deployments \
            -H "Authorization: Bearer $FOCAL_DEPLOY_API_KEY" \
            -H "Content-Type: application/json" \
            -d '{"projectId": "'"$FOCAL_DEPLOY_PROJECT_ID"'", "branch": "${{ github.ref_name }}"}'

      - name: Comment PR with preview URL
        if: github.event_name == 'pull_request'
        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 at: https://pr-' + context.issue.number + '-${{ secrets.FOCAL_DEPLOY_PROJECT_ID }}.focuswithfocal.com'
            })

📝 To add this workflow:

  1. Create a new file: .github/workflows/deploy.yml
  2. Paste one of the workflows above
  3. Customize it for your project (change Node version, test commands, etc.)
  4. Commit and push to your repository

Step 4: Test Your Workflow

  1. 1

    Push a commit to your main branch (or create a PR if using the advanced workflow)

    git add .
    git commit -m "Add GitHub Actions deployment"
    git push origin main
  2. 2

    Go to your repository → Actions tab to watch the workflow run

  3. 3

    Click on the workflow run to see real-time logs

  4. 4

    Once completed, verify your deployment in the Focal Deploy dashboard

Success!

Your workflow is now active. Every push to main will automatically deploy to Focal Deploy!

Advanced Configuration Options

Deploy on Git Tag (Releases)

Trigger deployments only when you create a release tag:

on:
  push:
    tags:
      - 'v*'  # Triggers on tags like v1.0.0

Environment-Specific Deployments

Deploy to different environments based on branch:

- name: Deploy to Production
  if: github.ref == 'refs/heads/main'
  run: curl -X POST https://api.focuswithfocal.io/api/deployments -H "Authorization: Bearer $API_KEY" -d '{"env":"production"}'

- name: Deploy to Staging
  if: github.ref == 'refs/heads/develop'
  run: curl -X POST https://api.focuswithfocal.io/api/deployments -H "Authorization: Bearer $API_KEY" -d '{"env":"staging"}'

Slack Notifications

Get notified on Slack when deployments complete:

- name: Notify Slack
  uses: 8398a7/action-slack@v3
  with:
    status: ${{ job.status }}
    text: 'Deployment ${{ job.status }}'
    webhook_url: ${{ secrets.SLACK_WEBHOOK }}
  if: always()

Security Best Practices

Never hardcode API keys

Always use GitHub Secrets for sensitive values

Rotate API keys regularly

Generate new API keys quarterly and update GitHub Secrets

Use branch protection rules

Require pull request reviews before deploying to production

Limit workflow permissions

Use read-only tokens when possible and scope permissions appropriately

Troubleshooting

Workflow Fails with "API Key Invalid"

Check that:

  • The secret name matches exactly (case-sensitive)
  • No extra spaces were added when copying the API key
  • The API key hasn't been revoked or expired

Deployment Times Out

Increase the timeout in your workflow with timeout-minutes: 30 in the deploy job.

Build Fails on GitHub but Works Locally

Ensure environment variables are set in GitHub Secrets. Check that your build doesn't depend on local files not in git.

Need Help? Check the GitHub Actions documentation or contact Focal Deploy support

Related Guides