Fragment: Using Git Commit Messages as a Command Line?

Pondering the way in which the fastai/fastpages repo (as described here) generates a PR from the first commit after the repo is cloned, I started pondering this:

name: Setup
on: push

    if: (github.event.commits[0].message == 'Initial commit') && (github.run_number == 1)
    runs-on: ubuntu-latest

    - name: Set up Python
      uses: actions/setup-python@v1
        python-version: 3.6

    - name: Copy Repository Contents
      uses: actions/checkout@v2
    - name: modify files
      run: |
        import re, os
        from pathlib import Path
        nwo = os.getenv('GITHUB_REPOSITORY')
        username, repo_name = nwo.split('/')
        readme_template_path = Path('')
        readme_path = Path('')
        config_path = Path('_config.yml')
        pr_msg_path = Path('')
        assert readme_template_path.exists(), 'Did not find in the current directory!'
        assert readme_path.exists(), 'Did not find in the current directory!'
        assert config_path.exists(), 'Did not find _config.yml in the current directory!'
        assert pr_msg_path.exists(), 'Did not find in the current directory!'
        # replace content of README with template
        readme = readme_template_path.read_text().replace('{_username_}', username).replace('{_repo_name_}', repo_name)
        # update _config.yml
        cfg = config_path.read_text()
        cfg = re.sub(r'^(github_username: )(fastai)', r'\1{}'.format(username), cfg, flags=re.MULTILINE)
        cfg = re.sub(r'^(baseurl: )("")', r'\1"/{}"'.format(repo_name), cfg, flags=re.MULTILINE)
        cfg = re.sub(r'^(github_repo: ")(fastpages)', r'\1{}'.format(repo_name), cfg, flags=re.MULTILINE)
        cfg = re.sub(r'^(url: "https://)(")', r'\1{}\3'.format(username), cfg, flags=re.MULTILINE)
        # prepare the pr message
        pr = pr_msg_path.read_text().replace('{_username_}', username).replace('{_repo_name_}', repo_name)
      shell: python

    - name: commit changes
      run: |
        git config --global "${GH_EMAIL}"
        git config --global "${GH_USERNAME}"
        git checkout -B fastpages-automated-setup
        git rm CNAME action.yml _checkbox.png
        git rm _notebooks/2020-02-21-introducing-fastpages.ipynb
        git rm .github/workflows/chatops.yaml
        git rm -rf .github/ISSUE_TEMPLATE
        git add _config.yml
        git commit -m'setup repo'
        git push -f --set-upstream origin fastpages-automated-setup
        GH_EMAIL: ${{ github.event.commits[0] }}
        GH_USERNAME: ${{ github.event.commits[0].author.username }}

    - name: Open a PR
      uses: actions/github-script@0.5.0
        github-token: ${{secrets.GITHUB_TOKEN}}
        script: |
          var fs = require('fs');
          var contents = fs.readFileSync('', 'utf8');
                        owner: context.repo.owner,
                        repo: context.repo.repo,
                        title: 'Initial Setup',
                        head: 'fastpages-automated-setup',
                        base: 'master',
                        body: `${contents}`

In particular, the line if: (github.event.commits[0].message == 'Initial commit') got me wondering: what if we use commit messages to perform some other actions?

For example, something I keep wondering about is how to generate Binder environment specifications that can be easily reused. I’ve pondered this before in the context of “Binder base boxes”, the most useful approach (I think) being to define a basebox repo that is prebuilt and then nbgitpull your own repo into it.

Another approach I’ve idly wondered about was a simple script that could generate binder/ setups for you. For example binder_base chemistry might generate you a binder/ directory with apt.txt, requirements.txt and postBuild files preconfigured with packages that are relevant to working with chemistry related content; binder_base astronomy might create you a binder/environment.yml that will pull in a load of astronomy packages. Other switches might let you automatically add-in config info around package installation and setup for various extensions, and so on.

Putting these two together, I can imagine a commit message that would call an action that could:

  • create a domain relevant set of binder/ files;
  • commit them to the repo (if permissions available), or create a PR.

Author: Tony Hirst

I'm a Senior Lecturer at The Open University, with an interest in #opendata policy and practice, as well as general web tinkering...