From 15d23865be0f37c0feb73d6829981277c1b03fa8 Mon Sep 17 00:00:00 2001 From: Deniz Cengiz <48965855+dnzxy@users.noreply.github.com> Date: Thu, 3 Aug 2023 06:53:22 +0200 Subject: [PATCH 01/13] Added improved validation and more descriptive error messages --- .github/workflows/validate_secrets.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/validate_secrets.yml b/.github/workflows/validate_secrets.yml index 70401888c6..77777aac64 100644 --- a/.github/workflows/validate_secrets.yml +++ b/.github/workflows/validate_secrets.yml @@ -23,6 +23,9 @@ jobs: elif [ ${#TEAMID} -ne 10 ]; then failed=true echo "::error::TEAMID secret is set but has wrong length. Verify that it is set correctly and try again." + elif ! [[ $TEAMID =~ ^[A-Z0-9]+$ ]]; then + failed=true + echo "::error::TEAMID is set but invalid. Verify that it is set correctly (only uppercase letters and numbers) and try again." fi # Validate GH_PAT @@ -32,14 +35,28 @@ jobs: elif [ "$(gh api -H "Accept: application/vnd.github+json" /repos/${{ github.repository_owner }}/Match-Secrets | jq --raw-output '.permissions.push')" != "true" ]; then failed=true echo "::error::GH_PAT secret is set but invalid or lacking appropriate privileges on the ${{ github.repository_owner }}/Match-Secrets repository. Verify that it is set correctly and try again." + elif [ "$(gh repo list --json name | jq --raw-output 'any(.name=="Match-Secrets")')" != "true" ]; then + failed=true + echo "::error::GH_PAT secret is set but Match-Secrets repository is missing or configured incorrectly. Verify that the repository was created and that its name is spelled correctly (uppercase 'M' for 'Match', uppercase 'S' and plural for 'Secrets', dash character '-' between the words as separator)." fi # Validate FASTLANE_ISSUER_ID, FASTLANE_KEY_ID, and FASTLANE_KEY + FASTLANE_KEY_ID_PATTERN='^[A-Z0-9]+$' + FASTLANE_ISSUER_ID_PATTERN='^\{?[A-F0-9a-f]{8}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{12}\}?$' if [ -z "$FASTLANE_ISSUER_ID" ] || [ -z "$FASTLANE_KEY_ID" ] || [ -z "$FASTLANE_KEY" ]; then failed=true [ -z "$FASTLANE_ISSUER_ID" ] && echo "::error::The FASTLANE_ISSUER_ID secret is unset or empty. Set it and try again." [ -z "$FASTLANE_KEY_ID" ] && echo "::error::The FASTLANE_KEY_ID secret is unset or empty. Set it and try again." [ -z "$FASTLANE_KEY" ] && echo "::error::The FASTLANE_KEY secret is unset or empty. Set it and try again." + elif [ ${#FASTLANE_KEY_ID} -ne 10 ]; then + failed=true + echo "::error::FASTLANE_KEY_ID secret is set but has wrong length. Verify that it is set correctly and try again." + elif ! [[ $FASTLANE_KEY_ID =~ $FASTLANE_KEY_ID_PATTERN ]]; then + failed=true + echo "::error::FASTLANE_KEY_ID is set but invalid. Verify that it is set correctly (only uppercase letters and numbers) and try again." + elif ! [[ $FASTLANE_ISSUER_ID =~ $FASTLANE_ISSUER_ID_PATTERN ]]; then + failed=true + echo "::error::FASTLANE_ISSUER_ID is set but invalid. Verify that it is set correctly (adhering to UUID format) and try again." elif ! echo "$FASTLANE_KEY" | openssl pkcs8 -nocrypt >/dev/null; then failed=true echo "::error::The FASTLANE_KEY secret is set but invalid. Verify that it is set correctly and try again." From 8be04b3498342230fde0cde38d65eb0ff9125666 Mon Sep 17 00:00:00 2001 From: Deniz Cengiz <48965855+dnzxy@users.noreply.github.com> Date: Wed, 16 Aug 2023 23:07:24 +0200 Subject: [PATCH 02/13] Add validations from suggestions and test feedback --- .github/workflows/validate_secrets.yml | 115 +++++++++++++++++-------- 1 file changed, 78 insertions(+), 37 deletions(-) diff --git a/.github/workflows/validate_secrets.yml b/.github/workflows/validate_secrets.yml index 77777aac64..5ce76bb30e 100644 --- a/.github/workflows/validate_secrets.yml +++ b/.github/workflows/validate_secrets.yml @@ -1,20 +1,80 @@ name: 1. Validate Secrets run-name: Validate Secrets on: [workflow_call, workflow_dispatch] - + jobs: - validate: - runs-on: macos-12 + validate-access-token: + name: Access + runs-on: macos-13 + env: + GH_PAT: ${{ secrets.GH_PAT }} + GH_TOKEN: ${{ secrets.GH_PAT }} + steps: + - name: Validate Access Token + run: | + # Validate Fastlane Access Token (GH_PAT) + if [ -z "$GH_PAT" ]; then + failed=true + echo "::error::GH_PAT secret is unset or empty. Set it and try again." + elif [ "$(gh api -H "Accept: application/vnd.github+json" /repos/${{ github.repository_owner }}/LoopWorkspace | jq --raw-output '.permissions.push')" != "true" ]; then + failed=true + echo "::error::GH_PAT secret is set but invalid or lacking 'repo' permission scope. Verify that it is created/set correctly and try again." + fi + + # Exit unsuccessfully if secret validation failed. + if [ $failed ]; then + exit 2 + fi + + validate-match-secrets: + name: Match-Secrets + needs: validate-access-token + runs-on: macos-13 + env: + GH_TOKEN: ${{ secrets.GH_PAT }} + steps: + - name: Validate Match-Secrets + run: | + # Validate Match-Secrets + if [ "$(gh repo list --json name | jq --raw-output 'any(.name=="Match-Secrets")')" != "true" ]; then + echo "A 'Match-Secrets' repository could not be found. Attempting to create one..."; + + if [ gh repo create Match-Secrets --private && "$(gh repo list --json name,visibility | jq --raw-output '.[] | select(.name=="Match-Secrets") | .visibility == "PRIVATE"')" == "true" ]; then + echo "Created a 'Match-Secrets' private repository." + else + failed=true + echo "::error::A private 'Match-Secrets' repository could not be created. Create a private `Match-Secrets` repository manually or try again.\ + If a private 'Match-Secrets' repository already exists, ensure that the GH_PAT has appropriate permissions to access it." + fi + elif [ "$(gh repo list --json name,visibility | jq --raw-output '.[] | select(.name=="Match-Secrets") | .visibility == "PUBLIC"')" == "true" ]; then + failed=true + echo "::error::A 'Match-Secrets' repository was found, but it is is public. Delete it and try again (a private repository will be created for you)." + fi + + # Exit unsuccessfully if secret validation failed. + if [ $failed ]; then + exit 2 + fi + + validate-fastlane-secrets: + name: Fastlane + needs: validate-match-secrets + runs-on: macos-13 + env: + GH_PAT: ${{ secrets.GH_PAT }} + GH_TOKEN: ${{ secrets.GH_PAT }} + FASTLANE_ISSUER_ID: ${{ secrets.FASTLANE_ISSUER_ID }} + FASTLANE_KEY_ID: ${{ secrets.FASTLANE_KEY_ID }} + FASTLANE_KEY: ${{ secrets.FASTLANE_KEY }} + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + TEAMID: ${{ secrets.TEAMID }} steps: - # Checks-out the repo - name: Checkout Repo uses: actions/checkout@v3 - # Validates the repo secrets - - name: Validate Secrets + - name: Validate Fastlane Secrets run: | - # Validate Secrets - echo Validating Repository Secrets... + # Validate Fastlane Secrets # Validate TEAMID if [ -z "$TEAMID" ]; then @@ -28,21 +88,13 @@ jobs: echo "::error::TEAMID is set but invalid. Verify that it is set correctly (only uppercase letters and numbers) and try again." fi - # Validate GH_PAT - if [ -z "$GH_PAT" ]; then - failed=true - echo "::error::GH_PAT secret is unset or empty. Set it and try again." - elif [ "$(gh api -H "Accept: application/vnd.github+json" /repos/${{ github.repository_owner }}/Match-Secrets | jq --raw-output '.permissions.push')" != "true" ]; then - failed=true - echo "::error::GH_PAT secret is set but invalid or lacking appropriate privileges on the ${{ github.repository_owner }}/Match-Secrets repository. Verify that it is set correctly and try again." - elif [ "$(gh repo list --json name | jq --raw-output 'any(.name=="Match-Secrets")')" != "true" ]; then + # Validate MATCH_PASSWORD + if [ -z "$MATCH_PASSWORD" ]; then failed=true - echo "::error::GH_PAT secret is set but Match-Secrets repository is missing or configured incorrectly. Verify that the repository was created and that its name is spelled correctly (uppercase 'M' for 'Match', uppercase 'S' and plural for 'Secrets', dash character '-' between the words as separator)." + echo "::error::The MATCH_PASSWORD secret is unset or empty. Set it and try again." fi # Validate FASTLANE_ISSUER_ID, FASTLANE_KEY_ID, and FASTLANE_KEY - FASTLANE_KEY_ID_PATTERN='^[A-Z0-9]+$' - FASTLANE_ISSUER_ID_PATTERN='^\{?[A-F0-9a-f]{8}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{12}\}?$' if [ -z "$FASTLANE_ISSUER_ID" ] || [ -z "$FASTLANE_KEY_ID" ] || [ -z "$FASTLANE_KEY" ]; then failed=true [ -z "$FASTLANE_ISSUER_ID" ] && echo "::error::The FASTLANE_ISSUER_ID secret is unset or empty. Set it and try again." @@ -60,28 +112,17 @@ jobs: elif ! echo "$FASTLANE_KEY" | openssl pkcs8 -nocrypt >/dev/null; then failed=true echo "::error::The FASTLANE_KEY secret is set but invalid. Verify that it is set correctly and try again." - elif ! fastlane validate_secrets; then - failed=true - echo "::error::Unable to create a valid authorization token for the App Store Connect API.\ - Verify that the FASTLANE_ISSUER_ID, FASTLANE_KEY_ID, and FASTLANE_KEY secrets are set correctly and try again." - fi - - # Validate MATCH_PASSWORD - if [ -z "$MATCH_PASSWORD" ]; then + elif ! fastlane validate_secrets 2>&1 | tee fastlane.log; then failed=true - echo "::error::The MATCH_PASSWORD secret is unset or empty. Set it and try again." + if grep -q "bad decrypt" fastlane.log; then + echo "::error::Unable to decrypt the Match-Secrets repository using the MATCH_PASSWORD secret. Verify that it is set correctly and try again." + else + echo "::error::Unable to create a valid authorization token for the App Store Connect API.\ + Verify that the FASTLANE_ISSUER_ID, FASTLANE_KEY_ID, and FASTLANE_KEY secrets are set correctly and try again." + fi fi # Exit unsuccessfully if secret validation failed. if [ $failed ]; then exit 2 fi - shell: bash - env: - TEAMID: ${{ secrets.TEAMID }} - GH_PAT: ${{ secrets.GH_PAT }} - FASTLANE_ISSUER_ID: ${{ secrets.FASTLANE_ISSUER_ID }} - FASTLANE_KEY_ID: ${{ secrets.FASTLANE_KEY_ID }} - FASTLANE_KEY: ${{ secrets.FASTLANE_KEY }} - MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} - GH_TOKEN: ${{ secrets.GH_PAT }} From dcee4f779923626ea1ddab345df3af40e3ae15ec Mon Sep 17 00:00:00 2001 From: Deniz Cengiz <48965855+dnzxy@users.noreply.github.com> Date: Wed, 16 Aug 2023 23:08:22 +0200 Subject: [PATCH 03/13] Modify validate_secrets to run in readonly mode --- fastlane/Fastfile | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 6b83bcaee9..3008caefe7 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -60,7 +60,7 @@ platform :ios do "com.#{TEAMID}.loopkit.Loop.LoopWatch.watchkitextension", "com.#{TEAMID}.loopkit.Loop.LoopWatch", "com.#{TEAMID}.loopkit.Loop.Loop-Intent-Extension", - "com.#{TEAMID}.loopkit.Loop.LoopWidgetExtension" + "com.#{TEAMID}.loopkit.Loop.SmallStatusWidget" ] ) @@ -123,9 +123,9 @@ platform :ios do update_code_signing_settings( path: "#{GITHUB_WORKSPACE}/Loop/Loop.xcodeproj", - profile_name: mapping["com.#{TEAMID}.loopkit.Loop.LoopWidgetExtension"], + profile_name: mapping["com.#{TEAMID}.loopkit.Loop.SmallStatusWidget"], code_sign_identity: "iPhone Distribution", - targets: ["Loop Widget Extension"] + targets: ["SmallStatusWidgetExtension"] ) gym( @@ -201,7 +201,7 @@ platform :ios do Spaceship::ConnectAPI::BundleIdCapability::Type::SIRIKIT ]) - configure_bundle_id("Loop Widget Extension", "com.#{TEAMID}.loopkit.Loop.LoopWidgetExtension", [ + configure_bundle_id("Small Status Widget", "com.#{TEAMID}.loopkit.Loop.SmallStatusWidget", [ Spaceship::ConnectAPI::BundleIdCapability::Type::APP_GROUPS ]) @@ -228,7 +228,7 @@ platform :ios do "com.#{TEAMID}.loopkit.Loop.LoopWatch.watchkitextension", "com.#{TEAMID}.loopkit.Loop.LoopWatch", "com.#{TEAMID}.loopkit.Loop.Loop-Intent-Extension", - "com.#{TEAMID}.loopkit.Loop.LoopWidgetExtension", + "com.#{TEAMID}.loopkit.Loop.SmallStatusWidget", ] ) end @@ -249,6 +249,13 @@ platform :ios do end find_bundle_id("com.#{TEAMID}.loopkit.Loop") + + match( + type: "appstore", + git_basic_authorization: Base64.strict_encode64("#{GITHUB_REPOSITORY_OWNER}:#{GH_PAT}"), + app_identifier: [], + ) + end desc "Nuke Certs" From ab8777fce048f6a3df3bc9c4bf55a661383f02ac Mon Sep 17 00:00:00 2001 From: Deniz Cengiz <48965855+dnzxy@users.noreply.github.com> Date: Wed, 16 Aug 2023 23:09:14 +0200 Subject: [PATCH 04/13] Streamline naming 1/3 --- .github/workflows/create_certs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/create_certs.yml b/.github/workflows/create_certs.yml index 82961983c0..7a4e8cb04a 100644 --- a/.github/workflows/create_certs.yml +++ b/.github/workflows/create_certs.yml @@ -4,12 +4,12 @@ on: workflow_dispatch: jobs: - secrets: + validate: uses: ./.github/workflows/validate_secrets.yml secrets: inherit certificates: - needs: secrets + needs: validate runs-on: macos-12 steps: # Uncomment to manually select latest Xcode if needed From 5785021df5c316db6a24245174443759ea9156a7 Mon Sep 17 00:00:00 2001 From: Deniz Cengiz <48965855+dnzxy@users.noreply.github.com> Date: Wed, 16 Aug 2023 23:09:30 +0200 Subject: [PATCH 05/13] Streamline naming 2/3 --- .github/workflows/add_identifiers.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/add_identifiers.yml b/.github/workflows/add_identifiers.yml index 62a2b543f5..6d6e25f2c9 100644 --- a/.github/workflows/add_identifiers.yml +++ b/.github/workflows/add_identifiers.yml @@ -4,12 +4,12 @@ on: workflow_dispatch: jobs: - secrets: + validate: uses: ./.github/workflows/validate_secrets.yml secrets: inherit identifiers: - needs: secrets + needs: validate runs-on: macos-12 steps: # Uncomment to manually select latest Xcode if needed From 84fbe137b0739a82ec344ec0931cf343cffd9e65 Mon Sep 17 00:00:00 2001 From: Deniz Cengiz <48965855+dnzxy@users.noreply.github.com> Date: Wed, 16 Aug 2023 23:11:02 +0200 Subject: [PATCH 06/13] Streamline naming 3/3, add back validation preceding build --- .github/workflows/build_loop.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build_loop.yml b/.github/workflows/build_loop.yml index 74cd09e56c..c5b52e1f22 100644 --- a/.github/workflows/build_loop.yml +++ b/.github/workflows/build_loop.yml @@ -18,7 +18,12 @@ env: SYNC_UPSTREAM: ${{ vars.SYNC_UPSTREAM }} # set an optional "SYNC_UPSTREAM" repository variable to 'false' to disable syncing of fork with the upstream repository jobs: + validate: + uses: ./.github/workflows/validate_secrets.yml + secrets: inherit + check_latest_from_upstream: + needs: validate runs-on: ubuntu-latest name: Check upstream and keep alive outputs: From 8a75a0974716eaa466642a3c699b3a80f5fa2ebb Mon Sep 17 00:00:00 2001 From: Deniz Cengiz <48965855+dnzxy@users.noreply.github.com> Date: Wed, 16 Aug 2023 23:18:10 +0200 Subject: [PATCH 07/13] Fix LoopWidgetExtension bundle identifier --- fastlane/Fastfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 3008caefe7..f918b3aa41 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -60,7 +60,7 @@ platform :ios do "com.#{TEAMID}.loopkit.Loop.LoopWatch.watchkitextension", "com.#{TEAMID}.loopkit.Loop.LoopWatch", "com.#{TEAMID}.loopkit.Loop.Loop-Intent-Extension", - "com.#{TEAMID}.loopkit.Loop.SmallStatusWidget" + "com.#{TEAMID}.loopkit.Loop.LoopWidgetExtension" ] ) @@ -123,9 +123,9 @@ platform :ios do update_code_signing_settings( path: "#{GITHUB_WORKSPACE}/Loop/Loop.xcodeproj", - profile_name: mapping["com.#{TEAMID}.loopkit.Loop.SmallStatusWidget"], + profile_name: mapping["com.#{TEAMID}.loopkit.Loop.LoopWidgetExtension"], code_sign_identity: "iPhone Distribution", - targets: ["SmallStatusWidgetExtension"] + targets: ["Loop Widget Extension"] ) gym( @@ -201,7 +201,7 @@ platform :ios do Spaceship::ConnectAPI::BundleIdCapability::Type::SIRIKIT ]) - configure_bundle_id("Small Status Widget", "com.#{TEAMID}.loopkit.Loop.SmallStatusWidget", [ + configure_bundle_id("Loop Widget Extension", "com.#{TEAMID}.loopkit.Loop.LoopWidgetExtension", [ Spaceship::ConnectAPI::BundleIdCapability::Type::APP_GROUPS ]) @@ -228,7 +228,7 @@ platform :ios do "com.#{TEAMID}.loopkit.Loop.LoopWatch.watchkitextension", "com.#{TEAMID}.loopkit.Loop.LoopWatch", "com.#{TEAMID}.loopkit.Loop.Loop-Intent-Extension", - "com.#{TEAMID}.loopkit.Loop.SmallStatusWidget", + "com.#{TEAMID}.loopkit.Loop.LoopWidgetExtension", ] ) end From d04e239cfb0c0778c702be160479b0b31a64ea42 Mon Sep 17 00:00:00 2001 From: Deniz Cengiz <48965855+dnzxy@users.noreply.github.com> Date: Fri, 18 Aug 2023 17:09:21 +0200 Subject: [PATCH 08/13] Add fastlane patterns back after accidentally removing them --- .github/workflows/validate_secrets.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/validate_secrets.yml b/.github/workflows/validate_secrets.yml index 5ce76bb30e..5969537375 100644 --- a/.github/workflows/validate_secrets.yml +++ b/.github/workflows/validate_secrets.yml @@ -95,6 +95,9 @@ jobs: fi # Validate FASTLANE_ISSUER_ID, FASTLANE_KEY_ID, and FASTLANE_KEY + FASTLANE_KEY_ID_PATTERN='^[A-Z0-9]+$' + FASTLANE_ISSUER_ID_PATTERN='^\{?[A-F0-9a-f]{8}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{12}\}?$' + if [ -z "$FASTLANE_ISSUER_ID" ] || [ -z "$FASTLANE_KEY_ID" ] || [ -z "$FASTLANE_KEY" ]; then failed=true [ -z "$FASTLANE_ISSUER_ID" ] && echo "::error::The FASTLANE_ISSUER_ID secret is unset or empty. Set it and try again." From d9a8841a487e4db1e46a6bdc1de940d0ceea8c0f Mon Sep 17 00:00:00 2001 From: Deniz Cengiz <48965855+dnzxy@users.noreply.github.com> Date: Fri, 18 Aug 2023 17:39:46 +0200 Subject: [PATCH 09/13] Fix Match-Secrets auto-creation and if-condition --- .github/workflows/validate_secrets.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate_secrets.yml b/.github/workflows/validate_secrets.yml index 5969537375..1b042799c7 100644 --- a/.github/workflows/validate_secrets.yml +++ b/.github/workflows/validate_secrets.yml @@ -39,7 +39,7 @@ jobs: if [ "$(gh repo list --json name | jq --raw-output 'any(.name=="Match-Secrets")')" != "true" ]; then echo "A 'Match-Secrets' repository could not be found. Attempting to create one..."; - if [ gh repo create Match-Secrets --private && "$(gh repo list --json name,visibility | jq --raw-output '.[] | select(.name=="Match-Secrets") | .visibility == "PRIVATE"')" == "true" ]; then + if gh repo create Match-Secrets --private >/dev/null && [ "$(gh repo list --json name,visibility | jq --raw-output '.[] | select(.name=="Match-Secrets") | .visibility == "PRIVATE"')" == "true" ]; then echo "Created a 'Match-Secrets' private repository." else failed=true From 5fa3d0e481166ab47e0997ef73ea8c0593f309dc Mon Sep 17 00:00:00 2001 From: Billy Booth Date: Mon, 21 Aug 2023 12:15:27 -0500 Subject: [PATCH 10/13] validate_secrets.yml: Set pipefail option so that fastlane exit codes are handled correctly --- .github/workflows/validate_secrets.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/validate_secrets.yml b/.github/workflows/validate_secrets.yml index 1b042799c7..92903ddf97 100644 --- a/.github/workflows/validate_secrets.yml +++ b/.github/workflows/validate_secrets.yml @@ -94,6 +94,9 @@ jobs: echo "::error::The MATCH_PASSWORD secret is unset or empty. Set it and try again." fi + # Ensure that fastlane exit codes are handled when output is piped. + set -o pipefail + # Validate FASTLANE_ISSUER_ID, FASTLANE_KEY_ID, and FASTLANE_KEY FASTLANE_KEY_ID_PATTERN='^[A-Z0-9]+$' FASTLANE_ISSUER_ID_PATTERN='^\{?[A-F0-9a-f]{8}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{12}\}?$' @@ -116,10 +119,11 @@ jobs: failed=true echo "::error::The FASTLANE_KEY secret is set but invalid. Verify that it is set correctly and try again." elif ! fastlane validate_secrets 2>&1 | tee fastlane.log; then - failed=true if grep -q "bad decrypt" fastlane.log; then + failed=true echo "::error::Unable to decrypt the Match-Secrets repository using the MATCH_PASSWORD secret. Verify that it is set correctly and try again." - else + elif ! grep -q "No code signing identity found" fastlane.log; then + failed=true echo "::error::Unable to create a valid authorization token for the App Store Connect API.\ Verify that the FASTLANE_ISSUER_ID, FASTLANE_KEY_ID, and FASTLANE_KEY secrets are set correctly and try again." fi From 9376317575686aea7b04ec4194680ba3f85bf3bf Mon Sep 17 00:00:00 2001 From: Billy Booth Date: Mon, 21 Aug 2023 12:34:53 -0500 Subject: [PATCH 11/13] workflows: Include branch in (run) names and use consistent capitalization across reusable job names * This commit is purely aesthetic and aims to make the display names of Jobs consistent across workflows. Likewise, makes spacing and validation error messages consistent. --- .github/workflows/add_identifiers.yml | 6 ++++-- .github/workflows/build_loop.yml | 28 +++++++++++++------------- .github/workflows/create_certs.yml | 6 ++++-- .github/workflows/validate_secrets.yml | 28 +++++++++++++------------- 4 files changed, 36 insertions(+), 32 deletions(-) diff --git a/.github/workflows/add_identifiers.yml b/.github/workflows/add_identifiers.yml index 6d6e25f2c9..868ca857d1 100644 --- a/.github/workflows/add_identifiers.yml +++ b/.github/workflows/add_identifiers.yml @@ -1,14 +1,16 @@ name: 2. Add Identifiers -run-name: Add Identifiers +run-name: Add Identifiers (${{ github.ref_name }}) on: workflow_dispatch: jobs: validate: + name: Validate uses: ./.github/workflows/validate_secrets.yml secrets: inherit - + identifiers: + name: Add Identifiers needs: validate runs-on: macos-12 steps: diff --git a/.github/workflows/build_loop.yml b/.github/workflows/build_loop.yml index 6762cd9756..fdc86f4e0c 100644 --- a/.github/workflows/build_loop.yml +++ b/.github/workflows/build_loop.yml @@ -5,7 +5,7 @@ on: ## Remove the "#" sign from the beginning of the line below to get automated builds on push (code changes in your repository) #push: - + schedule: - cron: '0 8 * * 3' # Checks for updates at 08:00 UTC every Wednesday - cron: '0 8 1 * 6' # Builds the app on the 1st Saturday every month at 08:00 UTC @@ -19,9 +19,10 @@ env: jobs: validate: + name: Validate uses: ./.github/workflows/validate_secrets.yml secrets: inherit - + # Checks if GH_PAT holds workflow permissions # Checks for existence of alive branch; if non-existent creates it check_alive_and_permissions: @@ -32,7 +33,7 @@ jobs: contents: write outputs: WORKFLOW_PERMISSION: ${{ steps.workflow-permission.outputs.has_permission }} - + steps: - name: Check for workflow permissions id: workflow-permission @@ -49,7 +50,7 @@ jobs: echo "Automated build features will be skipped!" echo "has_permission=false" >> $GITHUB_OUTPUT # Set WORKFLOW_PERMISSION to false. fi - + - name: Check for alive branch if: steps.workflow-permission.outputs.has_permission == 'true' env: @@ -62,7 +63,7 @@ jobs: echo "Branch 'alive' does not exist." echo "ALIVE_BRANCH_EXISTS=false" >> $GITHUB_ENV # Set ALIVE_BRANCH_EXISTS to false fi - + - name: Create alive branch if: env.ALIVE_BRANCH_EXISTS != 'true' env: @@ -82,7 +83,7 @@ jobs: /repos/${{ github.repository_owner }}/LoopWorkspace/git/refs \ -f ref='refs/heads/alive' \ -f sha=$SHA - + # Checks for changes in upstream repository; if changes exist prompts sync for build # Performs keepalive to avoid stale fork check_latest_from_upstream: @@ -91,7 +92,7 @@ jobs: name: Check upstream and keep alive outputs: NEW_COMMITS: ${{ steps.sync.outputs.has_new_commits }} - + steps: - name: Checkout target repo if: | @@ -101,7 +102,7 @@ jobs: with: token: ${{ secrets.GH_PAT }} ref: alive - + - name: Sync upstream changes if: | # do not run the upstream sync action on the upstream repository needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' && @@ -114,7 +115,7 @@ jobs: target_repo_token: ${{ secrets.GH_PAT }} upstream_sync_branch: ${{ env.UPSTREAM_BRANCH }} upstream_sync_repo: ${{ env.UPSTREAM_REPO }} - + # Display a sample message based on the sync output var 'has_new_commits' - name: New commits found if: | @@ -127,7 +128,7 @@ jobs: needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' && vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'false' run: echo "There were no new commits." - + - name: Show value of 'has_new_commits' if: needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' && vars.SCHEDULED_SYNC != 'false' run: | @@ -142,7 +143,7 @@ jobs: uses: gautamkrishnar/keepalive-workflow@v1 # using the workflow with default settings with: time_elapsed: 20 # Time elapsed from the previous commit to trigger a new automated commit (in days) - + - name: Show scheduled build configuration message if: needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION != 'true' run: | @@ -152,7 +153,6 @@ jobs: echo "If you want to enable automatic builds and updates for your Loop, please follow the instructions \ under the following path LoopWorkspace/fastlane/testflight.md." >> $GITHUB_STEP_SUMMARY - # Builds Loop build: name: Build @@ -169,7 +169,7 @@ jobs: steps: - name: Select Xcode version run: "sudo xcode-select --switch /Applications/Xcode_14.3.1.app/Contents/Developer" - + - name: Checkout Repo for syncing if: | needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' && @@ -178,7 +178,7 @@ jobs: with: token: ${{ secrets.GH_PAT }} ref: ${{ env.TARGET_BRANCH }} - + - name: Sync upstream changes if: | # do not run the upstream sync action on the upstream repository needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' && diff --git a/.github/workflows/create_certs.yml b/.github/workflows/create_certs.yml index 7a4e8cb04a..a5e076ffaa 100644 --- a/.github/workflows/create_certs.yml +++ b/.github/workflows/create_certs.yml @@ -1,14 +1,16 @@ name: 3. Create Certificates -run-name: Create Certificates +run-name: Create Certificates (${{ github.ref_name }}) on: workflow_dispatch: jobs: validate: + name: Validate uses: ./.github/workflows/validate_secrets.yml secrets: inherit - + certificates: + name: Create Certificates needs: validate runs-on: macos-12 steps: diff --git a/.github/workflows/validate_secrets.yml b/.github/workflows/validate_secrets.yml index 92903ddf97..aa10e01491 100644 --- a/.github/workflows/validate_secrets.yml +++ b/.github/workflows/validate_secrets.yml @@ -1,5 +1,5 @@ name: 1. Validate Secrets -run-name: Validate Secrets +run-name: Validate Secrets (${{ github.ref_name }}) on: [workflow_call, workflow_dispatch] jobs: @@ -15,17 +15,17 @@ jobs: # Validate Fastlane Access Token (GH_PAT) if [ -z "$GH_PAT" ]; then failed=true - echo "::error::GH_PAT secret is unset or empty. Set it and try again." + echo "::error::The GH_PAT secret is unset or empty. Set it and try again." elif [ "$(gh api -H "Accept: application/vnd.github+json" /repos/${{ github.repository_owner }}/LoopWorkspace | jq --raw-output '.permissions.push')" != "true" ]; then failed=true - echo "::error::GH_PAT secret is set but invalid or lacking 'repo' permission scope. Verify that it is created/set correctly and try again." + echo "::error::The GH_PAT secret is set but invalid or lacking 'repo' permission scope. Verify that it is created/set correctly and try again." fi # Exit unsuccessfully if secret validation failed. if [ $failed ]; then exit 2 fi - + validate-match-secrets: name: Match-Secrets needs: validate-access-token @@ -40,7 +40,7 @@ jobs: echo "A 'Match-Secrets' repository could not be found. Attempting to create one..."; if gh repo create Match-Secrets --private >/dev/null && [ "$(gh repo list --json name,visibility | jq --raw-output '.[] | select(.name=="Match-Secrets") | .visibility == "PRIVATE"')" == "true" ]; then - echo "Created a 'Match-Secrets' private repository." + echo "Created a private 'Match-Secrets' repository." else failed=true echo "::error::A private 'Match-Secrets' repository could not be created. Create a private `Match-Secrets` repository manually or try again.\ @@ -50,12 +50,12 @@ jobs: failed=true echo "::error::A 'Match-Secrets' repository was found, but it is is public. Delete it and try again (a private repository will be created for you)." fi - + # Exit unsuccessfully if secret validation failed. if [ $failed ]; then exit 2 fi - + validate-fastlane-secrets: name: Fastlane needs: validate-match-secrets @@ -71,7 +71,7 @@ jobs: steps: - name: Checkout Repo uses: actions/checkout@v3 - + - name: Validate Fastlane Secrets run: | # Validate Fastlane Secrets @@ -79,13 +79,13 @@ jobs: # Validate TEAMID if [ -z "$TEAMID" ]; then failed=true - echo "::error::TEAMID secret is unset or empty. Set it and try again." + echo "::error::The TEAMID secret is unset or empty. Set it and try again." elif [ ${#TEAMID} -ne 10 ]; then failed=true - echo "::error::TEAMID secret is set but has wrong length. Verify that it is set correctly and try again." + echo "::error::The TEAMID secret is set but has wrong length. Verify that it is set correctly and try again." elif ! [[ $TEAMID =~ ^[A-Z0-9]+$ ]]; then failed=true - echo "::error::TEAMID is set but invalid. Verify that it is set correctly (only uppercase letters and numbers) and try again." + echo "::error::The TEAMID secret is set but invalid. Verify that it is set correctly (only uppercase letters and numbers) and try again." fi # Validate MATCH_PASSWORD @@ -108,13 +108,13 @@ jobs: [ -z "$FASTLANE_KEY" ] && echo "::error::The FASTLANE_KEY secret is unset or empty. Set it and try again." elif [ ${#FASTLANE_KEY_ID} -ne 10 ]; then failed=true - echo "::error::FASTLANE_KEY_ID secret is set but has wrong length. Verify that it is set correctly and try again." + echo "::error::The FASTLANE_KEY_ID secret is set but has wrong length. Verify that it is set correctly and try again." elif ! [[ $FASTLANE_KEY_ID =~ $FASTLANE_KEY_ID_PATTERN ]]; then failed=true - echo "::error::FASTLANE_KEY_ID is set but invalid. Verify that it is set correctly (only uppercase letters and numbers) and try again." + echo "::error::The FASTLANE_KEY_ID secret is set but invalid. Verify that it is set correctly (only uppercase letters and numbers) and try again." elif ! [[ $FASTLANE_ISSUER_ID =~ $FASTLANE_ISSUER_ID_PATTERN ]]; then failed=true - echo "::error::FASTLANE_ISSUER_ID is set but invalid. Verify that it is set correctly (adhering to UUID format) and try again." + echo "::error::The FASTLANE_ISSUER_ID secret is set but invalid. Verify that it is set correctly (adhering to UUID format) and try again." elif ! echo "$FASTLANE_KEY" | openssl pkcs8 -nocrypt >/dev/null; then failed=true echo "::error::The FASTLANE_KEY secret is set but invalid. Verify that it is set correctly and try again." From ef05130a852b5cc4bb6f4333dd34d5ca08ebee49 Mon Sep 17 00:00:00 2001 From: Billy Booth Date: Mon, 21 Aug 2023 13:28:13 -0500 Subject: [PATCH 12/13] validate_secrets.yml: Make annotations more "actionable". --- .github/workflows/validate_secrets.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/validate_secrets.yml b/.github/workflows/validate_secrets.yml index aa10e01491..8dc4637ddc 100644 --- a/.github/workflows/validate_secrets.yml +++ b/.github/workflows/validate_secrets.yml @@ -18,7 +18,8 @@ jobs: echo "::error::The GH_PAT secret is unset or empty. Set it and try again." elif [ "$(gh api -H "Accept: application/vnd.github+json" /repos/${{ github.repository_owner }}/LoopWorkspace | jq --raw-output '.permissions.push')" != "true" ]; then failed=true - echo "::error::The GH_PAT secret is set but invalid or lacking 'repo' permission scope. Verify that it is created/set correctly and try again." + echo "::error::The GH_PAT secret is set but invalid or lacking at least 'repo' permission scope ('repo, workflow' is okay too).\ + Verify that token permissions are set correctly (or update them) at https://github.com/settings/tokens and try again." fi # Exit unsuccessfully if secret validation failed. @@ -108,16 +109,16 @@ jobs: [ -z "$FASTLANE_KEY" ] && echo "::error::The FASTLANE_KEY secret is unset or empty. Set it and try again." elif [ ${#FASTLANE_KEY_ID} -ne 10 ]; then failed=true - echo "::error::The FASTLANE_KEY_ID secret is set but has wrong length. Verify that it is set correctly and try again." + echo "::error::The FASTLANE_KEY_ID secret is set but has wrong length. Verify that you copied it correctly from https://appstoreconnect.apple.com/access/api and try again." elif ! [[ $FASTLANE_KEY_ID =~ $FASTLANE_KEY_ID_PATTERN ]]; then failed=true - echo "::error::The FASTLANE_KEY_ID secret is set but invalid. Verify that it is set correctly (only uppercase letters and numbers) and try again." + echo "::error::The FASTLANE_KEY_ID secret is set but invalid. Verify that you copied it correctly from https://appstoreconnect.apple.com/access/api and try again." elif ! [[ $FASTLANE_ISSUER_ID =~ $FASTLANE_ISSUER_ID_PATTERN ]]; then failed=true - echo "::error::The FASTLANE_ISSUER_ID secret is set but invalid. Verify that it is set correctly (adhering to UUID format) and try again." + echo "::error::The FASTLANE_ISSUER_ID secret is set but invalid. Verify that you copied it correctly from https://appstoreconnect.apple.com/access/api and try again." elif ! echo "$FASTLANE_KEY" | openssl pkcs8 -nocrypt >/dev/null; then failed=true - echo "::error::The FASTLANE_KEY secret is set but invalid. Verify that it is set correctly and try again." + echo "::error::The FASTLANE_KEY secret is set but invalid. Verify that you copied it correctly from the API Key file (*.p8) you downloaded and try again." elif ! fastlane validate_secrets 2>&1 | tee fastlane.log; then if grep -q "bad decrypt" fastlane.log; then failed=true From 0d0ead59bfeeafefb896a20a6e444abd6e5dbecd Mon Sep 17 00:00:00 2001 From: Billy Booth Date: Mon, 21 Aug 2023 15:08:06 -0500 Subject: [PATCH 13/13] validate_secrets.yml: Improve error annotations around GH_PAT permissions * Trivial changes to FASTLANE / ASC error annotations (mention 'Keys' tab) --- .github/workflows/validate_secrets.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/validate_secrets.yml b/.github/workflows/validate_secrets.yml index 8dc4637ddc..2b03713011 100644 --- a/.github/workflows/validate_secrets.yml +++ b/.github/workflows/validate_secrets.yml @@ -44,8 +44,8 @@ jobs: echo "Created a private 'Match-Secrets' repository." else failed=true - echo "::error::A private 'Match-Secrets' repository could not be created. Create a private `Match-Secrets` repository manually or try again.\ - If a private 'Match-Secrets' repository already exists, ensure that the GH_PAT has appropriate permissions to access it." + echo "::error::Cannot access or create a private 'Match-Secrets' repository. The GH_PAT secret is lacking at least the 'repo' permission scope required to access or create the repository.\ + Verify that token permissions are set correctly (or update them) at https://github.com/settings/tokens and try again." fi elif [ "$(gh repo list --json name,visibility | jq --raw-output '.[] | select(.name=="Match-Secrets") | .visibility == "PUBLIC"')" == "true" ]; then failed=true @@ -109,13 +109,13 @@ jobs: [ -z "$FASTLANE_KEY" ] && echo "::error::The FASTLANE_KEY secret is unset or empty. Set it and try again." elif [ ${#FASTLANE_KEY_ID} -ne 10 ]; then failed=true - echo "::error::The FASTLANE_KEY_ID secret is set but has wrong length. Verify that you copied it correctly from https://appstoreconnect.apple.com/access/api and try again." + echo "::error::The FASTLANE_KEY_ID secret is set but has wrong length. Verify that you copied it correctly from the 'Keys' tab at https://appstoreconnect.apple.com/access/api and try again." elif ! [[ $FASTLANE_KEY_ID =~ $FASTLANE_KEY_ID_PATTERN ]]; then failed=true - echo "::error::The FASTLANE_KEY_ID secret is set but invalid. Verify that you copied it correctly from https://appstoreconnect.apple.com/access/api and try again." + echo "::error::The FASTLANE_KEY_ID secret is set but invalid. Verify that you copied it correctly from the 'Keys' tab at https://appstoreconnect.apple.com/access/api and try again." elif ! [[ $FASTLANE_ISSUER_ID =~ $FASTLANE_ISSUER_ID_PATTERN ]]; then failed=true - echo "::error::The FASTLANE_ISSUER_ID secret is set but invalid. Verify that you copied it correctly from https://appstoreconnect.apple.com/access/api and try again." + echo "::error::The FASTLANE_ISSUER_ID secret is set but invalid. Verify that you copied it correctly from the 'Keys' tab at https://appstoreconnect.apple.com/access/api and try again." elif ! echo "$FASTLANE_KEY" | openssl pkcs8 -nocrypt >/dev/null; then failed=true echo "::error::The FASTLANE_KEY secret is set but invalid. Verify that you copied it correctly from the API Key file (*.p8) you downloaded and try again."