-
Notifications
You must be signed in to change notification settings - Fork 2
267 lines (231 loc) · 13 KB
/
launchpad_ppa.yml
File metadata and controls
267 lines (231 loc) · 13 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
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# .github/workflows/launchpad_ppa.yml
name: Upload to Launchpad PPA
# ═══════════════════════════════════════════════════════════════
# Workflow Triggers
# ═══════════════════════════════════════════════════════════════
# This workflow runs when:
# 1. Manually triggered via workflow_dispatch
# 2. Called from another workflow
# ───────────────────────────────────────────────────────────────
on:
workflow_dispatch:
inputs:
release_tag:
description: 'Release tag to upload to PPA (e.g. v0.5.0). Empty = latest release'
required: false
distributions:
description: 'Target distributions (comma-separated: jammy,noble,oracular)'
required: false
default: 'jammy,noble'
# Required permissions
permissions:
contents: read
jobs:
# ═══════════════════════════════════════════════════════════════
# Job: Upload to Launchpad PPA
# ═══════════════════════════════════════════════════════════════
# Creates source packages and uploads them to Ubuntu PPA
# ───────────────────────────────────────────────────────────────
upload-ppa:
name: Upload to PPA (${{ matrix.distro }})
runs-on: ubuntu-latest
# Access secrets from "packaging" environment
environment: packaging
strategy:
fail-fast: false
matrix:
distro: [jammy, noble, oracular]
steps:
# ───────────────────────────────────────────────────────────────
# Step 1: Checkout source code
# ───────────────────────────────────────────────────────────────
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for changelog generation
# ───────────────────────────────────────────────────────────────
# Step 2: Check if distribution is requested
# ───────────────────────────────────────────────────────────────
- name: Check distribution
id: check_distro
run: |
DISTRIBUTIONS="${{ github.event.inputs.distributions }}"
if [[ ",$DISTRIBUTIONS," == *",${{ matrix.distro }},"* ]]; then
echo "should_run=true" >> "$GITHUB_OUTPUT"
else
echo "should_run=false" >> "$GITHUB_OUTPUT"
echo "Skipping ${{ matrix.distro }} - not in requested distributions"
fi
# ───────────────────────────────────────────────────────────────
# Step 3: Determine release tag
# ───────────────────────────────────────────────────────────────
- name: Get release tag
if: steps.check_distro.outputs.should_run == 'true'
id: get_tag
run: |
if [ -n "${{ github.event.inputs.release_tag }}" ]; then
echo "tag=${{ github.event.inputs.release_tag }}" >> "$GITHUB_OUTPUT"
else
# Get the latest release tag
TAG=$(gh release list --limit 1 --json tagName -q '.[0].tagName')
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
fi
env:
GH_TOKEN: ${{ github.token }}
# ───────────────────────────────────────────────────────────────
# Step 4: Update changelog with auto-increment
# ───────────────────────────────────────────────────────────────
- name: Update debian/changelog from release
if: steps.check_distro.outputs.should_run == 'true'
run: |
# Install curl for the version check script
sudo apt-get update && sudo apt-get install -y curl
# Update changelog with auto-increment flag
bash ./debian/update-changelog.sh \
-d ${{ matrix.distro }} \
-p lablup/backend-ai \
--auto-increment \
${{ steps.get_tag.outputs.tag }}
env:
GH_TOKEN: ${{ github.token }}
# ───────────────────────────────────────────────────────────────
# Step 5: Install build dependencies
# ───────────────────────────────────────────────────────────────
- name: Install build dependencies
if: steps.check_distro.outputs.should_run == 'true'
run: |
sudo apt update
sudo apt install -y \
devscripts \
debhelper \
dh-make \
fakeroot \
dput \
gpg \
dpkg-dev \
build-essential
# ───────────────────────────────────────────────────────────────────
# Step 6: Prepare package version
# ───────────────────────────────────────────────────────────────
- name: Prepare package version
if: steps.check_distro.outputs.should_run == 'true'
run: |
# Get version from release tag (remove 'v' prefix)
VERSION="${{ steps.get_tag.outputs.tag }}"
VERSION="${VERSION#v}"
echo "PACKAGE_VERSION=${VERSION}" >> "$GITHUB_ENV"
# Get the actual version from changelog (with auto-increment)
CHANGELOG_VERSION=$(head -n 1 debian/changelog | awk '{print $2}' | tr -d '()')
echo "FULL_PACKAGE_VERSION=${CHANGELOG_VERSION}" >> "$GITHUB_ENV"
echo "Package version: ${CHANGELOG_VERSION}"
# Verify changelog contains the base version
head -n 1 debian/changelog | grep -q "${VERSION}-" || {
echo "Error: Changelog doesn't contain expected version ${VERSION}"
exit 1
}
# ───────────────────────────────────────────────────────────────
# Step 7: Import GPG signing key
# ───────────────────────────────────────────────────────────────
- name: Import GPG key
if: steps.check_distro.outputs.should_run == 'true'
run: |
# Import the GPG key
echo "${{ secrets.GPG_PRIVATE_KEY }}" | gpg --batch --import
# List the imported key to verify
gpg --list-secret-keys --keyid-format LONG
# Get the full fingerprint for the key
FINGERPRINT=$(gpg --list-secret-keys --with-colons | grep '^fpr:' | head -1 | cut -d: -f10)
echo "Key fingerprint: $FINGERPRINT"
echo "GPG_FINGERPRINT=$FINGERPRINT" >> "$GITHUB_ENV"
# Trust the key using the full fingerprint
echo "${FINGERPRINT}:6:" | gpg --import-ownertrust
# ───────────────────────────────────────────────────────────────
# Step 8: Configure GPG for non-interactive signing
# ───────────────────────────────────────────────────────────────
- name: Configure GPG
if: steps.check_distro.outputs.should_run == 'true'
run: |
export GNUPGHOME=/home/runner/.gnupg
mkdir -p $GNUPGHOME
chmod 700 $GNUPGHOME
# Configure gpg-agent for batch mode
cat > $GNUPGHOME/gpg-agent.conf << 'EOF'
allow-loopback-pinentry
default-cache-ttl 300
max-cache-ttl 3600
EOF
# Configure gpg for batch mode
cat > $GNUPGHOME/gpg.conf << 'EOF'
use-agent
pinentry-mode loopback
batch
no-tty
EOF
# Set up passphrase for signing
if [ -n "${{ secrets.GPG_PASSPHRASE }}" ]; then
echo "${{ secrets.GPG_PASSPHRASE }}" > $GNUPGHOME/passphrase
chmod 600 $GNUPGHOME/passphrase
fi
# Restart gpg-agent with new config
gpgconf --kill gpg-agent || true
# ───────────────────────────────────────────────────────────────
# Step 9: Build source package
# ───────────────────────────────────────────────────────────────
- name: Build source package
if: steps.check_distro.outputs.should_run == 'true'
run: |
# Clean any build artifacts
rm -f bssh
rm -rf target/
# Ensure Architecture field is 'any' for source package
sed -i 's/Architecture: .*/Architecture: any/' debian/control
# Ensure debian/rules has proper permissions
chmod +x debian/rules
# Configure environment for signing
export GNUPGHOME=/home/runner/.gnupg
# Build and sign source package in one step
if [ -n "${{ secrets.GPG_PASSPHRASE }}" ]; then
echo "Building and signing source package with passphrase..."
# Create a script to handle GPG signing with passphrase
cat > /tmp/gpg-sign.sh << 'EOSCRIPT'
#!/bin/bash
echo "$GPG_PASSPHRASE" | gpg --batch --yes --passphrase-fd 0 --pinentry-mode loopback "$@"
EOSCRIPT
chmod +x /tmp/gpg-sign.sh
# Export passphrase for the script
export GPG_PASSPHRASE="${{ secrets.GPG_PASSPHRASE }}"
# Build with custom gpg command
dpkg-buildpackage -S -sa -k"$GPG_FINGERPRINT" -d \
--sign-command="/tmp/gpg-sign.sh"
else
echo "Building and signing source package without passphrase..."
dpkg-buildpackage -S -sa -k"$GPG_FINGERPRINT" -d
fi
echo "Source package built and signed successfully"
# ───────────────────────────────────────────────────────────────
# Step 10: Upload to PPA
# ───────────────────────────────────────────────────────────────
- name: Upload to Ubuntu PPA
if: steps.check_distro.outputs.should_run == 'true'
run: |
# Configure dput for PPA upload
cat > ~/.dput.cf << 'EOF'
[backend-ai-ppa]
fqdn = ppa.launchpad.net
method = ftp
incoming = ~lablup/ubuntu/backend-ai/
login = anonymous
allow_unsigned_uploads = 0
EOF
# Verify the .changes file exists
CHANGES_FILE=$(ls ../*_source.changes 2>/dev/null | head -1)
if [ -z "$CHANGES_FILE" ]; then
echo "Error: No source .changes file found"
exit 1
fi
echo "Uploading $CHANGES_FILE to PPA lablup/backend-ai"
# Upload source package to PPA
dput backend-ai-ppa "$CHANGES_FILE"
echo "✅ Successfully uploaded to PPA"
echo "📦 Version: $FULL_PACKAGE_VERSION"
echo "📦 Package will be available at: https://launchpad.net/~lablup/+archive/ubuntu/backend-ai"