move secrets to hashicorp, don't use match (wip)
Some checks failed
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 1m41s
Build and release debug APK / Build APK (pull_request) Failing after 4m46s
Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 16s

This commit is contained in:
Remy Moll 2024-12-14 16:39:27 +01:00
parent 4a542a4a1f
commit cbada7e4a4
6 changed files with 115 additions and 41 deletions

View File

@ -39,11 +39,23 @@ jobs:
# remove the 'v' prefix from the tag name
echo "BUILD_NAME=${REF_NAME//v}" >> $GITHUB_ENV
- name: Load secrets from github
- name: Load secrets
id: load-secrets
uses: hashicorp/vault-action@v3
with:
url: https://api.hashicorp.com
token: ${{ secrets.VAULT_TOKEN }}
secrets: |
secret/release GOOGLE_MAPS_API_KEY | GOOGLE_MAPS_API_KEY ;
secret/release ANDROID_SECRET_PROPERTIES_BASE64 | ANDROID_SECRET_PROPERTIES_BASE64 ;
secret/release ANDROID_GOOGLE_PLAY_JSON_BASE64 | ANDROID_GOOGLE_PLAY_JSON_BASE64 ;
secret/release ANDROID_KEYSTORE_BASE64 | ANDROID_KEYSTORE_BASE64 ;
- name: Put selected secrets into files
run: |
echo "${{ secrets.ANDROID_SECRET_PROPERTIES_BASE64 }}" | base64 -d > secrets.properties
echo "${{ secrets.ANDROID_GOOGLE_PLAY_JSON_BASE64 }}" | base64 -d > google-key.json
echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 -d > release.keystore
echo "${{ steps.load-secrets.outputs.ANDROID_SECRET_PROPERTIES_BASE64 }}" | base64 -d > secrets.properties
echo "${{ steps.load-secrets.outputs.ANDROID_GOOGLE_PLAY_JSON_BASE64 }}" | base64 -d > google-key.json
echo "${{ steps.load-secrets.outputs.ANDROID_KEYSTORE_BASE64 }}" | base64 -d > release.keystore
working-directory: android
- name: Install fastlane
@ -56,4 +68,4 @@ jobs:
env:
BUILD_NUMBER: ${{ github.run_number }}
# BUILD_NAME is implicitly available
GOOGLE_MAPS_API_KEY: ${{ secrets.GOOGLE_MAPS_API_KEY }}
GOOGLE_MAPS_API_KEY: ${{ steps.load-secrets.outputs.GOOGLE_MAPS_API_KEY }}

View File

@ -30,12 +30,17 @@ jobs:
# remove the 'v' prefix from the tag name
echo "BUILD_NAME=${REF_NAME//v}" >> $GITHUB_ENV
- name: Load secrets from github
run: |
echo "${{ secrets.IOS_SECRET_PROPERTIES_BASE64 }}" | base64 -d > secrets.properties
echo "${{ secrets.IOS_GOOGLE_PLAY_JSON_BASE64 }}" | base64 -d > google-key.json
echo "${{ secrets.IOS_KEYSTORE_BASE64 }}" | base64 -d > release.keystore
working-directory: ios
- name: Load secrets
id: load-secrets
uses: hashicorp/vault-action@v3
with:
url: https://api.hashicorp.com
token: ${{ secrets.VAULT_TOKEN }}
secrets: |
secret/release GOOGLE_MAPS_API_KEY | GOOGLE_MAPS_API_KEY ;
secret/release IOS_ASC_KEY_ID | IOS_ASC_KEY_ID ;
secret/release IOS_ASC_ISSUER_ID | IOS_ASC_ISSUER_ID ;
secret/release IOS_ASC_KEY_P8 | IOS_ASC_KEY_P8 ;
- name: Install fastlane
run: bundle install
@ -47,7 +52,7 @@ jobs:
env:
BUILD_NUMBER: ${{ github.run_number }}
# BUILD_NAME is implicitly available
GOOGLE_MAPS_API_KEY: ${{ secrets.GOOGLE_MAPS_API_KEY }}
IOS_ASC_KEY_ID: ${{ secrets.IOS_ASC_KEY_ID }}
IOS_ASC_ISSUER_ID: ${{ secrets.IOS_ASC_ISSUER_ID }}
IOS_ASC_KEY_P8: ${{ secrets.IOS_ASC_KEY_P8 }}
GOOGLE_MAPS_API_KEY: ${{ steps.load-secrets.outputs.GOOGLE_MAPS_API_KEY }}
IOS_ASC_KEY_ID: ${{ GOOGLE_MAPS_API_KEY.IOS_ASC_KEY_ID }}
IOS_ASC_ISSUER_ID: ${{ GOOGLE_MAPS_API_KEY.IOS_ASC_ISSUER_ID }}
IOS_ASC_KEY_P8: ${{ GOOGLE_MAPS_API_KEY.IOS_ASC_KEY_P8 }}

View File

@ -46,12 +46,17 @@ bundle exec fastlane <lane>
```
This is reused in the CI/CD pipeline to automate the deployment process.
Fastlane assumes mutliple secrets to be present as files in the platform directories. These are:
- for android:
- `secrets.properties` used by gradle to load secrets needed at execution time
- `release.keystore` used by gradle to sign the apk
- `google-key.json` used by fastlane to authenticate with the Google Play Store
- for ios:
- TODO
Secrets used by fastlane are stored on hashicorp vault and are fetched by the CI/CD pipeline. See below.
These files are stored as secrets in the GitHub repository so that the CI pipeline can access them.
## Secrets
These are mostly used by the CI/CD pipeline to deploy the application. The main usage for github actions is documented under [https://github.com/hashicorp/vault-action](https://github.com/hashicorp/vault-action).
**Global secrets** are used for both versions of the app (android and ios).
- `GOOGLE_MAPS_API_KEY` is used to authenticate with the Google Maps API
**Platform-specific secrets** are used by the CI/CD pipeline to deploy to the respective app stores.
- `ANDROID_KEYSTORE` is used to sign the android apk
- `ANDROID_GOOGLE_KEY` is used to authenticate with the Google Play Store api
- `IOS_GOOGLE_...`
- `IOS_GOOGLE_...`
- `IOS_GOOGLE_...`
- `IOS_GOOGLE_...`

View File

@ -63,11 +63,3 @@ Compared to the flutter template application, a few changes have to be made:
}
```
### Using the credentials in CI
- Add the secret files to the repository secrets (e.g. `ANDROID_SECRETS_PROPERTIES`).
- temporarily write them back to files during the CI execution:
```bash
echo {{ secrets.ANDROID_SECRETS }} >> android/secrets.properties
```

View File

@ -1,10 +1,7 @@
default_platform(:ios)
platform :ios do
before_all do
load_asc_api_token
end
desc "Load the App Store Connect API token"
lane :load_asc_api_token do
app_store_connect_api_key(
@ -16,17 +13,66 @@ platform :ios do
)
end
desc "Installs signing certificate in the keychain and downloads provisioning profiles from App Store Connect"
lane :prepare_signing do |options|
team_id = CredentialsManager::AppfileConfig.try_fetch_value(:team_id)
api_key = lane_context[SharedValues::APP_STORE_CONNECT_API_KEY]
keychain_name = "signing"
keychain_password = "temp"
delete_keychain(
name: keychain_name
) if File.exist? File.expand_path("~/Library/Keychains/#{keychain_name}-db")
create_keychain(
name: keychain_name,
password: keychain_password,
default_keychain: true,
unlock: true,
timeout: 3600
)
import_certificate(
certificate_path: ENV["SIGNING_KEY_FILE_PATH"],
certificate_password: ENV["SIGNING_KEY_PASSWORD"],
keychain_name: keychain_name,
keychain_password: keychain_password
)
# fetches and installs provisioning profiles from ASC
sigh(
adhoc: options[:adhoc],
api_key: api_key,
readonly: true
)
end
desc "Deploy a new version to closed testing (testflight)"
lane :deploy_testing do
build_name = ENV["BUILD_NAME"]
build_number = ENV["BUILD_NUMBER"]
api_key = lane_context[SharedValues::APP_STORE_CONNECT_API_KEY]
sync_code_signing(
api_key: api_key,
type: "appstore",
readonly: true,
app_identifier = CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier)
load_asc_api_token
prepare_signing
profile_name = "App Provisioning Profile" # replace with the name of the profile to use for the build
output_name = "example-iOS" # specify the name of the .ipa file to generate
export_method = "app-store" # specify the export method
# turn off automatic signing during build so correct code signing identity is guaranteed to be used
update_code_signing_settings(
use_automatic_signing: false,
targets: ["main-target"], # specify which targets to update code signing settings for
code_sign_identity: "Apple Distribution", # replace with name of code signing identity if different
bundle_identifier: app_identifier,
profile_name: profile_name,
build_configurations: ["Release"] # only toggle code signing settings for Release configurations
)
sh(
"flutter",
@ -40,7 +86,11 @@ platform :ios do
# sign the app (whithout rebuilding it)
build_app(
skip_build_archive: true,
archive_path: "../build/ios/archive/Runner.xarchive"
archive_path: "../build/ios/archive/Runner.xcarchive"
provisioningProfiles: {
app_identifier => profile_name
}
)
upload_to_testflight

View File

@ -0,0 +1,10 @@
# SAMPLE env file that replicates the env in the CI/CD pipeline
# DO NOT EDIT THIS FILE
# Copy this file to local.env and edit the values to match your local environment
IOS_ASC_KEY_ID="sample"
IOS_ASC_ISSUER_ID="sample"
IOS_ASC_KEY_P8="sample"
SIGNING_KEY_FILE_PATH="sample"
SIGNING_KEY_PASSWORD="sample"
BUILD_NAME="sample"
BUILD_NUMBER="sample"