Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: docker-publish

on:
push:
branches: [main]
release:
types: [published]
workflow_call:
inputs:
tag:
description: Published release tag to build
required: true
type: string

permissions:
contents: read

concurrency:
group: docker-publish-${{ inputs.tag || github.event.release.tag_name || github.ref }}
cancel-in-progress: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
with:
ref: ${{ (inputs.tag && format('refs/tags/{0}', inputs.tag)) || (github.event.release.tag_name && format('refs/tags/{0}', github.event.release.tag_name)) || github.sha }}
persist-credentials: false
- name: Read build metadata
id: build
run: |
{
echo "version=$(cat VERSION)"
echo "commit=$(git rev-parse HEAD)"
echo "date=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
} >> "$GITHUB_OUTPUT"
- uses: docker/setup-buildx-action@v3
- name: Generate image tags and labels
id: meta
uses: docker/metadata-action@v5
with:
context: workflow
images: ghcr.io/${{ github.repository }}
flavor: latest=false
tags: |
type=raw,value=${{ inputs.tag || github.event.release.tag_name || 'latest' }}
type=sha,format=long
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push image
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
VERSION=${{ steps.build.outputs.version }}
COMMIT=${{ steps.build.outputs.commit }}
BUILD_DATE=${{ steps.build.outputs.date }}
DIRTY=false
cache-from: type=gha
cache-to: type=gha,mode=max
10 changes: 10 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,13 @@ jobs:
--title "$RELEASE_TAG" --generate-notes \
./*.tar.gz SHA256SUMS
gh release edit "$RELEASE_TAG" --draft=false

# GITHUB_TOKEN-created releases do not trigger release-event workflows.
image:
needs: publish
permissions:
contents: read
packages: write
uses: ./.github/workflows/docker-publish.yml
with:
tag: ${{ github.ref_name }}
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,19 @@ The version endpoint confirms that the proxy is running; it does not contact you
gateway. Next, configure the client you use below. Keep your existing API
credentials: the proxy forwards them to the gateway.

Prebuilt Linux amd64 images are published to GitHub Container Registry:

```bash
docker pull ghcr.io/xllent-ai/steady-proxy:latest
```

`latest` follows `main`; release tags such as `v0.1.1` select a release instead.
To use a prebuilt image with the example Compose configuration, change its
`image:` to `ghcr.io/xllent-ai/steady-proxy:latest`, remove the `build:` block, then
run `docker compose pull && docker compose up -d`. See
[container publishing](docs/RELEASING.md#container-images) for tagging and registry
access details.

### Claude Code

Merge this `env` block into `~/.claude/settings.json`, keeping your other settings
Expand Down
32 changes: 29 additions & 3 deletions docs/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,33 @@ The workflow then:
4. Refuses to proceed if any release already uses the tag, including a draft.
5. Creates a draft with generated GitHub release notes and all five assets, then
publishes it after uploading succeeds.
6. Calls the container publishing workflow to build the tagged source and push
`ghcr.io/xllent-ai/steady-proxy:v0.1.1` (using the actual release tag).

The workflow uses GitHub's automatic token; no personal token is needed. It does
not upload container images. Review the published release notes for any migration
or configuration guidance that commit and pull-request summaries do not explain.
The workflows use GitHub's automatic token; no personal token is needed. The
container job has `packages: write` permission. Review the published release notes
for any migration or configuration guidance that commit and pull-request summaries
do not explain.

## Container images

The [container workflow](../.github/workflows/docker-publish.yml) publishes Linux
amd64 images to `ghcr.io/xllent-ai/steady-proxy`:

- Every push to `main` updates `latest` from that push's commit.
- Publishing a GitHub release builds its tag and publishes an image with that
tag, such as `v0.1.1`. Release images never move `latest`.
- Both paths also publish `sha-<full-commit-sha>` and stamp the executable with
`VERSION`, the checked-out commit, build time, and clean working-tree status.

The release workflow calls the container workflow directly because releases
created with `GITHUB_TOKEN` do not trigger another workflow via a `release` event.
Manually published releases use the `release: published` trigger instead.

After the first image is published, check the package's visibility in GitHub's
package settings; change it to public to allow unauthenticated pulls. The image's
source label links it to this repository. If a package with the same name already
exists, grant this repository Actions access to it before publishing.

## If a release fails

Expand All @@ -76,6 +99,9 @@ failure creates no GitHub release. An upload or publication failure can leave a
draft; inspect it and delete that draft before rerunning the failed jobs. The
workflow will not overwrite its assets automatically.

If only the container job fails after the release is published, rerun that failed
job; do not recreate the release. It rebuilds the same release tag.

If a published release needs a fix, use a new version and tag. Keep existing
published tags and assets unchanged so downloads continue to identify the same
code and checksums.
Loading