Intelligent container build automation for modern development workflows.
Automated Docker/Container builds with branch-aware tagging for Docker Hub and GitHub Container Registry.
Stop writing repetitive Docker build workflows. This GitHub Action automatically detects your branch context (PR, dev, patch, or WIP) and builds container images with intelligent tagsβno configuration gymnastics required.
The Problem:
Building containers across multiple branches with different tagging strategies is repetitive and error-prone. Teams waste time writing similar workflows for PRs, development, staging, and production.
The Solution:
One action that intelligently detects your workflow context and applies the right tags automatically. Whether it's a feature PR, a devβmain promotion, or an emergency hotfix, your containers get tagged correctlyβevery time.
This action analyzes your GitHub workflow context and automatically determines the appropriate build flow:
graph LR
A[Push/PR Event] --> B{Detect Context}
B -->|PR β dev| C[pr-sha]
B -->|dev β main| D[dev-sha]
B -->|hotfix β main| E[patch-sha]
B -->|push β main| F[staging-sha]
B -->|other| G[wip-sha]
C --> H[Build & Push]
D --> H
E --> H
F --> H
G --> H
H --> I[PR Comment]
No manual configuration needed. Just add the action to your workflow, and it handles branch detection, tagging, building, and PR comments automatically for all flow typesβwhether triggered by pull requests or direct pushes to tracked branches.
- π― Intelligent Flow Detection - Automatically detects PR context and assigns appropriate build tags
- π³ Dual Registry Support - Push to Docker Hub, GHCR, or both simultaneously
- π·οΈ Smart Tagging Strategy -
pr-{sha},dev-{sha},patch-{sha},wip-{sha}flows - π§ Highly Configurable - Customize branches, registries, build options, and more
- π¬ Smart PR Comments - Automatic pull instructions posted to PRs for all flow types (push and pull_request events)
- π Multi-Platform Builds - Support for
linux/amd64,linux/arm64, and more - π Security-First - Built-in SBOM and provenance attestations
- π Built-in Security Scanning - Comprehensive vulnerability scanning with Trivy (source code, Dockerfile, and container images)
- β‘ Build Cache - GitHub Actions cache integration for faster builds
Note
Security scanning is enabled by default with built-in optimizations: intelligent caching, fallback registries (mirror.gcr.io), and minimal overhead (~2-5 min). First run downloads the vulnerability database; subsequent scans use cached data.
| β Without This Action | β With This Action |
|---|---|
# Multiple jobs for different flows
build-pr:
if: github.event_name == 'pull_request'
steps:
- run: docker build -t app:pr-$SHA .
build-dev:
if: github.ref == 'refs/heads/dev'
steps:
- run: docker build -t app:dev-$SHA .
build-patch:
if: contains(github.head_ref, 'hotfix')
steps:
- run: docker build -t app:patch-$SHA .
# ... 50+ lines of repetitive config |
# One job handles everything
build:
steps:
- uses: wgtechlabs/container-build-flow-action@v1
with:
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
# Done! Automatically detects flow,
# builds, tags, and pushes correctly |
Result: Reduce workflow complexity by 80%+ while gaining automatic PR comments, multi-registry support, and intelligent tagging.
All flow types use commit SHA (first 7 characters) for tagging, ensuring traceability back to the exact code that was built.
| Flow Type | Trigger | Tag Format | Use Case |
|---|---|---|---|
| PR | Pull Request β dev branch |
pr-{sha} |
Feature development and testing |
| DEV | Pull Request from dev β main OR Push to dev branch |
dev-{sha} |
Development images |
| PATCH | Pull Request β main (not from dev) |
patch-{sha} |
Hotfixes and emergency patches |
| STAGING | Direct push to main branch (after PR merge) |
staging-{sha} |
Pre-production validation before release |
| WIP | Other branches/commits | wip-{sha} |
Work in progress experiments |
Note: The
{sha}in each tag represents the HEAD commit SHA of the PR or push event, not the PR number. This ensures every build can be traced to its exact source code.
Every image tag includes the commit SHA (first 7 characters) instead of PR numbers for several important reasons:
- Traceability: Directly links images to exact source code in Git history
- Uniqueness: Guarantees unique tags even across multiple PRs
- Reproducibility: Makes it easy to rebuild or debug specific versions
- CI/CD Integration: Works seamlessly with GitOps workflows
# Feature PR #42 with commit abc1234
myorg/myapp:pr-abc1234
# Dev branch with commit def5678
myorg/myapp:dev-def5678
# Staging build after merge to main with commit ghi9012
myorg/myapp:staging-ghi9012
# With custom prefix/suffix
myorg/myapp:v1-pr-abc1234-alpine# In your deployment workflow, reference by SHA
- name: Deploy to Staging
run: |
docker pull myorg/myapp:staging-${{ github.sha:0:7 }}
docker tag myorg/myapp:staging-${{ github.sha:0:7 }} myorg/myapp:latest
# Deploy...name: Container Build
on:
pull_request:
branches: [main, dev]
push:
branches: [main, dev]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build and Push Container
uses: wgtechlabs/container-build-flow-action@v1
with:
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}- name: Build and Push to Docker Hub
uses: wgtechlabs/container-build-flow-action@v1
with:
registry: docker-hub
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}- name: Build and Push to GHCR
uses: wgtechlabs/container-build-flow-action@v1
with:
registry: ghcr
ghcr-token: ${{ secrets.GITHUB_TOKEN }}- name: Build with Custom Branches
uses: wgtechlabs/container-build-flow-action@v1
with:
main-branch: production
dev-branch: staging
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}- name: Multi-Platform Build
uses: wgtechlabs/container-build-flow-action@v1
with:
platforms: linux/amd64,linux/arm64
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}- name: Advanced Container Build
uses: wgtechlabs/container-build-flow-action@v1
with:
# Registry
registry: both
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
# Branch Configuration
main-branch: main
dev-branch: dev
# Build Configuration
dockerfile: ./docker/Dockerfile
context: .
platforms: linux/amd64,linux/arm64
build-args: |
NODE_ENV=production
VERSION=${{ github.sha }}
# Tagging
tag-prefix: v1-
tag-suffix: -alpine
# PR Comments
pr-comment-enabled: true
# Security
provenance: true
sbom: trueThis action includes comprehensive built-in security scanning using Trivy, providing vulnerability detection for your container images, source code, and Dockerfilesβall enabled by default.
- π Pre-Build Scanning: Scan source code and Dockerfile before building
- π³ Container Image Scanning: Scan final container images for vulnerabilities
- π GitHub Security Integration: Automatic SARIF upload to GitHub Security tab
- π¬ PR Comments: Detailed vulnerability reports in pull request comments
- π Baseline Comparison: Compare vulnerabilities against baseline images
- π¨ Fail on Vulnerabilities: Optional build failure on security issues
- β‘ Fast & Configurable: Customizable severity levels, timeouts, and ignore patterns
Default Behavior - Security scanning is enabled automatically:
- name: Build with Security Scanning
uses: wgtechlabs/container-build-flow-action@v1
with:
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
# Security scanning runs automatically!
# - Source code scan
# - Dockerfile scan
# - Container image scan
# - Results uploaded to GitHub Security tab
# - Vulnerabilities shown in PR commentsIf you use your own security tools or want to skip scanning:
- name: Build without Security Scanning
uses: wgtechlabs/container-build-flow-action@v1
with:
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
pre-build-scan-enabled: false
image-scan-enabled: false
vulnerability-comment-enabled: falseFail the build if HIGH or CRITICAL vulnerabilities are found:
- name: Strict Security Build
uses: wgtechlabs/container-build-flow-action@v1
with:
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
trivy-severity: HIGH,CRITICAL
trivy-ignore-unfixed: true
fail-on-vulnerability: trueInclude all vulnerabilities (UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL):
- name: Comprehensive Security Scan
uses: wgtechlabs/container-build-flow-action@v1
with:
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
trivy-severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICALTrack security improvements by comparing against a baseline image:
- name: Build with Baseline Comparison
uses: wgtechlabs/container-build-flow-action@v1
with:
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
enable-image-comparison: true
comparison-baseline-image: myorg/myapp:latestExclude directories from scanning (e.g., test fixtures, vendor code):
- name: Build with Selective Scanning
uses: wgtechlabs/container-build-flow-action@v1
with:
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
trivy-skip-dirs: tests/,vendor/,node_modules/Organize security results with custom categories:
- name: Build with Custom SARIF Categories
uses: wgtechlabs/container-build-flow-action@v1
with:
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
upload-sarif: true
sarif-category-source: my-app-source-scan
sarif-category-dockerfile: my-app-dockerfile-scan
sarif-category-image: my-app-container-scanIncrease scan timeout for large container images:
- name: Build Large Image with Extended Timeout
uses: wgtechlabs/container-build-flow-action@v1
with:
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
trivy-timeout: 20m0sCreate a .trivyignore file in your repository root:
# Copy example file
cp .trivyignore.example .trivyignore
# Add CVEs to ignore
echo "CVE-2021-12345" >> .trivyignoreExample .trivyignore:
# Known false positive in test dependencies
CVE-2021-44228
# Accepted risk with mitigations
CVE-2022-12345
Best Practice: Always document why a vulnerability is ignored.
GitHub Security Tab: View detailed vulnerability reports:
- Navigate to your repository
- Click Security tab
- Click Code scanning alerts
- Filter by tool: Trivy
PR Comments: Vulnerability summaries are automatically added to PR comments with:
- Pre-build scan results
- Container vulnerability counts by severity
- Comparison with baseline (if enabled)
- Expandable details for each vulnerability
- Links to GitHub Security tab
| Input | Description | Required | Default |
|---|---|---|---|
pre-build-scan-enabled |
Enable pre-build security scanning | No | true |
scan-source-code |
Scan source code and dependencies | No | true |
scan-dockerfile |
Scan Dockerfile for misconfigurations | No | true |
image-scan-enabled |
Enable post-build container image scanning | No | true |
trivy-severity |
Severity levels to scan (comma-separated) | No | HIGH,CRITICAL |
trivy-ignore-unfixed |
Ignore vulnerabilities without fixes | No | false |
trivy-timeout |
Trivy scan timeout duration | No | 10m0s |
trivy-skip-dirs |
Directories to skip (comma-separated) | No | '' |
trivy-skip-files |
Files to skip (comma-separated) | No | '' |
upload-sarif |
Upload results to GitHub Security tab | No | true |
sarif-category-source |
SARIF category for source code scan | No | trivy-source-scan |
sarif-category-dockerfile |
SARIF category for Dockerfile scan | No | trivy-dockerfile-scan |
sarif-category-image |
SARIF category for container image scan | No | trivy-container-scan |
vulnerability-comment-enabled |
Add vulnerability info to PR comments | No | true |
enable-image-comparison |
Compare with baseline image | No | false |
comparison-baseline-image |
Baseline image for comparison | No | '' |
fail-on-vulnerability |
Fail build if vulnerabilities found | No | false |
| Output | Description |
|---|---|
vulnerability-scan-completed |
Whether scanning completed successfully |
total-vulnerabilities |
Total number of vulnerabilities found |
critical-vulnerabilities |
Number of CRITICAL vulnerabilities |
high-vulnerabilities |
Number of HIGH vulnerabilities |
medium-vulnerabilities |
Number of MEDIUM vulnerabilities |
low-vulnerabilities |
Number of LOW vulnerabilities |
Using Outputs:
- name: Build Container
id: build
uses: wgtechlabs/container-build-flow-action@v1
with:
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Check Vulnerability Results
run: |
echo "Scan completed: ${{ steps.build.outputs.vulnerability-scan-completed }}"
echo "Total vulnerabilities: ${{ steps.build.outputs.total-vulnerabilities }}"
echo "Critical: ${{ steps.build.outputs.critical-vulnerabilities }}"
echo "High: ${{ steps.build.outputs.high-vulnerabilities }}"Trivy is:
- β Open source and free
- β No vendor lock-in
- β Comprehensive (CVE, misconfigurations, secrets, licenses)
- β Fast and lightweight
- β Well-maintained by Aqua Security
- β Native GitHub Actions integration
Yes! Disable the built-in scanning:
pre-build-scan-enabled: false
image-scan-enabled: false
vulnerability-comment-enabled: falseThen add your own security scanning steps.
Security scanning adds approximately:
- Source code scan: 30-60 seconds
- Dockerfile scan: 5-10 seconds
- Container image scan: 1-3 minutes
Total overhead: 2-5 minutes on average.
To minimize impact:
- Use
trivy-severity: HIGH,CRITICAL(default) - Set
trivy-ignore-unfixed: true - Use GitHub Actions caching (automatic)
- Create a
.trivyignorefile in your repository root - Add CVE IDs to ignore (one per line)
- Document why each CVE is ignored
- Review ignored CVEs regularly
Example:
# Create from example
cp .trivyignore.example .trivyignore
# Add specific CVE
echo "CVE-2021-12345 # False positive in test deps" >> .trivyignoreFor full security scanning features, add these to your workflow:
permissions:
contents: read # Read repository content
packages: write # Push to registries
security-events: write # Upload SARIF to Security tab
pull-requests: write # Comment on PRsSee the examples/ directory for complete workflow examples:
basic-scanning.yml- Default security scanningstrict-security.yml- Fail on vulnerabilitieswith-comparison.yml- Baseline comparison
| Input | Description | Required | Default |
|---|---|---|---|
registry |
Target registry (docker-hub, ghcr, both) |
No | both |
dockerhub-username |
Docker Hub username | No | '' |
dockerhub-token |
Docker Hub access token | No | '' |
ghcr-token |
GitHub token for GHCR | No | ${{ github.token }} |
ghcr-username |
GitHub username for GHCR | No | ${{ github.repository_owner }} |
| Input | Description | Required | Default |
|---|---|---|---|
main-branch |
Name of main/production branch | No | main |
dev-branch |
Name of development branch | No | dev |
| Input | Description | Required | Default |
|---|---|---|---|
dockerfile |
Path to Dockerfile | No | ./Dockerfile |
context |
Build context path | No | . |
platforms |
Target platforms (comma-separated) | No | linux/amd64 |
build-args |
Build arguments (newline-separated) | No | '' |
labels |
Image labels (newline-separated) | No | '' |
cache-enabled |
Enable build cache | No | true |
| Input | Description | Required | Default |
|---|---|---|---|
image-name |
Container image name | No | Repository name |
tag-prefix |
Prefix for image tags | No | '' |
tag-suffix |
Suffix for image tags | No | '' |
| Input | Description | Required | Default |
|---|---|---|---|
pr-comment-enabled |
Enable PR comments | No | true |
pr-comment-template |
Custom comment template | No | Default template |
| Input | Description | Required | Default |
|---|---|---|---|
push-enabled |
Enable registry push | No | true |
load-enabled |
Load to Docker daemon | No | false |
provenance |
Enable provenance attestation | No | true |
sbom |
Enable SBOM attestation | No | true |
| Input | Description | Required | Default |
|---|---|---|---|
pre-build-scan-enabled |
Enable pre-build security scanning | No | true |
scan-source-code |
Scan source code and dependencies | No | true |
scan-dockerfile |
Scan Dockerfile for misconfigurations | No | true |
image-scan-enabled |
Enable post-build container image scanning | No | true |
trivy-severity |
Severity levels to scan (comma-separated) | No | HIGH,CRITICAL |
trivy-ignore-unfixed |
Ignore vulnerabilities without fixes | No | false |
trivy-timeout |
Trivy scan timeout duration | No | 10m0s |
trivy-skip-dirs |
Directories to skip (comma-separated) | No | '' |
trivy-skip-files |
Files to skip (comma-separated) | No | '' |
upload-sarif |
Upload results to GitHub Security tab | No | true |
sarif-category-source |
SARIF category for source code scan | No | trivy-source-scan |
sarif-category-dockerfile |
SARIF category for Dockerfile scan | No | trivy-dockerfile-scan |
sarif-category-image |
SARIF category for container image scan | No | trivy-container-scan |
vulnerability-comment-enabled |
Add vulnerability info to PR comments | No | true |
enable-image-comparison |
Compare with baseline image | No | false |
comparison-baseline-image |
Baseline image for comparison | No | '' |
fail-on-vulnerability |
Fail build if vulnerabilities found | No | false |
| Output | Description |
|---|---|
image-tags |
Complete list of applied image tags |
registry-urls |
Full image URLs for each registry |
build-digest |
SHA256 digest of built image |
build-flow-type |
Detected flow type (pr, dev, patch, staging, wip) |
short-sha |
Short commit SHA used in tags |
vulnerability-scan-completed |
Whether vulnerability scanning completed successfully |
total-vulnerabilities |
Total number of vulnerabilities found |
critical-vulnerabilities |
Number of CRITICAL severity vulnerabilities |
high-vulnerabilities |
Number of HIGH severity vulnerabilities |
medium-vulnerabilities |
Number of MEDIUM severity vulnerabilities |
low-vulnerabilities |
Number of LOW severity vulnerabilities |
- name: Build Container
id: build
uses: wgtechlabs/container-build-flow-action@v1
with:
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Display Build Info
run: |
echo "Build Flow: ${{ steps.build.outputs.build-flow-type }}"
echo "Image Tags: ${{ steps.build.outputs.image-tags }}"
echo "Registry URLs: ${{ steps.build.outputs.registry-urls }}"
echo "Digest: ${{ steps.build.outputs.build-digest }}"Context: Pull request from feature/new-api to dev
Result:
- Flow Type:
pr - Tag:
pr-abc1234(uses PR HEAD commit SHA) - Comment: Docker pull instructions automatically posted to PR
- Logs:
β Step 2: Build flow detection complete!ββ Step 3: PR comment complete!ββ Step 4: Output generation complete!
Context: Direct push to dev branch with open PR #18
Result:
- Flow Type:
dev - Tag:
dev-def5678(uses actual commit SHA) - Comment: Finds and updates PR #18 automatically
- Logs:
π Push event detected on branch: devββ Found associated PR #18ββ Step 3: PR comment complete!
Context: Pull request from dev to main
Result:
- Flow Type:
dev - Tag:
dev-xyz5678 - Registries: Both Docker Hub and GHCR
Context: Direct push to main branch (typically after merging a PR)
Result:
- Flow Type:
staging - Tag:
staging-abc1234(uses the merge commit SHA) - Purpose: Pre-production validation - test the exact code that will be released
- Workflow: Build β Deploy to staging environment β Manual validation β Tag for production
Best Practice: Use
staging-{sha}images for pre-production testing. Once validated, create a semantic version tag (e.g.,v1.2.3) pointing to the same commit for production deployment.
Context: Pull request from hotfix/critical-bug to main
Result:
- Flow Type:
patch - Tag:
patch-def9012 - Fast-tracked: Emergency fix workflow
Context: Push to experiment/new-feature branch
Result:
- Flow Type:
wip - Tag:
wip-ghi3456 - Usage: Testing and experimentation
Problem: Login to Docker Hub or GHCR fails
Solution:
# Ensure secrets are properly configured
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
# For GHCR, ensure token has proper permissions
ghcr-token: ${{ secrets.GITHUB_TOKEN }}Problem: Dockerfile or context path invalid
Solution:
dockerfile: ./path/to/Dockerfile # Relative to repository root
context: ./app # Build context directoryProblem: Platforms not supported or QEMU missing
Solution:
# Add QEMU setup before action
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Build Multi-Platform
uses: wgtechlabs/container-build-flow-action@v1
with:
platforms: linux/amd64,linux/arm64- Docker Build Push Action
- Docker Metadata Action
- GitHub Actions Documentation
- Container Registry Best Practices
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.
Waren Gonzaga
WG Technology Labs
If this action helps your workflow, please consider:
- β Starring the repository
- π Reporting issues
- π‘ Suggesting new features
- π’ Sharing with others