Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dive into GitHub Actions #2

Open
4 tasks
lakruzz opened this issue Oct 30, 2023 · 0 comments
Open
4 tasks

Dive into GitHub Actions #2

lakruzz opened this issue Oct 30, 2023 · 0 comments
Labels
Template Template issue

Comments

@lakruzz
Copy link
Member

lakruzz commented Oct 30, 2023

GitHub actions

GitHub actions are an almost endless source of features that will allow you to trigger on any kind of event that happens on GitHub. The trigger is executed in a container injected with your source code. GitHub actions are extensions which are effectively repos on GitHub. You can then use them from the workflow (.yml file).

Some actions are officially published but you and your team can just create your own actions and store them on GitHub and use then directly from there - no official release is required for it to be available.

The actions that trigger are defined in a workflow file - and since the runtime environment for the execution is a linux based container you can literally run anything that you can script - either embedded in the workflow file or in a separate script you call from the the workflow.

The runtime environment in which the action is triggered is default pre-authenticated (you can turn it off) so it can access the GitHub eco-system with the same credentials as yourself.

GitHub has a full fledged API that allows you to do access all GitHub features. But it's tedious and verbose to use an API like that from a shell script. So in January 2020 GitHub released the first version of the GitHub CLI gh. Although it it doesn't (yet) cover all features it's amazingly comprehensive. It gives you command line access to 'all' GitHub features - from the terminal. Which means that your actions can do anything.

In this issue:

  • Understand the workflow yaml file; on, env, permissions, jobs, usesand run.
  • See the gh CLI in action
  • Use the GitHub REST API for additional stuff gh doesn't support (yet)
  • Log messages to the action execution using different log levels
  • Use the GitHub web interface to create new workflows from 100's of predefined templates

Let's examine the workflow that was triggered on repo-creation - when you pushed "Use this template".

Here's the context:

Problem Solution Value
When I do tutorials and training materials in GitHub I want to present the material and exercises as issues. But both forks and templates on GitHub ignores the GitHub issues from the source repo — they are simply not copied over in the new repo. Use GitHub Actions to start a workflow that triggers on the creation of a repo based on using another repo as a template. In that workflow use the GitHub CLI gh to reach back into the source repo, read the issues there and recreate them in the copy. Issues from the source are now conceptually part of the template. From the perspective of didactics it has the advantage that meta data is kept out from cluttering the git filesystem. Rather they are stored in the same place at developers would naturally have that kind of meta data. Learners get to familiarize themselves with GitHub issues too and they'll have a natural place to record notes on their individual earning process.
  • 👉 Go to the ▶️ Actions panel and open the workflow that just ran on "Initial commit" 👈

image You will see something similar to this. Each section is expandable/collapsable and gives you exact details on what happened during the workflow execution.

  • 👉 Open the worflow file that ran this particular workflow" 👈

In the left panel you'll find a read-only reference to the workflow file, in the version as it looked in the actual commit that triggered the workflow.

  • 👉 Find the original workflow file in the git repo at /.github/worflows/template.yml and open that in the web editor 👈

You'll see the same file, but in the editable version from masterbranch. Since you are now in a genuine VS Code IDE you'll the IntelliSense support you expect.

image

As an example, if you hover on: you'll get instant access to a tool-tip box on this particular keyword. Apparently VS Code has built in support for GitHub Actions Workflow files.

  • 👉 Hover over the keywords in the worflow file and see how much you'll learn about GitHub Actions 👈

A rundown on what goes on in this particular workflow:

In the reminder of this particular issue I'll not throw exercises at you, but rater walk you through some of the finer details in this flow. If you are already familiar with the semantics of the workflow files you may skip it - and then again; It does take you through some special cases, that serves to clarify the point, that a lot can be done with small means, by standing on the shoulders of other's general abstractions: Fight software complexity with more software!

Workflow: /.github/worflows/template.yml

Lines 1-6
name: Initial commit workflow

on:
  push:
    branches:
      - '**' 

name is optional, it serves as a heading in the workflow execution. on- defines what should trigger this workflow. Since there is not an actual event for creating a new repo the hack is to use '**' this will make the trigger fire on any branch.

Lines 8-9
env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

env is the section that defines environment variables. Setting GITHUB_TOKEN is the standard way of authenticating the GitHub CLI. GitHub actions support secrets and GitHub automatically generate the a token when strating a workflow, it's stored in the secrets so this becomes that standard way of using the automatic token authentications

Lines 11-15
permissions:
  checks: write
  actions: write
  contents: write
  issues: write

permissions is used to change the permission if you need anything other than the default permissions. For this particular run I had to add explicit write permissions to actions (as you'll see later I'll disable this flow as soon as it has run once) and issues so the workflow can create new issues.

Lines 17-20
jobs:
  cpissues:
    name: "Initial commit only"
    runs-on: ubuntu-latest

jobs is where the action happens - the section defines all the jobs that the workflow knows of. Each job has it's on tag (you define the name yourself) in this case I only have one job and I came up with the clever name cpissues.

runs-on specifies the runner and image that this workflow will run in. I only need to do small bits in the terminal, so I'm happy with the default latest Ubuntu But even though runs-on is just a small clause it has a huge impact and by defining your own runners and images you can open up a complete customized world to Platform Engineering and Internal Development Platforms where you can configure the actions to support anything as code - quite literally "anything"! I will point you to a an example of using a customized docker container in a bit, but the finder details of the world that opens up underneath runs-on is beyond the scope of this tutorial. So go and explore yourself.

Lines 21-25
    if: ${{ contains(github.event.head_commit.message, 'Initial commit') }}
    steps:       
      - name: "Checkout"
        uses: actions/checkout@v3

steps defined the different steps executed in this workflow. Each that becomes an expandable/collabsable setting in the job execution log you saw earlier, so this is how tiy add abit of readbility to your workflows. The rest of the this workflow happens in the context of these steps but before the workflow continues and if statement is used to fix the inconvenient fact that there is not dedicated event that fires on repository creation only that this workflow then fires on everything; The steps are simply ignored, unless the commit message of the commit spells exactly 'Initial commit'. Because this is exactly the commit message the GitHub always uses when it creates new repos off of templates.

uses i referring to actions so -apparently - the workflow somehow has access to to a GitHub Action called actions/checkout which is executed with no additional parameters in version 3.

As hinted earlier the access is simply that this is a Github repo called checkout under the GitHub user or organisations with handle actions. Consequently there should be somthing of interest at:

https://github.com/actions/checkout

There is! The user actions is controlled by GitHub self, so you know that if an action is located here it's considered GitHub standard. Almost every workflow will call this particular action as the first - It makes sure, that the rest of the workflow execution has access to the content of the repo.

Lines 25-38
      - name: "Raise semaphore or quit"
        run: |
          ... 
          ...
          if $(gh workflow disable template.yml); then
            echo ::notice title=Workflow successfully disabled::This also works as a raised semaphore - parallel workflow runs will see it and cancel
          else
            echo "::warning title=Another job got here first::This room is crowded - I'm outta here!"
            curl -X POST \
              -H "Accept: application/vnd.github.v3+json" \
              -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
              https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/cancel
              exit 1
          fi

run is similar to uses but where uses calls a predefined action, run executes native shell commands. Starting the run clause with a pipe | followed by a new-line is a notation used to make the rest of the clause - a shell script.

The first thing that happens is that the workflow template.ymlis disabled. The is done simply by using the gh cli The command will raise an error if it doesn't succeed - like if it's already disabled.

image

The next line demonstrate how to use simple echo statements to create messages in the workflow execution log four levels are supported: debug, notice, warning and error. You already saw the output from this earlier, when you browsed the content on the ▶️ Actions panel.

The else clause runs if we didn't succeed to disable the workflow - as the message states, another job got here first. This is a precaution that deals with the occasional abnormality that sometimes GitHub fires the workflow twice on the same catch-all '**' branch pattern. When that is the case, I'd rather have this workflow cancelled, that having the record of a failed workflow. But cancelling a running instance of a workflow is is not supported from the gh CLI. It is hover supported by a webhook on the GitHub REST API.

Consequently this worflow now works as intended: It runs once - and only once, and only on the initial commit. And it doesn't take up any polling resources after, because it's effectively disabled.

Lines 39-41
      - name: "Copying issues over"
        run: .github/template/cpissues.sh

run executes the script I provided in this repo at /.github/template/cpissues.sh In large; It starts by reading settings from a local gitconfig file (lines #3-7) and it then uses gh to generate a json output of all issues in the source repo that has the designated label template (line #18). It then iterates over this json and uses an unholy mix of jq, base64 and sed - which are all standard linux commands - to capture the title of the issue (lines #22-26) and then, checks if an issue with the same title doesn't already exit (line #28) if not it pipes the issue body into a temporary file and uses a special flag on on the gh cli to create an issue from the file (lines #30-35)

Lines 42-49
      - name: "Set the README"
        run: |
          cp .github/template/README.md .
          git config --global user.email "[email protected]"
          git config --global user.name "The GitHub Action Bot"
          git add .
          git commit -m "Updated the README"
          git push origin

This bit uses run to replace the README.md in the root with the one that's designed, to be shown in the copy. This needs to be committed and pushed, and in order to do that we need to verify to git who we are by name and email.

This creates a new commit - If you go and take a look, your repo already has two commits, but also notice that you only have one job execution - despite that the workflow subscribes to any branch '**'; the disablement of the job works as intended.

@lakruzz lakruzz added the Template Template issue label Oct 30, 2023
@lakruzz lakruzz changed the title Examine the action that was triggered on repo-creation Take action on GitHub Actions Oct 31, 2023
@lakruzz lakruzz changed the title Take action on GitHub Actions 2: Take action on GitHub Actions Nov 1, 2023
@lakruzz lakruzz changed the title 2: Take action on GitHub Actions 2: Dive into GitHub Actions Nov 1, 2023
@lakruzz lakruzz changed the title 2: Dive into GitHub Actions Dive into GitHub Actions Nov 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Template Template issue
Projects
None yet
Development

No branches or pull requests

1 participant