단어의 뜻은 코드에 대한 지속적인 통합(Continous Integration) 및 지속적인 배포(Continous Delivery)이다.
나눠서 보자면 CI는 빌드 및 테스트 자동화하는 것, CD는 배포를 자동화하는 것이라고 볼 수 있다.
큰 틀에서는 앱 출시를 위한 과정을 자동화하는 과정이다.
사용량에 따라 비용이 있어서 self-hosted 환경으로 진행했다.

https://danawalab.github.io/common/2022/08/24/Self-Hosted-Runner.html
project/.github/workflows/test.yaml
테스트 부분 코드
name: Test development branch
on:
  push:
  	branches:
      - development
jobs:
  checkot:
    runs-on: macOS
    steps:
     - uses: actions/checkout@v4
     - run: ls -al
project/.github/workflows/deploy_prod.yaml
스토어 배포 부분 코드
name: deploy project to testFlight, playstore internal track
on:
  push:
    branches:
      - main
jobs:
  # IOS
  deploy_ios:
    runs-on: macOS
    steps:    
      - uses: actions/checkout@v4
      - name: Install fastlane
        run: brew install fastlane
      # 빌드 및 배포
      - name: Deploy Product to Store
        run: fastlane build_deploy_prod
        working-directory: ios
        env:
          FASTLANE_TEAM_ID: ${{ secrets.FASTLANE_TEAM_ID }}
          FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: ${{ secrets.FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD }}
  # AOS
  deploy_android:
    runs-on: macOS
    needs: [ deploy_ios ]
    steps:
      - uses: actions/checkout@v4
      - name: Install fastlane
        run: brew install fastlane
      # upload key 복호화
      - name: Generate Android keystore
        id: android_keystore
        uses: timheuer/base64-to-file@v1.1
        with:
          fileName: key.jks
          encodedString: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
      # key.properties 생성
      - name: Create key properties
        run: |
          echo "storeFile=${{ steps.android_keystore.outputs.filePath }}" >> android/key.properties
          echo "storePassword=${{ secrets.ANDROID_KEYSTORE_PASSWORD }}" >> android/key.properties
          echo "keyPassword=${{ secrets.ANDROID_KEY_PASSWORD }}" >> android/key.properties
          echo "keyAlias=${{ secrets.ANDROID_KEY_ALIAS }}" >> android/key.properties
      # 빌드 및 배포
      - name: Deploy Product to Store
        run: fastlane build_deploy_prod
        working-directory: android
https://velog.io/@sangwoo24/Flutter-Fastlane-%EC%9C%BC%EB%A1%9C-CICD-%EA%B5%AC%EC%B6%95-Android
https://velog.io/@parkgyurim/iOS-fastlane-match

ios/fastlane/${keyId}.json
{
    "key_id": keyID,
    "issuer_id": issuerID,
    "key": "-----BEGIN PRIVATE KEY-----\nkey Conetent\n-----END PRIVATE KEY-----",
    "duration": 1200,
    "in_house": false
}
project/ios/fastlane/Appfile
app_identifier "com.foopolog" # The bundle identifier of your app
apple_id "apple@gmail.com"  # Your Apple email address
# You can uncomment the lines below and add your own
# team selection in case you're in multiple teams
# team_name "Felix Krause"
team_id "ZZZZZZZZZZ"
# To select a team for App Store Connect use
# itc_team_name "Company Name"
# itc_team_id "18742801"
project/ios/fastlane/Matchfile
git_url("git@github.com:git_id/Fastlane_Cert.git")
storage_mode("git")
type("appstore") # The default type, can be: appstore, adhoc, enterprise or development
app_identifier(["com.foopolog"])
username("apple@gmail.com") # Your Apple Developer Portal username
# For all available options run `fastlane match --help`
# Remove the # in the beginning of the line to enable the other options
# The docs are available on https://docs.fastlane.tools/actions/match
project/ios/fastlane/Fastfile
default_platform(:ios)
desc "Deploy a product version to Apple App Store"
lane :build_deploy_prod do
    ## match
    match(readonly: true)
    ## flutter init
    sh('flutter pub get')
    cocoapods(
        repo_update: true,
        use_bundle_exec: false,
    )
    ## build App
    build_app(
        clean: true,
        scheme: "Runner",
        workspace: "Runner.xcworkspace",
    )
    ## deploy App
    upload_to_testflight(
	    api_key_path: "fastlane/${keyId}.json",
        team_id: ENV["FASTLANE_TEAM_ID"],
        skip_waiting_for_build_processing: true,
    )
end
project/andorid/fastlane/Appfile
json_key_file("경로/serviceAccount.json")
package_name("com.foopolog")
project/andorid/fastlane/Fastfile
desc "Deploy a Product version to Google Play Store"
lane :build_deploy_prod do
    ## build APP
    sh("flutter build appbundle")
    ## deploy APP
    upload_to_play_store(
        aab: "../build/app/outputs/bundle/release/app-release.aab",
        track: 'internal',
        skip_upload_metadata: true,
    )
end
