Skip to content
capacitor-ci-cd logo

CI/CD for Capacitor Applications

capacitor-ci-cd

Complete CI/CD guide for Capacitor apps covering GitHub Actions, GitLab CI, build automation, app signing, and deployment pipelines. Use this skill when users need to automate their build and release process.

yeohj0710/wellnessbox0installs0stars

SKILL.md

Full skill instructions

CI/​CD for Capacitor Applications

Automate building, testing, and deploying Capacitor apps.

When to Use This Skill

  • User wants to automate builds
  • User needs CI/​CD pipeline
  • User asks about GitHub Actions
  • User needs app signing automation
  • User wants automated releases

GitHub Actions

Complete Workflow

# .github/​workflows/​build.yml
name: Build and Deploy

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

env:
  NODE_VERSION: '20'

jobs:
  # Run tests and linting
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/​checkout@v4

      - uses: oven-sh/​setup-bun@v1

      - name: Install dependencies
        run: bun install

      - name: Lint
        run: bun run lint

      - name: Type check
        run: bun run typecheck

      - name: Unit tests
        run: bun test --coverage

      - name: Upload coverage
        uses: codecov/​codecov-action@v4

  # Security scan
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/​checkout@v4
      - uses: oven-sh/​setup-bun@v1
      - run: bunx capsec scan --ci

  # Build web assets
  build-web:
    runs-on: ubuntu-latest
    needs: [test, security]
    steps:
      - uses: actions/​checkout@v4

      - uses: oven-sh/​setup-bun@v1

      - name: Install dependencies
        run: bun install

      - name: Build
        run: bun run build

      - name: Upload build artifacts
        uses: actions/​upload-artifact@v4
        with:
          name: web-build
          path: dist/

  # Build iOS
  build-ios:
    runs-on: macos-latest
    needs: build-web
    steps:
      - uses: actions/​checkout@v4

      - uses: oven-sh/​setup-bun@v1

      - name: Download web build
        uses: actions/​download-artifact@v4
        with:
          name: web-build
          path: dist/

      - name: Install dependencies
        run: bun install

      - name: Sync Capacitor
        run: bunx cap sync ios

      - name: Setup Ruby
        uses: ruby/​setup-ruby@v1
        with:
          ruby-version: '3.2'
          bundler-cache: true
          working-directory: ios/​App

      - name: Install CocoaPods
        run: cd ios/​App && pod install

      - name: Import certificates
        env:
          CERTIFICATE_P12: ${{ secrets.CERTIFICATE_P12 }}
          CERTIFICATE_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }}
          PROVISIONING_PROFILE: ${{ secrets.PROVISIONING_PROFILE }}
        run: |
          # Create keychain
          security create-keychain -p "" build.keychain
          security default-keychain -s build.keychain
          security unlock-keychain -p "" build.keychain
          security set-keychain-settings -t 3600 -u build.keychain

          # Import certificate
          echo "$CERTIFICATE_P12" | base64 --decode > certificate.p12
          security import certificate.p12 -k build.keychain -P "$CERTIFICATE_PASSWORD" -T /​usr/​bin/​codesign
          security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "" build.keychain

          # Install provisioning profile
          mkdir -p ~/​Library/​MobileDevice/​Provisioning\ Profiles
          echo "$PROVISIONING_PROFILE" | base64 --decode > ~/​Library/​MobileDevice/​Provisioning\ Profiles/​profile.mobileprovision

      - name: Build iOS
        run: |
          cd ios/​App
          xcodebuild -workspace App.xcworkspace \
            -scheme App \
            -configuration Release \
            -archivePath build/​App.xcarchive \
            archive

      - name: Export IPA
        run: |
          cd ios/​App
          xcodebuild -exportArchive \
            -archivePath build/​App.xcarchive \
            -exportPath build/ \
            -exportOptionsPlist ExportOptions.plist

      - name: Upload IPA
        uses: actions/​upload-artifact@v4
        with:
          name: ios-build
          path: ios/​App/​build/​*.ipa

  # Build Android
  build-android:
    runs-on: ubuntu-latest
    needs: build-web
    steps:
      - uses: actions/​checkout@v4

      - uses: oven-sh/​setup-bun@v1

      - name: Download web build
        uses: actions/​download-artifact@v4
        with:
          name: web-build
          path: dist/

      - name: Setup Java
        uses: actions/​setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Setup Android SDK
        uses: android-actions/​setup-android@v3

      - name: Install dependencies
        run: bun install

      - name: Sync Capacitor
        run: bunx cap sync android

      - name: Decode keystore
        env:
          KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
        run: |
          echo "$KEYSTORE_BASE64" | base64 --decode > android/​app/​release.keystore

      - name: Build APK
        env:
          KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
          KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
          KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
        run: |
          cd android
          ./​gradlew assembleRelease \
            -Pandroid.injected.signing.store.file=release.keystore \
            -Pandroid.injected.signing.store.password=$KEYSTORE_PASSWORD \
            -Pandroid.injected.signing.key.alias=$KEY_ALIAS \
            -Pandroid.injected.signing.key.password=$KEY_PASSWORD

      - name: Build AAB
        env:
          KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
          KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
          KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
        run: |
          cd android
          ./​gradlew bundleRelease \
            -Pandroid.injected.signing.store.file=release.keystore \
            -Pandroid.injected.signing.store.password=$KEYSTORE_PASSWORD \
            -Pandroid.injected.signing.key.alias=$KEY_ALIAS \
            -Pandroid.injected.signing.key.password=$KEY_PASSWORD

      - name: Upload APK
        uses: actions/​upload-artifact@v4
        with:
          name: android-apk
          path: android/​app/​build/​outputs/​apk/​release/​*.apk

      - name: Upload AAB
        uses: actions/​upload-artifact@v4
        with:
          name: android-aab
          path: android/​app/​build/​outputs/​bundle/​release/​*.aab

  # Deploy to Capgo
  deploy-capgo:
    runs-on: ubuntu-latest
    needs: build-web
    if: github.ref == 'refs/​heads/​main'
    steps:
      - uses: actions/​checkout@v4

      - uses: oven-sh/​setup-bun@v1

      - name: Download web build
        uses: actions/​download-artifact@v4
        with:
          name: web-build
          path: dist/

      - name: Deploy to Capgo
        run: bunx @capgo/​cli upload
        env:
          CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }}

  # Deploy to App Store
  deploy-ios:
    runs-on: macos-latest
    needs: build-ios
    if: github.ref == 'refs/​heads/​main'
    steps:
      - uses: actions/​checkout@v4

      - name: Download IPA
        uses: actions/​download-artifact@v4
        with:
          name: ios-build
          path: build/

      - name: Upload to App Store Connect
        env:
          APP_STORE_CONNECT_API_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY }}
        run: |
          xcrun altool --upload-app \
            --type ios \
            --file build/​*.ipa \
            --apiKey ${{ secrets.API_KEY_ID }} \
            --apiIssuer ${{ secrets.API_ISSUER_ID }}

  # Deploy to Play Store
  deploy-android:
    runs-on: ubuntu-latest
    needs: build-android
    if: github.ref == 'refs/​heads/​main'
    steps:
      - uses: actions/​checkout@v4

      - name: Download AAB
        uses: actions/​download-artifact@v4
        with:
          name: android-aab
          path: build/

      - name: Upload to Play Store
        uses: r0adkll/​upload-google-play@v1
        with:
          serviceAccountJsonPlainText: ${{ secrets.PLAY_SERVICE_ACCOUNT }}
          packageName: com.yourapp.id
          releaseFiles: build/​*.aab
          track: internal

Fastlane Integration

# .github/​workflows/​fastlane.yml
name: Fastlane Build

on:
  push:
    tags: ['v*']

jobs:
  ios:
    runs-on: macos-latest
    steps:
      - uses: actions/​checkout@v4

      - uses: ruby/​setup-ruby@v1
        with:
          ruby-version: '3.2'
          bundler-cache: true

      - name: Install Fastlane
        run: gem install fastlane

      - name: Build and Deploy
        run: fastlane ios release
        env:
          MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
          APP_STORE_CONNECT_API_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY }}

  android:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/​checkout@v4

      - uses: ruby/​setup-ruby@v1
        with:
          ruby-version: '3.2'
          bundler-cache: true

      - name: Install Fastlane
        run: gem install fastlane

      - name: Build and Deploy
        run: fastlane android release
        env:
          PLAY_STORE_JSON_KEY: ${{ secrets.PLAY_SERVICE_ACCOUNT }}

Fastlane Setup

iOS Fastfile

# ios/​App/​fastlane/​Fastfile
default_platform(:ios)

platform :ios do
  desc "Build and deploy to TestFlight"
  lane :release do
    setup_ci

    # Match for code signing
    match(
      type: "appstore",
      readonly: true
    )

    # Increment build number
    increment_build_number(
      build_number: ENV["GITHUB_RUN_NUMBER"]
    )

    # Build
    build_app(
      workspace: "App.xcworkspace",
      scheme: "App",
      export_method: "app-store"
    )

    # Upload to TestFlight
    upload_to_testflight(
      skip_waiting_for_build_processing: true
    )
  end

  desc "Build for development"
  lane :build do
    match(type: "development", readonly: true)

    build_app(
      workspace: "App.xcworkspace",
      scheme: "App",
      export_method: "development"
    )
  end
end

Android Fastfile

# android/​fastlane/​Fastfile
default_platform(:android)

platform :android do
  desc "Build and deploy to Play Store"
  lane :release do
    # Increment version code
    increment_version_code(
      version_code: ENV["GITHUB_RUN_NUMBER"].to_i
    )

    # Build AAB
    gradle(
      task: "bundle",
      build_type: "Release"
    )

    # Upload to Play Store
    upload_to_play_store(
      track: "internal",
      aab: lane_context[SharedValues::GRADLE_AAB_OUTPUT_PATH]
    )
  end

  desc "Build APK"
  lane :build do
    gradle(
      task: "assemble",
      build_type: "Release"
    )
  end
end

GitLab CI

# .gitlab-ci.yml
stages:
  - test
  - build
  - deploy

variables:
  BUN_VERSION: "1.0"

.bun-cache: &bun-cache
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/
      - ~/​.bun/​install/​cache

test:
  stage: test
  image: oven/​bun:${BUN_VERSION}
  <<: *bun-cache
  script:
    - bun install
    - bun run lint
    - bun test --coverage
  coverage: '/​All files[^|]*\|[^|]*\s+([\d\.]+)/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/​cobertura-coverage.xml

security:
  stage: test
  image: oven/​bun:${BUN_VERSION}
  script:
    - bunx capsec scan --ci --output json --output-file security.json
  artifacts:
    reports:
      security: security.json

build-web:
  stage: build
  image: oven/​bun:${BUN_VERSION}
  <<: *bun-cache
  script:
    - bun install
    - bun run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 day

build-ios:
  stage: build
  tags:
    - macos
  needs: [build-web]
  script:
    - bun install
    - bunx cap sync ios
    - cd ios/​App && fastlane build
  artifacts:
    paths:
      - ios/​App/​build/​*.ipa
  only:
    - main
    - tags

build-android:
  stage: build
  image: thyrlian/​android-sdk
  needs: [build-web]
  script:
    - bun install
    - bunx cap sync android
    - cd android && ./​gradlew assembleRelease
  artifacts:
    paths:
      - android/​app/​build/​outputs/​apk/​release/​*.apk
  only:
    - main
    - tags

deploy-capgo:
  stage: deploy
  image: oven/​bun:${BUN_VERSION}
  needs: [build-web]
  script:
    - bunx @capgo/​cli upload --channel production
  only:
    - main
  environment:
    name: production

Secrets Management

Required Secrets

SecretDescription
CERTIFICATE_P12iOS distribution certificate (base64)
CERTIFICATE_PASSWORDCertificate password
PROVISIONING_PROFILEiOS provisioning profile (base64)
KEYSTORE_BASE64Android keystore (base64)
KEYSTORE_PASSWORDKeystore password
KEY_ALIASSigning key alias
KEY_PASSWORDSigning key password
CAPGO_TOKENCapgo API token
APP_STORE_CONNECT_API_KEYApp Store Connect API key
PLAY_SERVICE_ACCOUNTPlay Store service account JSON

Encoding Secrets

# iOS certificate
base64 -i certificate.p12 | pbcopy

# iOS provisioning profile
base64 -i profile.mobileprovision | pbcopy

# Android keystore
base64 -i release.keystore | pbcopy

Version Management

Semantic Release

bun add -D semantic-release @semantic-release/​git @semantic-release/​changelog
// .releaserc.json
{
  "branches": ["main"],
  "plugins": [
    "@semantic-release/​commit-analyzer",
    "@semantic-release/​release-notes-generator",
    "@semantic-release/​changelog",
    [
      "@semantic-release/​npm",
      { "npmPublish": false }
    ],
    [
      "@semantic-release/​git",
      {
        "assets": ["package.json", "CHANGELOG.md"],
        "message": "chore(release): ${nextRelease.version}"
      }
    ],
    "@semantic-release/​github"
  ]
}

Version Bumping

# .github/​workflows/​release.yml
name: Release

on:
  push:
    branches: [main]

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/​checkout@v4
        with:
          fetch-depth: 0
          persist-credentials: false

      - uses: oven-sh/​setup-bun@v1

      - run: bun install

      - name: Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: bunx semantic-release

Build Caching

Gradle Cache

- name: Cache Gradle
  uses: actions/​cache@v4
  with:
    path: |
      ~/​.gradle/​caches
      ~/​.gradle/​wrapper
    key: gradle-${{ runner.os }}-${{ hashFiles('**/​*.gradle*', '**/​gradle-wrapper.properties') }}
    restore-keys: gradle-${{ runner.os }}-

CocoaPods Cache

- name: Cache CocoaPods
  uses: actions/​cache@v4
  with:
    path: ios/​App/​Pods
    key: pods-${{ runner.os }}-${{ hashFiles('ios/​App/​Podfile.lock') }}
    restore-keys: pods-${{ runner.os }}-

Resources

More skills from yeohj0710

capacitor-testing logo
yeohj0710/wellnessbox

capacitor-testing

Complete testing guide for Capacitor apps covering unit tests, integration tests, E2E tests, and native testing. Includes Jest, Vitest, Playwright, Appium, and native testing frameworks. Use this skill when users need to test their mobile apps.

0 0
View
vercel-composition-patterns logo
yeohj0710/wellnessbox

vercel-composition-patterns

Composition patterns for building flexible, maintainable React components. Avoid boolean prop proliferation by using compound components, lifting state, and composing internals. These patterns make codebases easier for both humans and AI agents to work with as they scale.

0 0
View

Postgres performance optimization and best practices from Supabase. Use this skill when writing, reviewing, or optimizing Postgres queries, schema designs, or database configurations.

0 0
View
next-upgrade logo
yeohj0710/wellnessbox

next-upgrade

Upgrade Next.js to the latest version following official migration guides and codemods

0 0
View
capacitor-deep-linking logo
yeohj0710/wellnessbox

capacitor-deep-linking

Complete guide to implementing deep links and universal links in Capacitor apps. Covers iOS Universal Links, Android App Links, custom URL schemes, and navigation handling. Use this skill when users need to open their app from links.

0 0
View
tailwind-capacitor logo
yeohj0710/wellnessbox

tailwind-capacitor

Guide to using Tailwind CSS in Capacitor mobile apps. Covers mobile-first design, touch targets, safe areas, dark mode, and performance optimization. Use this skill when users want to style Capacitor apps with Tailwind.

0 0
View
vercel-deploy logo
yeohj0710/wellnessbox

vercel-deploy

Deploy applications and websites to Vercel. Use when the user requests deployment actions like "deploy my app", "deploy and give me the link", "push this live", or "create a preview deployment".

0 0
View
capacitor-keyboard logo
yeohj0710/wellnessbox

capacitor-keyboard

Guide to handling keyboard in Capacitor apps including visibility detection, accessory bar, scroll behavior, and input focus. Use this skill when users have keyboard-related issues.

0 0
View
frontend-design logo
yeohj0710/wellnessbox

frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beaut...

0 0
View
ios-android-logs logo
yeohj0710/wellnessbox

ios-android-logs

Guide to accessing device logs on iOS and Android for Capacitor apps. Covers command-line tools, GUI applications, filtering, and real-time streaming. Use this skill when users need to view device logs for debugging.

0 0
View
vercel-react-native-skills logo
yeohj0710/wellnessbox

vercel-react-native-skills

Comprehensive best practices for React Native and Expo applications. Contains rules across multiple categories covering performance, animations, UI patterns, and platform-specific optimizations.

0 0
View
develop-ai-functions-example logo
yeohj0710/wellnessbox

develop-ai-functions-example

Develop examples for AI SDK functions. Use when creating, running, or modifying examples under examples/ai-functions/src to validate provider support, demonstrate features, or create test fixtures.

0 0
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View