PR Build Test #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: PR Build Test | ||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| pr_number: | ||
| description: 'PR number to build' | ||
| type: number | ||
| required: true | ||
| host: | ||
| description: 'Target host (x86_64-Linux, aarch64-Linux, or ALL)' | ||
| type: choice | ||
| options: | ||
| - x86_64-Linux | ||
| - aarch64-Linux | ||
| - ALL | ||
| default: x86_64-Linux | ||
| permissions: | ||
| contents: read | ||
| packages: write | ||
| pull-requests: write | ||
| concurrency: | ||
| group: pr-build-${{ inputs.pr_number }} | ||
| cancel-in-progress: true | ||
| jobs: | ||
| detect-changes: | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| changed_recipes: ${{ steps.detect.outputs.changed_recipes }} | ||
| has_changes: ${{ steps.detect.outputs.has_changes }} | ||
| pr_head_sha: ${{ steps.pr-info.outputs.head_sha }} | ||
| steps: | ||
| - name: Get PR info | ||
| id: pr-info | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| PR_DATA=$(gh api repos/${{ github.repository }}/pulls/${{ inputs.pr_number }}) | ||
| HEAD_SHA=$(echo "$PR_DATA" | jq -r '.head.sha') | ||
| BASE_SHA=$(echo "$PR_DATA" | jq -r '.base.sha') | ||
| HEAD_REF=$(echo "$PR_DATA" | jq -r '.head.ref') | ||
| echo "head_sha=${HEAD_SHA}" >> $GITHUB_OUTPUT | ||
| echo "base_sha=${BASE_SHA}" >> $GITHUB_OUTPUT | ||
| echo "head_ref=${HEAD_REF}" >> $GITHUB_OUTPUT | ||
| echo "::notice::PR #${{ inputs.pr_number }}: ${HEAD_REF} (${HEAD_SHA})" | ||
| - name: Checkout PR | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| ref: ${{ steps.pr-info.outputs.head_sha }} | ||
| fetch-depth: 0 | ||
| - name: Detect changed recipes | ||
| id: detect | ||
| env: | ||
| BASE_SHA: ${{ steps.pr-info.outputs.base_sha }} | ||
| run: | | ||
| # Get changed files between base and PR head | ||
| CHANGED_FILES=$(git diff --name-only "${BASE_SHA}" HEAD -- 'binaries/**/*.yaml' 'packages/**/*.yaml' 2>/dev/null || true) | ||
| echo "Changed recipe files:" | ||
| echo "$CHANGED_FILES" | ||
| CHANGED_RECIPES="[]" | ||
| for file in $CHANGED_FILES; do | ||
| if [ -f "$file" ]; then | ||
| CHANGED_RECIPES=$(echo "$CHANGED_RECIPES" | jq --arg path "$file" '. + [{"path": $path}]') | ||
| fi | ||
| done | ||
| RECIPE_COUNT=$(echo "$CHANGED_RECIPES" | jq 'length') | ||
| echo "::notice::Found ${RECIPE_COUNT} changed recipes" | ||
| echo "changed_recipes=$(echo "$CHANGED_RECIPES" | jq -c .)" >> $GITHUB_OUTPUT | ||
| if [ "$RECIPE_COUNT" -gt 0 ]; then | ||
| echo "has_changes=true" >> $GITHUB_OUTPUT | ||
| else | ||
| echo "has_changes=false" >> $GITHUB_OUTPUT | ||
| fi | ||
| build: | ||
|
Check failure on line 88 in .github/workflows/pr-build-test.yaml
|
||
| needs: detect-changes | ||
| if: needs.detect-changes.outputs.has_changes == 'true' | ||
| strategy: | ||
| fail-fast: false | ||
| max-parallel: 2 | ||
| matrix: | ||
| recipe: ${{ fromJson(needs.detect-changes.outputs.changed_recipes) }} | ||
| uses: ./.github/workflows/matrix_builds.yaml | ||
| with: | ||
| host: ${{ inputs.host }} | ||
| sbuild-url: "https://raw.githubusercontent.com/${{ github.repository }}/${{ needs.detect-changes.outputs.pr_head_sha }}/${{ matrix.recipe.path }}" | ||
| ghcr-url: ${{ contains(matrix.recipe.path, 'packages/') && format('ghcr.io/{0}/pkgcache', github.repository_owner) || format('ghcr.io/{0}/bincache', github.repository_owner) }} | ||
| pkg-family: ${{ github.event.repository.name }} | ||
| rebuild: true | ||
| logs: true | ||
| metadata-release: false | ||
| secrets: inherit | ||
| update-cache: | ||
| needs: [detect-changes, build] | ||
| if: always() && needs.detect-changes.outputs.has_changes == 'true' | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout PR | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| ref: ${{ needs.detect-changes.outputs.pr_head_sha }} | ||
| - name: Download sbuild-linter (for hash) | ||
| run: | | ||
| curl -fsSL "https://github.com/pkgforge/sbuilder/releases/download/latest/sbuild-linter-x86_64-linux" \ | ||
| -o /usr/local/bin/sbuild-linter || exit 0 | ||
| chmod +x /usr/local/bin/sbuild-linter | ||
| - name: Download sbuild-cache | ||
| run: | | ||
| curl -fsSL "https://github.com/pkgforge/sbuilder/releases/download/latest/sbuild-cache-x86_64-linux" \ | ||
| -o /usr/local/bin/sbuild-cache || exit 0 | ||
| chmod +x /usr/local/bin/sbuild-cache | ||
| - name: Download existing cache | ||
| continue-on-error: true | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| gh release download build-cache -p build_cache.sdb -D /tmp/ --repo "${{ github.repository }}" || \ | ||
| sbuild-cache --cache /tmp/build_cache.sdb init | ||
| - name: Update cache with recipe hashes | ||
| run: | | ||
| RECIPES='${{ needs.detect-changes.outputs.changed_recipes }}' | ||
| BUILD_RESULT="${{ needs.build.result }}" | ||
| echo "$RECIPES" | jq -c '.[]' | while read -r recipe; do | ||
| path=$(echo "$recipe" | jq -r '.path') | ||
| pkg_name=$(basename "$(dirname "$path")") | ||
| # Extract version from recipe's pkgver field | ||
| pkg_version="unknown" | ||
| if [ -f "$path" ]; then | ||
| pkg_version=$(grep -E "^pkgver:" "$path" | head -1 | sed 's/pkgver:[[:space:]]*//; s/^["'"'"']//; s/["'"'"']$//' || echo "unknown") | ||
| [ -z "$pkg_version" ] && pkg_version="unknown" | ||
| fi | ||
| # Compute recipe hash (excluding version for consistency) | ||
| if [ -f "$path" ]; then | ||
| recipe_hash=$(sbuild-linter hash --exclude-version "$path" 2>/dev/null || sha256sum "$path" | cut -d' ' -f1) | ||
| else | ||
| recipe_hash="unknown" | ||
| fi | ||
| status="success" | ||
| if [ "$BUILD_RESULT" != "success" ]; then | ||
| status="failure" | ||
| fi | ||
| echo "Caching: $pkg_name v${pkg_version} (hash: ${recipe_hash:0:16}..., status: $status)" | ||
| sbuild-cache --cache /tmp/build_cache.sdb update \ | ||
| --package "$pkg_name" \ | ||
| --version "$pkg_version" \ | ||
| --hash "$recipe_hash" \ | ||
| --status "$status" || true | ||
| done | ||
| - name: Upload updated cache | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| if [ -f "/tmp/build_cache.sdb" ]; then | ||
| gh release upload build-cache /tmp/build_cache.sdb --clobber --repo "${{ github.repository }}" || { | ||
| gh release create build-cache \ | ||
| --title "Build Cache" \ | ||
| --notes "Build cache for CI" \ | ||
| --prerelease \ | ||
| --repo "${{ github.repository }}" \ | ||
| /tmp/build_cache.sdb | ||
| } | ||
| fi | ||
| comment-result: | ||
| needs: [detect-changes, build] | ||
| if: always() && needs.detect-changes.outputs.has_changes == 'true' | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| pull-requests: write | ||
| steps: | ||
| - name: Post build result comment | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| BUILD_STATUS="${{ needs.build.result }}" | ||
| RECIPES='${{ needs.detect-changes.outputs.changed_recipes }}' | ||
| HOST="${{ inputs.host }}" | ||
| RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | ||
| if [ "$BUILD_STATUS" == "success" ]; then | ||
| EMOJI="✅" | ||
| STATUS_TEXT="succeeded" | ||
| elif [ "$BUILD_STATUS" == "failure" ]; then | ||
| EMOJI="❌" | ||
| STATUS_TEXT="failed" | ||
| else | ||
| EMOJI="⚠️" | ||
| STATUS_TEXT="completed with status: ${BUILD_STATUS}" | ||
| fi | ||
| RECIPE_LIST=$(echo "$RECIPES" | jq -r '.[].path' | sed 's/^/- `/' | sed 's/$/`/') | ||
| COMMENT_BODY="## ${EMOJI} Build Test ${STATUS_TEXT} | ||
| **Host:** \`${HOST}\` | ||
| **Workflow Run:** [View Details](${RUN_URL}) | ||
| ### Recipes tested: | ||
| ${RECIPE_LIST} | ||
| --- | ||
| *Triggered manually via workflow_dispatch*" | ||
| gh pr comment "${{ inputs.pr_number }}" \ | ||
| --repo "${{ github.repository }}" \ | ||
| --body "$COMMENT_BODY" | ||
| no-changes: | ||
| needs: detect-changes | ||
| if: needs.detect-changes.outputs.has_changes != 'true' | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: No recipes to build | ||
| run: | | ||
| echo "::warning::No recipe changes detected in PR #${{ inputs.pr_number }}" | ||