Understanding the Main and Post Phases in actions/checkout: A Complete Guide
The actions/checkout GitHub Action executes in two distinct phases: the Main phase runs at job start to handle repository checkout and authentication, while the Post phase automatically runs after job completion to remove persisted credentials and clean up temporary files.
The actions/checkout action is one of the most widely used utilities in GitHub Actions workflows, but its execution model relies on a critical two-phase architecture that separates repository setup from secure cleanup. Understanding how these main and post phases in actions/checkout work together helps you manage authentication securely and troubleshoot credential-related issues in your CI/CD pipelines.
What Are the Main and Post Phases in actions/checkout?
GitHub Actions supports lifecycle hooks that allow actions to run logic before and after the primary job steps. The actions/checkout implementation leverages this by splitting its operation into distinct main and post phases.
Main Phase (Job Start)
The Main phase executes immediately when the uses: actions/checkout step runs in your workflow. According to the source code in [src/main.ts](https://github.com/actions/checkout/blob/main/src/main.ts), this phase handles:
- Input processing: Reads all workflow inputs including
ref,repository,fetch-depth,submodules,lfs, andpersist-credentials - Authentication setup: Configures Git PAT (Personal Access Token) or SSH key authentication based on provided secrets
- Repository operations: Executes the actual Git commands for cloning, fetching, sparse checkout, and submodule initialization
- Credential persistence: When
persist-credentials: trueis set, writes the authentication token to the local Git configuration so subsequent steps can access the repository
Post Phase (Job Cleanup)
The Post phase executes automatically after all job steps complete, regardless of whether the job succeeded or failed. As defined in [action.yml](https://github.com/actions/checkout/blob/main/action.yml) at line 118, this phase runs the compiled script at dist/index.js to perform security-critical cleanup operations.
How the Main Phase Works in Detail
When your workflow reaches the checkout step, [src/main.ts](https://github.com/actions/checkout/blob/main/src/main.ts) orchestrates the repository setup through several key operations:
- Input validation: The helper functions in
src/input-helper.tsparse and validate workflow inputs - Git configuration: Sets up user name, email, and authentication headers in the local Git config
- Repository fetch: Executes
git fetchwith the specified depth and ref, or performs a full clone if necessary - Submodule handling: If
submodules: recursiveis specified, initializes and updates nested repositories - Credential storage: When
persist-credentialsis enabled, stores the PAT in.git/configfor use by later steps
- name: Checkout with persisted credentials
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: true # Default behavior: token available to subsequent steps
token: ${{ secrets.GITHUB_TOKEN }}
How the Post Phase Cleans Up Credentials
The post-job cleanup is defined in the action metadata. The [action.yml](https://github.com/actions/checkout/blob/main/action.yml) file specifies post: dist/index.js, which instructs GitHub Actions to execute the compiled cleanup script after the job finishes.
According to the architectural decision record in [adrs/0153-checkout-v2.md](https://github.com/actions/checkout/blob/main/adrs/0153-checkout-v2.md), the post phase performs these specific security tasks:
- Removes the PAT: Deletes the Personal Access Token from
.git/configthat was added during the main phase - Deletes SSH keys: Removes any temporary SSH private keys added to the SSH agent
- Cleans temporary files: Removes files stored under
$RUNNER_TEMPthat were used during checkout - Resets Git config: Restores Git configuration to its pre-checkout state
This automatic cleanup ensures that no secrets remain on the runner after your workflow completes, mitigating the risk of credential leakage to subsequent jobs or processes.
Configuring Credential Persistence
You control whether the main phase persists credentials—and consequently whether the post phase has cleanup work to do—using the persist-credentials input.
- name: Checkout without credential persistence
uses: actions/checkout@v4
with:
persist-credentials: false # Main phase skips writing token; Post phase has no credentials to clean
When persist-credentials: false, the main phase configures authentication only for the initial fetch operation without writing to the Git config. The post phase still runs but performs minimal cleanup since no credentials were persisted.
Summary
- The main phase in
actions/checkoutruns at job start insrc/main.tsto handle inputs, authentication, and repository checkout operations. - The post phase automatically executes after job completion via
dist/index.js(defined inaction.yml) to remove credentials and secure the runner. - The
persist-credentialsinput controls whether authentication tokens are written to the Git config during the main phase and subsequently cleaned up during the post phase. - Architectural decisions documented in
adrs/0153-checkout-v2.mdmandate that the post phase specifically removes PATs and SSH keys to prevent secret leakage.
Frequently Asked Questions
What triggers the post phase in actions/checkout?
The post phase triggers automatically after all job steps complete, regardless of success or failure. The [action.yml](https://github.com/actions/checkout/blob/main/action.yml) file defines post: dist/index.js, which GitHub Actions invokes as a post-job hook. You do not need to add explicit configuration to trigger this cleanup.
How do I prevent actions/checkout from persisting credentials?
Set persist-credentials: false in your workflow configuration. This prevents the main phase from writing the token to .git/config, meaning the post phase will have no credentials to remove. This is useful when you want to ensure no authentication data touches disk during the workflow execution.
Why does the post phase matter for security?
The post phase removes sensitive authentication data—including PATs and SSH keys—that the main phase adds to the Git configuration. Without this cleanup step, subsequent jobs running on the same self-hosted runner could access these credentials. As documented in the project's ADR, this automatic cleanup ensures secrets are available only for the duration of the current job.
Can I disable the post phase cleanup?
No, you cannot disable the post phase when using actions/checkout. The cleanup hook is hardcoded in action.yml and executes automatically. However, if you set persist-credentials: false, the cleanup operations will find nothing to remove, effectively making the post phase a no-op while still satisfying the security requirements.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →