git-ents.gitmain
⌘K
foforge
commit f2d4241
Dockerfile: build git-ents in-image instead of copying a prebuilt binary

docker/bin/git-ents was a musl binary cross-compiled by hand on the host (cargo zigbuild) and materialized into the build context before docker build — the exact step someone forgot right after today’s signed-push fix landed, silently deploying stale code that never advertised push-cert despite the config changes taking effect. The Dockerfile now has a builder stage (rust:1-slim-bookworm + musl-tools) that compiles crates/cli/git-ents for x86_64-unknown-linux-musl from the same source tree the rest of the image comes from; .dockerignore now admits Cargo.toml/Cargo.lock/crates/ instead of excluding everything but docker/. flyctl deploy alone is the whole pipeline again.

Also fixes the earlier nginx redirect fix landing here: the .git-less clone-URL redirect hardcodes https:// rather than $scheme, since Fly’s edge terminates TLS and always forwards plain HTTP to this app — $scheme as nginx sees it is always http and was downgrading every redirected client to plaintext.

Joseph D. Carpinelli · 29 days ago

Reviews

No reviews of this commit yet — record a verdict below.

Start a review

verdict

.dockerignore @@ -1,6 +1,10 @@ -# The Dockerfile only ever COPYs docker/*; ignore everything else so the -# build context stays a few KB instead of the whole workspace (including -# target/, which alone can run into the tens of GB). +# The Dockerfile's builder stage compiles the workspace, so the build +# context needs the actual sources — but never `target/`, which alone can +# run into the tens of GB and would balloon every build upload. * +!Cargo.toml +!Cargo.lock +!crates/ +!crates/** !docker/ !docker/**
.gitignore @@ -1,5 +1,2 @@ .DS_Store target/ -# Materialized from refs/meta/releases/<sha> just before `docker build`; -# never a normal tracked file. -docker/bin/
Dockerfile @@ -4,11 +4,24 @@ # nginx+fcgiwrap) invokes its `pre-receive`/`post-receive` hooks. No # Postgres/Tigris/gix-receive here — that is `git-ents-server`, phase 8. # -# No Rust toolchain, no cargo build, in this image: `docker/bin/git-ents` is -# a musl static binary cross-compiled on the host (`cargo zigbuild --target -# x86_64-unknown-linux-musl`) and materialized here from the on-disk blob -# recorded at `refs/meta/releases/<source-commit-sha>` — never a normal -# tracked file on `refs/heads` (see `.gitignore`). +# The binary builds *in* this image, from the same source tree the rest +# of the deploy comes from — never a separately cross-compiled artifact +# copied in by hand. That used to be `docker/bin/git-ents`, a musl binary +# built on the host and materialized here before `docker build`; the +# whole point of that indirection was to skip a slow in-container Rust +# build, but it silently deployed stale code whenever someone forgot the +# manual rebuild step, exactly the failure mode a deploy pipeline exists +# to prevent. +FROM rust:1-slim-bookworm AS builder +RUN apt-get update \ + && apt-get install -y --no-install-recommends musl-tools \ + && rm -rf /var/lib/apt/lists/* +RUN rustup target add x86_64-unknown-linux-musl +WORKDIR /src +COPY Cargo.toml Cargo.lock ./ +COPY crates crates +RUN cargo build --release --locked --target x86_64-unknown-linux-musl -p git-ents + FROM debian:bookworm-slim AS runtime WORKDIR /app # git: the bare repo + git-http-backend CGI itself. @@ -26,7 +39,7 @@ RUN curl -fsSL https://sprites.dev/install.sh \ | env SPRITE_INSTALL_PREFERRED_DIRS=/usr/local/bin \ SPRITE_INSTALL_DEFAULT_BIN_DIR=/usr/local/bin bash -COPY docker/bin/git-ents /usr/local/bin/git-ents +COPY --from=builder /src/target/x86_64-unknown-linux-musl/release/git-ents /usr/local/bin/git-ents RUN chmod +x /usr/local/bin/git-ents COPY docker/nginx.conf /etc/git-ents/nginx.conf COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
docker/nginx.conf @@ -41,11 +41,17 @@ # to the canonical `.git` path above. git's http client re-issues # every request of the clone/fetch/push against the redirected # base, not just this first one, so one redirect here is enough. + # + # Hardcoded `https://`, not `$scheme`: Fly's edge terminates TLS + # and always forwards plain HTTP to this app (`force_https=true` + # in fly.toml already guarantees no real client reaches here over + # HTTP), so `$scheme` as nginx sees it is always `http` and would + # downgrade every redirected client to plaintext. location = /git-ents/git-ents { - return 301 $scheme://$host/git-ents/git-ents.git; + return 301 https://$host/git-ents/git-ents.git; } location ~ ^/git-ents/git-ents/(.*)$ { - return 301 $scheme://$host/git-ents/git-ents.git/$1$is_args$args; + return 301 https://$host/git-ents/git-ents.git/$1$is_args$args; } # The server key's public half (`git ents setup --hosted` writes