Skip to content

Commit

Permalink
Merge pull request #79 from kiwix/66-non-kiwix-environment
Browse files Browse the repository at this point in the history
Use dynamic environment for cd builds
  • Loading branch information
BPerlakiH authored Feb 4, 2025
2 parents 105dfd4 + 4e4f84f commit 09c8a38
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 29 deletions.
33 changes: 12 additions & 21 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ jobs:
- platform: iOS
xcode_extra: -sdk iphoneos
runs-on: macos-13
environment: ${{ contains(github.ref, 'dwds') && 'dwds' || 'internal' }}
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down Expand Up @@ -59,7 +60,7 @@ jobs:
- name: Generate project based on tag
env:
DWDS_HTTP_BASIC_ACCESS_AUTHENTICATION: ${{ secrets.DWDS_HTTP_BASIC_ACCESS_AUTHENTICATION }}
HTTP_BASIC_ACCESS_AUTHENTICATION: ${{ secrets.HTTP_BASIC_ACCESS_AUTHENTICATION }}
run:
|
# move the custom files under the same folder as the kiwix repo
Expand All @@ -82,17 +83,26 @@ jobs:
ls -la


- name: Set up scheme, version, build_number from files
- name: Set up scheme, version, build_number, and team-id from files
run: |
# move the checked out github actions to root folder:
mv apple/.github/ .
# each of these dot files below contain a single value
# and are created by: src/tag_validator.py
# brand_name comes from the valid tag
BRAND=$(<./apple/custom/.brand_name)
echo "BRAND=$BRAND" >> $GITHUB_ENV
# version comes from the tag
VERSION=$(<./apple/custom/.version_number)
echo "VERSION=$VERSION" >> $GITHUB_ENV
# team_id comes from the brand's json file
TEAM_ID=$(<./apple/custom/.team_id)
echo "TEAM_ID=$TEAM_ID" >> $GITHUB_ENV
# taken from: kiwix/kiwix-apple .github/workflows/cd.yml
- name: Set up variables for build
env:
Expand Down Expand Up @@ -120,11 +130,9 @@ jobs:
env:
APPLE_DISTRIBUTION_SIGNING_CERTIFICATE: ${{ secrets.APPLE_DISTRIBUTION_SIGNING_CERTIFICATE }}
APPLE_DISTRIBUTION_SIGNING_P12_PASSWORD: ${{ secrets.APPLE_DISTRIBUTION_SIGNING_P12_PASSWORD }}
APPLE_DEVELOPMENT_SIGNING_IDENTITY: ${{ secrets.APPLE_DEVELOPMENT_SIGNING_IDENTITY }}
run: |
echo "SIGNING_CERTIFICATE=${APPLE_DISTRIBUTION_SIGNING_CERTIFICATE}" >> "$GITHUB_ENV"
echo "SIGNING_CERTIFICATE_P12_PASSWORD=${APPLE_DISTRIBUTION_SIGNING_P12_PASSWORD}" >> "$GITHUB_ENV"
echo "SIGNING_IDENTITY=${APPLE_DEVELOPMENT_SIGNING_IDENTITY}" >> "$GITHUB_ENV"
- name: Add Apple Store Key
env:
Expand Down Expand Up @@ -153,23 +161,6 @@ jobs:
KEYCHAIN_PROFILE: ${{ env.KEYCHAIN_PROFILE }}
EXTRA_XCODEBUILD: ${{ env.EXTRA_XCODEBUILD }}

- name: Add altool credentials to Keychain
shell: bash
env:
APPLE_SIGNING_ALTOOL_USERNAME: ${{ secrets.APPLE_SIGNING_ALTOOL_USERNAME }}
APPLE_SIGNING_ALTOOL_PASSWORD: ${{ secrets.APPLE_SIGNING_ALTOOL_PASSWORD }}
APPLE_SIGNING_TEAM: ${{ secrets.APPLE_SIGNING_TEAM }}
run: |
security find-identity -v $KEYCHAIN
security unlock-keychain -p $KEYCHAIN_PASSWORD $KEYCHAIN
xcrun notarytool store-credentials \
--apple-id "${APPLE_SIGNING_ALTOOL_USERNAME}" \
--password "${APPLE_SIGNING_ALTOOL_PASSWORD}" \
--team-id "${APPLE_SIGNING_TEAM}" \
--validate \
--keychain $KEYCHAIN \
$KEYCHAIN_PROFILE
- name: Prepare export for ${{ env.EXPORT_METHOD }}
run: |
plutil -create xml1 ./export.plist
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
- name: Generate project based on tag
env:
DWDS_HTTP_BASIC_ACCESS_AUTHENTICATION: ${{ secrets.DWDS_HTTP_BASIC_ACCESS_AUTHENTICATION }}
HTTP_BASIC_ACCESS_AUTHENTICATION: ${{ secrets.HTTP_BASIC_ACCESS_AUTHENTICATION }}
run:
|
# move the custom files under the same folder as the kiwix repo
Expand Down
124 changes: 122 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ existing one if you need to create a new custom app.
- `about_app_url` - this is an external link that is placed in the "About section" of the application. (Eg. "https://www.dwds.de")
- `about_text` - this is a custom text that is placed in the "About section" describing what the application is about. It is not supporting html tags, but new lines can be added with '\n'.
- `app_name` - Name of the app, as it will appear on device, and in App Store
- `app_store_id` - this should to be taken from the developer.apple.com, where the application release is prepared. Note you can use the app_store_id even if the app is not yet released. The id is used within the app in the "Rate the app" section, so users can be redirected to a specific app in the App Store, to rate it.
- `development_team` - this is the development team id used for the build, it can be found in the relevant Apple Development Account (for apps under the Kiwix organisation it will be the same value: L7HWM3SP3L)
- `app_store_id` - this should to be taken from the developer.apple.com, where the application release is prepared. Note you can use the app_store_id even if the app is not yet released. You can find this by visiting: https://appstoreconnect.apple.com/apps/, selecting your app, and go to General tab (on the left), and it will be under AppleID. The id is used within the app in the "Rate the app" section, so users can be redirected to a specific app in the App Store, to rate it. it is a sequence of numbers usually, although for the json file we need to append "id" to it. Eg.: "1281693200" becomes "id1281693200".
- `development_team` - this is the development team id used for the build, it can be found in the relevant Apple Development Account (for apps under the Kiwix organisation it will be the same value: L7HWM3SP3L). You can find your team id in the upper right corner of the screen (after you login to) your [Apple Developer Account](https://developer.apple.com/account/resources/certificates/list).
- `enforced_lang` - ISO 639-1 language code (eg: en, de, he) if it is set, it will include only this language in the final app, meaning no other languages can be selected (on iOS) for the application UI. See the current list of supported languages [already translated in the main repo](https://github.com/kiwix/kiwix-apple/tree/main/Support). When using this option, make sure that [the translation coverage](https://translatewiki.net/wiki/Special:MessageGroupStats/kiwix-apple?group=kiwix-apple&messages=&suppressempty=1&x=D) is 100% for the enforced language.

If enforced_lang is not added to the info.json file, all languages will be supported by the app, just like in Kiwix.
Expand Down Expand Up @@ -87,6 +87,126 @@ Where the:

Note: Both iOS and macOS applications are created from the same source code and are versioned and released together.

# Release from an external Apple Account (non Kiwix)
In order to use a different Apple Account for your app, further setup is required.

## Creating the App and the Bundle ID for it
First you need to register a bundleID, which is a unique identifier for the app, here:
https://developer.apple.com/account/resources/identifiers/bundleId/add

Apple recommends a reverse domain name, so something like: org.kiwix.app (adjusted to your domain accordingly)

Please leave the "explicit option", and not use a "wildcard one".
For the app itself, please select both iOS and macOS platforms. We support both of those.

The question marks helpfully explain how the values from each input field of the from will be used later on.
You can leave the "full access" turned on, it will allow each team member (of the developer account) to use the app,
so you don't need to invite them one by one (if that's easier for you that is).

Take note of the bundleID you pick for your application, that should be put into info.json (see above).

## TEAM ID:
Take note of your Apple Team ID, this should be also put into the info.json file for your brand.
The team ID can be found at the bottom of the following page (after signing), under "Membership details":
https://developer.apple.com/account

## Storing secrets in GitHub
A dedicated GitHub environment will be created for your brand, where your secrets will be kept.

> [!NOTE]
> **The values for the below keys contain secret values, do not send them publicly to GitHub tickets, or any publicly available space.** These secrets need to be sent over e-mail or via other Private Message solution.
## Create the development certificate:
You need to create a development certificate for the app here:
https://developer.apple.com/account/resources/certificates/list
- press create a certificate
- select the first option: Apple Development
- press continue (upper right corner)
- Upload a Certificate Signing Request, to create it you need to follow these steps:
https://developer.apple.com/help/account/create-certificates/create-a-certificate-signing-request

> (Note on macOS Sequoia the KeyChain app is not visible by default, but can be found it under: `/System/Library/CoreServices/Applications/Keychain Access.app`, you can create a link to it, that you can add to your `Application` folder. Open Finder, from the top menu select Go -> Go To Folder, copy paste in: "/System/Library/CoreServices/Applications/". To create a link to the "KeyChain Access.app", have it selected and right click on it, and from the hover menu, select: "Make Alias", this will create a link to it on your Desktop. Optionally you can move this link - by draging it - to your Application folder, if you want.)

For the common name you can use something like: "Kiwix Development" (*adjusted to your app name accordingly)
Note: You don't need to do the openssl command-line steps here, only the "Keychain Access" ones.
For convenience, when saving the .certSigningRequest file you can rename it to something like: "Kiwix_Development.certSigningRequest".

Once it's approved, you should download your .cer file to your computer, and keep it safe (also you can rename the .cer file to something more meaningful eg: Kiwix_Development.cer).

You can go back to: "All certificates"

## Create a distribution certificate:

Similarly to the former step, start here:
https://developer.apple.com/account/resources/certificates/list
- press create a certificate
- select the second option: Apple Distribution
- again you need to create a new Certificate Signing Request (a seperate one), following the same steps (see above):
https://developer.apple.com/help/account/create-certificates/create-a-certificate-signing-request

For the common name you can use something like: "Kiwix Distribution" (*adjusted to your app name accordingly)
And as above you can rename the files in this process accrodingly eg to: "Kiwix_Distribution.certSigningRequest", and "Kiwix_Distribution.cer"

## Export the above certificates to .p12 files.
By opening those .cer files on your mac (both Kiwix_Development.cer and Kiwix_Distribution.cer), they will be added to your system keychain, and they will appear in the Keychain App (see above). For each of those - in the Keychain App - you should right click on the certificate, and select "Export ...", and leave the file format on .p12.
In the export process, you need to choose a password for the exported item (you can use password assistant, by clicking on the key icon).
Please take a note of these password for both certificates (it is recommended to have a different pass for development and distribution).
(In the end, the export process will ask for your system user password as well to finish this process.)

The content of the .p12 files and the associated passwords, should be added to GitHub Secrets, under the following keys:
- APPLE_DEVELOPMENT_SIGNING_CERTIFICATE
- APPLE_DEVELOPMENT_SIGNING_P12_PASSWORD
- APPLE_DISTRIBUTION_SIGNING_CERTIFICATE
- APPLE_DISTRIBUTION_SIGNING_P12_PASSWORD

## Creating an App Store Connect API Key

- Create a new App Store Connect API Key in the [Users and Access page](https://appstoreconnect.apple.com/access/users)

- For more info, go to the [App Store Connect API Docs](https://developer.apple.com/documentation/appstoreconnectapi/creating_api_keys_for_app_store_connect_api)

- Open the `Integrations` tab, select `App Store Connect API`, and create a new "Team Key" using the + button
- Note that if you can't see the App Store Connect API tab, this means you don't have permission yet. Please refer to the docs above to know how to get this permission

- Give your API Key an appropriate role (Account Holder) for the task at hand. You can read more about roles in [Permissions in App Store Connect](https://developer.apple.com/support/roles/)

- Note the Issuer ID as you will need it for the configuration steps below

- Download the newly created API Key file (.p8)
- This file cannot be downloaded again after the page has been refreshed

From this step you will have the values for the following GitHub secret keys:

- APPLE_STORE_AUTH_KEY
- APPLE_STORE_AUTH_KEY_ID
- APPLE_STORE_AUTH_KEY_ISSUER_ID

## Create a Development Signing Identity (optional)

If you whish to have the macOS application distributed outside of the AppStore, it needs to be signed with yet another type of certificate, called Developer Signing Identity.
It can be obtained from App Store Connect with an Account Holder Account here:
https://developer.apple.com/account/resources/certificates/add

Select `Developer ID Application` and proceed.

Once you have the certificate file, it should be exported into a .p12 format, as above (Export those certificates as .p12 files.)

These will be stored under Github Secrets:
- APPLE_DEVELOPER_ID_SIGNING_CERTIFICATE
- APPLE_DEVELOPER_ID_SIGNING_P12_PASSWORD

## Create an app-specific password for notary tool (optional)

If you whish to have the macOS application distributed outside of the AppStore, it needs to verified by Apple, in a process called notarization. For this to happen, you need to provide your App Store Connect credentials (the you use to sign into developer.apple.com). Instead of giving away your very own user name and password, you can create an app-specific password for the notary tool, as described here:
https://support.apple.com/en-us/102654

These also goes to GitHub Secrets:
- APPLE_SIGNING_ALTOOL_USERNAME
- APPLE_SIGNING_ALTOOL_PASSWORD

## ZIM file behind http authentication (optional)
- HTTP_BASIC_ACCESS_AUTHENTICATION - (optional) this is the http basic authentication username:password, it is required to be set if the ZIM file to be downloaded during automated build is behind authentication. This is using the format: "my_user:secret_password".

License
-------

Expand Down
6 changes: 3 additions & 3 deletions dwds/info.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
"about_app_url": "https://www.dwds.de",
"about_text": "Für Schreibende, Lernende, Lehrende und Sprachinteressierte: Das Digitale Wörterbuch der deutschen Sprache (DWDS) ist das große Bedeutungswörterbuch des Deutschen der Gegenwart. Es bietet umfassende und wissenschaftlich verlässliche lexikalische Informationen, kostenlos und werbefrei.",
"app_name": "DWDS",
"app_store_id": "id6473090365",
"development_team": "L7HWM3SP3L",
"app_store_id": "id6741328425",
"development_team": "Q2QUKNPZG9",
"enforced_lang": "de",
"settings_default_external_link_to": "alwaysLoad",
"settings_show_external_link_option": false,
"settings_show_search_snippet": false,
"zim_auth": "DWDS_HTTP_BASIC_ACCESS_AUTHENTICATION",
"zim_auth": "HTTP_BASIC_ACCESS_AUTHENTICATION",
"zim_url": "https://www.dwds.de/kiwix/f/dwds_de_dictionary_nopic_2024-11-15.zim"
}
1 change: 1 addition & 0 deletions src/info_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def __init__(self, json_path, build_number):
self.data[JSON_KEY_ZIM_URL])
self.version = Version.from_file_name(file_name=self.zim_file_name,
build_number=build_number)
self.development_team_id = self._development_team()

def create_plist(self, based_on_plist_file):
with based_on_plist_file.open(mode="rb") as file:
Expand Down
1 change: 1 addition & 0 deletions src/tag_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def _is_valid(tag):
Path('.brand_name').write_text(f"{brand.name}")
Path('.build_number').write_text(f"{version.build_number}")
Path('.version_number').write_text(f"{version.semantic}")
Path('.team_id').write_text(f"{parser.development_team_id}")

# required as an output, we can pipe on:
print(f"{brand.name} {version.build_number}")
Expand Down
2 changes: 1 addition & 1 deletion tests/test.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"settings_default_external_link_to": "alwaysLoad",
"settings_show_search_snippet": false,
"settings_show_external_link_option": false,
"zim_auth": "DWDS_HTTP_BASIC_ACCESS_AUTHENTICATION",
"zim_auth": "HTTP_BASIC_ACCESS_AUTHENTICATION",
"zim_url": "https://www.dwds.de/kiwix/f/dwds_de_dictionary_nopic_2023-12-15.zim",
"build_number": 3
}
2 changes: 1 addition & 1 deletion tests/test_info_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def test_zimfile_path(self):

def test_auth_value(self):
self.assertEqual(self.parser.download_auth(), os.getenv(
"DWDS_HTTP_BASIC_ACCESS_AUTHENTICATION"))
"HTTP_BASIC_ACCESS_AUTHENTICATION"))


if __name__ == '__main__':
Expand Down

0 comments on commit 09c8a38

Please sign in to comment.