Update release for fastsurfer 2.4.2 #137
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: Test Release PR Containers | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened] | |
| paths: | |
| - "releases/*/**.json" | |
| branches: | |
| - master | |
| - main | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| id-token: write | |
| jobs: | |
| detect-changes: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| modified-releases: ${{ steps.detect.outputs.modified-releases }} | |
| has-changes: ${{ steps.detect.outputs.has-changes }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Detect release files | |
| id: detect | |
| run: | | |
| # Get list of modified release JSON files | |
| MODIFIED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep 'releases/.*/.*\.json' || true) | |
| if [ -z "$MODIFIED_FILES" ]; then | |
| echo "has-changes=false" >> $GITHUB_OUTPUT | |
| echo "modified-releases=[]" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| echo "has-changes=true" >> $GITHUB_OUTPUT | |
| echo "Modified release files:" | |
| echo "$MODIFIED_FILES" | |
| # Extract container name and version from release file paths | |
| RELEASES_JSON="[" | |
| FIRST=true | |
| for file in $MODIFIED_FILES; do | |
| # Extract from path like releases/container_name/version.json | |
| CONTAINER_NAME=$(echo "$file" | sed 's|releases/\([^/]*\)/.*|\1|') | |
| VERSION=$(echo "$file" | sed 's|releases/.*/\([^/]*\)\.json|\1|') | |
| if [ "$FIRST" = true ]; then | |
| FIRST=false | |
| else | |
| RELEASES_JSON="$RELEASES_JSON," | |
| fi | |
| RELEASES_JSON="$RELEASES_JSON{\"name\":\"$CONTAINER_NAME\",\"version\":\"$VERSION\",\"file\":\"$file\"}" | |
| done | |
| RELEASES_JSON="$RELEASES_JSON]" | |
| echo "Generated releases JSON: $RELEASES_JSON" | |
| echo "modified-releases=$RELEASES_JSON" >> $GITHUB_OUTPUT | |
| test-containers: | |
| needs: detect-changes | |
| if: needs.detect-changes.outputs.has-changes == 'true' | |
| runs-on: self-hosted | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| release: ${{ fromJson(needs.detect-changes.outputs.modified-releases) }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r requirements.txt | |
| - name: Verify container runtimes | |
| run: | | |
| # Verify that container runtimes are available on self-hosted runner | |
| docker --version | |
| apptainer --version || singularity --version | |
| - name: Debug matrix values | |
| run: | | |
| echo "Matrix release data:" | |
| echo "Name: ${{ matrix.release.name }}" | |
| echo "Version: ${{ matrix.release.version }}" | |
| echo "File: ${{ matrix.release.file }}" | |
| echo "Current directory: $(pwd)" | |
| echo "Release file exists: $([ -f '${{ matrix.release.file }}' ] && echo 'yes' || echo 'no')" | |
| - name: Find test configuration | |
| id: find-tests | |
| run: | | |
| # Look for test configuration in recipe directory | |
| RECIPE_DIR="recipes/${{ matrix.release.name }}" | |
| TEST_CONFIG="" | |
| if [ -f "$RECIPE_DIR/test.yaml" ]; then | |
| TEST_CONFIG="$RECIPE_DIR/test.yaml" | |
| echo "Found test.yaml" | |
| elif [ -f "$RECIPE_DIR/build.yaml" ]; then | |
| TEST_CONFIG="$RECIPE_DIR/build.yaml" | |
| echo "Found build.yaml (will extract tests from build directives)" | |
| else | |
| echo "No test configuration found in $RECIPE_DIR" | |
| ls -la "$RECIPE_DIR" || echo "Recipe directory not found" | |
| fi | |
| echo "test-config=$TEST_CONFIG" >> $GITHUB_OUTPUT | |
| - name: Run container tests | |
| id: test | |
| env: | |
| RECIPE: ${{ matrix.release.name }} | |
| VERSION: ${{ matrix.release.version }} | |
| RELEASE_FILE: ${{ matrix.release.file }} | |
| TEST_CONFIG: ${{ steps.find-tests.outputs.test-config }} | |
| run: | | |
| echo "Testing container: ${RECIPE}:${VERSION}" | |
| echo "Release file: ${RELEASE_FILE}" | |
| echo "Test config: ${TEST_CONFIG}" | |
| mkdir -p builder | |
| python - <<'PY' | |
| from pathlib import Path | |
| import os | |
| from workflows.test_runner import ContainerTestRunner, TestRequest | |
| recipe = os.environ["RECIPE"] | |
| version = os.environ.get("VERSION") or None | |
| release_file = os.environ.get("RELEASE_FILE") or None | |
| test_config = os.environ.get("TEST_CONFIG") or None | |
| runner = ContainerTestRunner() | |
| request = TestRequest( | |
| recipe=recipe, | |
| version=version, | |
| release_file=release_file, | |
| test_config=test_config if test_config else None, | |
| runtime="apptainer", | |
| location="auto", | |
| cleanup=True, | |
| auto_cleanup=False, | |
| verbose=True, | |
| allow_missing_tests=True, | |
| output_dir=Path("builder"), | |
| results_path=Path(f"builder/test-results-{recipe}.json"), | |
| ) | |
| outcome = runner.run(request) | |
| print(f"Status: {outcome.status}") | |
| if outcome.reason: | |
| print(f"Reason: {outcome.reason}") | |
| with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as handle: | |
| handle.write(f"status={outcome.status}\n") | |
| if outcome.reason: | |
| handle.write(f"reason={outcome.reason}\n") | |
| import sys | |
| sys.exit(0 if outcome.status != "failed" else 1) | |
| PY | |
| continue-on-error: true | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: test-results-${{ matrix.release.name }} | |
| path: | | |
| builder/test-results-${{ matrix.release.name }}.json | |
| builder/test-report-${{ matrix.release.name }}.md | |
| - name: Comment test results on PR | |
| if: always() | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| const releaseName = '${{ matrix.release.name }}'; | |
| const releaseVersion = '${{ matrix.release.version }}'; | |
| const reportFile = `builder/test-report-${releaseName}.md`; | |
| let reportContent = `## Test Results for ${releaseName}:${releaseVersion}\n\n`; | |
| try { | |
| if (fs.existsSync(reportFile)) { | |
| reportContent = fs.readFileSync(reportFile, 'utf8'); | |
| } else { | |
| reportContent += "❌ Test report not generated - check logs for errors."; | |
| } | |
| } catch (error) { | |
| reportContent += `❌ Error reading test report: ${error.message}`; | |
| } | |
| // Find existing comment for this release | |
| const comments = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| }); | |
| const botComment = comments.data.find(comment => | |
| comment.user.type === 'Bot' && | |
| comment.body.includes(`Test Results for ${releaseName}:${releaseVersion}`) | |
| ); | |
| const commentBody = `${reportContent}\n\n---\n*Automated test results for container: ${releaseName}:${releaseVersion}*`; | |
| if (botComment) { | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: botComment.id, | |
| body: commentBody | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: commentBody | |
| }); | |
| } | |
| summarize-results: | |
| needs: [detect-changes, test-containers] | |
| if: always() && needs.detect-changes.outputs.has-changes == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Download all test results | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: test-results-* | |
| merge-multiple: true | |
| path: test-results | |
| - name: Summarize test results | |
| id: summary | |
| run: | | |
| cd test-results | |
| TOTAL_RECIPES=0 | |
| PASSED_RECIPES=0 | |
| FAILED_RECIPES=0 | |
| for file in test-results-*.json; do | |
| if [ -f "$file" ]; then | |
| TOTAL_RECIPES=$((TOTAL_RECIPES + 1)) | |
| # Check if any tests failed | |
| FAILED_TESTS=$(jq '.failed' "$file" 2>/dev/null || echo "1") | |
| if [ "$FAILED_TESTS" -eq 0 ]; then | |
| PASSED_RECIPES=$((PASSED_RECIPES + 1)) | |
| else | |
| FAILED_RECIPES=$((FAILED_RECIPES + 1)) | |
| fi | |
| fi | |
| done | |
| echo "total=$TOTAL_RECIPES" >> $GITHUB_OUTPUT | |
| echo "passed=$PASSED_RECIPES" >> $GITHUB_OUTPUT | |
| echo "failed=$FAILED_RECIPES" >> $GITHUB_OUTPUT | |
| echo "Test Summary: $PASSED_RECIPES/$TOTAL_RECIPES recipes passed" | |
| - name: Set PR status | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const total = parseInt('${{ steps.summary.outputs.total }}'); | |
| const passed = parseInt('${{ steps.summary.outputs.passed }}'); | |
| const failed = parseInt('${{ steps.summary.outputs.failed }}'); | |
| let summary = `## 🧪 Container Test Summary\n\n`; | |
| summary += `**Results:** ${passed}/${total} recipes passed\n\n`; | |
| if (failed > 0) { | |
| summary += `❌ ${failed} recipe(s) failed testing\n`; | |
| summary += `Please check the individual test results above for details.\n\n`; | |
| } else { | |
| summary += `✅ All modified containers passed testing!\n\n`; | |
| } | |
| summary += `*This comment will be updated as tests complete.*`; | |
| // Find existing summary comment | |
| const comments = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| }); | |
| const summaryComment = comments.data.find(comment => | |
| comment.user.type === 'Bot' && | |
| comment.body.includes('Container Test Summary') | |
| ); | |
| if (summaryComment) { | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: summaryComment.id, | |
| body: summary | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: summary | |
| }); | |
| } | |
| // Fail the workflow if any tests failed | |
| if (failed > 0) { | |
| core.setFailed(`${failed} out of ${total} container tests failed`); | |
| } |