Add a Docker workflow that publishes multi-arch images
Pushes :edge for main and :x.y.z, :x.y and :latest for release tags, optionally mirrored to another registry. The release workflow no longer builds the image itself, so a tag does not publish it twice. The README covers running the image anywhere and the settings the workflows read. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b53af0e196
commit
8f01c6213f
3 files changed
+122
-30
No files matched your search
@@ -0,0 +1,87 @@
|
|||||||
|
name: Docker
|
||||||
|
|
||||||
|
# Publishes the container image (linux/amd64 and linux/arm64):
|
||||||
|
# push to main -> :edge and :sha-<commit>
|
||||||
|
# tag v1.2.3 -> :1.2.3, :1.2 and :latest (pre-releases like v1.2.3-rc1 get only :1.2.3-rc1)
|
||||||
|
# Run it by hand from the Actions tab to rebuild the current branch.
|
||||||
|
#
|
||||||
|
# Settings (all optional):
|
||||||
|
# secret REGISTRY_TOKEN access token with package write permission, if the job token can't push
|
||||||
|
# variable REGISTRY_USER user for that token (defaults to the person who triggered the run)
|
||||||
|
# variable MIRROR_IMAGE also push to another registry, e.g. ghcr.io/you/spinner or docker.io/you/spinner
|
||||||
|
# secret MIRROR_TOKEN and variable MIRROR_USER: login for that registry
|
||||||
|
# variable PUBLISH_DOCKER set to "false" to skip this workflow
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
tags: ['v*']
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
image:
|
||||||
|
if: ${{ vars.PUBLISH_DOCKER != 'false' }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GOPRIVATE: git.veillax.com
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
|
||||||
|
- name: Let Go fetch modules from this server
|
||||||
|
run: git config --global url."https://x-access-token:${{ secrets.GITHUB_TOKEN }}@git.veillax.com/".insteadOf "https://git.veillax.com/"
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: |
|
||||||
|
go vet ./...
|
||||||
|
go test ./...
|
||||||
|
|
||||||
|
# The Dockerfile packages these binaries, so the image needs no Go toolchain or emulation.
|
||||||
|
- name: Build the binaries
|
||||||
|
env:
|
||||||
|
TARGETS: linux/amd64 linux/arm64
|
||||||
|
run: sh deploy/build.sh
|
||||||
|
|
||||||
|
- name: Log in
|
||||||
|
env:
|
||||||
|
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN || secrets.GITHUB_TOKEN }}
|
||||||
|
REGISTRY_USER: ${{ vars.REGISTRY_USER || github.actor }}
|
||||||
|
MIRROR_IMAGE: ${{ vars.MIRROR_IMAGE }}
|
||||||
|
MIRROR_USER: ${{ vars.MIRROR_USER }}
|
||||||
|
MIRROR_TOKEN: ${{ secrets.MIRROR_TOKEN }}
|
||||||
|
run: |
|
||||||
|
host=${GITHUB_SERVER_URL#*://}
|
||||||
|
echo "$REGISTRY_TOKEN" | docker login "$host" -u "$REGISTRY_USER" --password-stdin
|
||||||
|
if [ -n "$MIRROR_IMAGE" ]; then
|
||||||
|
echo "$MIRROR_TOKEN" | docker login "${MIRROR_IMAGE%%/*}" -u "$MIRROR_USER" --password-stdin
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
env:
|
||||||
|
MIRROR_IMAGE: ${{ vars.MIRROR_IMAGE }}
|
||||||
|
run: |
|
||||||
|
host=${GITHUB_SERVER_URL#*://}
|
||||||
|
owner=$(echo "$GITHUB_REPOSITORY_OWNER" | tr 'A-Z' 'a-z')
|
||||||
|
images="$host/$owner/spinner"
|
||||||
|
[ -n "$MIRROR_IMAGE" ] && images="$images $MIRROR_IMAGE"
|
||||||
|
|
||||||
|
if [ "$GITHUB_REF_TYPE" = tag ]; then
|
||||||
|
v=${GITHUB_REF_NAME#v}
|
||||||
|
tags="$v"
|
||||||
|
case "$v" in
|
||||||
|
*-*) ;; # pre-releases don't move :1.2 or :latest
|
||||||
|
*) tags="$tags ${v%.*} latest" ;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
tags="edge sha-$(echo "$GITHUB_SHA" | cut -c1-7)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
args=""
|
||||||
|
for i in $images; do for t in $tags; do args="$args -t $i:$t"; done; done
|
||||||
|
docker buildx create --name spinner --driver docker-container --use >/dev/null 2>&1 || docker buildx use spinner
|
||||||
|
echo "pushing:$args"
|
||||||
|
docker buildx build --platform linux/amd64,linux/arm64 $args --push .
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
name: Release
|
name: Release
|
||||||
|
|
||||||
# Push a tag such as v0.2.0 to build and publish a release:
|
# Push a tag such as v0.2.0 to publish a release. The Docker workflow builds the image from the same tag:
|
||||||
# git tag -a v0.2.0 -m "spinner v0.2.0" && git push origin v0.2.0
|
# git tag -a v0.2.0 -m "spinner v0.2.0" && git push origin v0.2.0
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -37,26 +37,3 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
TOKEN: ${{ secrets.RELEASE_TOKEN || secrets.GITHUB_TOKEN }}
|
TOKEN: ${{ secrets.RELEASE_TOKEN || secrets.GITHUB_TOKEN }}
|
||||||
run: sh deploy/publish-release.sh "${GITHUB_REF_NAME}"
|
run: sh deploy/publish-release.sh "${GITHUB_REF_NAME}"
|
||||||
|
|
||||||
# Skipped when the repository variable PUBLISH_DOCKER is "false", or fails alone
|
|
||||||
# if this runner has no Docker: the release above is already published by then.
|
|
||||||
# Optional secret REGISTRY_TOKEN (and variable REGISTRY_USER): an access token
|
|
||||||
# with package write permission, for servers where the job token can't push.
|
|
||||||
- name: Build and push the container image
|
|
||||||
if: ${{ vars.PUBLISH_DOCKER != 'false' }}
|
|
||||||
env:
|
|
||||||
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
REGISTRY_USER: ${{ vars.REGISTRY_USER || github.actor }}
|
|
||||||
run: |
|
|
||||||
host=${GITHUB_SERVER_URL#*://}
|
|
||||||
owner=$(echo "$GITHUB_REPOSITORY_OWNER" | tr 'A-Z' 'a-z')
|
|
||||||
image="$host/$owner/spinner"
|
|
||||||
echo "$REGISTRY_TOKEN" | docker login "$host" -u "$REGISTRY_USER" --password-stdin
|
|
||||||
# a container-driver builder can build several architectures in one go
|
|
||||||
docker buildx create --name release --driver docker-container --use >/dev/null 2>&1 || docker buildx use release
|
|
||||||
tags="-t $image:$GITHUB_REF_NAME"
|
|
||||||
case "$GITHUB_REF_NAME" in
|
|
||||||
*-*) ;; # pre-releases (v1.0.0-rc1) don't move :latest
|
|
||||||
*) tags="$tags -t $image:latest" ;;
|
|
||||||
esac
|
|
||||||
docker buildx build --platform linux/amd64,linux/arm64 $tags --push .
|
|
||||||
@@ -48,24 +48,52 @@ All except `/` need `Authorization: Bearer <token>`.
|
|||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
|
|
||||||
|
The image is `git.veillax.com/veillax/spinner` for linux/amd64 and linux/arm64. It runs as a non-root user, keeps its config in the `/data` volume, and writes a starter `spinner.json` there on first start. The admin page on port 8080 is the quickest way to add servers; keep it private or behind HTTPS.
|
||||||
|
|
||||||
|
| Tag | Meaning |
|
||||||
|
| --- | --- |
|
||||||
|
| `latest` | The newest release |
|
||||||
|
| `1.2.3`, `1.2` | An exact release, or the newest patch of a minor version |
|
||||||
|
| `edge` | The latest commit on `main` |
|
||||||
|
| `sha-<commit>` | One specific commit |
|
||||||
|
|
||||||
|
Run it anywhere Docker runs:
|
||||||
|
|
||||||
```
|
```
|
||||||
cp .env.example .env # set SPINNER_ADMIN_TOKEN
|
docker run -d --name spinner --restart unless-stopped \
|
||||||
docker compose -f deploy/docker-compose.yml up -d
|
-p 25565:25565 -p 127.0.0.1:8080:8080 \
|
||||||
|
-e SPINNER_ADMIN_TOKEN=change-me \
|
||||||
|
-v spinner-data:/data \
|
||||||
|
git.veillax.com/veillax/spinner:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
The image is `git.veillax.com/veillax/spinner` (linux/amd64 and linux/arm64). It keeps its config in the `/data` volume and writes a starter `spinner.json` there on first start, so the admin page on port 8080 is the quickest way to add servers. Keep that port private or behind HTTPS.
|
Or with Compose: `cp .env.example .env`, set `SPINNER_ADMIN_TOKEN`, then `docker compose -f deploy/docker-compose.yml up -d`. Backends on the Docker host are reachable at `host.docker.internal` (add `--add-host host.docker.internal:host-gateway` on Linux), or put Spinner and the Minecraft containers on one Docker network and use their container names.
|
||||||
|
|
||||||
|
If the registry is private, run `docker login git.veillax.com` first.
|
||||||
|
|
||||||
## Releases
|
## Releases
|
||||||
|
|
||||||
Push a tag to build archives, publish a release and push the image:
|
Push a tag to publish a release and its image:
|
||||||
|
|
||||||
```
|
```
|
||||||
git tag -a v0.1.0 -m "spinner v0.1.0" && git push origin v0.1.0
|
git tag -a v0.1.0 -m "spinner v0.1.0" && git push origin v0.1.0
|
||||||
```
|
```
|
||||||
|
|
||||||
`.gitea/workflows/release.yml` runs `deploy/build.sh`, uploads the archives with `deploy/publish-release.sh`, then builds and pushes the image. Set the repository variable `PUBLISH_DOCKER` to `false` to skip the image. If the job token cannot write releases or packages, add the secrets `RELEASE_TOKEN` and `REGISTRY_TOKEN` (and the variable `REGISTRY_USER`).
|
Two workflows run on the tag:
|
||||||
|
|
||||||
To build by hand: `sh deploy/build.sh` puts binaries and archives in `dist/`, then `docker buildx build .` packages the linux binary.
|
* `.gitea/workflows/release.yml` builds archives with `deploy/build.sh` and uploads them with `deploy/publish-release.sh`.
|
||||||
|
* `.gitea/workflows/docker.yml` tests, builds both Linux binaries and pushes the image. It also pushes `edge` on every push to `main`, and can be run by hand from the Actions tab.
|
||||||
|
|
||||||
|
Settings, all optional:
|
||||||
|
|
||||||
|
| Name | Kind | Use |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `REGISTRY_TOKEN`, `REGISTRY_USER` | secret, variable | Token with package write permission, if the job token cannot push |
|
||||||
|
| `RELEASE_TOKEN` | secret | Token that can write releases, if the job token cannot |
|
||||||
|
| `MIRROR_IMAGE`, `MIRROR_USER`, `MIRROR_TOKEN` | variable, variable, secret | Also push to another registry, for example `ghcr.io/you/spinner` or `docker.io/you/spinner` |
|
||||||
|
| `PUBLISH_DOCKER` | variable | Set to `false` to skip the image |
|
||||||
|
|
||||||
|
The runner needs Docker with buildx. To build by hand: `sh deploy/build.sh` puts binaries and archives in `dist/`, then `docker buildx build .` packages the linux binary for your platform.
|
||||||
|
|
||||||
## Not in v1
|
## Not in v1
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user