When to Use pull_request_target Instead of pull_request in GitHub Actions
I recently was pulling my hair out trying to debug why my GitHub Actions weren't receiving secrets during one of my Actions executions.
And it turned out I needed to use pull_request_target
instead of pull_request
.
Choosing the right one is crucial for both functionality and security.
What is pull_request
?
The pull_request
event is used for day-to-day tasks related to pull requests. These include building, testing, and linting your code whenever someone opens, updates, or reopens a pull request. It's safe and straightforward for use within your repository. It's usually the option you'll choose unless you are writing Actions for external contributors.
What is pull_request_target
?
The pull_request_target
event is a bit different. It's used when you need to perform more sensitive operations that require access to secrets – like deploying code or accessing private data. This event is more powerful and riskier because it can access more information.
When to Use pull_request_target
You should use pull_request_target
in scenarios where:
Access to Secrets is Required: If your workflow needs to use secrets, like deploying code to a server,
pull_request_target
is the way to go.Handling Forks Safely: When dealing with pull requests from forks, especially in open-source projects,
pull_request_target
ensures that your secrets are not exposed to potentially untrusted code.
Situational Example: Using GitHub Secrets
Let's say you have a workflow that deploys your code to a cloud service. You must use a secret API key stored in GitHub Secrets to do this.
With
pull_request
, if someone from outside your team makes a pull request from a fork, your workflow won't have access to this secret API key. It keeps your secrets safe, but you can't auto-deploy from these pull requests.With
pull_request_target
, you can access this secret API key even in pull requests from forks. This is great for automation, but you need to be extra careful. Make sure you trust the code you're deploying!
Here's the example of where I needed pull_request_target
to allow my tests to run with a secret so you can see it in action:
name: Playwright Tests on: push: branches: [develop] pull_request_target: branches: [develop] types: [opened, synchronize, reopened, ready_for_review] jobs: test: timeout-minutes: 60 runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 18 - name: Install dependencies run: npm ci - name: Install Playwright Browsers run: npx playwright install --with-deps - name: Run Playwright tests env: DATABASE_URL: ${{ secrets.DATABASE_URL }} run: npx playwright test - uses: actions/upload-artifact@v3 if: always() with: name: playwright-report path: playwright-report/ retention-days: 30
Be Careful!
Remember, pull_request_target
can expose your secrets if not used carefully.
Always review and validate the changes in pull requests before they are merged.
Happy coding! ✨