Create and publish custom GitHub actions

Prepearing for GitHub certification - Create and publish custom GitHub actions

Table of Contents


Create a custom GitHub action

Types of GitHub Actions

  • Actions are individual tasks that you can use to customize your development workflows.
  • Can create your actions by writing custom code that interacts with your repository to perform custom tasks or by using actions shared by GitHub
  • Types of Actions
    • Docker container action
    • JavaScript action
    • Composite run steps action

Docker container action

  • Package the environment with the GitHub Actions code
  • Consistent and reliable environment, all dependencies within a container
  • Good when the action needs to run in a specific env config
  • Can Customize OS and tools
  • Are slower than JavasScript actions - needs to build and retrieve a container

Recommendations before building creating one:

  • Basic understanding of how to use environment variables
  • How to use Docker container filesystem

Steps to create Docker container action

  1. Create a Dockerfile to define the commands to assemble the Docker image.
  2. Create an action.yml metadata file to define the inputs and outputs of the action. Set the runs: using: value to docker and the runs: image: value to Dockerfile in the file.
  3. Create an entrypoint.sh file to describe the docker image.
  4. Commit and push your action to GitHub with the following files: action.yml, entrypoint.sh, Dockerfile, and README.md.

JavaScript actions

  • Can run directly on the runner machine
  • Separate the action code from env that is used to run the action
  • Thanks to that action code is simplified and execute faster than Docker container actions

Prerequisits for creating

  • Download Node.js with npm
  • Optional step (recommended) - use GitHub Actions Toolkit Node.js.

Steps to creat JavaScript action

  1. Create an action.yml metadata file to define the inputs and outputs of the action as well as tell the action runner how to start running this JavaScript action.
  2. Create an index.js file with context information about the Toolkit packages, routing, and other functions of the action.
  3. Commit and push your action to GitHub with the following files: action.yml, index.js, node_modules, package.json, package-lock.json, and README.md.

Composite run steps actions

  • A composite run steps action allows you to combine multiple workflow run steps within one action.
  • Reuse actions using shell scripts
  • Mix multiple shell languages within the same action

Metadata and syntax needed to create an action

  • Review action.yml file to assess which inputs, outputs, description, runs, and other configuration information are needed for the action

  • Metadata syntac for GitHub Actions

Inputs

  • Specify data the action expects during its runtime
  • Sample:
inputs:

  firstNameStudent:

    description: 'First name of student'

    required: false

    default: '1'

  studentGrade:

    description: 'Grade of the student'

    required: true

Outputs

  • Enable you to declare data - can be used in later running actions in a workflow
  • Sample:
outputs:

average:

  description: 'The average grade of the students'

Runs

  • Defines the command necessary to execute your action
  • Depends on how an action is created

  • Samples:
  • runs for Docker actions
    • using: needs to be set to docker to run a Docker container action.
    • image: Docker image used as the container to run the action.
    runs:

        using: 'docker'

        image: 'Dockerfile'

    
  • runs for Javascript actions
    • using: application used to execute the code as defined in main.
    • main: file that contains the action code. The application-defined in using executes this file
    runs:

      using: 'node12'

      main: 'main.js'

    
  • runs for composite run steps actions
    • using: needs to be set to “composite” to run a composite run step.
    • steps: run steps to run the action.
    • steps[*].run: command you want to run (can be inline or a script in your action repository).

    {% highlight yml %} runs: using: “composite” steps: - run: ${{ github.action_path }}/test/script.sh shell: bash {% endhighlight %}

Branding

  • Can customize badge of action
branding:

  icon: 'shield'  

  color: 'blue'

Workflow commands

  • Enable you to communicate with the GitHub Actions runner machine by printing formatted lines of text to the console
  • Use either with shell commands or within action
  • Useful to share info between workflow steps
  • Most use echo command in a specific format
  echo "::workflow-command parameter1={data},parameter2={data}::{command value}"
- name: workflow commands logging messages

  run: |

    echo "::debug::This is a debug message"

    echo "This is an info message"

    echo "::error::This is an error message"

    echo "::warning::This is a warning message"
  • Print log with filename, line nr , col nr.
  echo "::error file=app.js,line=10,col=15::Something went wrong"

Note: It’s important to note that these workflow commands need to be on a single line

  • Can set exit codes to set the status of action
  • Use @actions/core for JS Actions
  • use entrypoint.sh for Docker container actions

Publish a custom GitHub action

Public

  • Can be used by workflows in any repository
  • Recommendation:
    • Own repo for action
    • Enables version, track and release action
    • simplifies collaboration

Private

  • Can only be used in workflows with the same repository
  • Recommendations:
    • store action in .github directory

Document your action

  • Create a README.md and include everything a user should know to use the action

Release and version your action

  • Define a release management strategy to control how updates are distributed
  • Major version updates including necessary critical fixes and security patches that affect compatibility need to be documented clearly

Good practices for release and version management

  • Specify a major version when using the action
  • Only direct users to a more specific version if they encounter issues
  • Can be done by their GitHub Actions workflow to target a tag, commit SHA, or a specific branch name for a release

Tags

  • Good way to manage releases
  • Easily distinguish between major and minor version
  • Good practices:
    • Use semantic versioning
    • Create and validate a release on a release branch before creating the release tag
    • Move the major version tag (such as v1, v2) to point to the Git ref of the current release
    • Introduce a new major version tag (v2) for changes that will break existing workflows
    • Release major versions with a beta tag to indicate their status

Use a commit’s SHA

  • Tags are useful but they can be deleted or moved
  • Using a commit SHA for versioning will give you the most reliable and secure way to version and use an action
  • If you are using the commit’s SHA for release management, you need to use the full SHA value and not the abbreviated value
steps:

    - uses: actions/javascript-action@2522385f6f7ba04fe7327647b213799853a8f55c

Publish an action to the GitHub Marketplace

  • Are published right away if requirements are met
  • Ensure that repo only includes: metadata file, code and files necessary for the action
  • Requirements (Apply to JS and Docker-based actions ):
    • The action must be in a public repository.
    • Each repository must contain a single action.
    • The action’s metadata file (action.yml or action.yaml) must be in the root directory of the repository.
    • The name in the action’s metadata file must be unique on the GitHub Marketplace.
      • The name cannot match a user or organization on GitHub unless the user or organization owner is publishing the action. For example, only the GitHub organization can publish an action named github.
      • The name cannot match an existing GitHub Marketplace category.
      • The name cannot match an existing GitHub feature.

Excercise : Creating JavaScript Action

Note:

  • I had issues with the last action in the exercise. If you manage to complete that please let me know how you did it.