Comparison of GitHub Actions with competitors
Deep dive into workflow syntax, triggers, and job configuration
Explore matrices, reusable workflows, and composite actions
•Runner Types and Execution Environments
•Persisting Build Outputs with Artifacts
•Controlling GitHub Permissions
•Authenticating to Third-Party Systems
•Matrix Strategies, Conditionals, and Concurrency Controls
Discover and integrate community actions from the GitHub Marketplace
Build custom JavaScript and Docker actions from scratch
•JavaScript and TypeScript Actions
Optimize logs, secrets, environments, and permissions for teams
•Developer Experience (Actions)
Harden workflows with security, reliability, and cost-saving techniques
•Maintainable Workflow Patterns
Apply course concepts by automating a real-world deployment pipeline
Container actions let you pick any runtime or dependency stack. GitHub can build
the image from a local Dockerfile
, or you can point to a registry-hosted image
to avoid rebuilding on every run.
name: Hello (Python)
description: Greet someone and expose a greeting output
inputs:
who-to-greet:
description: Name to greet
required: true
default: World
outputs:
greeting:
description: The greeting that was printed
runs:
using: docker
# Option A – let GitHub build from Dockerfile each run
image: Dockerfile
# Option B – use a pre-built image to avoid rebuilds:
# image: docker://ghcr.io/your-org/hello-python-action:v1
args:
- ${{ inputs.who-to-greet }}
The entrypoint script has to speak “workflow command” by printing specific
strings and writing to files such as GITHUB_OUTPUT
:
#!/usr/bin/env python3
import os, datetime as dt
# GitHub injects INPUT_WHO_TO_GREET based on the input name
name = os.getenv("INPUT_WHO_TO_GREET", "World")
# Alternatively, you could read it from the args list using its position
# (you would need to import sys package above)
# name = sys.argv[1] if len(sys.argv) > 1 else "World"
greeting = f"Hello, {name}! Time is {dt.datetime.now(dt.timezone.utc):%H:%M:%S} UTC."
print(greeting)
# We can use workflow commands from: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions
# For example, to emit a GitHub-Actions NOTICE annotation
print(f"::notice file=entrypoint.py,line=17::{greeting}")
# Expose an output for downstream steps/jobs
with open(os.environ["GITHUB_OUTPUT"], "a") as fh:
fh.write(f"greeting={greeting}\n")
The container action workflow showcases three approaches:
jobs:
shell-dockerfile:
runs-on: ubuntu-latest
name: Shell Container Action (dynamic Dockerfile build)
steps:
- name: Checkout
uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v5.0.0
with:
submodules: true
- name: Run container action
uses: ./06-authoring-actions/container-actions/shell-container-action
id: hello
with:
who-to-greet: "from a container github action đź‘‹"
- name: Get the output greeting
run: echo "The greeting was ${{ steps.hello.outputs.greeting }}"
shell-public-container-image:
runs-on: ubuntu-latest
name: Shell Container Action (public container image)
steps:
- name: Checkout
uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v5.0.0
- name: Run container action
uses: ./06-authoring-actions/container-actions/shell-container-action-prebuilt
id: hello
with:
who-to-greet: "from a container github action đź‘‹"
- name: Get the output greeting
run: echo "The greeting was ${{ steps.hello.outputs.greeting }}"
python-dockerfile:
runs-on: ubuntu-latest
name: Python Container Action (dynamic Dockerfile build)
steps:
- name: Checkout
uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v5.0.0
- name: Run container action
uses: ./06-authoring-actions/container-actions/python-container-action
id: hello
with:
who-to-greet: "from a container github action đź‘‹"
- name: Get the output time
run: echo "The time was ${{ steps.hello.outputs.greeting }}"