AAriam
AAriam

Reputation: 417

GitHub `actions/checkout`: Fetch history up to before the push event

In a GitHub Actions workflow triggered by a push event, I want to use the actions/checkout action to fetch the git history of all commits in the push event, plus the last commit before the push event (without having to fetch the entire history).

However, actions/checkout only provides the fetch-depth parameter, which inputs the number of commits to fetch, but that is not known. The push event payload contains the list of commits as an array, but there is no native function in GitHub Actions to count the length of an array. One could write an extra step before using checkout to count the number of commits in the payload, but that seems a bit too hacky.

Isn't there a straightforward way to fetch the history from right before a push event? That seems like a very common thing to do, so it's odd that I can't find an easy way to do it, something like:

  - needs: actions/checkout@v3
    with:
      - from-ref: ${{ github.event.before }}

Upvotes: 3

Views: 3166

Answers (3)

Mayank Kumar Chaudhari
Mayank Kumar Chaudhari

Reputation: 18638

So, multiple commits may be there during push as well. And the way I handled it is as follows

  - uses: actions/checkout@v4
    with:
      token: ${{ secrets.GITHUB_TOKEN }}
      ref: ${{ github.event.before }}

  - name: Check if package.json was modified
    id: pub
    run: |
      git fetch && git checkout main

Full workflow here - https://github.com/react18-tools/turborepo-template/blob/main/.github/workflows/docs.yml

Upvotes: 0

Scramjet
Scramjet

Reputation: 458

A cleaner way that I could find for pull_requests was:

jobs:
  my-job:
    runs-on: ubuntu-latest
    steps:
       - name: Checkout
         uses: actions/checkout@v3
         with:
             fetch-depth: $(( ${{ github.event_name == 'pull_request' && github.event.pull_request.commits || 0 }} + 1 ))

Using the ternary operation mentioned in the docs. So we don't need an additional step.
You could use the same format for push too, though the event name and commit count would need to be changed.

Upvotes: 2

AAriam
AAriam

Reputation: 417

Currently, this is my workaround:

jobs:

  my-job:
    runs-on: ubuntu-latest
    steps:

      - name: Calculate fetch-depth
        id: pre-checkout
        env:
          COMMITS: ${{ toJson(github.event.commits) }}
        run: |
          if [[ "${{ github.event_name }}" == "push" ]]; then
            COUNT=$(( $(echo "$COMMITS" | jq length) + 1 ))
          else
            COUNT=1
          fi
          echo "fetch-depth=$COUNT" >> "$GITHUB_OUTPUT"

      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: ${{ steps.pre-checkout.outputs.fetch-depth }}

As mentioned in the question, an additional step is needed before using actions/checkout to calculate the fetch-depth. Here, we first check the github.event_name context; if it's push, we then output the length of the github.event.commits array plus 1, otherwise we output 1, and then use this output in the checkout step as the fetch-depth argument.

It's not pretty, but currently it's the most straightforward approach I could find. I have opened an issue in actions/checkout to add native support: https://github.com/actions/checkout/issues/1444

Upvotes: 0

Related Questions