6

A CI/CD pipeline in GitHub needs to first push code from the dev branch to the test branch, and then immediately run a workflow on the test branch as soon as code has been pushed into the test branch.

The dev-environ-workflow below does successfully push code from the dev branch into the test branch when code is pushed into the dev branch from a devbox outside of GitHub.

The problem is that the test-environ-workflow fails to run when code is pushed into the test branch from the dev-environ-workflow.

Any GitHub account can reproduce this problem with only three files and the following structure:

.gihub/workflows/
    dev-workflow.yaml
    test-workflow.yaml
myapp.py

myapp.py:

print('Hello from myapp!')

dev-workflow.yaml:

name: dev-environ-workflow
on:
  push:
    branches:
      - dev
jobs:
  push-to-test-branch:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - shell: bash
        name: Push changes to test branch
        env:
          GIT_PAT: ${{ secrets.GIT_PAT }}
        run: |
          repoWithToken="https://"$GIT_PAT"@github.com/myAccountName/trigger.git"
          git config --global user.email "me@mydomain.com"
          git config --global user.name "myAccountName"
          git init
          git remote set-url origin $repoWithToken
          git branch -M test
          git add --all
          git push --force -u origin test

test-workflow.yaml:

name: test-environ-workflow
on:
  push:
    branches:
      - test
jobs:
  push-to-test-branch:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - shell: bash
        name: Do anything
        run: echo "Successfully triggered test-environ-workflow"

The commands to trigger the dev-environ-workflow from a remote devbox anywhere on the internet outside of GitHub are:

git init
git add --all
git commit -m "some changes"
git branch -M dev
git push -u origin dev

You also need to create an environment variable for the GitHub repository called GIT_PAT which contains a personal access token that will be used to push code into the test branch.

What specifically needs to change in the above in order for the test-environ-workflow to be successfully triggered whenever the dev-environ-workflow successfully pushes code into the test branch?

Dharman
  • 30,962
  • 25
  • 85
  • 135
CodeMed
  • 9,527
  • 70
  • 212
  • 364
  • For what I understand looking at the doc, you shouldn't set the secret variable as an env named `GIT_PAT`, but as `GITHUB_TOKEN`. [reference](https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow). Following the example there using `secrets.MY_TOKEN`. – GuiFalourd Sep 02 '22 at 01:43
  • @GuiFalourd Thank you. I can change that in the actual code. ... But the code **does** successfully push into the `test` branch in its current form. ... Do you have any suggestion to resolve the problem stated in the OP? – CodeMed Sep 02 '22 at 01:58
  • 2
    This doesn't really have anything to do with Git. It appears to be some sort of GitHub magic, where they detect an internal push from themselves and don't run workflows. (I don't know for sure, but I speculate that this is to prevent an endless loop.) The obvious workaround would be to set up the "push to foo" workflow to *include* the "push to bar" workflow right after the `git push -u origin bar` step. – torek Sep 02 '22 at 08:24
  • **CodeMed**: What I meant was that the problem may be related to the fact you're not overwriting the `GITHUB_TOKEN` with your PAT secret (I understand that the GITHUB_TOKEN variable is automatically used by git commands on workflow). And it's exactly as you explained **torek**, this is to avoid endless loops. – GuiFalourd Sep 02 '22 at 11:21
  • @torek Are you willing to show a working example of what you suggest? The minimal code in the OP above makes this very easy to reproduce in any GitHub account. I have researched reusable workflows as you suggest, but certain things are not clear to me from the docs like how to make sure that the called workflow only runs on the intended `test` branch. Also, we need a clean approach that allows flexibility for the `test-environ-workflow` to do things like push to a `staging` branch that would run its own `staging-environ-workflow`. This OP's scope is narrow, but the answer must be flexible. – CodeMed Sep 02 '22 at 17:11
  • I'm no GitHub-actions-expert but my (vague) understanding is that one action can refer to another. So let's say that "operation X" needs to do "action X" and "operation Y" needs to do "procedure Y followed by action X". You'd write a separate, callable "action X" and have the yml file say "when X happens, run action X; when Y happens, do these things (direct list) and then run action X". – torek Sep 02 '22 at 22:36
  • In short, we use the old CS rule [add another level of indirection](https://stackoverflow.com/q/288623/1256452). What you need the GitHub expert for (i.e., someone who's not me today) is: what options are there for this indirection, and which one(s) are preferable here and why? How do we pass parameters *to* an abstracted operation? – torek Sep 02 '22 at 22:37
  • 1
    Please do not rollback useful edits! – Dharman Sep 08 '22 at 09:28

1 Answers1

3

As you probably know from the GitHub docs:

When you use the repository's GITHUB_TOKEN to perform tasks, events triggered by the GITHUB_TOKEN, with the exception of workflow_dispatch and repository_dispatch, will not create a new workflow run. This prevents you from accidentally creating recursive workflow runs.

You're using a Personal Access Token to get around this issue, but actions/checkout stores the GITHUB_TOKEN in the local repo config anyways and will use that instead of your PAT when performing git operations.

That is documented in the actions/checkout README file

The auth token is persisted in the local git config. This enables your scripts to run authenticated git commands. The token is removed during post-job cleanup. Set persist-credentials: false to opt-out.

You need to tell actions/checkout to not persist the token using persist-credentials: false.

So the uses step in your dev workflow becomes this:

steps:
  - uses: actions/checkout@v3
    with:
      persist-credentials: false
  - more steps...

UPDATE

@GuiFalourd mentioned in the question comments that you may just need to override the GITHUB_TOKEN environment variable. I actually like that solution better because then you don't have to pass the token in the repo URL, meaning you don't have to override the repo remote at all. I'm not actually overriding the GITHUB_TOKEN environment variable here, but you can pass your PAT to actions/checkout instead.

steps:
  - uses: actions/checkout@v3
    with:
      token: ${{ secrets.GIT_PAT }}
  - more steps...

Here is my minimal working version of your dev workflow:

Changes:

  • You don't need to initialize the repo because actions/checkout has already done that.
  • You don't need to change the remote URL anymore because we're not passing the token in the URL.
  • You don't need to git add --all because you're not changing any files.
  • You don't need to set the user name or email because you're not creating any new commits.
  • You don't have to change or rename your branch to test. You can push the currently checked out HEAD commit to any remote branch by name.
name: dev-environ-workflow
on:
  push:
    branches:
      - dev
jobs:
  push-to-test-branch:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          token: ${{ secrets.GIT_PAT }}
      - shell: bash
        name: Push changes to test branch
        run: git push -f origin HEAD:test
BrokenBinary
  • 7,731
  • 3
  • 43
  • 54
  • @CodeMed GitHub also just implemented a change that allows you to use the `GITHUB_TOKEN` with `workflow_dispatch` or `repository_dispatch` events: https://github.blog/changelog/2022-09-08-github-actions-use-github_token-with-workflow_dispatch-and-repository_dispatch/ However, your question specifically mentions pushing code between branches and those events don't trigger on that. So I'm not going to update my answer. – BrokenBinary Sep 10 '22 at 00:09