Skip to Content

Automation & CI/CD

Automating your testing and deployment process is a best practice for any serious application. For a WebF project, this typically involves setting up two separate, but related, CI/CD pipelines: one for your WebF application and one for the native host app.

CI/CD for Your WebF Application

As a web developer, your primary focus will be on the CI/CD pipeline for your WebF app assets. You can use any standard CI service like GitHub Actions, GitLab CI, or CircleCI.

The workflow is identical to that of a typical modern WebF application:

  1. On push or merge to main: The CI server checks out your code.
  2. Install & Test: It installs dependencies (npm ci) and runs all your tests (npm test).
  3. Build: If tests pass, it creates a production build of your WebF app assets (npm run build).
  4. Deploy: The contents of the output dist directory are automatically deployed to your CDN or static hosting provider (e.g., Vercel, Netlify, AWS S3).

This ensures that every time you merge a new feature, it is automatically tested and deployed, providing instant “Over-the-Air” updates to your users.

GitHub Actions

GitHub Actions is a popular choice for CI/CD with excellent integration into GitHub repositories.

Basic Workflow

Create .github/workflows/deploy.yml:

name: Deploy WebF Application on: push: branches: [ main ] pull_request: branches: [ main ] jobs: test: runs-on: ubuntu-latest steps: - 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 linter run: npm run lint - name: Run tests run: npm test -- --run - name: Build run: npm run build - name: Upload build artifacts uses: actions/upload-artifact@v4 with: name: dist path: dist/ deploy: needs: test runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - name: Download build artifacts uses: actions/download-artifact@v4 with: name: dist path: dist/ - name: Deploy to Vercel uses: amondnet/vercel-action@v25 with: vercel-token: ${{ secrets.VERCEL_TOKEN }} vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }} vercel-args: '--prod' working-directory: ./dist

Deploy to AWS S3

- name: Deploy to S3 env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} run: | aws s3 sync dist/ s3://${{ secrets.S3_BUCKET }} --delete aws cloudfront create-invalidation \ --distribution-id ${{ secrets.CLOUDFRONT_DIST_ID }} \ --paths "/*"

Deploy to Netlify

- name: Deploy to Netlify uses: nwtgck/actions-netlify@v3 with: publish-dir: './dist' production-deploy: true env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}

Environment-Specific Builds

deploy-staging: needs: test runs-on: ubuntu-latest if: github.ref == 'refs/heads/develop' steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' - run: npm ci - run: npm run build env: VITE_API_URL: ${{ secrets.STAGING_API_URL }} VITE_ENV: 'staging' - name: Deploy to Staging run: | # Deploy to staging environment

GitLab CI

GitLab CI uses a .gitlab-ci.yml file:

image: node:20 stages: - test - build - deploy cache: paths: - node_modules/ test: stage: test script: - npm ci - npm run lint - npm test -- --run artifacts: reports: junit: test-results.xml coverage: coverage/ build: stage: build script: - npm ci - npm run build artifacts: paths: - dist/ expire_in: 1 week deploy_production: stage: deploy script: - npm install -g netlify-cli - netlify deploy --prod --dir=dist environment: name: production url: https://my-app.netlify.app only: - main when: manual deploy_staging: stage: deploy script: - netlify deploy --dir=dist environment: name: staging url: https://staging--my-app.netlify.app only: - develop

CircleCI

CircleCI uses a .circleci/config.yml file:

version: 2.1 orbs: node: circleci/node@5.1 jobs: test: docker: - image: cimg/node:20.0 steps: - checkout - node/install-packages: pkg-manager: npm - run: name: Run tests command: npm test -- --run - run: name: Run linter command: npm run lint build: docker: - image: cimg/node:20.0 steps: - checkout - node/install-packages: pkg-manager: npm - run: name: Build application command: npm run build - persist_to_workspace: root: . paths: - dist deploy: docker: - image: cimg/node:20.0 steps: - attach_workspace: at: . - run: name: Deploy to Netlify command: | npm install -g netlify-cli netlify deploy --prod --dir=dist workflows: version: 2 test_build_deploy: jobs: - test - build: requires: - test - deploy: requires: - build filters: branches: only: main

Best Practices

1. Use Secrets Management

Never commit secrets to your repository. Use your CI platform’s secrets management:

GitHub Actions:

env: API_KEY: ${{ secrets.API_KEY }}

GitLab CI:

variables: API_KEY: $CI_SECRET_API_KEY

2. Run Tests Before Deployment

Always run your full test suite before deploying:

deploy: needs: test # Deploy only if tests pass # ... deployment steps

3. Use Caching

Cache dependencies to speed up builds:

# GitHub Actions - uses: actions/setup-node@v4 with: cache: 'npm' # GitLab CI cache: paths: - node_modules/

4. Implement Quality Gates

Fail the build if quality thresholds aren’t met:

- name: Check test coverage run: | npm test -- --coverage npx nyc check-coverage --lines 80 --functions 80 - name: Check bundle size run: | npm run build npx bundlesize

5. Use Environment Variables

Separate config for different environments:

# .env.production VITE_API_URL=https://api.production.com VITE_ANALYTICS_ID=prod-123 # .env.staging VITE_API_URL=https://api.staging.com VITE_ANALYTICS_ID=staging-123

6. Implement Deployment Approvals

For production deploys, add manual approval:

# GitHub Actions deploy: environment: name: production # Requires approval in GitHub settings # GitLab CI deploy: when: manual # Requires manual trigger

7. Monitor Deployment Status

Add status checks and notifications:

- name: Notify Slack on Success if: success() uses: 8398a7/action-slack@v3 with: status: success text: 'Deployment to production succeeded!' webhook_url: ${{ secrets.SLACK_WEBHOOK }} - name: Notify Slack on Failure if: failure() uses: 8398a7/action-slack@v3 with: status: failure text: 'Deployment to production failed!' webhook_url: ${{ secrets.SLACK_WEBHOOK }}

8. Implement Rollback Strategy

Include rollback capabilities:

rollback: stage: deploy script: - aws s3 sync s3://backup-bucket/previous-version/ s3://production-bucket/ when: manual only: - main

Advanced Workflows

Preview Deployments

Create preview deployments for pull requests:

deploy-preview: runs-on: ubuntu-latest if: github.event_name == 'pull_request' steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 - run: npm ci - run: npm run build - name: Deploy Preview uses: nwtgck/actions-netlify@v3 with: publish-dir: './dist' production-deploy: false github-token: ${{ secrets.GITHUB_TOKEN }} deploy-message: "Deploy from PR #${{ github.event.number }}" env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}

Multi-Environment Pipeline

deploy-dev: stage: deploy script: - npm run build:dev - ./deploy.sh dev only: - develop deploy-staging: stage: deploy script: - npm run build:staging - ./deploy.sh staging only: - main when: manual deploy-production: stage: deploy script: - npm run build:production - ./deploy.sh production only: - tags when: manual

CI/CD for the Native Host App

The CI/CD pipeline for the native host app (which contains the WebF engine) is a separate process, usually managed by a Flutter development team. It handles building the native code, code signing, and publishing new versions of the app itself to the app stores.

This process is outside the scope of this guide. For details, refer to the Guide for Flutter Developers (coming soon).

Monitoring and Alerts

Set Up Error Monitoring

- name: Initialize Sentry Release run: | npx @sentry/cli releases new "${{ github.sha }}" npx @sentry/cli releases set-commits "${{ github.sha }}" --auto npx @sentry/cli releases finalize "${{ github.sha }}" env: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_ORG: your-org SENTRY_PROJECT: your-project

Performance Monitoring

- name: Lighthouse CI run: | npm install -g @lhci/cli lhci autorun

CI/CD Checklist

  • Automated tests run on every commit
  • Build succeeds before deployment
  • Secrets are managed securely
  • Dependencies are cached
  • Multiple environments configured (dev, staging, prod)
  • Manual approval required for production
  • Rollback strategy in place
  • Notifications configured for success/failure
  • Preview deployments for pull requests
  • Error monitoring integrated
  • Performance monitoring enabled
  • Documentation is up to date