diff --git a/.dockerignore b/.dockerignore index 2e1b785e0..b7f28c69f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,7 +4,6 @@ changelog/ doc/ docker/ -helpers/ # Files .gitignore diff --git a/docker/Dockerfile.release b/docker/Dockerfile.release index a2564b6d5..01f9df150 100644 --- a/docker/Dockerfile.release +++ b/docker/Dockerfile.release @@ -1,20 +1,18 @@ -FROM --platform=$BUILDPLATFORM alpine:latest as helper +# the official binaries are cross-built from Linux running on an AMD64 host +# other architectures also seem to generate identical binaries but stay on the safe side +FROM --platform=linux/amd64 restic/builder:latest as helper -ARG VERSION ARG TARGETOS ARG TARGETARCH -# add release binary for the appropriate platform -COPY restic_${VERSION}_${TARGETOS}_${TARGETARCH}.bz2 / -RUN apk add --update --no-cache bzip2 -RUN set -e && \ - bzcat restic_${VERSION}_${TARGETOS}_${TARGETARCH}.bz2 > restic && \ - chmod +x restic +COPY . /restic +RUN go run helpers/build-release-binaries/main.go --platform $TARGETOS/$TARGETARCH --skip-compress +RUN mv /output/restic_${TARGETOS}_${TARGETARCH} /output/restic FROM alpine:latest -COPY --from=helper /restic /usr/bin +COPY --from=helper /output/restic /usr/bin RUN apk add --update --no-cache ca-certificates fuse openssh-client tzdata jq ENTRYPOINT ["/usr/bin/restic"] diff --git a/helpers/build-release-binaries/main.go b/helpers/build-release-binaries/main.go index 6938aff84..caa90ff82 100644 --- a/helpers/build-release-binaries/main.go +++ b/helpers/build-release-binaries/main.go @@ -22,6 +22,8 @@ var opts = struct { OutputDir string Tags string PlatformSubset string + Platform string + SkipCompress bool Version string }{} @@ -31,6 +33,8 @@ func init() { pflag.StringVarP(&opts.OutputDir, "output", "o", "/output", "path to the output `directory`") pflag.StringVar(&opts.Tags, "tags", "", "additional build `tags`") pflag.StringVar(&opts.PlatformSubset, "platform-subset", "", "specify `n/t` to only build this subset") + pflag.StringVarP(&opts.Platform, "platform", "p", "", "specify `os/arch` to only build this specific platform") + pflag.BoolVar(&opts.SkipCompress, "skip-compress", false, "skip binary compression step") pflag.StringVar(&opts.Version, "version", "", "use `x.y.z` as the version for output files") pflag.Parse() } @@ -188,7 +192,9 @@ func buildForTarget(sourceDir, outputDir, goos, goarch string) (filename string) filename = build(sourceDir, outputDir, goos, goarch) touch(filepath.Join(outputDir, filename), mtime) chmod(filepath.Join(outputDir, filename), 0755) - filename = compress(goos, outputDir, filename) + if !opts.SkipCompress { + filename = compress(goos, outputDir, filename) + } return filename } @@ -311,6 +317,8 @@ func main() { if err != nil { die("%s", err) } + } else if opts.Platform != "" { + targets = buildPlatformList([]string{opts.Platform}) } sourceDir := abs(opts.SourceDir) diff --git a/helpers/prepare-release/main.go b/helpers/prepare-release/main.go index 2340a65d4..a6c7bd4f4 100644 --- a/helpers/prepare-release/main.go +++ b/helpers/prepare-release/main.go @@ -4,6 +4,7 @@ import ( "bufio" "bytes" "fmt" + "math/rand" "os" "os/exec" "path/filepath" @@ -409,19 +410,19 @@ func signFiles(filenames ...string) { } } -func updateDocker(outputDir, version string) string { - run("docker", "buildx", "create", "--name", "restic-release-builder", "--driver", "docker-container", "--bootstrap") +func updateDocker(sourceDir, version string) string { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + builderName := fmt.Sprintf("restic-release-builder-%d", r.Int()) + run("docker", "buildx", "create", "--name", builderName, "--driver", "docker-container", "--bootstrap") - cmds := "" + buildCmd := fmt.Sprintf("docker buildx build --builder %s --platform linux/386,linux/amd64,linux/arm,linux/arm64 --pull -f docker/Dockerfile.release %q", builderName, sourceDir) + run("sh", "-c", buildCmd+" --no-cache") + publishCmds := "" for _, tag := range []string{"restic/restic:latest", "restic/restic:" + version} { - cmd := fmt.Sprintf("docker buildx build --builder restic-release-builder --platform linux/386,linux/amd64,linux/arm,linux/arm64 --pull --tag %q -f docker/Dockerfile.release --build-arg VERSION=%q %q", tag, version, outputDir) - run("sh", "-c", cmd) - - cmds += cmd + " --push\n" + publishCmds += buildCmd + fmt.Sprintf(" --tag %q --push\n", tag) } - - return cmds + "\ndocker buildx rm restic-release-builder" + return publishCmds + "\ndocker buildx rm " + builderName } func tempdir(prefix string) string { @@ -470,15 +471,14 @@ func main() { extractTar(tarFilename, sourceDir) runBuild(sourceDir, opts.OutputDir, opts.Version) - rmdir(sourceDir) sha256sums(opts.OutputDir, filepath.Join(opts.OutputDir, "SHA256SUMS")) signFiles(filepath.Join(opts.OutputDir, "SHA256SUMS"), tarFilename) - dockerCmds := updateDocker(opts.OutputDir, opts.Version) + dockerCmds := updateDocker(sourceDir, opts.Version) msg("done, output dir is %v", opts.OutputDir) - msg("now run:\n\ngit push --tags origin master\n%s\n", dockerCmds) + msg("now run:\n\ngit push --tags origin master\n%s\n\nrm -rf %q", dockerCmds, sourceDir) }