From 7db4dcb5ecc006318164b12ba622bd8ece324db7 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 15 Nov 2023 09:57:17 +0700 Subject: [PATCH 1/4] [#498] Update Script: SetUpCICDService to ask for runner type Wwe create 2 folders for each runner type with the same workflows but different runs-on. When the developer chooses a runner type, the chosen type will be copied to the workflow directory. --- .../automatic_pull_request_review.yml | 64 ++++++++++ .../deploy_app_store.yml | 104 ++++++++++++++++ .../deploy_production_firebase.yml | 105 +++++++++++++++++ .../deploy_staging_firebase.yml | 111 ++++++++++++++++++ .../draft_a_new_release.yml | 18 +++ .../publish_docs_to_wiki.yml | 19 +++ .../iOSTemplateMaker/SetUpCICDService.swift | 20 +++- 7 files changed, 439 insertions(+), 2 deletions(-) create mode 100644 .github/self_hosted_project_workflows/automatic_pull_request_review.yml create mode 100644 .github/self_hosted_project_workflows/deploy_app_store.yml create mode 100644 .github/self_hosted_project_workflows/deploy_production_firebase.yml create mode 100644 .github/self_hosted_project_workflows/deploy_staging_firebase.yml create mode 100644 .github/self_hosted_project_workflows/draft_a_new_release.yml create mode 100644 .github/self_hosted_project_workflows/publish_docs_to_wiki.yml diff --git a/.github/self_hosted_project_workflows/automatic_pull_request_review.yml b/.github/self_hosted_project_workflows/automatic_pull_request_review.yml new file mode 100644 index 00000000..d539c914 --- /dev/null +++ b/.github/self_hosted_project_workflows/automatic_pull_request_review.yml @@ -0,0 +1,64 @@ +name: Automatic pull request review + +on: + pull_request: + types: [opened, reopened, edited, synchronize] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + review_pull_request: + name: Pull request review by Danger + runs-on: [self-hosted, macOS] + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - uses: actions/cache@v3 + id: bunlderCache + with: + path: vendor/bundle + key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} + restore-keys: | + ${{ runner.os }}-gems- + + - name: Setup ENV file + env: + ENV: ${{ secrets.ENV }} + run: | + touch .env + echo $ENV | base64 --decode > .env + + - name: Bundle install + run: bundle install --path vendor/bundle + + - name: Run Arkana + run: bundle exec arkana + + - name: Cache Pods + uses: actions/cache@v3 + id: cocoapodCache + with: + path: Pods + key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} + restore-keys: | + ${{ runner.os }}-pods- + + - name: Install Pods Dependencies + run: bundle exec pod install + + - name: Build and Test + run: bundle exec fastlane buildAndTest + env: + CI: true + + - name: Clean up previous code coverage report + run: bundle exec fastlane cleanUpOutput + + - name: Review pull request by Danger + env: + DANGER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bundle exec danger diff --git a/.github/self_hosted_project_workflows/deploy_app_store.yml b/.github/self_hosted_project_workflows/deploy_app_store.yml new file mode 100644 index 00000000..a29955de --- /dev/null +++ b/.github/self_hosted_project_workflows/deploy_app_store.yml @@ -0,0 +1,104 @@ +name: Deploy Build To App Store + +# SECRETS needed: +### SSH_PRIVATE_KEY for Match Repo +### MATCH_PASS +### APPSTORE_CONNECT_API_KEY +### API_KEY_ID +### ISSUER_ID + +on: + push: + branches: [ master, main ] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Run SwiftLint + uses: docker://norionomura/swiftlint:0.53.0_swift-5.7 + with: + args: swiftlint --strict + + build: + name: Build + runs-on: [self-hosted, macOS] + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + # Set fetch-depth (default: 1) to get whole tree + with: + fetch-depth: 0 + + - name: Install SSH key + uses: webfactory/ssh-agent@v0.7.0 + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + + - name: Setup ENV file + env: + ENV: ${{ secrets.ENV }} + run: | + touch .env + echo $ENV | base64 --decode > .env + + - name: Bundle install + run: bundle install + + - name: Run Arkana + run: bundle exec arkana + + - name: Cache Pods + uses: actions/cache@v3 + id: cocoapodCache + with: + path: Pods + key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} + restore-keys: | + ${{ runner.os }}-pods- + + - name: Install Pods Dependencies + run: bundle exec pod install + shell: bash + + - name: Build and Test + run: bundle exec fastlane buildAndTest + + - name: Match AppStore + run: bundle exec fastlane syncAppStoreCodeSigning + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASS }} + + - name: Build App and Distribute to AppStore + run: bundle exec fastlane buildAndUploadToAppStore + env: + APPSTORE_CONNECT_API_KEY: ${{ secrets.APPSTORE_CONNECT_API_KEY }} + API_KEY_ID: ${{ secrets.API_KEY_ID }} + ISSUER_ID: ${{ secrets.ISSUER_ID }} + BUMP_APP_STORE_BUILD_NUMBER: "true" + + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: ${{ format('v{0}({1})-{2}', env.VERSION_NUMBER, env.BUILD_NUMBER, env.TAG_TYPE) }} + path: | + ${{ env.IPA_OUTPUT_PATH }} + ${{ env.DSYM_OUTPUT_PATH }} + env: + TAG_TYPE: App_Store + + - name: Remove keychain + if: ${{ always() }} + run: bundle exec fastlane removeKeychain + continue-on-error: true diff --git a/.github/self_hosted_project_workflows/deploy_production_firebase.yml b/.github/self_hosted_project_workflows/deploy_production_firebase.yml new file mode 100644 index 00000000..461bdd01 --- /dev/null +++ b/.github/self_hosted_project_workflows/deploy_production_firebase.yml @@ -0,0 +1,105 @@ +name: Deploy Production Build To Firebase + +# SECRETS needed: +### SSH_PRIVATE_KEY for Match Repo +### MATCH_PASS +### FIREBASE_GOOGLE_APPLICATION_CREDENTIALS_BASE64 + +on: + push: + branches: [ release/** ] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + Lint: + name: lint + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Run SwiftLint + uses: docker://norionomura/swiftlint:0.53.0_swift-5.7 + with: + args: swiftlint --strict + + build: + name: Build + runs-on: [self-hosted, macOS] + steps: + - uses: actions/checkout@v3 + # Set fetch-depth (default: 1) to get whole tree + with: + fetch-depth: 0 + + - name: Install SSH key + uses: webfactory/ssh-agent@v0.7.0 + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + + - name: Setup ENV file + env: + ENV: ${{ secrets.ENV }} + run: | + touch .env + echo $ENV | base64 --decode > .env + + - name: Read Google Service Account + id: firebase_service_account + uses: timheuer/base64-to-file@v1.2 + with: + fileName: 'firebase_service_account.json' + encodedString: ${{ secrets.FIREBASE_GOOGLE_APPLICATION_CREDENTIALS_BASE64 }} + + - name: Bundle install + run: bundle install + + - name: Run Arkana + run: bundle exec arkana + + - name: Cache Pods + uses: actions/cache@v3 + id: cocoapodCache + with: + path: Pods + key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} + restore-keys: | + ${{ runner.os }}-pods- + + - name: Install Pods Dependencies + run: bundle exec pod install + shell: bash + + - name: Build and Test + run: bundle exec fastlane buildAndTest + + - name: Match Ad-hoc + run: bundle exec fastlane syncAdHocProductionCodeSigning + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASS }} + + - name: Build Production App and Distribute to Firebase + run: bundle exec fastlane buildProductionAndUploadToFirebase + env: + GOOGLE_APPLICATION_CREDENTIALS: ${{ steps.firebase_service_account.outputs.filePath }} + + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: ${{ format('v{0}({1})-{2}', env.VERSION_NUMBER, env.BUILD_NUMBER, env.TAG_TYPE) }} + path: | + ${{ env.IPA_OUTPUT_PATH }} + ${{ env.DSYM_OUTPUT_PATH }} + env: + TAG_TYPE: Production_Firebase + + - name: Remove keychain + if: ${{ always() }} + run: bundle exec fastlane removeKeychain + continue-on-error: true diff --git a/.github/self_hosted_project_workflows/deploy_staging_firebase.yml b/.github/self_hosted_project_workflows/deploy_staging_firebase.yml new file mode 100644 index 00000000..21ce2095 --- /dev/null +++ b/.github/self_hosted_project_workflows/deploy_staging_firebase.yml @@ -0,0 +1,111 @@ +name: Deploy Staging Build To Firebase + +# SECRETS needed: +### SSH_PRIVATE_KEY for Match Repo +### MATCH_PASS +### FIREBASE_GOOGLE_APPLICATION_CREDENTIALS_BASE64 + +on: + push: + branches: [ develop ] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Run SwiftLint + uses: docker://norionomura/swiftlint:0.53.0_swift-5.7 + with: + args: swiftlint --strict + + build: + name: Build + runs-on: [self-hosted, macOS] + steps: + - uses: actions/checkout@v3 + # Set fetch-depth (default: 1) to get whole tree + with: + fetch-depth: 0 + + - name: Install SSH key + uses: webfactory/ssh-agent@v0.7.0 + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + + - name: Install Firebase-Tools + run: | + yarn global add firebase-tools + echo "$(yarn global bin)" >> $GITHUB_PATH + + - name: Setup ENV file + env: + ENV: ${{ secrets.ENV }} + run: | + touch .env + echo $ENV | base64 --decode > .env + + - name: Read Google Service Account + id: firebase_service_account + uses: timheuer/base64-to-file@v1.2 + with: + fileName: 'firebase_service_account.json' + encodedString: ${{ secrets.FIREBASE_GOOGLE_APPLICATION_CREDENTIALS_BASE64 }} + + - name: Bundle install + # if: steps.bundleCache.outputs.cache-hit != 'true' + run: bundle install + + - name: Run Arkana + run: bundle exec arkana + + - name: Cache Pods + uses: actions/cache@v2 + id: cocoapodCache + with: + path: Pods + key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} + restore-keys: | + ${{ runner.os }}-pods- + + - name: Install Pods Dependencies + run: bundle exec pod install + shell: bash + + - name: Build and Test + run: bundle exec fastlane buildAndTest + + - name: Match Ad-hoc + run: bundle exec fastlane syncAdHocStagingCodeSigning + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASS }} + + - name: Build App and Distribute to Firebase + run: bundle exec fastlane buildStagingAndUploadToFirebase + env: + GOOGLE_APPLICATION_CREDENTIALS: ${{ steps.firebase_service_account.outputs.filePath }} + + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: ${{ format('v{0}({1})-{2}', env.VERSION_NUMBER, env.BUILD_NUMBER, env.TAG_TYPE) }} + path: | + ${{ env.IPA_OUTPUT_PATH }} + ${{ env.DSYM_OUTPUT_PATH }} + env: + TAG_TYPE: Staging_Firebase + + - name: Remove keychain + if: ${{ always() }} + run: bundle exec fastlane removeKeychain + continue-on-error: true diff --git a/.github/self_hosted_project_workflows/draft_a_new_release.yml b/.github/self_hosted_project_workflows/draft_a_new_release.yml new file mode 100644 index 00000000..5550e4bc --- /dev/null +++ b/.github/self_hosted_project_workflows/draft_a_new_release.yml @@ -0,0 +1,18 @@ +name: Draft a new release + +on: + push: + branches: + - main +permissions: + contents: read + +jobs: + update_release_draft: + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - uses: release-drafter/release-drafter@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/self_hosted_project_workflows/publish_docs_to_wiki.yml b/.github/self_hosted_project_workflows/publish_docs_to_wiki.yml new file mode 100644 index 00000000..dc71b021 --- /dev/null +++ b/.github/self_hosted_project_workflows/publish_docs_to_wiki.yml @@ -0,0 +1,19 @@ +name: Publish docs to Wiki + +on: + push: + paths: + - .github/wiki/** + branches: + - main + - master + +jobs: + publish_docs_to_wiki: + name: Publish Wiki + uses: nimblehq/github-actions-workflows/.github/workflows/publish_wiki.yml@0.1.0 + with: + USER_NAME: team-nimblehq + USER_EMAIL: dev@nimblehq.co + secrets: + USER_TOKEN: ${{ secrets.NIMBLE_DEV_TOKEN }} diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift index 06436a46..3f830069 100644 --- a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift @@ -33,13 +33,29 @@ struct SetUpCICDService { switch service { case .github: + var runnerType: String? + while runnerType == nil { + print("Which workflow runner do you want to use? [(m)acos-latest/(s)elf-hosted]: ") + runnerType = readLine()?.lowercased() + if runnerType != "m" && runnerType != "s" { + print("Invalid input. Please enter 'm' for macOS-latest or 's' for self-hosted.") + runnerType = nil + } + } print("Setting template for Github Actions") fileManager.removeItems(in: "bitrise.yml") fileManager.removeItems(in: "codemagic.yaml") fileManager.removeItems(in: ".github/workflows") fileManager.createDirectory(path: ".github/workflows") - fileManager.moveFiles(in: ".github/project_workflows", to: ".github/workflows") - fileManager.removeItems(in: ".github/project_workflows") + if runnerType == "s" { + fileManager.moveFiles(in: ".github/self_hosted_project_workflows", to: ".github/workflows") + fileManager.removeItems(in: ".github/project_workflows") + fileManager.removeItems(in: ".github/self_hosted_project_workflows") + } else { + fileManager.moveFiles(in: ".github/project_workflows", to: ".github/workflows") + fileManager.removeItems(in: ".github/project_workflows") + fileManager.removeItems(in: ".github/self_hosted_project_workflows") + } case .bitrise: print("Setting template for Bitrise") fileManager.removeItems(in: "codemagic.yaml") From 4ec71c2162a708b262ce2b12a88612bd6584f4ee Mon Sep 17 00:00:00 2001 From: David Date: Mon, 4 Dec 2023 09:41:22 +0700 Subject: [PATCH 2/4] [#498] Create Enum for gifhub runner type --- .../iOSTemplateMaker/SetUpCICDService.swift | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift index 3f830069..182d6909 100644 --- a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift @@ -21,6 +21,24 @@ struct SetUpCICDService { } } } + + enum GithubRunnerType { + + case macOSLatest, selfHosted, later + + init?(_ name: String) { + switch name.lowercased() { + case "m", "macOS": + self = .macOSLatest + case "s", "self-hosted": + self = .selfHosted + case "l", "later": + self = .later + default: + return nil + } + } + } private let fileManager = FileManager.default @@ -33,28 +51,27 @@ struct SetUpCICDService { switch service { case .github: - var runnerType: String? + var runnerType: GithubRunnerType? while runnerType == nil { - print("Which workflow runner do you want to use? [(m)acos-latest/(s)elf-hosted]: ") - runnerType = readLine()?.lowercased() - if runnerType != "m" && runnerType != "s" { - print("Invalid input. Please enter 'm' for macOS-latest or 's' for self-hosted.") - runnerType = nil - } + print("Which workflow runner do you want to use? [(m)acos-latest/(s)elf-hosted/(l)ater]: ") + runnerType = GithubRunnerType(readLine().string) } print("Setting template for Github Actions") fileManager.removeItems(in: "bitrise.yml") fileManager.removeItems(in: "codemagic.yaml") fileManager.removeItems(in: ".github/workflows") fileManager.createDirectory(path: ".github/workflows") - if runnerType == "s" { - fileManager.moveFiles(in: ".github/self_hosted_project_workflows", to: ".github/workflows") + switch runnerType { + case .macOSLatest: + fileManager.moveFiles(in: ".github/project_workflows", to: ".github/workflows") fileManager.removeItems(in: ".github/project_workflows") fileManager.removeItems(in: ".github/self_hosted_project_workflows") - } else { - fileManager.moveFiles(in: ".github/project_workflows", to: ".github/workflows") + case .selfHosted: + fileManager.moveFiles(in: ".github/self_hosted_project_workflows", to: ".github/workflows") fileManager.removeItems(in: ".github/project_workflows") fileManager.removeItems(in: ".github/self_hosted_project_workflows") + case .later, .none: + print("You can manually setup the runner later.") } case .bitrise: print("Setting template for Bitrise") From cae4b35741e51ec6a04c9ed6ff361c60499006b3 Mon Sep 17 00:00:00 2001 From: David Date: Thu, 14 Dec 2023 09:05:41 +0700 Subject: [PATCH 3/4] [#498] Remove project workflows and self hosted project workflows in case CICD using bitrise or codemagic --- .../Sources/iOSTemplateMaker/SetUpCICDService.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift index 182d6909..e76ff47e 100644 --- a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift @@ -70,17 +70,21 @@ struct SetUpCICDService { fileManager.moveFiles(in: ".github/self_hosted_project_workflows", to: ".github/workflows") fileManager.removeItems(in: ".github/project_workflows") fileManager.removeItems(in: ".github/self_hosted_project_workflows") - case .later, .none: + case .later: print("You can manually setup the runner later.") } case .bitrise: print("Setting template for Bitrise") fileManager.removeItems(in: "codemagic.yaml") fileManager.removeItems(in: ".github/workflows") + fileManager.removeItems(in: ".github/project_workflows") + fileManager.removeItems(in: ".github/self_hosted_project_workflows") case .codemagic: print("Setting template for CodeMagic") fileManager.removeItems(in: "bitrise.yml") fileManager.removeItems(in: ".github/workflows") + fileManager.removeItems(in: ".github/project_workflows") + fileManager.removeItems(in: ".github/self_hosted_project_workflows") case .later, .none: print("You can manually setup the template later.") } From 70932c070a6993596f26659124fe8f850c5e2a08 Mon Sep 17 00:00:00 2001 From: David Date: Thu, 14 Dec 2023 09:06:21 +0700 Subject: [PATCH 4/4] [#498] Update case .none --- .../Sources/iOSTemplateMaker/SetUpCICDService.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift index e76ff47e..972e9250 100644 --- a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift @@ -70,7 +70,7 @@ struct SetUpCICDService { fileManager.moveFiles(in: ".github/self_hosted_project_workflows", to: ".github/workflows") fileManager.removeItems(in: ".github/project_workflows") fileManager.removeItems(in: ".github/self_hosted_project_workflows") - case .later: + case .later, .none: print("You can manually setup the runner later.") } case .bitrise: