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:
- On push or merge to
main: The CI server checks out your code. - Install & Test: It installs dependencies (
npm ci) and runs all your tests (npm test). - Build: If tests pass, it creates a production build of your WebF app assets (
npm run build). - Deploy: The contents of the output
distdirectory 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: ./distDeploy 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 environmentGitLab 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:
- developCircleCI
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: mainBest 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_KEY2. Run Tests Before Deployment
Always run your full test suite before deploying:
deploy:
needs: test # Deploy only if tests pass
# ... deployment steps3. 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 bundlesize5. 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-1236. 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 trigger7. 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:
- mainAdvanced 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: manualCI/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-projectPerformance Monitoring
- name: Lighthouse CI
run: |
npm install -g @lhci/cli
lhci autorunCI/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