Capacitor Ci Cd

cap-go/capgo-skills/skills/capacitor-ci-cd

作者 cap-go2cfb277a1488無授權條款72 個星標收錄於 2026年10月8日更新於 2026年10月8日儲存庫今天更新

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.

僅含說明DevOps & Cloud
AI 產生的概覽

指導 Capacitor 應用程式的 CI/CD 設定,涵蓋 GitHub Actions、GitLab CI、Fastlane、簽章與商店部署。

功能
提供用於建置、測試與發佈 Capacitor 行動應用程式的流程設定參考。內容涵蓋 GitHub Actions 與 GitLab CI 工作流程、iOS 與 Android 的 Fastlane lane、程式碼簽章與密鑰管理、以 semantic-release 進行的版本管理,以及建置快取。它產出的是設定片段與指引,本身不會執行任何自動化。
適用情境
適用於需要為 Capacitor 應用程式自動化建置、測試或發佈流程的情境。適合處理關於 GitHub Actions、GitLab CI、應用程式簽章自動化,或發佈至 App Store、Play Store、Capgo 的問題。
執行需求
不隨附指令碼,僅為說明與設定範例。依其操作需要具備 Node.js 與 npm 的 Capacitor 專案,以及平台工具鏈:iOS 需要 Xcode 與 CocoaPods,Android 需要 Java 與 Android SDK,另可選用 Ruby 與 Fastlane。簽章與部署需要儲存庫密鑰,例如憑證、金鑰庫與商店 API 認證,並需要存取 CI 執行器與商店服務的網路。

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

yaml
# .github/workflows/build.ymlname: 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: actions/setup-node@v4
      - name: Install dependencies        run: npm install
      - name: Lint        run: npm run lint
      - name: Type check        run: npm run typecheck
      - name: Unit tests        run: npm test -- --coverage
      - name: Upload coverage        uses: codecov/codecov-action@v4
  # Security scan  security:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4      - uses: actions/setup-node@v4      - run: npx capsec scan --ci
  # Build web assets  build-web:    runs-on: ubuntu-latest    needs: [test, security]    steps:      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
      - name: Install dependencies        run: npm install
      - name: Build        run: npm 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: actions/setup-node@v4
      - name: Download web build        uses: actions/download-artifact@v4        with:          name: web-build          path: dist/
      - name: Install dependencies        run: npm install
      - name: Sync Capacitor        run: npx 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: actions/setup-node@v4
      - 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: npm install
      - name: Sync Capacitor        run: npx 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: actions/setup-node@v4
      - name: Download web build        uses: actions/download-artifact@v4        with:          name: web-build          path: dist/
      - name: Deploy to Capgo        run: npx @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

yaml
# .github/workflows/fastlane.ymlname: 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

ruby
# ios/App/fastlane/Fastfiledefault_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"    )  endend

Android Fastfile

ruby
# android/fastlane/Fastfiledefault_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"    )  endend

GitLab CI

yaml
# .gitlab-ci.ymlstages:  - test  - build  - deploy
variables:  NODE_VERSION: "20"
.npm-cache: &npm-cache  cache:    key: ${CI_COMMIT_REF_SLUG}    paths:      - node_modules/      - ~/.npm
test:  stage: test  image: node:20  <<: *npm-cache  script:    - npm install    - npm run lint    - npm test -- --coverage  coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'  artifacts:    reports:      coverage_report:        coverage_format: cobertura        path: coverage/cobertura-coverage.xml
security:  stage: test  image: node:20  script:    - npx capsec scan --ci --output json --output-file security.json  artifacts:    reports:      security: security.json
build-web:  stage: build  image: node:20  <<: *npm-cache  script:    - npm install    - npm run build  artifacts:    paths:      - dist/    expire_in: 1 day
build-ios:  stage: build  tags:    - macos  needs: [build-web]  script:    - npm install    - npx 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:    - npm install    - npx cap sync android    - cd android && ./gradlew assembleRelease  artifacts:    paths:      - android/app/build/outputs/apk/release/*.apk  only:    - main    - tags
deploy-capgo:  stage: deploy  image: node:20  needs: [build-web]  script:    - npx @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

bash
# iOS certificatebase64 -i certificate.p12 | pbcopy
# iOS provisioning profilebase64 -i profile.mobileprovision | pbcopy
# Android keystorebase64 -i release.keystore | pbcopy

Version Management

Semantic Release

bash
npm install -D semantic-release @semantic-release/git @semantic-release/changelog
json
// .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

yaml
# .github/workflows/release.ymlname: Release
on:  push:    branches: [main]
jobs:  release:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4        with:          fetch-depth: 0          persist-credentials: false
      - uses: actions/setup-node@v4
      - run: npm install
      - name: Release        env:          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}        run: npx semantic-release

Build Caching

Gradle Cache

yaml
- 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

yaml
- 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

來源與署名

來源:cap-go/capgo-skills位於skills/capacitor-ci-cd提交2cfb277

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架