Common, reusable GitHub Actions workflows across PESU Developer Group (pesu-dev) projects.
In pesu-dev/actions, Reusable Workflows (workflow_call) are preferred over Composite Actions:
- Individual Step Visibility in GitHub UI: Composite actions collapse all execution into a single log step. Reusable workflows display each phase (payload validation, triggering, polling, summary generation) as its own separate step in the Actions web interface, making pipeline progress and failures instantly identifiable.
- Native Run Summaries:
Enables writing directly to
$GITHUB_STEP_SUMMARYto display rich status cards and dashboard links on the workflow run overview. - Runner Isolation & Job Capabilities:
Reusable workflows run in isolated environments with explicit
permissions,secrets, and future support for GitHub Environment protection rules (manual approvals).
| Workflow | Path | Description |
|---|---|---|
| Build & Push Docker Image | .github/workflows/build_push_image.yml |
Build and push Docker images to GHCR (and optionally Docker Hub) using Buildx and GitHub Actions layer caching. |
| Deploy to Render | .github/workflows/deploy_render.yml |
Trigger and monitor service deployments on Render via the official Render REST API v1. |
Builds a Docker container image using Docker Buildx and GitHub Actions layer caching, and pushes to GitHub Container Registry (and optionally Docker Hub). Automatically sets the GIT_SHA build argument and generates a rich run summary.
Test that the Docker image builds successfully without pushing to any registry:
jobs:
pr_image_build:
name: Build image on PR
uses: pesu-dev/actions/.github/workflows/build_push_image.yml@v1
with:
image_tag: ${{ github.event.pull_request.head.sha }}
push: falseBuild and push the commit image to GHCR:
jobs:
build_and_push:
name: Build and push commit image
uses: pesu-dev/actions/.github/workflows/build_push_image.yml@v1
with:
ref: ${{ github.sha }}
image_tag: ${{ github.sha }}
push: truePass optional Docker Hub credentials to push to both GHCR (ghcr.io/<org>/<repo>:<tag>) and Docker Hub (<username>/<repo>:<tag>):
jobs:
build_and_push:
name: Build and push image
uses: pesu-dev/actions/.github/workflows/build_push_image.yml@v1
with:
ref: main
image_tag: ${{ steps.vars.outputs.tag }}
push: true
secrets:
docker_username: ${{ secrets.DOCKER_USERNAME }}
docker_password: ${{ secrets.DOCKER_PASSWORD }}Specify image_name if the published container package name on GHCR and Docker Hub differs from the GitHub repository name:
jobs:
build_and_push:
name: Build and push image
uses: pesu-dev/actions/.github/workflows/build_push_image.yml@v1
with:
ref: main
image_name: pesu-auth
image_tag: ${{ github.sha }}
push: truePublish multi-architecture container images (e.g. for Apple Silicon developers and ARM64 cloud instances like AWS Graviton) using QEMU emulation:
jobs:
build_and_push:
name: Build and push multi-arch image
uses: pesu-dev/actions/.github/workflows/build_push_image.yml@v1
with:
ref: main
image_name: pesu-auth
image_tag: ${{ steps.vars.outputs.tag }}
platforms: linux/amd64,linux/arm64
push: truePerformance Tip: Emulating ARM64 on x86 GitHub runners via QEMU incurs compilation overhead. For PR validation, omit
platformsto validate builds rapidly on native runner architecture; enableplatformswhen building release images on push or tag.
| Input | Type | Required | Default | Description |
|---|---|---|---|---|
image_tag |
string | Yes | — | Target container image tag (e.g. Git commit SHA or semver string). |
image_name |
string | No | "" |
Custom image/package name (e.g. pesu-auth). Defaults to repository name if omitted. |
ref |
string | No | "" |
Git ref to checkout (branch, tag, or SHA). Defaults to workflow trigger ref. |
push |
boolean | No | false |
Whether to push the image to container registries. |
dockerfile |
string | No | "./Dockerfile" |
Path to Dockerfile relative to repository root. |
context |
string | No | "." |
Docker build context directory path. |
cache |
boolean | No | true |
Whether to enable GitHub Actions layer cache (type=gha). |
platforms |
string | No | "" |
Target container architectures (comma-separated, e.g. linux/amd64,linux/arm64). Defaults to native runner arch (linux/amd64). Automatically sets up QEMU when provided. |
| Secret | Required | Description |
|---|---|---|
docker_username |
No | Docker Hub username. If provided alongside docker_password, pushes to Docker Hub in addition to GHCR. |
docker_password |
No | Docker Hub password or personal access token. |
| Output | Description |
|---|---|
image |
Fully qualified GHCR image name (ghcr.io/<org>/<repo> or ghcr.io/<org>/<image_name>). |
image_tag |
Built image tag. |
ghcr_ref |
Complete image reference in GHCR (ghcr.io/<org>/<repo>:<tag>). |
dockerhub_ref |
Complete image reference in Docker Hub if pushed (<username>/<repo>:<tag>). |
digest |
Image digest (sha256:...). |
platforms |
Target container architectures built. |
Deploys a service to Render and tracks deployment progress until it is live.
When using GitHub Environments, define RENDER_SERVICE_ID as an environment variable (under Settings → Environments → [name] → Environment variables) and RENDER_API_KEY as a repository or environment secret:
jobs:
deploy:
name: Deploy to Render
uses: pesu-dev/actions/.github/workflows/deploy_render.yml@v1
with:
environment: production
image_url: ghcr.io/${{ github.repository }}:${{ github.sha }}
wait_for_completion: true
secrets: inheritYou can also pass service_id and render_api_key explicitly:
jobs:
deploy:
name: Deploy to Render
uses: pesu-dev/actions/.github/workflows/deploy_render.yml@v1
with:
service_id: ${{ vars.RENDER_SERVICE_ID }}
environment: production
image_url: ghcr.io/${{ github.repository }}:${{ github.sha }}
wait_for_completion: true
secrets:
render_api_key: ${{ secrets.RENDER_API_KEY }}| Input | Type | Required | Default | Description |
|---|---|---|---|---|
service_id |
string | No | "" |
Target Render Service ID (srv-...). If omitted, falls back to vars.RENDER_SERVICE_ID in the targeted environment/repository. |
environment |
string | No | "" |
Target GitHub Environment (e.g. staging, prod) to bind deployment protection rules and environment secrets. |
commit_sha |
string | No | "" |
Specific Git commit SHA to deploy (defaults to latest on connected branch). |
image_url |
string | No | "" |
Container image URL for image-backed Render services. |
clear_cache |
boolean | No | false |
Whether to clear build cache before building. |
wait_for_completion |
boolean | No | true |
Whether to poll until deploy reaches live or fails. |
timeout_seconds |
number | No | 900 |
Maximum seconds to poll before timing out (15 mins). |
poll_interval_seconds |
number | No | 10 |
Seconds between status polling requests. |
| Secret | Required | Description |
|---|---|---|
render_api_key |
No | Render Public REST API Bearer token. If omitted, falls back to secrets.RENDER_API_KEY (e.g. with secrets: inherit). |
| Output | Description |
|---|---|
deploy_id |
The created Render deploy ID (dep-...). |
deploy_status |
Final deployment status (live, build_failed, timed_out, etc.). |
deploy_url |
Render dashboard URL for this specific deploy. |
service_url |
Public live URL of the deployed service (for web services or static sites). |
actions/
├── .github/
│ └── workflows/
│ ├── build_push_image.yml # Reusable workflow: Build and Push Docker Image
│ ├── ci.yml # Action & workflow linting via actionlint
│ └── deploy_render.yml # Reusable workflow: Deploy to Render
├── .gitignore
├── LICENSE
└── README.md
- PR Source Checker: Standardized check ensuring PRs originate from forks and not from a fork's
mainbranch. - GHCR Retention Cleanup: Reusable workflow to prune stale commit-sha tags in GitHub Container Registry.
- Releases follow semantic versioning (
v1.0.0,v1.1.0, etc.). - Major version tags (e.g.,
v1) are kept updated to point to the latest stable release of that major version, allowing workflows to pin to@v1without breaking on backwards-compatible updates.
MIT © PESU Developer Group