Write a template
Node.js
Install locked npm dependencies, test, and build.
rzv-ubuntu-24.04-x64-2vcpu-8gb
Required files: package.json and package-lock.json.
Commit package-lock.json before using the npm dependency cache.
name: Node.js
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: nodejs-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
test:
runs-on: rzv-ubuntu-24.04-x64-2vcpu-8gb
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 24
cache: npm
cache-dependency-path: package-lock.json
- run: npm ci
- run: npm test
- run: npm run build
Python
Install requirements and run pytest.
rzv-ubuntu-24.04-x64-2vcpu-8gb
Required files: requirements.txt and tests.
name: Python
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: python-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
test:
runs-on: rzv-ubuntu-24.04-x64-2vcpu-8gb
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
with:
python-version: "3.13"
cache: pip
cache-dependency-path: requirements.txt
- run: python -m pip install --requirement requirements.txt
- run: python -m pytest
Go
Vet, test, and build a Go module.
rzv-ubuntu-24.04-x64-2vcpu-8gb
Required files: go.mod and go.sum.
name: Go
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: go-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
test:
runs-on: rzv-ubuntu-24.04-x64-2vcpu-8gb
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
with:
go-version-file: go.mod
cache: true
- run: go vet ./...
- run: go test ./...
- run: go build ./...
Java with Maven
Build and test a Maven project with its committed Maven Wrapper.
rzv-ubuntu-24.04-x64-2vcpu-8gb
Required files: pom.xml, mvnw, and .mvn/wrapper/.
Preserve the executable bit on mvnw.
name: Java with Maven
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: java-maven-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
test:
runs-on: rzv-ubuntu-24.04-x64-2vcpu-8gb
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
with:
distribution: temurin
java-version: "21"
cache: maven
- run: ./mvnw --batch-mode verify
Docker build and GHCR publish
Build pull requests and publish only from pushes to main.
rzv-ubuntu-24.04-x64-2vcpu-8gb
Required file: Dockerfile.
name: Docker build and GHCR publish
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: docker-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
build:
if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
runs-on: rzv-ubuntu-24.04-x64-2vcpu-8gb
timeout-minutes: 25
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: .
push: false
cache-from: type=gha
cache-to: type=gha,mode=max
publish:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: rzv-ubuntu-24.04-x64-2vcpu-8gb
timeout-minutes: 25
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- id: metadata
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
with:
images: ghcr.io/${{ github.repository }}
- uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: .
push: true
tags: ${{ steps.metadata.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
Ansible
Lint, syntax-check, and check-mode a local playbook.
rzv-ubuntu-24.04-x64-2vcpu-8gb
Required files: ansible/requirements-ci.txt, inventory.yml, and playbook.yml.
name: Ansible
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ansible-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
validate:
runs-on: rzv-ubuntu-24.04-x64-2vcpu-8gb
timeout-minutes: 20
defaults:
run:
working-directory: ansible
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
with:
python-version: "3.13"
cache: pip
cache-dependency-path: ansible/requirements-ci.txt
- run: python -m pip install --requirement requirements-ci.txt
- run: ansible-lint playbook.yml
- run: ansible-playbook --inventory inventory.yml --syntax-check playbook.yml
- run: ansible-playbook --inventory inventory.yml --check playbook.yml
Rust
Format-check, lint, test, and build a Cargo project.
rzv-ubuntu-24.04-x64-2vcpu-8gb
Required files: Cargo.toml and Cargo.lock.
Commit Cargo.lock before using the Cargo cache.
name: Rust
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: rust-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
test:
runs-on: rzv-ubuntu-24.04-x64-2vcpu-8gb
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions-rust-lang/setup-rust-toolchain@166cdcfd11aee3cb47222f9ddb555ce30ddb9659 # v1.17.0
with:
toolchain: stable
components: rustfmt, clippy
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
target/
key: rust-${{ runner.os }}-${{ hashFiles('Cargo.lock') }}
- run: cargo fmt --check
- run: cargo clippy --all-targets -- -D warnings
- run: cargo test
- run: cargo build --release
.NET
Restore, build, and test a .NET solution.
rzv-ubuntu-24.04-x64-2vcpu-8gb
Required files: global.json and a solution.
name: .NET
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: dotnet-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
test:
runs-on: rzv-ubuntu-24.04-x64-2vcpu-8gb
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0
env:
DOTNET_INSTALL_DIR: ${{ runner.temp }}/dotnet
with:
global-json-file: global.json
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ~/.nuget/packages
key: dotnet-${{ runner.os }}-${{ hashFiles('**/*.csproj', 'global.json') }}
- run: dotnet restore
- run: dotnet build --no-restore --configuration Release
- run: dotnet test --no-build --configuration Release
Reusable Go workflow
Call a reusable Go validation workflow.
rzv-ubuntu-24.04-x64-2vcpu-8gb
Required files: go.mod and go.sum.
Copy the selected file into .github/workflows/ before calling it from another workflow.
name: Reusable Go validation
on:
workflow_call:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: reusable-go-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
jobs:
test:
runs-on: rzv-ubuntu-24.04-x64-2vcpu-8gb
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
with:
go-version-file: go.mod
cache: true
- run: go vet ./...
- run: go test ./...
- run: go build ./...