Basic concepts of Github Actions
What is a Github Action ?
Simple, is a set of instructions that specify what actions should be performed when certain events occur in your GitHub repository.
Here’s an example of events and actions:
Event | Actions |
---|---|
Branch push |
Deploy code |
New pull_request |
Run tests |
New release |
Build and package the release and notify users |
schedule |
Perform code backups |
New issue |
Assign an issue to a developer |
Workflow File
A workflow file defines the events and instructios for your automation, is a YAML file that resides in the .github/workflows directory of your repository.
Structure
The minimum structure of a workflow file follows these components:
name
: Defines the name of the workflow.on
: Specifies the event(s) that trigger the workflow.jobs
: Defines one or more jobs to be executed within the workflow. Jobs are independent units of work that can run in parallel or sequentially.steps
: Contains a sequence of steps within a job.runs-on
: Allows you to specify the type of machine to run the job on.uses
: Allows you to reference an action or a composite action defined in your repository or from a public repository.run
: Allows you to run a command or a script directly within the step.
name: 'First workflow'
on:
push:
branches:
- main
jobs:
first-job:
runs-on: ubuntu-latest
steps:
- name: STEP 1 - Checkout main branch
uses: actions/checkout@v3
- name: STEP 2 - List repository files
run: ls -la
Flow control
GitHub Actions provides several flow options to control the execution behavior of jobs within a workflow. In this section, we will cover the basic options.
Parallel
Jobs defined under the jobs
are executed in parallel by default.
Example:
Let’s consider a scenario where you want to deploy your app to DEMO and PRODUCTION environments only when you push to the main branch. You can run the deploy-demo
and deploy-prod
jobs in parallel. The following figure illustrates this:
And here’s the corresponding workflow file:
name: Parallel Example
on:
push:
branches:
- main
jobs:
deploy-demo:
runs-on: ubuntu-latest
steps:
- name: Deploy DEMO
run: echo "Deploying DEMO"
deploy-prod:
runs-on: ubuntu-latest
steps:
- name: Deploy PROD
run: echo "Deploying PROD"
Needs
The needs
keyword in GitHub Actions specifies dependencies between jobs. It allows you to define which jobs should complete successfully before an other job starts.
Example:
In the previous example, let’s say you need to run tests before initiating any deployment process. To achieve this, you can create a tests
job and establish dependencies with the deploy-demo
and deploy-prod
jobs. The diagram below illustrates this scenario:
And here’s the corresponding workflow file:
name: Needs Example
on:
push:
branches:
- main
jobs:
tests:
runs-on: ubuntu-latest
steps:
- name: Run tests
run: echo "Running tests"
deploy-demo:
runs-on: ubuntu-latest
needs: tests
steps:
- name: Deploy DEMO
run: echo "Deploying DEMO"
deploy-prod:
runs-on: ubuntu-latest
needs: tests
steps:
- name: Deploy PROD
run: echo "Deploying PROD"
Strategy
The strategy
keyword allows you to create multiple jobs with different configurations.
Example: Let’s imagine that you have a variety of environments where you want to deploy your application. Instead of manually defining separate jobs for each environment, you can leverage the power of the strategy keyword. The following workflow file demonstrates this approach:
name: Strategy Example
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
strategy:
matrix:
environment: [development, staging, demo, production]
steps:
- name: Deploy Application to ${{ matrix.environment }}
run: echo "Deploying to ${{ matrix.environment }}"
If
The if
condition in GitHub Actions provides the ability to execute steps or jobs conditionally based on specific conditions. It allows you to control the flow of your workflow by defining when a particular step or job should run based on certain criteria, such as the values of environment variables.
Here’s an example of using the if
condition to conditionally execute a step within a job:
- name: Notification
if: matrix.environment == 'production'
run: echo "Notification: Deployment to production completed."
In this example, the Notification step will only execute if the value of the matrix.environment
variable is set to production.
Outputs
Outputs
allow you to pass data between jobs within a workflow, enabling communication and sharing of information.
Here’s a simplified example showcasing the usage of outputs
in a workflow:
name: Outputs Example
on:
push:
branches:
- main
jobs:
generate_message:
runs-on: ubuntu-latest
outputs:
message: ${{ steps.message.outputs.message }}
steps:
- name: Joan
id: joan
run: echo "name=JOAN" >> $GITHUB_OUTPUT
# Here's an example of how to use an output from a previous step
- name: Generate Message
id: message
run: echo "message=Hi ${{ steps.joan.outputs.name }}" >> $GITHUB_OUTPUT
display_message:
runs-on: ubuntu-latest
needs: generate_message
steps:
# This step uses the output from the generate_message job
- name: Display Message
run: echo "${{ needs.generate_message.outputs.message }}"
Repository with this examples
On the following repository you can find all the examples explained in this post: Github Actions course examples.
Using existing actions
Using existing GitHub Actions is a powerful practice that can significantly enhance your workflows. By leveraging pre-built actions created and shared by the GitHub community, you can save time and effort.
Some useful links to find existing GitHub Actions:
- GitHub Marketplace: Discover and explore a wide range of actions created by the community.
- GitHub Actions Repositories: Find curated collections of popular actions shared by GitHub Actions.