A GitHub Action that automatically checks for and updates Kamal accessories to their latest versions from Docker Hub, GitHub Container Registry (GHCR), and other OCI registries.
- 🔍 Automatic Version Detection - Scans your Kamal deployment configurations for accessories and checks registries for latest versions
- 🌐 Multi-Registry Support - Works with Docker Hub, GitHub Container Registry (ghcr.io), and other OCI-compliant registries
- 📦 Semantic Versioning - Intelligently compares semantic versions to ensure only newer versions are applied
- 🔒 SHA256 Support - Automatically fetches and includes SHA256 digests for enhanced security
- 📝 Pull Request Creation - Optionally creates pull requests with detailed update information
- ⚡ Caching - Caches Docker Hub API responses to improve performance and reduce API calls
- 🎯 Multiple Modes - Check-only, interactive update, or automatic update modes
Add this action to your workflow to automatically check for accessory updates:
name: Update Kamal Accessories
on:
workflow_dispatch:
schedule:
- cron: "0 8 * * 0" # Every Sunday at 8 AM UTC
jobs:
update:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
- name: Update Kamal accessories
uses: robfrank/kamal-accessories-updater@v25
with:
config-dir: config
mode: update-all
create-pr: true
github-token: ${{ secrets.GITHUB_TOKEN }}| Input | Description | Required | Default |
|---|---|---|---|
config-dir |
Directory containing Kamal deploy*.yml files |
No | config |
mode |
Update mode: check, update, or update-all |
No | update-all |
create-pr |
Whether to create a pull request with updates | No | true |
pr-branch |
Branch name for the pull request | No | update/kamal-accessories |
pr-title |
Title for the pull request | No | chore: bump Kamal accessories versions |
pr-body |
Body text for the pull request | No | See action.yml |
pr-labels |
Comma-separated list of labels for the PR | No | dependencies |
github-token |
GitHub token for creating pull requests | No | ${{ github.token }} |
check- Only check for updates, don't modify filesupdate- Update files but prompt for confirmation (not applicable in CI)update-all- Automatically update all accessories to latest versions
| Output | Description |
|---|---|
updates-available |
Whether any updates are available (true/false) |
updates-count |
Number of updates available |
updates-json |
JSON array of all updates |
pr-number |
Pull request number if created |
pr-url |
Pull request URL if created |
Check for updates and create a PR:
- name: Update accessories
uses: robfrank/kamal-accessories-updater@v25
with:
config-dir: config- name: Check for updates
id: check
uses: robfrank/kamal-accessories-updater@v25
with:
config-dir: config
mode: check
create-pr: false
- name: Comment on PR
if: steps.check.outputs.updates-available == 'true'
run: |
echo "Found ${{ steps.check.outputs.updates-count }} update(s)"
echo "${{ steps.check.outputs.updates-json }}"- name: Update accessories
uses: robfrank/kamal-accessories-updater@v25
with:
config-dir: config
mode: update-all
create-pr: false
- name: Commit 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 "chore: update Kamal accessories"
git push- name: Update accessories
uses: robfrank/kamal-accessories-updater@v25
with:
config-dir: config
pr-branch: dependencies/kamal-accessories
pr-title: "⬆️ Update Kamal accessories to latest versions"
pr-labels: "dependencies,automation,kamal"- Scans Configuration Files - Finds all
deploy*.ymlfiles in your config directory - Extracts Accessories - Parses YAML to identify accessories and their current versions
- Detects Registry - Automatically detects the registry (Docker Hub, GHCR, etc.) from the image name
- Queries Registry API - Fetches latest semantic versions from the appropriate registry
- Compares Versions - Intelligently compares versions to determine if updates are available
- Fetches Digests - Retrieves SHA256 digests for the latest versions
- Updates Files - Modifies your configuration files with new versions and digests
- Creates PR - Optionally creates a pull request with the changes
This action works with any Docker image used as a Kamal accessory. Common examples include:
- Redis (
redis) - PostgreSQL (
postgres) - MySQL (
mysql) - Memcached (
memcached) - BusyBox (
busybox) - Any custom Docker image on Docker Hub
The action supports multiple container registries:
Default registry - No authentication required for public images.
accessories:
redis:
image: redis:7.0.0 # Official image (implicit docker.io)
custom:
image: myorg/myapp:1.0.0 # Organization image
explicit:
image: docker.io/library/postgres:15 # Explicit registry prefixRequires authentication for most operations. Set the GHCR_TOKEN environment variable with a GitHub Personal Access Token (PAT) or use the automatic GITHUB_TOKEN.
accessories:
myapp:
image: ghcr.io/myorg/myapp:1.0.0
public:
image: ghcr.io/owner/public-image:2.0.0GitHub Action Configuration for GHCR:
- name: Update accessories
uses: robfrank/kamal-accessories-updater@v25
with:
config-dir: config
env:
GHCR_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Use GitHub token for GHCR accessFor private GHCR images, create a GitHub PAT with read:packages scope:
env:
GHCR_TOKEN: ${{ secrets.GHCR_PAT }} # Use custom PAT for private imagesThe action includes detection for:
- Google Container Registry (gcr.io)
- Quay.io (quay.io)
- Generic OCI registries (basic support)
Support for additional registries is being actively developed. Open an issue if you need support for a specific registry.
Your Kamal configuration files should follow the standard format:
accessories:
# Docker Hub - official image (default registry)
redis:
image: redis:7.0.0
host: 192.168.0.1
# ... other configuration
# Docker Hub - with SHA256 digest
postgres:
image: postgres:15.0@sha256:abc123...
host: 192.168.0.1
# ... other configuration
# GitHub Container Registry
myapp:
image: ghcr.io/myorg/myapp:1.2.3@sha256:def456...
host: 192.168.0.1
# ... other configuration
# Docker Hub - organization image
custom:
image: mycompany/myservice:2.0.0
host: 192.168.0.1
# ... other configurationThe action will:
- Automatically detect the registry from the image name
- Preserve your existing configuration structure
- Update only the image version
- Add or update SHA256 digests
- Keep all other settings intact
The action caches registry API responses for 1 hour to:
- Reduce API calls
- Improve performance
- Avoid rate limiting
Cache is stored in /tmp/docker-registry-cache and automatically cleaned up. Each registry is cached separately to ensure accuracy.
Run the test suite locally:
# Run all tests
./test/run-tests.sh
# Run unit tests only
./test/test-utils.sh
# Run integration tests only
./test/test-integration.sh.
├── action.yml # Action metadata
├── src/
│ ├── check-updates.sh # Main update logic
│ └── utils.sh # Utility functions
├── test/
│ ├── fixtures/ # Test configurations
│ ├── test-utils.sh # Unit tests
│ ├── test-integration.sh # Integration tests
│ └── run-tests.sh # Test runner
└── .github/
└── workflows/
├── test.yml # CI workflow
├── release.yml # Release workflow
└── upgrade-accessories-versions.yml # Example workflow
You can test the action locally with your own configuration:
# Check for updates only
./src/check-updates.sh path/to/config check
# Update all accessories
./src/check-updates.sh path/to/config update-allContributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for your changes
- Ensure all tests pass
- Submit a pull request
This project is licensed under the ASL 2.0 License - see the LICENSE file for details.
- Kamal Documentation
- Kamal Accessories Guide
- Docker Hub API
- GitHub Container Registry
- OCI Distribution Spec
- Built for use with Kamal by 37signals
- Uses peter-evans/create-pull-request for PR creation
If you encounter any issues or have questions: