Skip to content

Commit 56c24ca

Browse files
AlenaSviridenkolucascostiMartin Lopes
authored
Add page about signing Xcode apps in GitHub Actions (github#18188)
Co-authored-by: Lucas Costi <lucascosti@users.noreply.github.com> Co-authored-by: Martin Lopes <martin389@github.com>
1 parent 1a8ec87 commit 56c24ca

File tree

3 files changed

+139
-1
lines changed

3 files changed

+139
-1
lines changed

content/actions/guides/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ includeGuides:
4242
- /actions/guides/building-and-testing-java-with-maven
4343
- /actions/guides/building-and-testing-java-with-gradle
4444
- /actions/guides/building-and-testing-java-with-ant
45+
- /actions/guides/installing-an-apple-certificate-on-macos-runners-for-xcode-development
4546
- /actions/guides/publishing-nodejs-packages
4647
- /actions/guides/publishing-java-packages-with-maven
4748
- /actions/guides/publishing-java-packages-with-gradle
@@ -81,6 +82,7 @@ includeGuides:
8182
<!-- {% link_in_list /building-and-testing-java-with-maven %} -->
8283
<!-- {% link_in_list /building-and-testing-java-with-gradle %} -->
8384
<!-- {% link_in_list /building-and-testing-java-with-ant %} -->
85+
<!-- {% link_in_list /installing-an-apple-certificate-on-macos-runners-for-xcode-development %} -->
8486
<!-- {% link_in_list /about-packaging-with-github-actions %} -->
8587
<!-- {% link_in_list /publishing-nodejs-packages %} -->
8688
<!-- {% link_in_list /publishing-java-packages-with-maven %} -->
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
---
2+
title: Installing an Apple certificate on macOS runners for Xcode development
3+
intro: 'You can sign Xcode apps within your continuous integration (CI) workflow by installing an Apple code signing certificate on {% data variables.product.prodname_actions %} runners.'
4+
product: '{% data reusables.gated-features.actions %}'
5+
versions:
6+
free-pro-team: '*'
7+
enterprise-server: '>=2.22'
8+
github-ae: '*'
9+
type: 'tutorial'
10+
topics:
11+
- 'CI'
12+
- 'Xcode'
13+
---
14+
15+
{% data reusables.actions.enterprise-beta %}
16+
{% data reusables.actions.enterprise-github-hosted-runners %}
17+
{% data reusables.actions.ae-beta %}
18+
19+
### Introduction
20+
21+
This guide shows you how to add a step to your continuous integration (CI) workflow that installs an Apple code signing certificate and provisioning profile on {% data variables.product.prodname_actions %} runners. This will allow you to sign your Xcode apps for publishing to the Apple App Store, or distributing it to test groups.
22+
23+
### Prerequisites
24+
25+
You should be familiar with YAML and the syntax for {% data variables.product.prodname_actions %}. For more information, see:
26+
27+
- "[Learn {% data variables.product.prodname_actions %}](/actions/learn-github-actions)"
28+
- "[Workflow syntax for {% data variables.product.prodname_actions %}](/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions)"
29+
30+
You should have an understanding of Xcode app building and signing. For more information, see the [Apple developer documentation](https://developer.apple.com/documentation/).
31+
32+
### Creating secrets for your certificate and provisioning profile
33+
34+
The signing process involves storing certificates and provisioning profiles, transferring them to the runner, importing them to the runner's keychain, and using them in your build.
35+
36+
To use your certificate and provisioning profile on a runner, we strongly recommend that you use {% data variables.product.prodname_dotcom %} secrets. For more information on creating secrets and using them in a workflow, see "[Encrypted secrets](/actions/reference/encrypted-secrets)."
37+
38+
Create secrets in your repository or organization for the following items:
39+
40+
* Your Apple signing certificate.
41+
42+
- This is your `p12` certificate file. For more information on exporting your signing certificate from Xcode, see the [Xcode documentation](https://help.apple.com/xcode/mac/current/#/dev154b28f09).
43+
44+
- You should convert your certificate to Base64 when saving it as a secret. In this example, the secret is named `BUILD_CERTIFICATE_BASE64`.
45+
46+
- Use the following command to convert your certificate to Base64 and copy it to your clipboard:
47+
48+
```shell
49+
base64 <em>build_certificate</em>.p12 | pbcopy
50+
```
51+
* The password for your Apple signing certificate.
52+
- In this example, the secret is named `P12_PASSWORD`.
53+
54+
* Your Apple provisioning profile.
55+
56+
- For more information on exporting your provisioning profile from Xcode, see the [Xcode documentation](https://help.apple.com/xcode/mac/current/#/deva899b4fe5).
57+
58+
- You should convert your provisioning profile to Base64 when saving it as a secret. In this example, the secret is named `BUILD_PROVISION_PROFILE_BASE64`.
59+
60+
- Use the following command to convert your provisioning profile to Base64 and copy it to your clipboard:
61+
62+
```shell
63+
base64 <em>provisioning_profile.mobileprovision</em> | pbcopy
64+
```
65+
66+
* A keychain password.
67+
68+
- A new keychain will be created on the runner, so the password for the new keychain can be any new random string. In this example, the secret is named `KEYCHAIN_PASSWORD`.
69+
70+
### Add a step to your workflow
71+
72+
This example workflow includes a step that imports the Apple certificate and provisioning profile from the {% data variables.product.prodname_dotcom %} secrets, and installs them on the runner.
73+
74+
{% raw %}
75+
```yaml{:copy}
76+
name: App build
77+
on: push
78+
79+
jobs:
80+
build_with_signing:
81+
runs-on: macos-latest
82+
83+
steps:
84+
- name: Checkout repository
85+
uses: actions/checkout@v2
86+
- name: Install the Apple certificate and provisioning profile
87+
env:
88+
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
89+
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
90+
BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
91+
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
92+
run: |
93+
# create variables
94+
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
95+
PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
96+
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
97+
98+
# import certificate and provisioning profile from secrets
99+
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode --output $CERTIFICATE_PATH
100+
echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode --output $PP_PATH
101+
102+
# create temporary keychain
103+
security create-keychain -p $KEYCHAIN_PASSWORD $KEYCHAIN_PATH
104+
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
105+
security unlock-keychain -p $KEYCHAIN_PASSWORD $KEYCHAIN_PATH
106+
107+
# import certificate to keychain
108+
security import $CERTIFICATE_PATH -P $P12_PASSWORD -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
109+
security list-keychain -d user -s $KEYCHAIN_PATH
110+
111+
# apply provisioning profile
112+
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
113+
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
114+
- name: Build app
115+
...
116+
```
117+
{% endraw %}
118+
119+
### Required clean-up on self-hosted runners
120+
121+
{% data variables.product.prodname_dotcom %}-hosted runners are isolated virtual machines that are automatically destroyed at the end of the job execution. This means that the certificates and provisioning profile used on the runner during the job will be destroyed with the runner when the job is completed.
122+
123+
On self-hosted runners, the `$RUNNER_TEMP` directory is cleaned up at the end of the job execution, but the keychain and provisioning profile might still exist on the runner.
124+
125+
If you use self-hosted runners, you should add a final step to your workflow to help ensure that these sensitive files are deleted at the end of the job. The workflow step shown below is an example of how to do this.
126+
127+
{% raw %}
128+
```yaml
129+
- name: Clean up keychain and provisioning profile
130+
if: ${{ always() }}
131+
run: |
132+
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
133+
rm ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.mobileprovision
134+
```
135+
{% endraw %}

data/allowed-topics.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,6 @@ module.exports = [
8080
'sso',
8181
'teams',
8282
'usernames',
83-
'webhooks'
83+
'webhooks',
84+
'Xcode'
8485
]

0 commit comments

Comments
 (0)