How Pull Requests Are Handled in the apple/container Repository

Apple's container repository uses a tightly-coupled GitHub Actions pipeline to automatically validate, label, and test every pull request through three orchestrated stages before merge.

The apple/container project maintains rigorous code quality standards through automated CI/CD workflows that execute on every pull request. Understanding how pull requests are handled requires examining the repository's GitHub Actions configuration, which coordinates security verification, automated labeling, and comprehensive build testing. The process ensures that every contribution is signed, categorized, and fully tested before integration.

Stage 1: PR Metadata Capture with pr-label-analysis.yml

When a contributor opens a new pull request, the workflow defined in .github/workflows/pr-label-analysis.yml immediately triggers. This workflow serves as the foundation for the repository's automated labeling system.

The workflow performs a specific metadata capture operation:

  1. It extracts the pull request number from the GitHub event context.
  2. It writes this number to pr-metadata/pr-number.txt within the workflow runner.
  3. It uploads this file as a named artifact using actions/upload-artifact.

This artifact persists the PR identifier across workflow runs, enabling subsequent stages to apply labels without requiring direct access to the original event payload. The workflow runs on standard Ubuntu runners and completes quickly to minimize feedback latency.

Stage 2: Automated Label Application with pr-label-apply.yml

Once pr-label-analysis.yml completes successfully, it triggers .github/workflows/pr-label-apply.yml through a workflow_run event configured with workflow_run: completed. This decoupled approach follows GitHub's recommended pattern for workflows that require elevated permissions.

The label application workflow executes the following steps:

  • Downloads the artifact containing pr-number.txt from the previous workflow.
  • Extracts the PR number and exposes it to subsequent steps.
  • Invokes the actions/labeler action using the repository's configuration in .github/labeler.yml.

The .github/labeler.yml file defines glob patterns that automatically categorize pull requests based on modified file paths. For example, adding a rule for API changes would automatically apply labels when source files in specific directories are modified, ensuring maintainers can quickly identify the scope of changes.

Stage 3: Security Verification and Build Testing

Concurrently with labeling, .github/workflows/pr-build.yml triggers on pull_request events of type opened, reopened, or synchronize. This workflow serves as the primary quality gate, enforcing both security policies and build integrity.

Commit Signature Verification

Before any code compilation begins, the workflow verifies that every commit in the pull request contains a valid GPG signature. The implementation uses the GitHub CLI to enumerate commits:


# .github/workflows/pr-build.yml

jobs:
  verify-signatures:
    runs-on: ubuntu-latest
    steps:
      - name: Check all commits are signed
        env:
          GH_TOKEN: ${{ github.token }}
          REPO: ${{ github.repository }}
          PR_NUMBER: ${{ github.event.pull_request.number }}
        run: |
          commits=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}/commits" --paginate)
          # Validation logic fails the job if unsigned commits are detected

If any commit lacks a signature, the workflow fails immediately, prompting contributors to sign their commits before the build proceeds.

Reusable Build Workflows with common.yml

Following successful signature verification, pr-build.yml delegates to .github/workflows/common.yml using a reusable workflow call. This pattern centralizes build logic across different event types. The call passes specific parameters:


# .github/workflows/pr-build.yml

jobs:
  build-and-test:
    uses: ./.github/workflows/common.yml
    with:
      release: false
      coverage: true

The common.yml workflow executes on self-hosted macOS runners ([self-hosted, macos, tahoe, ARM64]) and performs the following operations:

  1. Formatting Verification: Installs the Hawkeye tool via scripts/install-hawkeye.sh and runs make fmt to verify code style.
  2. Protocol Buffer Checks: Executes make protos to ensure generated code is synchronized with protobuf definitions.
  3. Binary Compilation: Builds the container binary and debug symbols using make container dsym.
  4. Documentation Generation: Creates API documentation via make docs and archives the _site directory.
  5. Test Execution: Runs the complete test suite including kernel installation and integration tests with make install-kernel test.

Coverage Collection and Artifact Management

When the coverage input parameter is set to true, the workflow generates detailed coverage reports. The common.yml workflow extracts line-coverage percentages using jq and stores the data in a pr-coverage/ directory. It then uploads both the raw data and HTML reports as artifacts.

After successful completion, the workflow archives multiple outputs:

  • api-docs: Generated documentation from the build process.
  • container-package: Compiled binaries and packages.
  • container-test-logs: Detailed logs from the test execution.

A follow-up job named uploadPages subsequently publishes the documentation to GitHub Pages, making the generated API references available for review.

Summary

  • Apple's container repository handles pull requests through a three-stage pipeline: metadata capture, automated labeling, and comprehensive build testing.
  • .github/workflows/pr-label-analysis.yml captures PR numbers as artifacts to enable secure cross-workflow communication.
  • .github/workflows/pr-label-apply.yml downloads these artifacts and applies labels based on .github/labeler.yml configuration.
  • .github/workflows/pr-build.yml enforces GPG signature verification on all commits before triggering builds.
  • .github/workflows/common.yml performs formatting checks, compilation, documentation generation, and test execution with optional coverage collection.
  • Self-hosted macOS runners execute the actual build and test workloads, while Ubuntu runners handle metadata and verification tasks.

Frequently Asked Questions

What happens if a pull request contains unsigned commits?

The verify-signatures job in .github/workflows/pr-build.yml fails immediately. The workflow uses the GitHub CLI (gh api) to retrieve all commits for the pull request and validates that each contains a GPG signature. Contributors must amend their commits with signatures before the build can proceed.

How does the repository automatically categorize pull requests?

The repository uses a two-step labeling process. First, pr-label-analysis.yml captures the PR number and stores it as an artifact. Then, pr-label-apply.yml triggers automatically and uses the actions/labeler action to apply labels based on glob patterns defined in .github/labeler.yml, categorizing changes by modified file paths.

Where is the actual build and test logic defined?

The core build logic resides in .github/workflows/common.yml, which is a reusable workflow called by pr-build.yml. This workflow executes make fmt (formatting), make protos (protobuf verification), make container dsym docs (compilation), and make install-kernel test (testing) on self-hosted macOS runners.

What coverage metrics are collected during pull request builds?

When coverage: true is passed to common.yml, the workflow runs make coverage-new and extracts line-coverage percentages using jq. It stores these metrics in the pr-coverage/ directory and uploads both JSON data and HTML reports as artifacts for review alongside the pull request.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →