Skip to content

Commit f84881a

Browse files
committed
COPR builds for packages
1 parent 5e18a6b commit f84881a

1 file changed

Lines changed: 298 additions & 0 deletions

File tree

Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
# Build COPR packages when package specs change
2+
# Triggers builds in dependency order based on packages/README.md
3+
4+
name: Build COPR Packages
5+
6+
concurrency:
7+
group: ${{ github.workflow }}-${{ github.ref }}
8+
cancel-in-progress: false # Don't cancel - we need to cleanup COPR builds properly
9+
10+
on:
11+
push:
12+
branches:
13+
- main
14+
paths:
15+
- 'packages/**'
16+
- '.github/workflows/build-copr-packages.yml'
17+
workflow_dispatch:
18+
inputs:
19+
packages:
20+
description: 'Comma-separated list of packages to build (empty = auto-detect from changes)'
21+
required: false
22+
type: string
23+
rebuild_all:
24+
description: 'Rebuild all packages in dependency order'
25+
required: false
26+
type: boolean
27+
default: false
28+
29+
env:
30+
COPR_PROJECT: binarypie/hypercube
31+
32+
jobs:
33+
detect-changes:
34+
runs-on: ubuntu-latest
35+
outputs:
36+
packages: ${{ steps.detect.outputs.packages }}
37+
matrix: ${{ steps.build-matrix.outputs.matrix }}
38+
steps:
39+
- name: Checkout repository
40+
uses: actions/checkout@v6
41+
with:
42+
fetch-depth: 2
43+
44+
- name: Detect changed packages
45+
id: detect
46+
run: |
47+
# Define all packages and their dependencies
48+
declare -A DEPS
49+
DEPS[hyprutils]=""
50+
DEPS[hyprwayland-scanner]=""
51+
DEPS[hyprland-protocols]=""
52+
DEPS[glaze]=""
53+
DEPS[uwsm]=""
54+
DEPS[eza]=""
55+
DEPS[starship]=""
56+
DEPS[lazygit]=""
57+
DEPS[quickshell]=""
58+
DEPS[livesys-scripts]=""
59+
DEPS[wifitui]=""
60+
DEPS[regreet]=""
61+
DEPS[hyprlang]="hyprutils"
62+
DEPS[hyprgraphics]="hyprutils"
63+
DEPS[aquamarine]="hyprutils hyprwayland-scanner"
64+
DEPS[hyprcursor]="hyprlang"
65+
DEPS[hyprland-qt-support]="hyprlang"
66+
DEPS[hyprland]="aquamarine hyprcursor hyprgraphics hyprlang hyprutils glaze"
67+
DEPS[hyprlock]="hyprgraphics hyprlang hyprutils hyprwayland-scanner"
68+
DEPS[hypridle]="hyprland-protocols hyprlang hyprutils hyprwayland-scanner"
69+
DEPS[hyprpaper]="hyprgraphics hyprlang hyprutils hyprwayland-scanner"
70+
DEPS[xdg-desktop-portal-hyprland]="hyprland-protocols hyprlang hyprutils hyprwayland-scanner"
71+
DEPS[hyprpolkitagent]="hyprutils hyprland-qt-support"
72+
DEPS[hyprtoolkit]="aquamarine hyprgraphics hyprlang hyprutils hyprwayland-scanner"
73+
DEPS[hyprland-guiutils]="aquamarine hyprtoolkit hyprlang hyprutils"
74+
75+
# Define batch order (packages in same batch can build in parallel)
76+
BATCH1="hyprutils hyprwayland-scanner hyprland-protocols glaze uwsm eza starship lazygit quickshell livesys-scripts wifitui regreet"
77+
BATCH2="hyprlang hyprgraphics aquamarine"
78+
BATCH3="hyprcursor hyprland-qt-support"
79+
BATCH4="hyprland hyprlock hypridle hyprpaper xdg-desktop-portal-hyprland hyprpolkitagent hyprtoolkit"
80+
BATCH5="hyprland-guiutils"
81+
82+
# Function to get all downstream dependents of a package
83+
get_dependents() {
84+
local pkg=$1
85+
local dependents=""
86+
for p in "${!DEPS[@]}"; do
87+
if [[ " ${DEPS[$p]} " == *" $pkg "* ]]; then
88+
dependents="$dependents $p"
89+
# Recursively get dependents of dependents
90+
dependents="$dependents $(get_dependents $p)"
91+
fi
92+
done
93+
echo "$dependents"
94+
}
95+
96+
# Determine which packages to build
97+
if [[ "${{ inputs.rebuild_all }}" == "true" ]]; then
98+
echo "Rebuilding all packages..."
99+
CHANGED_PKGS="${!DEPS[*]}"
100+
elif [[ -n "${{ inputs.packages }}" ]]; then
101+
echo "Using manually specified packages..."
102+
CHANGED_PKGS=$(echo "${{ inputs.packages }}" | tr ',' ' ')
103+
else
104+
echo "Detecting changed packages..."
105+
CHANGED_PKGS=""
106+
for dir in packages/*/; do
107+
pkg=$(basename "$dir")
108+
if [[ "$pkg" != "README.md" ]]; then
109+
if git diff --name-only HEAD~1 HEAD | grep -q "^packages/$pkg/"; then
110+
CHANGED_PKGS="$CHANGED_PKGS $pkg"
111+
fi
112+
fi
113+
done
114+
fi
115+
116+
echo "Initially changed packages: $CHANGED_PKGS"
117+
118+
# Add all downstream dependents
119+
TO_BUILD="$CHANGED_PKGS"
120+
for pkg in $CHANGED_PKGS; do
121+
dependents=$(get_dependents "$pkg")
122+
TO_BUILD="$TO_BUILD $dependents"
123+
done
124+
125+
# Deduplicate
126+
TO_BUILD=$(echo "$TO_BUILD" | tr ' ' '\n' | sort -u | tr '\n' ' ')
127+
echo "Packages to build (including dependents): $TO_BUILD"
128+
129+
# Output as JSON array
130+
if [[ -z "$(echo $TO_BUILD | tr -d ' ')" ]]; then
131+
echo "packages=[]" >> $GITHUB_OUTPUT
132+
else
133+
JSON=$(echo "$TO_BUILD" | tr -s ' ' '\n' | grep -v '^$' | jq -R . | jq -s .)
134+
echo "packages=$JSON" >> $GITHUB_OUTPUT
135+
fi
136+
137+
- name: Build batch matrix
138+
id: build-matrix
139+
run: |
140+
PACKAGES='${{ steps.detect.outputs.packages }}'
141+
142+
if [[ "$PACKAGES" == "[]" ]]; then
143+
echo "matrix={\"batch\":[]}" >> $GITHUB_OUTPUT
144+
exit 0
145+
fi
146+
147+
# Define batches with their packages
148+
cat > /tmp/batches.json << 'EOF'
149+
{
150+
"batch": [
151+
{"id": 1, "packages": ["hyprutils", "hyprwayland-scanner", "hyprland-protocols", "glaze", "uwsm", "eza", "starship", "lazygit", "quickshell", "livesys-scripts", "wifitui", "regreet"]},
152+
{"id": 2, "packages": ["hyprlang", "hyprgraphics", "aquamarine"]},
153+
{"id": 3, "packages": ["hyprcursor", "hyprland-qt-support"]},
154+
{"id": 4, "packages": ["hyprland", "hyprlock", "hypridle", "hyprpaper", "xdg-desktop-portal-hyprland", "hyprpolkitagent", "hyprtoolkit"]},
155+
{"id": 5, "packages": ["hyprland-guiutils"]}
156+
]
157+
}
158+
EOF
159+
160+
# Filter batches to only include packages that need building
161+
FILTERED=$(jq --argjson pkgs "$PACKAGES" '
162+
.batch | map(
163+
.packages = (.packages | map(select(. as $p | $pkgs | index($p))))
164+
| select(.packages | length > 0)
165+
) | {batch: .}
166+
' /tmp/batches.json)
167+
168+
echo "matrix=$FILTERED" >> $GITHUB_OUTPUT
169+
echo "Build matrix:"
170+
echo "$FILTERED" | jq .
171+
172+
build-batch:
173+
needs: detect-changes
174+
if: ${{ needs.detect-changes.outputs.matrix != '{"batch":[]}' && needs.detect-changes.outputs.matrix != '' }}
175+
runs-on: ubuntu-latest
176+
strategy:
177+
max-parallel: 1 # Run batches sequentially
178+
fail-fast: false
179+
matrix: ${{ fromJson(needs.detect-changes.outputs.matrix) }}
180+
steps:
181+
- name: Checkout repository
182+
uses: actions/checkout@v6
183+
184+
- name: Install COPR CLI
185+
run: |
186+
sudo apt-get update
187+
sudo apt-get install -y python3-pip
188+
pip3 install copr-cli
189+
190+
- name: Configure COPR CLI
191+
run: |
192+
mkdir -p ~/.config
193+
cat > ~/.config/copr << EOF
194+
[copr-cli]
195+
login = ${{ secrets.COPR_API_LOGIN }}
196+
username = binarypie
197+
token = ${{ secrets.COPR_API_TOKEN }}
198+
copr_url = https://copr.fedorainfracloud.org
199+
EOF
200+
201+
- name: Build batch ${{ matrix.batch.id }} packages
202+
id: build
203+
run: |
204+
echo "Building batch ${{ matrix.batch.id }}: ${{ join(matrix.batch.packages, ', ') }}"
205+
206+
FAILED=""
207+
BUILD_IDS=""
208+
209+
# Trigger all builds in this batch
210+
for pkg in ${{ join(matrix.batch.packages, ' ') }}; do
211+
echo ""
212+
echo "========================================"
213+
echo "Triggering build for: $pkg"
214+
echo "========================================"
215+
216+
# Trigger SCM build
217+
BUILD_OUTPUT=$(copr-cli build-package \
218+
--name "$pkg" \
219+
"${{ env.COPR_PROJECT }}" 2>&1) || {
220+
echo "::error::Failed to trigger build for $pkg"
221+
echo "$BUILD_OUTPUT"
222+
FAILED="$FAILED $pkg"
223+
continue
224+
}
225+
226+
echo "$BUILD_OUTPUT"
227+
228+
# Extract build ID
229+
BUILD_ID=$(echo "$BUILD_OUTPUT" | grep -oP 'Build was added to .+builds/\K\d+' || echo "")
230+
if [[ -n "$BUILD_ID" ]]; then
231+
BUILD_IDS="$BUILD_IDS $BUILD_ID"
232+
echo "Build ID: $BUILD_ID"
233+
fi
234+
done
235+
236+
# Save build IDs for potential cleanup
237+
echo "build_ids=$BUILD_IDS" >> $GITHUB_OUTPUT
238+
239+
# Wait for all builds in this batch to complete
240+
echo ""
241+
echo "========================================"
242+
echo "Waiting for batch ${{ matrix.batch.id }} builds to complete..."
243+
echo "========================================"
244+
245+
for build_id in $BUILD_IDS; do
246+
echo "Waiting for build $build_id..."
247+
copr-cli watch-build "$build_id" || {
248+
echo "::warning::Build $build_id failed or was cancelled"
249+
# Get package name for this build
250+
FAILED="$FAILED (build:$build_id)"
251+
}
252+
done
253+
254+
if [[ -n "$FAILED" ]]; then
255+
echo ""
256+
echo "::error::Some packages failed to build:$FAILED"
257+
exit 1
258+
fi
259+
260+
echo ""
261+
echo "Batch ${{ matrix.batch.id }} completed successfully!"
262+
263+
- name: Cancel COPR builds on workflow cancellation
264+
if: cancelled()
265+
run: |
266+
echo "Workflow cancelled - cancelling COPR builds..."
267+
BUILD_IDS="${{ steps.build.outputs.build_ids }}"
268+
269+
for build_id in $BUILD_IDS; do
270+
echo "Cancelling COPR build $build_id..."
271+
copr-cli cancel "$build_id" || echo "Could not cancel build $build_id (may have already finished)"
272+
done
273+
274+
echo "COPR build cancellation complete"
275+
276+
- name: Generate batch summary
277+
if: always()
278+
run: |
279+
echo "## Batch ${{ matrix.batch.id }} Build Results" >> $GITHUB_STEP_SUMMARY
280+
echo "" >> $GITHUB_STEP_SUMMARY
281+
echo "**Packages:** ${{ join(matrix.batch.packages, ', ') }}" >> $GITHUB_STEP_SUMMARY
282+
echo "" >> $GITHUB_STEP_SUMMARY
283+
echo "[View builds on COPR](https://copr.fedorainfracloud.org/coprs/${{ env.COPR_PROJECT }}/builds/)" >> $GITHUB_STEP_SUMMARY
284+
285+
summary:
286+
needs: [detect-changes, build-batch]
287+
if: always()
288+
runs-on: ubuntu-latest
289+
steps:
290+
- name: Generate final summary
291+
run: |
292+
echo "## COPR Package Build Summary" >> $GITHUB_STEP_SUMMARY
293+
echo "" >> $GITHUB_STEP_SUMMARY
294+
echo "**Packages built:** ${{ needs.detect-changes.outputs.packages }}" >> $GITHUB_STEP_SUMMARY
295+
echo "" >> $GITHUB_STEP_SUMMARY
296+
echo "**Status:** ${{ needs.build-batch.result }}" >> $GITHUB_STEP_SUMMARY
297+
echo "" >> $GITHUB_STEP_SUMMARY
298+
echo "[View all builds](https://copr.fedorainfracloud.org/coprs/${{ env.COPR_PROJECT }}/builds/)" >> $GITHUB_STEP_SUMMARY

0 commit comments

Comments
 (0)