build: release a static image with scripts/release.sh
The image now packages a cross-compiled musl binary on distroless instead of compiling inside Docker. The script builds it, pushes :<version> and :latest to git.cosocial.info, and tags the commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9384e2bcea
commit
1a08d2efda
5 files changed
+64
-20
No files matched your search
+4
-5
@@ -1,5 +1,4 @@
|
|||||||
target
|
# only the release binary and the city list go into the image
|
||||||
.git
|
*
|
||||||
.env
|
!target/x86_64-unknown-linux-musl/release/cities-labeler
|
||||||
*.sqlite
|
!data
|
||||||
*.sqlite-*
|
|
||||||
+6
-15
@@ -1,21 +1,12 @@
|
|||||||
# Debian release pinned on both stages so the binary's glibc matches at runtime.
|
# Release image: packages the static binary built by scripts/release.sh.
|
||||||
# The image tag pins the compiler, so rust-toolchain.toml (and its editor
|
# No compiler runs here, so the image builds in seconds on any machine.
|
||||||
# components) is intentionally not copied in.
|
FROM gcr.io/distroless/static-debian12:nonroot
|
||||||
FROM rust:1.91-slim-bookworm AS build
|
COPY target/x86_64-unknown-linux-musl/release/cities-labeler /usr/local/bin/cities-labeler
|
||||||
WORKDIR /src
|
|
||||||
COPY Cargo.toml Cargo.lock ./
|
|
||||||
COPY src ./src
|
|
||||||
RUN cargo build --release --bin cities-labeler
|
|
||||||
|
|
||||||
FROM debian:bookworm-slim
|
|
||||||
RUN apt-get update \
|
|
||||||
&& apt-get install -y --no-install-recommends ca-certificates \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
COPY --from=build /src/target/release/cities-labeler /usr/local/bin/cities-labeler
|
|
||||||
COPY data /app/data
|
COPY data /app/data
|
||||||
ENV CITIES_PATH=/app/data/cities.json \
|
ENV CITIES_PATH=/app/data/cities.json \
|
||||||
DB_PATH=/data/labeler.sqlite \
|
DB_PATH=/data/labeler.sqlite \
|
||||||
PORT=4100
|
PORT=4100
|
||||||
|
# matches the owner of the ansible-managed data directory
|
||||||
USER 1000:1000
|
USER 1000:1000
|
||||||
EXPOSE 4100
|
EXPOSE 4100
|
||||||
CMD ["cities-labeler"]
|
ENTRYPOINT ["/usr/local/bin/cities-labeler"]
|
||||||
@@ -36,3 +36,24 @@ cargo run --bin setup -- declare # label definitions; gives the account a Subs
|
|||||||
cargo run --bin setup -- did # run after deploying; requires labeler account's main password + emailed code
|
cargo run --bin setup -- did # run after deploying; requires labeler account's main password + emailed code
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Release
|
||||||
|
|
||||||
|
Releases are made manually with the Rust toolchain. `scripts/release.sh` cross-compiles a static
|
||||||
|
linux/amd64 binary, packages it into a container image, pushes
|
||||||
|
`git.cosocial.info/cosocial-canada/atproto-cosocial-labeler:<version>` and `:latest`, and tags the
|
||||||
|
commit as `v<version>`. It refuses to run with uncommitted changes or an existing tag.
|
||||||
|
|
||||||
|
Prerequisites (once):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
brew install zig # linker and C compiler for cross-compiling
|
||||||
|
cargo install --locked cargo-zigbuild
|
||||||
|
docker login git.cosocial.info # token with the write:package scope
|
||||||
|
```
|
||||||
|
|
||||||
|
The pinned toolchain and its `x86_64-unknown-linux-musl` target come from `rust-toolchain.toml`.
|
||||||
|
Docker must be running. Then:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scripts/release.sh 0.1.0
|
||||||
|
```
|
||||||
@@ -2,3 +2,5 @@
|
|||||||
channel = "1.91.0"
|
channel = "1.91.0"
|
||||||
profile = "minimal"
|
profile = "minimal"
|
||||||
components = ["rustfmt", "clippy", "rust-analyzer", "rust-src"]
|
components = ["rustfmt", "clippy", "rust-analyzer", "rust-src"]
|
||||||
|
# release builds cross-compile a static binary (see scripts/release.sh)
|
||||||
|
targets = ["x86_64-unknown-linux-musl"]
|
||||||
Executable
+31
@@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Cuts a release: cross-compiles a static linux/amd64 binary, pushes it as a
|
||||||
|
# container image (:<version> and :latest), and tags the commit.
|
||||||
|
#
|
||||||
|
# scripts/release.sh 0.1.0
|
||||||
|
#
|
||||||
|
# Needs: zig + cargo-zigbuild, Docker running, and
|
||||||
|
# `docker login git.cosocial.info` with a write:package token.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
version="${1:?usage: scripts/release.sh <version>}"
|
||||||
|
image="git.cosocial.info/cosocial-canada/atproto-cosocial-labeler"
|
||||||
|
target="x86_64-unknown-linux-musl"
|
||||||
|
|
||||||
|
if [[ -n "$(git status --porcelain)" ]]; then
|
||||||
|
echo "working tree is dirty; commit first" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if git rev-parse -q --verify "refs/tags/v$version" >/dev/null; then
|
||||||
|
echo "tag v$version already exists" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cargo zigbuild --release --target "$target" --bin cities-labeler
|
||||||
|
docker build --platform linux/amd64 -t "$image:$version" -t "$image:latest" .
|
||||||
|
docker push "$image:$version"
|
||||||
|
docker push "$image:latest"
|
||||||
|
|
||||||
|
git tag -a "v$version" -m "v$version"
|
||||||
|
git push origin "v$version"
|
||||||
|
echo "released $image:$version"
|
||||||
Reference in new issue
Block a user