-
Notifications
You must be signed in to change notification settings - Fork 1
241 lines (211 loc) · 8 KB
/
upstream-release.yml
File metadata and controls
241 lines (211 loc) · 8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
name: Build macOS DMG from Upstream Release
on:
schedule:
# Check every 6 hours for new upstream tags
- cron: '0 */6 * * *'
workflow_dispatch:
inputs:
tag:
description: 'Upstream i2p/i2p.i2p tag (e.g., i2p-2.10.0 or 2.10.0-3)'
required: true
type: string
force:
description: 'Force rebuild even if release exists'
required: false
type: boolean
default: false
permissions:
contents: write
jobs:
check-upstream:
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.resolve.outputs.tag }}
version: ${{ steps.resolve.outputs.version }}
should_build: ${{ steps.resolve.outputs.should_build }}
steps:
- name: Resolve upstream tag
id: resolve
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
TAG="${{ inputs.tag }}"
FORCE="${{ inputs.force }}"
else
# Fetch all release tags from upstream (both i2p-X.Y.Z and X.Y.Z-N formats)
TAG=$(git ls-remote --tags https://github.com/i2p/i2p.i2p.git \
| grep -v '\^{}' \
| sed 's|.*refs/tags/||' \
| grep -vE '(cvs|_|post|rc)' \
| grep -E '^(i2p-)?[0-9]+\.[0-9]+\.[0-9]+' \
| awk '{orig=$0; gsub(/^i2p-/, ""); print $0"|"orig}' \
| sort -t'|' -k1 -V \
| tail -1 \
| cut -d'|' -f2)
FORCE="false"
fi
if [ -z "$TAG" ]; then
echo "No valid upstream tag found"
echo "should_build=false" >> "$GITHUB_OUTPUT"
exit 0
fi
# Strip i2p- prefix for version number
VERSION=$(echo "$TAG" | sed 's/^i2p-//')
echo "Found tag: $TAG (version: $VERSION)"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
if [ "$FORCE" = "true" ]; then
echo "Force build requested"
echo "should_build=true" >> "$GITHUB_OUTPUT"
elif gh release view "i2p-mac-${VERSION}" \
--repo "${{ github.repository }}" > /dev/null 2>&1; then
echo "Release i2p-mac-${VERSION} already exists, skipping"
echo "should_build=false" >> "$GITHUB_OUTPUT"
else
echo "New version detected, will build"
echo "should_build=true" >> "$GITHUB_OUTPUT"
fi
build-sign-notarize:
needs: check-upstream
if: needs.check-upstream.outputs.should_build == 'true'
runs-on: [self-hosted, macOS]
timeout-minutes: 120
env:
I2P_VERSION: ${{ needs.check-upstream.outputs.tag }}
PUBLISH_VERSION: ${{ needs.check-upstream.outputs.version }}
I2P_SIGNER_USERPHRASE: ${{ secrets.APPLE_SIGNING_IDENTITY }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Configure git for CI
run: |
git config --global user.name "GitHub Actions"
git config --global user.email "actions@github.com"
- name: Unlock keychain
env:
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
security unlock-keychain -p "$KEYCHAIN_PASSWORD" ~/Library/Keychains/login.keychain-db
security set-keychain-settings -t 7200 ~/Library/Keychains/login.keychain-db
echo "Available signing identities:"
security find-identity -v -p codesigning
- name: Set up JDK and build dependencies
run: |
brew install ant create-dmg 2>/dev/null || true
export JAVA_HOME=/opt/homebrew/opt/openjdk@21/libexec/openjdk.jdk/Contents/Home
echo "JAVA_HOME=$JAVA_HOME" >> "$GITHUB_ENV"
echo "$JAVA_HOME/bin" >> "$GITHUB_PATH"
echo "/opt/homebrew/bin" >> "$GITHUB_PATH"
$JAVA_HOME/bin/java -version
ant -version
- name: Build I2P macOS DMG
run: ./build.sh
- name: Notarize DMG
run: |
DMG="I2P-${PUBLISH_VERSION}.dmg"
echo "Submitting $DMG for notarization..."
xcrun notarytool submit "$DMG" --keychain-profile "i2p-notary" --wait
echo "Notarization complete"
- name: Staple notarization ticket
run: |
DMG="I2P-${PUBLISH_VERSION}.dmg"
xcrun stapler staple "$DMG"
- name: Import GPG key
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
run: |
echo "$GPG_PRIVATE_KEY" | gpg --batch --import
- name: Generate GPG signature
env:
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
DMG="I2P-${PUBLISH_VERSION}.dmg"
gpg --batch --yes --pinentry-mode loopback \
--passphrase "$GPG_PASSPHRASE" \
--detach-sign --armor \
-o "${DMG}.sig" "$DMG"
- name: Generate checksum
run: |
DMG="I2P-${PUBLISH_VERSION}.dmg"
shasum -a 256 "$DMG" | tee "${DMG}.sha256"
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: i2p-macos-${{ needs.check-upstream.outputs.version }}
path: |
I2P-${{ needs.check-upstream.outputs.version }}.dmg
I2P-${{ needs.check-upstream.outputs.version }}.dmg.sig
I2P-${{ needs.check-upstream.outputs.version }}.dmg.sha256
- name: Cleanup
if: always()
run: |
rm -rf build/ I2P.app/ i2p.i2p-jpackage-mac/
rm -f i2p.i2p.jpackage-mac.tar.gz
rm -f *.dmg *.sig *.sha256
gpg --batch --yes --delete-secret-and-public-keys \
$(gpg --list-secret-keys --keyid-format long 2>/dev/null \
| grep sec | head -1 | awk '{print $2}' \
| cut -d'/' -f2) 2>/dev/null || true
release:
needs: [check-upstream, build-sign-notarize]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
sparse-checkout: |
README.md
sparse-checkout-cone-mode: false
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: i2p-macos-${{ needs.check-upstream.outputs.version }}
path: artifacts/
- name: Create release on this repo
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ needs.check-upstream.outputs.version }}
UPSTREAM_TAG: ${{ needs.check-upstream.outputs.tag }}
run: |
TAG="i2p-mac-${VERSION}"
DMG="artifacts/I2P-${VERSION}.dmg"
SIG="artifacts/I2P-${VERSION}.dmg.sig"
SHA="artifacts/I2P-${VERSION}.dmg.sha256"
CHECKSUM=$(cat "$SHA")
cat > /tmp/release-notes.md <<EOF
## I2P macOS ${VERSION}
Built from upstream tag: \`${UPSTREAM_TAG}\`
Signed with Developer ID and Apple Notarized.
### Checksums
\`\`\`
${CHECKSUM}
\`\`\`
### Verification
\`\`\`bash
# Verify GPG signature
gpg --verify I2P-${VERSION}.dmg.sig I2P-${VERSION}.dmg
# Verify notarization (mount DMG first)
spctl -a -v /Volumes/I2P/I2P.app
\`\`\`
EOF
# Remove leading whitespace from heredoc
sed -i 's/^ //' /tmp/release-notes.md
gh release create "$TAG" \
--title "I2P macOS ${VERSION}" \
--notes-file /tmp/release-notes.md \
"$DMG" "$SIG" "$SHA"
echo "Release created: $TAG"
- name: Upload to upstream i2p/i2p.i2p release
env:
GH_TOKEN: ${{ secrets.UPSTREAM_RELEASE_TOKEN }}
run: |
VERSION="${{ needs.check-upstream.outputs.version }}"
TAG="${{ needs.check-upstream.outputs.tag }}"
DMG="artifacts/I2P-${VERSION}.dmg"
SIG="artifacts/I2P-${VERSION}.dmg.sig"
gh release upload "$TAG" "$DMG" "$SIG" \
--repo i2p/i2p.i2p \
--clobber || echo "Warning: Could not upload to upstream release"