|
1 | 1 | name: Build Mac installer |
2 | | - |
3 | 2 | on: |
4 | 3 | workflow_dispatch: |
5 | 4 | # Inputs the workflow accepts. |
|
46 | 45 | dmg-file-name: |
47 | 46 | description: "DMG file name" |
48 | 47 | value: ${{ jobs.build_dmg.outputs.dmg-file-name }} |
49 | | - |
50 | 48 | jobs: |
51 | 49 | build_dmg: |
52 | 50 | # This seems to be the only way to specify an intel based runner |
53 | 51 | runs-on: macos-15-intel |
54 | 52 | outputs: |
55 | 53 | dmg-file-name: ${{ steps.get-dmg-filename.outputs.dmg-file-name }} |
56 | 54 | env: |
57 | | - # We need the official Python, because the GA ones only support newer macOS versions |
58 | | - # The deployment target is picked up by the Python build tools automatically |
59 | | - PYTHON_VERSION: "3.10.10" |
60 | | - MACOSX_DEPLOYMENT_TARGET: "10.9" |
| 55 | + MACOSX_DEPLOYMENT_TARGET: "12.0" |
61 | 56 | steps: |
62 | | - - name: Validate whl reference inputs |
63 | | - if: ${{ (inputs.whl-file-name && inputs.whl-url) || (!inputs.whl-file-name && !inputs.whl-url) }} |
64 | | - run: | |
65 | | - echo "Must specify exactly one reference for the whl file to build the DMG with." |
66 | | - exit 1 |
67 | | - - uses: actions/checkout@v6 |
68 | | - if: ${{ !inputs.ref }} |
69 | | - - uses: actions/checkout@v6 |
70 | | - if: ${{ inputs.ref }} |
71 | | - with: |
72 | | - repository: learningequality/kolibri-app |
73 | | - ref: ${{ inputs.ref }} |
74 | | - - name: Cache Python download |
75 | | - id: cache-python-download |
76 | | - uses: actions/cache@v5 |
77 | | - with: |
78 | | - path: ~/python.pkg |
79 | | - key: macOS-Python-${{ env.PYTHON_VERSION }} |
80 | | - - name: Download Python ${{ env.PYTHON_VERSION }} |
81 | | - if: steps.cache-python-download.outputs.cache-hit != 'true' |
82 | | - run: curl https://www.python.org/ftp/python/${PYTHON_VERSION}/python-${PYTHON_VERSION}-macos11.pkg -o ~/python.pkg |
83 | | - - name: Install Python 3.10 |
84 | | - run: | |
85 | | - sudo installer -pkg ~/python.pkg -target / |
86 | | - unlink /usr/local/bin/python || true |
87 | | - unlink /usr/local/bin/pip || true |
88 | | - unlink /usr/local/bin/pip3 || true |
89 | | - ln -s /usr/local/bin/python3 /usr/local/bin/python |
90 | | - ln -s /Library/Frameworks/Python.framework/Versions/3.10/bin/pip3 /usr/local/bin/pip |
91 | | - - uses: actions/cache@v5 |
92 | | - with: |
93 | | - path: ~/Library/Caches/pip |
94 | | - key: ${{ runner.os }}-pip-${{ hashFiles('setup.py', 'build_requires.txt', '.github/workflows/build_mac.yml') }} |
95 | | - restore-keys: | |
96 | | - ${{ runner.os }}-pip- |
97 | | - - name: Install dependencies |
98 | | - run: make dependencies |
99 | | - - name: Download the whlfile from URL and install |
100 | | - if: ${{ inputs.whl-url }} |
101 | | - run: make get-whl whl=${{ inputs.whl-url }} |
102 | | - - name: Download the whlfile from artifacts |
103 | | - if: ${{ inputs.whl-file-name }} |
104 | | - uses: actions/download-artifact@v8 |
105 | | - with: |
106 | | - name: ${{ inputs.whl-file-name }} |
107 | | - path: whl |
108 | | - - name: Install WHL file from artifacts |
109 | | - if: ${{ inputs.whl-file-name }} |
110 | | - run: make install-whl whl=whl/${{ inputs.whl-file-name }} |
111 | | - - name: Setup app signing certificate |
112 | | - if: ${{ inputs.release }} |
113 | | - env: |
114 | | - KEYCHAIN_PASSWORD: ${{ hashFiles('*')}} |
115 | | - run: | |
116 | | - security create-keychain -p "$KEYCHAIN_PASSWORD" temp.keychain |
117 | | - security set-keychain-settings -lut 21600 temp.keychain |
118 | | - security unlock-keychain -p "$KEYCHAIN_PASSWORD" temp.keychain |
119 | | - echo -n "${{ secrets.KOLIBRI_MAC_APP_CERTIFICATE }}" | base64 --decode --output=certificate.p12 |
120 | | - # -A option allows any application to read keys. |
121 | | - # This would be insecure if the keychain was retained but GitHub action |
122 | | - # VMs are thrown away after use. |
123 | | - security import certificate.p12 -k temp.keychain -f pkcs12 -A -T '/usr/bin/codesign' -T '/usr/bin/security' -P "${{ secrets.KOLIBRI_MAC_APP_CERTIFICATE_PASSWORD }}" |
124 | | - security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" temp.keychain |
125 | | - security list-keychains -d user -s temp.keychain login.keychain |
126 | | - - name: Build the app |
127 | | - run: make build-mac-app |
128 | | - - name: Codesign the app |
129 | | - if: ${{ inputs.release }} |
130 | | - run: MAC_CODESIGN_IDENTITY="${{ secrets.KOLIBRI_MAC_APP_IDENTITY }}" make codesign-mac-app |
131 | | - - name: Build the DMG |
132 | | - run: make build-dmg |
133 | | - - name: Codesign the DMG |
134 | | - if: ${{ inputs.release }} |
135 | | - run: MAC_CODESIGN_IDENTITY="${{ secrets.KOLIBRI_MAC_APP_IDENTITY }}" make codesign-dmg |
136 | | - - name: Notarize the DMG |
137 | | - if: ${{ inputs.release }} |
138 | | - env: |
139 | | - MAC_NOTARIZE_USERNAME: ${{ secrets.KOLIBRI_MAC_APP_USERNAME }} |
140 | | - MAC_NOTARIZE_PASSWORD: ${{ secrets.KOLIBRI_MAC_APP_PASSWORD }} |
141 | | - MAC_NOTARIZE_TEAM_ID: ${{ secrets.KOLIBRI_MAC_APP_TEAM_ID }} |
142 | | - run: make notarize-dmg |
143 | | - - name: Get DMG filename |
144 | | - id: get-dmg-filename |
145 | | - run: echo "dmg-file-name=$(ls dist | grep .dmg | cat)" >> $GITHUB_OUTPUT |
146 | | - - uses: actions/upload-artifact@v7 |
147 | | - with: |
148 | | - name: ${{ steps.get-dmg-filename.outputs.dmg-file-name }} |
149 | | - path: dist/${{ steps.get-dmg-filename.outputs.dmg-file-name }} |
| 57 | + - name: Validate whl reference inputs |
| 58 | + if: ${{ (inputs.whl-file-name && inputs.whl-url) || (!inputs.whl-file-name && !inputs.whl-url) }} |
| 59 | + run: | |
| 60 | + echo "Must specify exactly one reference for the whl file to build the DMG with." |
| 61 | + exit 1 |
| 62 | + - uses: actions/checkout@v6 |
| 63 | + if: ${{ !inputs.ref }} |
| 64 | + with: |
| 65 | + fetch-depth: 0 |
| 66 | + - uses: actions/checkout@v6 |
| 67 | + if: ${{ inputs.ref }} |
| 68 | + with: |
| 69 | + repository: learningequality/kolibri-app |
| 70 | + ref: ${{ inputs.ref }} |
| 71 | + fetch-depth: 0 |
| 72 | + - uses: astral-sh/setup-uv@v7 |
| 73 | + with: |
| 74 | + enable-cache: true |
| 75 | + cache-python: true |
| 76 | + python-version: "3.10" |
| 77 | + cache-dependency-path: uv.lock |
| 78 | + - name: Install dependencies |
| 79 | + run: make dependencies |
| 80 | + - name: Download the whlfile from URL and install |
| 81 | + if: ${{ inputs.whl-url }} |
| 82 | + run: make get-whl whl=${{ inputs.whl-url }} |
| 83 | + - name: Download the whlfile from artifacts |
| 84 | + if: ${{ inputs.whl-file-name }} |
| 85 | + uses: actions/download-artifact@v8 |
| 86 | + with: |
| 87 | + name: ${{ inputs.whl-file-name }} |
| 88 | + path: whl |
| 89 | + - name: Install WHL file from artifacts |
| 90 | + if: ${{ inputs.whl-file-name }} |
| 91 | + run: make install-whl whl=whl/${{ inputs.whl-file-name }} |
| 92 | + - name: Setup app signing certificate |
| 93 | + if: ${{ inputs.release }} |
| 94 | + env: |
| 95 | + KEYCHAIN_PASSWORD: ${{ hashFiles('*')}} |
| 96 | + run: | |
| 97 | + security create-keychain -p "$KEYCHAIN_PASSWORD" temp.keychain |
| 98 | + security set-keychain-settings -lut 21600 temp.keychain |
| 99 | + security unlock-keychain -p "$KEYCHAIN_PASSWORD" temp.keychain |
| 100 | + echo -n "${{ secrets.KOLIBRI_MAC_APP_CERTIFICATE }}" | base64 --decode --output=certificate.p12 |
| 101 | + # -A option allows any application to read keys. |
| 102 | + # This would be insecure if the keychain was retained but GitHub action |
| 103 | + # VMs are thrown away after use. |
| 104 | + security import certificate.p12 -k temp.keychain -f pkcs12 -A -T '/usr/bin/codesign' -T '/usr/bin/security' -P "${{ secrets.KOLIBRI_MAC_APP_CERTIFICATE_PASSWORD }}" |
| 105 | + security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" temp.keychain |
| 106 | + security list-keychains -d user -s temp.keychain login.keychain |
| 107 | + - name: Build the app |
| 108 | + run: make build-mac-app |
| 109 | + - name: Codesign the app |
| 110 | + if: ${{ inputs.release }} |
| 111 | + run: MAC_CODESIGN_IDENTITY="${{ secrets.KOLIBRI_MAC_APP_IDENTITY }}" make codesign-mac-app |
| 112 | + - name: Build the DMG |
| 113 | + run: make build-dmg |
| 114 | + - name: Codesign the DMG |
| 115 | + if: ${{ inputs.release }} |
| 116 | + run: MAC_CODESIGN_IDENTITY="${{ secrets.KOLIBRI_MAC_APP_IDENTITY }}" make codesign-dmg |
| 117 | + - name: Notarize the DMG |
| 118 | + if: ${{ inputs.release }} |
| 119 | + env: |
| 120 | + MAC_NOTARIZE_USERNAME: ${{ secrets.KOLIBRI_MAC_APP_USERNAME }} |
| 121 | + MAC_NOTARIZE_PASSWORD: ${{ secrets.KOLIBRI_MAC_APP_PASSWORD }} |
| 122 | + MAC_NOTARIZE_TEAM_ID: ${{ secrets.KOLIBRI_MAC_APP_TEAM_ID }} |
| 123 | + run: make notarize-dmg |
| 124 | + - name: Get DMG filename |
| 125 | + id: get-dmg-filename |
| 126 | + run: | |
| 127 | + shopt -s nullglob |
| 128 | + dmgs=(dist/*.dmg) |
| 129 | + if [[ ${#dmgs[@]} -eq 0 ]]; then |
| 130 | + echo "No DMG found in dist/" >&2 |
| 131 | + exit 1 |
| 132 | + fi |
| 133 | + echo "dmg-file-name=$(basename "${dmgs[0]}")" >> "$GITHUB_OUTPUT" |
| 134 | + - uses: actions/upload-artifact@v7 |
| 135 | + with: |
| 136 | + name: ${{ steps.get-dmg-filename.outputs.dmg-file-name }} |
| 137 | + path: dist/${{ steps.get-dmg-filename.outputs.dmg-file-name }} |
0 commit comments