Sure! Here's a more detailed and comprehensive guide on GitHub Actions, covering as much ground as possible, including events, jobs, workflows, and many other advanced concepts:
GitHub Actions is a feature within GitHub that automates workflows in response to events that occur in a repository. It enables Continuous Integration (CI), Continuous Deployment (CD), and other automation tasks directly in GitHub repositories.
- Workflow: A YAML file that defines a set of automated tasks (jobs) that run in response to specific events.
- Event: An action that triggers a workflow, such as pushing code or creating a pull request.
- Job: A set of steps that run on a specified runner environment.
- Step: A single task in a job, which could be a script, a GitHub Action, or a shell command.
- Runner: A server or environment that runs your workflow jobs. It can be hosted by GitHub (GitHub-hosted runner) or self-hosted.
Events are the trigger points that activate workflows. Here are the different types of events you can use in GitHub Actions:
-
Push Event (
push
):- Triggered when commits are pushed to the repository.
- Can be limited to specific branches or paths.
on: push: branches: - main paths: - '**/*.js'
-
Pull Request Event (
pull_request
):- Triggered when a pull request is created or updated.
- Can be configured to trigger on specific actions, such as opened, edited, or closed.
on: pull_request: types: [opened, closed]
-
Issue Event (
issues
):- Triggered when an issue is created, edited, or closed.
- Useful for automating issue handling or interacting with GitHub Issues.
on: issues: types: [opened, edited, closed]
-
Release Event (
release
):- Triggered when a release is created, published, or deleted.
on: release: types: [created, published]
-
Workflow Dispatch (Manual Trigger) (
workflow_dispatch
):- Allows a workflow to be triggered manually via the GitHub UI.
- Supports inputs that can be specified during the manual trigger.
on: workflow_dispatch: inputs: deploy_env: description: 'Deployment Environment' required: true default: 'staging'
-
Scheduled Event (
schedule
):- Allows workflows to run at specific times, like cron jobs.
- Can be used for tasks that need to run periodically, such as nightly builds or cleanup jobs.
on: schedule: - cron: '0 0 * * *' # Runs at midnight every day
-
Webhooks (
webhook
):- Custom events that can trigger workflows based on external services or HTTP requests.
-
Commit Status Event (
status
):- Triggered when the status of a commit changes. This can be used for status checks, build results, etc.
-
Job: A set of steps that run in a defined environment, called a runner. Jobs can run in parallel or in a defined sequence (one after another).
Example:
jobs: build: runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@v2
-
Runners: The environment in which your jobs run. There are two types of runners:
- GitHub-hosted runners: Pre-configured environments provided by GitHub (e.g., Ubuntu, Windows, Mac).
- Self-hosted runners: Custom environments that you configure yourself.
Example of using a self-hosted runner:
jobs: build: runs-on: self-hosted steps: - name: Checkout code uses: actions/checkout@v2
A typical workflow consists of the following components:
- name: A name for your workflow.
-
on: Specifies the event that triggers the workflow (e.g.,
push
,pull_request
). - jobs: Contains one or more jobs to be executed.
- steps: A sequence of individual tasks that make up a job.
Example workflow structure:
name: CI Workflow
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- name: Run tests
run: npm test
Steps are individual tasks that run in a sequence. A step can either run a command or use an action.
-
Using Actions: Actions are reusable pieces of code that automate common tasks. GitHub provides a marketplace for actions.
Example:
steps: - name: Checkout repository uses: actions/checkout@v2
-
Running Commands: Steps can also run shell commands directly.
Example:
steps: - name: Run test script run: npm test
GitHub Actions provides contexts and expressions to use dynamic values in your workflows. These allow you to access information about the workflow, job, and other entities.
A context provides information about the workflow run and is used within expressions. Examples include:
-
github
– Information about the GitHub environment (repository name, actor, etc.). -
env
– Access to environment variables. -
secrets
– Access to secrets stored in GitHub.
Expressions allow you to evaluate and access context variables dynamically using ${{ }}
syntax.
Example:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Print current commit SHA
run: echo "Commit SHA: ${{ github.sha }}"
- Environment Variables: These are global values that are available for the entire job. You can use them to store values that you want to access in multiple steps.
Example of setting environment variables:
jobs:
build:
runs-on: ubuntu-latest
env:
NODE_ENV: 'production'
steps:
- name: Print NODE_ENV
run: echo $NODE_ENV
-
Secrets: Store sensitive data securely in the repository settings, and reference them in your workflow using
${{ secrets.SECRET_NAME }}
.
Example of using a secret:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy to server
run: deploy.sh
env:
API_KEY: ${{ secrets.API_KEY }}
A matrix build allows you to run multiple jobs with different configurations (like testing on different versions of Node.js or Python).
Example of a job matrix:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node: [12, 14, 16] # Test across three versions of Node.js
steps:
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node }}
- name: Run tests
run: npm test
GitHub Actions allows you to cache dependencies between workflow runs to save time. This is particularly useful for managing package dependencies (e.g., Node.js npm
or Python pip
).
Example:
steps:
- name: Cache Node.js dependencies
uses: actions/cache@v2
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
GitHub Actions can be used to automate deployments and publish content, such as pushing Docker images to Docker Hub or creating releases.
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Publish to GitHub Package Registry
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
You can use GitHub Actions to deploy applications to cloud services (e.g., AWS, Azure, Google Cloud) by setting up the appropriate actions or using CLI commands in your steps.
Setting up self-hosted runners enables you to use your own machines to run workflows. This is useful for more control, custom environments, or private network access.
Workflows can be reused across multiple repositories or workflows to avoid duplication.
Example:
jobs
:
reuse:
uses: user/repo/.github/workflows/reusable-workflow.yml@v1
If existing actions do not meet your needs, you can create custom GitHub Actions using Docker or JavaScript.
-
Workflow Status Badge: Add a status badge to your README to show the status of your workflows.
-
Handling Failures: Use
continue-on-error: true
for steps or jobs that you do not want to fail the workflow. -
Workflow Secrets Management: Always use GitHub's secrets feature to manage sensitive data securely.
-
Job Matrix for Parallel Testing: Use job matrices to run tests across multiple environments (e.g., different OS versions or languages).
This comprehensive guide should help you dive deep into GitHub Actions and its capabilities. Let me know if you need more clarification or further examples!
GitHub Actions supports a wide range of built-in webhook events. These events are emitted when specific actions occur in your GitHub repository or organization. Below is a categorized list of commonly used events:
-
push
: Triggered on agit push
to a branch. -
pull_request
: Triggered on PR events likeopened
,closed
,merged
, etc. -
issues
: Triggered on issue events likeopened
,edited
,deleted
. -
create
/delete
: Triggered when a branch or tag is created or deleted. -
fork
: Triggered when a repository is forked. -
repository_dispatch
: Custom external trigger (discussed below in detail).
-
release
: Triggered on events like creating, editing, or publishing a release. -
workflow_dispatch
: Manual workflow trigger via GitHub Actions UI. -
deployment
: Triggered when a deployment is created. -
deployment_status
: Triggered when a deployment status changes.
-
pull_request_review
: Triggered when a PR review is submitted. -
pull_request_target
: Similar topull_request
, but runs with the target repository's permissions. -
discussion
: Triggered on GitHub Discussions events. -
star
: Triggered when someone stars a repository.
-
schedule
: Triggered on a cron-like schedule (time-based workflows). -
workflow_run
: Triggered when another workflow completes. -
check_run
/check_suite
: Triggered by status checks.
This allows you to manually trigger workflows via the GitHub Actions UI, with optional input parameters.
Example Workflow:
name: Manual Trigger Workflow
on:
workflow_dispatch:
inputs:
environment:
description: 'Deployment environment'
required: true
default: 'production'
jobs:
manual-trigger:
runs-on: ubuntu-latest
steps:
- name: Print Environment
run: echo "Deploying to ${{ github.event.inputs.environment }}"
This is triggered by external systems sending a POST
request to the GitHub API, allowing workflows to respond to events outside GitHub.
Example Workflow:
name: External Trigger Workflow
on:
repository_dispatch:
types:
- sync-data
jobs:
external-trigger:
runs-on: ubuntu-latest
steps:
- name: Print Payload
run: echo "Triggered by: ${{ toJSON(github.event.client_payload) }}"
API Call to Trigger:
curl -X POST \
-H "Authorization: Bearer YOUR_GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/<OWNER>/<REPO>/dispatches \
-d '{"event_type": "sync-data", "client_payload": {"key": "value"}}'
You can define multiple custom event_type
values:
- sync-data
- run-tests
- update-logs
- These are arbitrary and allow you to customize workflows based on your needs.
Feature | workflow_dispatch |
repository_dispatch |
---|---|---|
Triggered By | Manual via GitHub UI | External system/API call |
Supports Inputs | Yes | Yes (via client_payload ) |
Use Case | Manual triggers for workflows | Integrating with external systems |
Use repository_dispatch
to trigger a CI/CD pipeline when a new version of software is released in an external system.
Trigger workflows to fetch data from APIs, update configurations, or sync databases.
Combine schedule
and repository_dispatch
for complex time-based tasks that also require external system integration.
These webhook triggers make GitHub Actions versatile, allowing automation for both internal GitHub events and external systems.
In GitHub Actions, conditionals control whether a workflow, job, or step should run. These conditions use the if
keyword and evaluate expressions based on context and variables.
Here’s a breakdown of conditionals in GitHub Actions:
While workflows don’t have direct if
conditions, you can control execution using specific events and filters (e.g., branches, tags).
Example: Run workflow only on main
branch:
on:
push:
branches:
- main
Jobs can have conditions using the if
keyword.
Syntax:
jobs:
job-name:
if: <condition>
runs-on: ubuntu-latest
Example: Run a job only for PRs:
jobs:
build:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- run: echo "This job runs only for PRs"
Steps can also use the if
keyword to control execution.
Syntax:
steps:
- name: Step Name
if: <condition>
run: <command>
Example: Run step only if a previous step succeeds:
steps:
- name: Build
run: echo "Building..."
- name: Deploy
if: success()
run: echo "Deploying..."
Here are some commonly used conditions:
-
success()
: Step or job runs if all previous steps/jobs succeeded. -
failure()
: Runs if a previous step/job failed. -
always()
: Runs regardless of success or failure. -
cancelled()
: Runs if the workflow was canceled.
-
Check event type:
if: github.event_name == 'push'
-
Filter branch or tag:
if: startsWith(github.ref, 'refs/heads/main')
-
Use GitHub context:
if: github.actor == 'octocat'
-
Use inputs:
if: inputs.environment == 'production'
Combine multiple conditions using &&
, ||
, and !
.
Example: Only on main branch and success:
if: github.ref == 'refs/heads/main' && success()
name: Conditional Workflow
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Build Code
run: echo "Building..."
- name: Deploy to Production
if: github.ref == 'refs/heads/main' && success()
run: echo "Deploying to production!"
on:
workflow_dispatch:
inputs:
deploy:
description: 'Should deploy'
required: true
default: 'false'
jobs:
deploy:
runs-on: ubuntu-latest
if: github.event.inputs.deploy == 'true'
steps:
- run: echo "Deploying as per input!"
Conditionals in GitHub Actions allow workflows to adapt dynamically based on context, inputs, and statuses, providing flexibility and control over execution!
Expressions in GitHub Actions are used to evaluate conditions and set dynamic values. Here’s a concise guide covering all the essentials:
Expressions are enclosed in double curly braces {{ }}
and evaluated with the $
symbol:
if: ${{ <expression> }}
-
+
,-
,*
,/
,%
- Example:
$((3 + 2))
→5
-
==
,!=
,<
,<=
,>
,>=
- Example:
$((1 > 0))
→true
-
&&
(AND),||
(OR),!
(NOT) - Example:
$((true && false))
→false
-
success()
→ Returnstrue
if previous steps/jobs succeeded. -
failure()
→ Returnstrue
if any previous step/job failed. -
cancelled()
→ Returnstrue
if the workflow was canceled. -
always()
→ Always returnstrue
.
startsWith(string, prefix)
endsWith(string, suffix)
contains(string, substring)
- Example:
$((startsWith('main', 'm')))
→true
-
format()
→ Formats a string. -
join(array, delimiter)
→ Joins array elements. -
toJSON(value)
→ Converts a value to JSON.
Contexts provide dynamic information. Common ones include:
-
github.event_name
→ The name of the triggering event. -
github.actor
→ The user who triggered the workflow. -
github.ref
→ The branch or tag ref.
-
job.status
→ Status of the current job:success
,failure
, orcancelled
.
-
runner.os
→ Operating system of the runner.
-
secrets.<name>
→ Access to GitHub secrets. - Example:
secrets.MY_SECRET
-
env.<name>
→ Access to environment variables. - Example:
env.DEPLOY_ENV
-
inputs.<name>
→ Inputs passed to the workflow. - Example:
inputs.environment
if: ${{ github.ref == 'refs/heads/main' }}
if: ${{ github.event.pull_request.user.login == 'octocat' }}
if: ${{ success() }}
run: echo "${{ format('Deploying to {0}', github.ref) }}"
if: ${{ github.actor == 'octocat' && github.event_name == 'push' }}
These expressions allow dynamic, flexible workflows tailored to your automation needs!
In GitHub Actions, runners are the virtual environments where your workflows are executed. They are responsible for running the jobs defined in your workflow files. Runners are where the actual execution of your code, commands, and steps takes place.
-
GitHub-Hosted Runners: These are virtual machines provided by GitHub that are preconfigured with popular software tools. GitHub maintains, updates, and manages these runners, so you don’t need to worry about the underlying infrastructure. They are typically used for general-purpose workflows.
-
Operating Systems Available:
- Ubuntu (latest versions)
- Windows (latest versions)
- macOS (latest versions)
-
Example of using a GitHub-hosted runner:
jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - run: echo "Hello, World!"
-
Advantages:
- No setup required—GitHub takes care of the infrastructure.
- Preconfigured with common tools and languages (Node.js, Python, Java, etc.).
- Automatically updated with the latest patches.
-
Disadvantages:
- Limited control over the environment (you can't install custom software by default).
- They might have resource limitations (e.g., CPU, memory, disk space) depending on your usage.
-
-
Self-Hosted Runners: These are machines that you set up and configure yourself, either on your own hardware or in a cloud environment. They allow more customization and control over the environment, enabling you to install specific software, tools, or configurations that are required for your workflows.
-
Example of using a self-hosted runner:
jobs: build: runs-on: self-hosted steps: - uses: actions/checkout@v2 - run: echo "Custom build on self-hosted runner!"
-
Advantages:
- Full control over the environment (you can install any software you need).
- Can be used for workflows that require specific tools or hardware configurations.
- Can be more cost-effective for large-scale workflows or for workflows that require more resources than GitHub-hosted runners provide.
-
Disadvantages:
- You need to set up and maintain the runner (including updates, security, etc.).
- You are responsible for scaling and handling issues such as hardware failures.
-
-
Runs-on: The
runs-on
key specifies which type of runner the job should run on. It can either beubuntu-latest
,windows-latest
,macos-latest
(for GitHub-hosted runners) or a custom label for a self-hosted runner. -
Self-hosted Runners Labels: When using self-hosted runners, you can assign labels to them to help organize or filter which runners to use for specific jobs. For example:
jobs: build: runs-on: [self-hosted, linux]
-
Environment Setup: For self-hosted runners, you can install any software you need for your workflows (e.g., database servers, specific language versions, etc.).
-
Virtual Environments: GitHub-hosted runners use virtual environments that are discarded after the workflow completes. This means that each workflow run starts with a fresh environment. For self-hosted runners, the environment persists between workflow runs, so you can maintain data or software installed from previous runs.
- Job Queue: When a workflow is triggered, GitHub checks for an available runner to execute the job.
-
Runner Start: If the runner is not already running, GitHub starts the appropriate runner based on the
runs-on
specification. - Job Execution: The runner executes each step in the workflow until it completes or fails.
- Post-job Cleanup: For GitHub-hosted runners, the environment is discarded once the job is done. For self-hosted runners, the environment persists for further jobs until manually cleaned up.
name: Build and Test
on: [push]
jobs:
test:
runs-on: ubuntu-latest # Use a GitHub-hosted Ubuntu runner
steps:
- uses: actions/checkout@v2
- run: npm install
- run: npm test
deploy:
runs-on: self-hosted # Use a self-hosted runner
steps:
- uses: actions/checkout@v2
- run: ./deploy-script.sh
- GitHub-hosted runners are easier to use and set up, suitable for most general use cases.
- Self-hosted runners provide greater control and flexibility, ideal for custom environments, complex workflows, or specific resource needs.
You can choose between these based on your project’s needs, scale, and level of customization required for your workflows.
Workflow commands in GitHub Actions allow you to interact with the workflow runner's environment. These commands are executed using special syntax inside a workflow and help set environment variables, add annotations, mask secrets, and more.
Here’s a list of commonly used workflow commands:
To invoke a command, you use echo
with the prefix ::
.
echo "::command parameter=value::message"
You can create or update an environment variable using the set-env
command.
echo "MY_VAR=value" >> $GITHUB_ENV
- Example:
- name: Set environment variable run: echo "MY_VAR=Hello World" >> $GITHUB_ENV - name: Use the variable run: echo "The value is $MY_VAR"
Pass values from one step to another using outputs.
echo "::set-output name=var_name::value"
- Example:
- name: Set output id: step1 run: echo "value=Hello World" >> $GITHUB_ENV - name: Use output run: echo "The output is ${{ steps.step1.outputs.var_name }}"
Note:
set-output
is deprecated. UseGITHUB_ENV
for modern workflows.
Group related logs for better readability in the Actions console.
echo "::group::Group Name"
# Log output
echo "Log message"
echo "::endgroup::"
- Example:
- name: Group logs run: | echo "::group::Start of logs" echo "This is inside the group." echo "::endgroup::"
Add annotations like warnings, errors, or notices to the logs.
-
Warning:
echo "::warning file=app.js,line=10,col=15::This is a warning message"
-
Error:
echo "::error file=app.js,line=10,col=15::This is an error message"
-
Notice:
echo "::notice file=app.js,line=10,col=15::This is a notice"
To hide sensitive information in logs, use the add-mask
command.
echo "::add-mask::sensitive_value"
- Example:
- name: Mask sensitive data run: echo "::add-mask::my-secret-value"
Enable debug messages for troubleshooting.
echo "::debug::This is a debug message"
- Example:
- name: Debug example run: echo "::debug::Debugging workflow step"
You can cancel or skip steps using cancel
or fail
.
-
Cancel Workflow:
echo "::cancel::Cancelling the workflow"
-
Fail Workflow:
echo "::error::Failing the workflow intentionally"
Report success or failure of individual steps or actions.
echo "::set-output name=step-result::success"
Use the actions/upload-artifact
action to save files or logs for later use.
- name: Upload logs
uses: actions/upload-artifact@v3
with:
name: my-logs
path: ./logs/
Command | Description |
---|---|
GITHUB_ENV |
Set environment variables. |
::group:: |
Start a log group. |
::endgroup:: |
End a log group. |
::debug:: |
Add debug information. |
::warning:: |
Add a warning annotation. |
::error:: |
Add an error annotation. |
::notice:: |
Add a notice annotation. |
::add-mask:: |
Mask sensitive data in logs. |
::set-output:: |
Pass outputs between steps (deprecated). |
actions/upload-artifact |
Save files for later use. |
Would you like to see how these commands can be used in a complete workflow example?
GitHub Actions provides contexts that allow workflows to access information about the workflow run, repository, and environment. These are predefined variables that you can use in expressions or directly in workflows.
Provides details about the repository, event, and workflow.
run: echo "Repository: ${{ github.repository }}"
run: echo "Event name: ${{ github.event_name }}"
run: echo "Run number: ${{ github.run_number }}"
run: echo "Commit SHA: ${{ github.sha }}"
Access environment variables set during the workflow.
run: echo "Environment variable MY_VAR: ${{ env.MY_VAR }}"
Contains information about the current job.
run: echo "Job ID: ${{ job.id }}"
run: echo "Job status: ${{ job.status }}"
Provides information about the runner instance.
run: echo "Runner OS: ${{ runner.os }}"
run: echo "Runner temp directory: ${{ runner.temp }}"
run: echo "Runner tool cache directory: ${{ runner.tool_cache }}"
Access secrets defined in the repository or organization.
run: echo "My secret: ${{ secrets.MY_SECRET }}" # Avoid echoing secrets in production!
Access outputs from previous steps within the same job.
- name: Set output in step
id: example_step
run: echo "output_value=Hello" >> $GITHUB_ENV
- name: Use output from previous step
run: echo "Output value: ${{ env.output_value }}"
Provides details about the strategy matrix (used with matrix
).
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
python: [3.8, 3.9]
- run: echo "OS: ${{ matrix.os }}"
- run: echo "Python version: ${{ matrix.python }}"
Access outputs from jobs this job depends on (when using needs
).
jobs:
first_job:
runs-on: ubuntu-latest
outputs:
my_output: ${{ steps.output_step.outputs.value }}
steps:
- id: output_step
run: echo "value=First job output" >> $GITHUB_ENV
second_job:
runs-on: ubuntu-latest
needs: first_job
steps:
- run: echo "Output from first job: ${{ needs.first_job.outputs.my_output }}"
Access inputs from reusable workflows.
inputs:
my_input: DefaultValue
steps:
- run: echo "Input value: ${{ inputs.my_input }}"
Indicates whether the job or step always runs regardless of the result of earlier jobs/steps.
if: ${{ always() }}
name: Workflow Contexts Demo
on:
push:
branches:
- main
jobs:
demo-contexts:
runs-on: ubuntu-latest
steps:
# GitHub Context
- name: GitHub Context
run: |
echo "Repository: ${{ github.repository }}"
echo "Event name: ${{ github.event_name }}"
# Environment Context
- name: Environment Context
run: |
echo "MY_ENV_VAR=Hello World" >> $GITHUB_ENV
echo "Environment variable: ${{ env.MY_ENV_VAR }}"
# Runner Context
- name: Runner Context
run: |
echo "Runner OS: ${{ runner.os }}"
echo "Runner Temp Directory: ${{ runner.temp }}"
# Secrets Context
- name: Secrets Context
run: echo "Secret Value: ${{ secrets.MY_SECRET }}" # Avoid in production!
# Strategy Context
- name: Strategy Context
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
steps:
- run: echo "Matrix OS: ${{ matrix.os }}"
Dependent jobs are a way to define job execution order in a workflow. In GitHub Actions, you can set dependencies between jobs using the needs
keyword. Jobs that depend on others will wait for their prerequisites to complete successfully before executing.
-
needs
Keyword:- Specifies which jobs must complete before the current job runs.
- Ensures proper execution order in workflows.
-
Implicit Dependency:
- If a job does not have a
needs
keyword, it runs independently unless there is a workflow-wide dependency.
- If a job does not have a
-
Sequential Execution:
- By chaining jobs with
needs
, you can execute jobs sequentially.
- By chaining jobs with
name: Dependent Jobs Demo
on:
push:
branches:
- main
jobs:
job1:
runs-on: ubuntu-latest
steps:
- name: Step 1
run: echo "This is Job 1"
job2:
runs-on: ubuntu-latest
needs: job1
steps:
- name: Step 2
run: echo "This is Job 2, dependent on Job 1"
job3:
runs-on: ubuntu-latest
needs: [job1, job2]
steps:
- name: Step 3
run: echo "This is Job 3, dependent on Job 1 and Job 2"
-
job1
runs first because it has no dependencies. -
job2
waits forjob1
to complete. -
job3
waits for bothjob1
andjob2
to complete.
Dependent jobs can use outputs from their prerequisite jobs. Outputs are defined in one job and accessed in the dependent job.
name: Job Outputs Demo
on:
push:
branches:
- main
jobs:
job1:
runs-on: ubuntu-latest
outputs:
job1_output: ${{ steps.get_output.outputs.result }}
steps:
- name: Generate Output
id: get_output
run: echo "::set-output name=result::Output from Job 1"
job2:
runs-on: ubuntu-latest
needs: job1
steps:
- name: Use Job 1 Output
run: echo "Received output from Job 1: ${{ needs.job1.outputs.job1_output }}"
-
Defining Outputs:
- In
job1
, an output namedjob1_output
is defined with the valueOutput from Job 1
.
- In
-
Using Outputs:
-
job2
depends onjob1
and uses the output throughneeds.job1.outputs.job1_output
.
-
Jobs without explicit dependencies (needs
) run in parallel.
You can use conditional expressions with if
to control whether a dependent job runs.
name: Conditional Dependencies
on:
push:
branches:
- main
jobs:
job1:
runs-on: ubuntu-latest
steps:
- run: echo "Job 1"
job2:
runs-on: ubuntu-latest
needs: job1
if: ${{ success() && github.event_name == 'push' }}
steps:
- run: echo "Job 2 only runs if Job 1 succeeds and event is a push"
-
Sequential Execution: Use
needs
to enforce order. -
Parallel Execution: Omit
needs
for independent jobs. -
Conditional Pipelines: Combine
needs
andif
to create dynamic workflows. -
Pass Outputs: Share data between jobs using outputs and
needs
.
-
Minimize Dependencies: Keep dependency chains short for faster workflows.
-
Error Handling: Use
if: failure()
orif: always()
for cleanup or fallback jobs. -
Documentation: Clearly document dependencies to avoid confusion in complex workflows.
job1 is dependent on job 2 and 3 job2 is dependent on job 3 job3 is dependent on none so it starts first
Relation: job3 ---> job2 ---> job1
The GITHUB_TOKEN
is a built-in secret in GitHub Actions that allows your workflow to interact with the GitHub API securely. It is automatically created for each workflow run and provides scoped permissions based on your workflow's context.
-
Automatic Creation:
- GitHub automatically creates the
GITHUB_TOKEN
secret for every workflow run.
- GitHub automatically creates the
-
Usage:
- It is used to authenticate requests made by your workflow, such as pushing commits, creating issues, or accessing repositories.
-
Scope and Permissions:
- The token's permissions depend on the repository's settings (e.g.,
read/write
for private repositories orread-only
for public repositories).
- The token's permissions depend on the repository's settings (e.g.,
-
Lifecycle:
- The token is valid only for the duration of the workflow run.
-
Security:
- It is restricted to the repository where the workflow runs, and access can be further limited via permissions in the workflow file.
name: GITHUB_TOKEN Example
on:
push:
branches:
- main
jobs:
update-branch:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Make Changes
run: |
echo "New content" >> file.txt
- name: Commit and Push Changes
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add .
git commit -m "Automated update"
git push
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
Publishing Packages:
- Use it to authenticate with GitHub Packages.
-
API Requests:
- Make API calls using the token for actions like creating issues or labeling pull requests.
-
Workflow Automation:
- Automate tasks like merging pull requests or commenting on issues.
You can use GITHUB_TOKEN
to make authenticated API calls.
name: API Request Example
on:
push:
branches:
- main
jobs:
create-issue:
runs-on: ubuntu-latest
steps:
- name: Create GitHub Issue
run: |
curl -X POST -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/${{ github.repository }}/issues \
-d '{"title": "Automated Issue", "body": "This is an issue created by a workflow."}'
You can restrict the permissions of the GITHUB_TOKEN
in your workflow using the permissions
key.
name: Restrict GITHUB_TOKEN Permissions
on:
push:
branches:
- main
jobs:
restricted-permissions:
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
steps:
- name: Check Permissions
run: echo "Using GITHUB_TOKEN with restricted permissions"
- Avoid printing the
GITHUB_TOKEN
in logs. - Use the
GITHUB_TOKEN
instead of creating personal access tokens (PAT) for workflows. - Combine it with conditional expressions to control when certain tasks execute.
Let me know if you'd like to explore specific use cases!
Running scripts in GitHub Actions workflows allows you to automate tasks using shell commands, custom scripts, or external tools.
-
Inline Commands: Directly write commands using the
run
key.steps: - name: Inline script run: | echo "Hello, World!" pwd ls -la
-
Run External Scripts: Use scripts saved in your repository.
steps: - name: Checkout code uses: actions/checkout@v3 - name: Run external script run: ./scripts/myscript.sh
Ensure the script has executable permissions (
chmod +x scripts/myscript.sh
). -
Use Different Shells: Specify a shell for the script.
steps: - name: Run with Bash run: echo "Running with Bash" shell: bash - name: Run with PowerShell run: Write-Output "Running with PowerShell" shell: pwsh
-
Run Node.js/Python/Other Language Scripts:
# Running a Node.js script steps: - name: Run Node.js script run: node scripts/myscript.js # Running a Python script steps: - name: Run Python script run: python scripts/myscript.py
-
Environment Variables: Use
env
for reusable configurations.env: MY_VAR: "Hello" steps: - name: Use environment variable run: echo "Value is $MY_VAR"
-
Dependencies: Install dependencies before running scripts.
steps: - name: Install Node.js dependencies run: npm install
-
Error Handling: Use
set -e
for stopping on errors in shell scripts.
To publish a package (e.g., npm, Docker) to GitHub Packages via GitHub Actions:
name: Publish npm Package
on:
push:
branches:
- main
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 16
registry-url: https://npm.pkg.github.com/
- name: Login to GitHub Package Registry
run: npm config set "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}"
- name: Install dependencies
run: npm install
- name: Build the package
run: npm run build
- name: Publish package
run: npm publish
name: Publish Docker Image
on:
push:
branches:
- main
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Log in to GitHub Docker Registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $GITHUB_ACTOR --password-stdin
- name: Build Docker image
run: docker build -t ghcr.io/<owner>/<image-name>:latest .
- name: Push Docker image
run: docker push ghcr.io/<owner>/<image-name>:latest
- Use
GITHUB_TOKEN
for authentication. - Replace placeholders like
<owner>
,<image-name>
, etc. - Ensure your repository has a
package.json
(for npm) or Dockerfile (for Docker).