name: Execd Tests on: pull_request: branches: [ main ] permissions: contents: read pull-requests: read concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true jobs: changes: uses: ./.github/workflows/detect-changes.yml with: area: execd test: needs: changes if: needs.changes.outputs.relevant == 'true' runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v6 - name: Set up Go uses: actions/setup-go@v6 with: go-version: '1.25.9' - name: Check gofmt working-directory: components/execd run: | files="$(gofmt -l . ../internal)" if [ -n "$files" ]; then echo "$files" exit 1 fi - name: Run golint working-directory: components/execd run: | make golint - name: Build (Multi platform compile) working-directory: components/execd run: | make multi-build - name: Run tests with coverage working-directory: components/execd run: | go test -v -coverpkg=./... -coverprofile=coverage.out -covermode=atomic ./pkg/... - name: Calculate coverage and generate summary working-directory: components/execd id: coverage run: | # Extract total coverage percentage TOTAL_COVERAGE=$(go tool cover -func=coverage.out | grep total | awk '{print $3}') echo "total_coverage=$TOTAL_COVERAGE" >> $GITHUB_OUTPUT # Generate GitHub Actions job summary echo "## 📊 execd Test Coverage Report" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Total Line Coverage:** $TOTAL_COVERAGE" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "Coverage report generated for commit \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "---" >> $GITHUB_STEP_SUMMARY echo "*Coverage targets: Core packages >80%, API layer >70%*" >> $GITHUB_STEP_SUMMARY smoke: needs: changes if: needs.changes.outputs.relevant == 'true' strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} defaults: run: shell: bash steps: - name: Checkout code uses: actions/checkout@v6 - name: Set up Go uses: actions/setup-go@v6 with: go-version: '1.25.9' - name: Set up Python uses: actions/setup-python@v6 with: python-version: '3.10' - name: Install make (Windows) if: matrix.os == 'windows-latest' shell: powershell run: choco install make -y - name: Build working-directory: components/execd run: | make build - name: Run smoke test working-directory: components/execd run: | chmod +x tests/smoke.sh ./tests/smoke.sh sleep 5 python3 tests/smoke_api.py - name: SIGTERM forward test if: matrix.os == 'ubuntu-latest' working-directory: components/execd run: | chmod +x tests/sigterm_forward.sh ./tests/sigterm_forward.sh - name: Smoke test bwrap (Docker image build + extraction) if: matrix.os == 'ubuntu-latest' shell: bash run: | chmod +x components/execd/tests/smoke_bwrap.sh bash components/execd/tests/smoke_bwrap.sh - name: Show logs if: always() run: | set -x cat components/execd/startup.log || true cat components/execd/execd.log || true bwrap-smoke: needs: changes if: needs.changes.outputs.relevant == 'true' runs-on: ubuntu-latest timeout-minutes: 10 steps: - name: Checkout code uses: actions/checkout@v6 - name: Set up Go uses: actions/setup-go@v6 with: go-version: '1.25.9' - name: Build latest bubblewrap (v0.11.2) run: | sudo apt-get install -y meson ninja-build libcap-dev pkg-config git clone --depth 1 --branch v0.11.2 https://github.com/containers/bubblewrap /tmp/bwrap cd /tmp/bwrap meson setup builddir -Dprefix=/usr -Dman=disabled -Dtests=false ninja -C builddir sudo cp builddir/bwrap /usr/local/bin/bwrap bwrap --version - name: Run bwrap integration tests working-directory: components/execd run: sudo -E env "PATH=$PATH" go test -tags="linux,bwrap" -v -count=1 -timeout=5m ./pkg/runtime/bwrap_test/ required: name: Execd CI if: always() needs: [changes, test, smoke, bwrap-smoke] runs-on: ubuntu-latest steps: - name: Verify required jobs env: RELEVANT: ${{ needs.changes.outputs.relevant }} CHANGES_RESULT: ${{ needs.changes.result }} TEST_RESULT: ${{ needs.test.result }} SMOKE_RESULT: ${{ needs.smoke.result }} BWRAP_SMOKE_RESULT: ${{ needs.bwrap-smoke.result }} run: | if [[ "$CHANGES_RESULT" != "success" ]]; then echo "Change detection failed: $CHANGES_RESULT" exit 1 fi if [[ "$RELEVANT" == "true" ]]; then [[ "$TEST_RESULT" == "success" && "$SMOKE_RESULT" == "success" && "$BWRAP_SMOKE_RESULT" == "success" ]] else [[ "$RELEVANT" == "false" && "$TEST_RESULT" == "skipped" && "$SMOKE_RESULT" == "skipped" && "$BWRAP_SMOKE_RESULT" == "skipped" ]] fi