2

I am attempting to push code to a GitHub repository from a workflow run in GitHub Actions Beta (the YAML ones). This is easy to do by just running git push after setting the origin remote URL to one containing credentials, so that Git knows how to authenticate with GitHub.

GitHub Actions even get a PAT out of the box: GITHUB_TOKEN, which can be used and the whole system is smart enough to know not to schedule another action when commits are pushed to a repository using a PAT known to be associated with a previous workflow run.

This is great, however, there are use-cases for using a custom PAT (in my case to trigger GitHub Pages to build, which the out of the box PAT won't do) and using custom PAT loses the advantage of having GitHub know not to run another workflow after pushing commits from the current one.

As a result, one finds themselves in an infinite loop of workflows when using a custom PAT. Many CI solutions honor ***NO_CI*** in a commit message and won't run any checks/builds/whatever if this string is present in the commit message. GitHub Actions Beta do not care about it.

The only thing I could come up with is to make the GitHub Action workflow job/step conditional and construct a condition like this:

- if: !contains(github.commit_message, "***NO_CI***")

However the github context object does not have a field that would contain the commit message and the contexts do not seem to be expressive enough to allow me to run a command to obtain the commit message from the SHA using Git and run the contains on that.

Do I have any options to achieve this?

Tomáš Hübelbauer
  • 9,179
  • 14
  • 63
  • 125

4 Answers4

2

You can configure Github Actions the way you want.

- if: "!contains(github.event.head_commit.message, '***NO_CI***')"

# dump all github context
- name: Dump GitHub context
  env:
    GITHUB_CONTEXT: ${{ toJson(github) }}
  run: echo "$GITHUB_CONTEXT"

Also do not forget to enclose the sentence in quotes when using !.

Reference: https://help.github.com/en/github/automating-your-workflow-with-github-actions/contexts-and-expression-syntax-for-github-actions

seunggi
  • 166
  • 6
1

Check if an alternative approach exists within the GitHub Actions for GitHub Pages

For instance: peaceiris/actions-gh-pages, where an ACTIONS_DEPLOY_KEY SSH key is added and used for that workflow.

The GitHub Pages Deploy only includes:

Remember to add appropriate filter action as dependencies on this action to avoid deploying from all branches, as well as to avoid "infinite loops" where the deployment itself would trigger another run.

Such filters are used (in this commit or this one) in the workflow I mentioned above.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • This is a great starting point for taking inspiration from others' codebases. I am serving my GitHub Pages from docs though so this won't work for me. I have figured out a solution of my own which I will post. – Tomáš Hübelbauer Sep 07 '19 at 12:50
1

GitHub Actions do not support ***NO_CI*** natively, instead they rely on you using the predefined secrets.GITHUB_TOKEN context value to push to the repository. GitHub Actions will special-case this token and not issue any new workflow runs if this token is used. But they will also not deploy GitHub Pages when a push is made with this token.

I have found that in order to get both this behavior (workflow push to repository doesn't cause another workflow run + GitHub Pages get built from the workflow run artifacts pushed to the repository), it's necessary to combine two things:

  • Use secrets.GITHUB_TOKEN to do the push to the repository
  • Use a custom PAT with repo_public (or repo for private) scope placed in the Secrets tab in the repository settings and accessed using secrets.GITHUB_PAGES_PAT
  • Run GitHub Pages deployment manually using the API with the custom PAT (the default token is marked as an integration token and is not allowed to invoke this API method)

An example .github/workflows/main.yml:

name: github-pages
on:
  push:
    branches:
    # Limit to the `master` branch
    - master
  schedule:
    # Run hourly
    - cron:  '0 * * * *'
jobs:
  github-pages:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - name: Generate GitHub Pages
      run: |
        set -x
        # Configure Git for the push from the workflow to the repository
        git config --global user.email "tomas@hubelbauer.net"
        git config --global user.name "Tomas Hubelbauer"
        # Check out the `master` branch because by default GitHub Actions checks out detached HEAD
        git checkout master
        # Run script which generates your artifacts to push to the repo
        ./script.sh
        # Add generated artifacts to Git stage
        git add out
        # Reset unstaged changes to prevent `git commit` from yelling if there's changes outside of `out` (cache, …)
        git checkout -- .
        # Commit the changes to the Git repository to deploy GitHub Pages (if any)
        if git diff-index --quiet HEAD --; then
          exit
        fi
        git commit -m "Generate GitHub Pages"
        # Authenticate with GitHub using the default integration PAT (this one won't deploy GitHub Pages)
        git remote set-url origin https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
        # Pull before pushing to integrate fast forward changes if any
        git pull --rebase
        # Push the changes to GitHub without causing another workflow run thanks to the default integration PAT
        git push
        # Enqueue a GitHub Pages deployment using the API with the custom PAT with repo_public or repo (private) scope
        curl -f -X POST -H "Authorization: token ${{ secrets.GITHUB_PAGES_PAT }}" -H "Accept: application/vnd.github.mister-fantastic-preview+json" "https://api.github.com/repos/${{ github.repository }}/pages/builds"
Tomáš Hübelbauer
  • 9,179
  • 14
  • 63
  • 125
1

Here is a workaround for ***NO_CI*** and [skip ci].

name: github pages

on:
  push:
    branches:
      - master  # Set a branch name to trigger deployment

jobs:
  skipci:
    runs-on: ubuntu-18.04
    steps:
      - run: echo "[skip ci] ${{ contains(github.event.head_commit.message, '[skip ci]') }}"

  deploy:
    runs-on: ubuntu-18.04
    if: contains(github.event.head_commit.message, '[skip ci]') == false
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true  # Fetch Hugo themes (true OR recursive)
          fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod

      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v2
        with:
          hugo-version: '0.76.3'

      - name: Build
        run: hugo --minify

      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./public

The deploy job skipped with the commit message update [skip ci] Log: https://i.stack.imgur.com/3rVFG.png

peaceiris
  • 106
  • 1
  • 1