Create a custom action
Why Create a Custom Action ?
- Boost Efficiency: One of the key advantages is increased efficiency. Consider the scenario where you need to modify deployment workflows or add a new feature to multiple workflows, such as sending notifications after deployment. By creating your own GitHub Action, you only need to make the changes in one place, update the action version, and you’re done.
- Version Control: Custom actions allow you to ensure that critical workflows run on a stable version, while also providing flexibility to experiment with new features without disrupting existing workflows.
Types of Custom Actions
There are several types of custom actions you can create:
- Docker: Action code packaged in a Docker container image.
- JavaScript: Action code packaged in a JavaScript file.
- Composite: Packages a series of actions into a single reusable unit.
On this course we will focus on Composite actions, as Docker and JavaScript actions are mostly used for more complex and specific tasks. Also, I want to highlight that we can substitute big workflows with a single composite action, simplifying your workflows and enhancing readability.
Creating a Composite Action
The composite action is defined in a YAML file named action.yaml in the root directory of your repository. The file must have the following structure:
name
: Name of the action.description
: Description of the action.inputs
: Defines the action’s inputs, which can be required, optional, or have default values.outputs
: Defines the action’s outputs, which can be utilized in subsequent steps of the workflow using the action.steps
: Contains a sequence of steps of the action.uses
Allows you to reference an existing action.shell
: Specifies the script type (bash, pwsh, python, etc.).run
Defines the command to execute.
Example:
name: Basic Composite Action
description: 'A basic composite action'
inputs:
name:
description: 'Your name'
required: true
default: 'Joan'
outputs:
greeting:
description: 'The generated greeting'
value: ${{ steps.generate-greeting.outputs.greeting }}
runs:
using: 'composite'
steps:
- name: Step 1
id: generate-greeting
shell: bash
run: |
echo "Hello, ${{ inputs.name }}!"
echo "::set-output name=greeting::Hello, ${{ inputs.name }}!"
Versioning
Versioning plays a critical role in effectively managing the development and deployment of GitHub Actions. By utilizing version numbers, you can clearly track changes made to your actions and ensure compatibility with existing workflows.
GitHub Actions employ a combination of major and minor version numbers. Major versions (e.g., v1, v2, v3) are typically used for stable releases in production environments. Minor versions (e.g., v1.1, v1.2) are employed during active development for testing and iteration, without disrupting production workflows.
Procedure
- After committing changes, retrieve the latest tag using the following commands:
git fetch
# Search for the last minor version using the pattern "*.*"
git describe --tags --match "*.*" `git rev-list --tags --max-count=1`
- Increment the last minor version to create a new tag. For example, if the last minor version is v1.9, execute:
git tag v1.10 -m "Bump minor version"
- If the new version is stable and ready for production, create or force update the major tag to point to the latest commit:
git tag -fa v1 -m "Update major tag"
- Push the new tags, ensuring the major version tag is force-pushed to overwrite any existing tags:
git push origin v1.10
git push -f origin v1
Hands-On
In this section, we will guide you through the process of creating a new GitHub Action and versioning it.
STEP 1 - Create a New Action
1. Create a new repository on GitHub.
2. Inside the repository, create a file named action.yaml with the following content:
name: Basic Composite Action
description: 'A basic composite action'
inputs:
name:
description: 'Your name'
required: true
default: 'Joan'
outputs:
greeting:
description: 'The generated greeting'
value: ${{ steps.generate-greeting.outputs.greeting }}
runs:
using: 'composite'
steps:
- name: Step 1
id: generate-greeting
shell: bash
run: |
echo "Hello, ${{ inputs.name }}!"
echo "::set-output name=greeting::Hello, ${{ inputs.name }}!"
git add .
git commit -m "feat: First version of the greeting action."
git tag v0.1
git push origin main v0.1
STEP 2 - Create a Workflow Using Minor Version v0.1 of the Action
1. Inside your repository, create a file named test-action-v0.1.yaml inside .github/workflows/ folder with the following content:
name: Test Action minor version v0.1
on:
push:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Test v0.1 minor version - Greeting
id: greeting
uses: joanplaja/action-template@v0.1
with:
name: "Pau Lozano"
- name: Show greeting
run: echo ${{steps.greeting.outputs.greeting}}
git add .
git commit -m "feat: Adding a workflow to test action version v0.1"
git push origin main
STEP 3 - Update the Action and Align the Major Version
1. Update the action.yaml contents with the following:
name: Dummy deploy
description: 'This is not real deploy'
inputs:
app_name:
description: 'Application name'
required: true
environment:
description: 'Target environment for deployment'
required: true
runs:
using: 'composite'
steps:
- name: Build the application
id: build
shell: bash
run: echo "Building application ${{ inputs.app_name }}"
- name: Deploy application
id: deploy
shell: bash
run: |
echo "Deploying application to ${{ inputs.targetEnvironment }}"
echo "::set-output name=deployStatus::success"
- name: Notify success
id: notify_success
if: steps.deploy.outputs.deployStatus == 'success'
shell: bash
run: echo "Notify the new deployment"
- name: Notify error
id: notify_error
if: steps.deploy.outputs.deployStatus != 'success'
shell: bash
run: echo "Notify the team about the error"
git add .
git commit -m "feat: New version of the action, now it deploys a dummy environment."
git tag v0.2
git push origin v0.2
git tag -fa v0 -m "Update major tag"
git push -f origin v0
STEP 4 - Create a Workflow Using Major Version v0 of the Action
Inside your repository, create a file named test-action-v0.yaml inside .github/workflows/ folder with the following content:
name: Test Action major version v0
on:
push:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Test v0 major version - Dummy deploy
uses: joanplaja/action-template@v0
with:
app_name: Backend
environment: test
- Commit and push the changes to the repository.
git add .
git commit -m "feat: Adding a workflow to test action version v0"
git push origin main
- Check the results on the Actions tab of your repository.
Template repository
You can find all the hands-on project, which can be used as a template for creating any custom action, on the following repository.
Image by storyset on Freepik