Skip to content
This repository has been archived by the owner on Jun 10, 2024. It is now read-only.

Commit

Permalink
Merge pull request #7 from AkihiroSuda/dev
Browse files Browse the repository at this point in the history
version: automatically detect downloadable version
  • Loading branch information
AkihiroSuda authored Oct 11, 2022
2 parents 016316d + bf88f29 commit 8bc078f
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 20 deletions.
4 changes: 1 addition & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@ PREFIX ?= /usr/local
DEST := $(shell echo "$(DESTDIR)/$(PREFIX)" | sed 's:///*:/:g; s://*$$::')

VERSION ?=$(shell git describe --match 'v[0-9]*' --dirty='.m' --always --tags)
# DOWNLOADABLE_VERSION <= VERSION
DOWNLOADABLE_VERSION ?= $(shell git describe --abbrev=0)
PACKAGE := github.com/reproducible-containers/repro-get

export CGO_ENABLED ?= 0
export DOCKER_BUILDKIT := 1
export SOURCE_DATE_EPOCH ?= $(shell git log -1 --pretty=%ct)

GO ?= go
GO_BUILD ?= $(GO) build -trimpath -ldflags="-s -w -X $(PACKAGE)/pkg/version.Version=$(VERSION) -X $(PACKAGE)/pkg/version.DownloadableVersion=$(DOWNLOADABLE_VERSION)"
GO_BUILD ?= $(GO) build -trimpath -ldflags="-s -w -X $(PACKAGE)/pkg/version.Version=$(VERSION)"
DOCKER ?= docker
DOCKER_BUILD ?= $(DOCKER) build
UPX ?= upx --best --lzma
Expand Down
25 changes: 14 additions & 11 deletions cmd/repro-get/dockerfile_generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"bytes"
"errors"
"fmt"
"os"
"regexp"
Expand Down Expand Up @@ -64,6 +63,8 @@ To build "Dockerfile.generate-hash" and "Dockerfile":

DisableFlagsInUseLine: true,
}
flags := cmd.Flags()
flags.String("repro-get-version", version.Auto, "The version of repro-get binary to be downloaded, \"vX.Y.Z\", \"auto\", or \"latest\"")
return cmd
}

Expand All @@ -86,6 +87,16 @@ func dockerfileGenerateAction(cmd *cobra.Command, args []string) error {
}

ctx := cmd.Context()

reproGetVersion, err := flags.GetString("repro-get-version")
if err != nil {
return err
}
downloadable, err := version.DetectDownloadable(ctx, reproGetVersion)
if err != nil {
return err
}

dir := args[0]
baseImageOrig := args[1]
pkgs := args[2:]
Expand All @@ -99,22 +110,14 @@ func dockerfileGenerateAction(cmd *cobra.Command, args []string) error {
return err
}

if version.DownloadableVersion == "" {
return errors.New("variable pkg/version.DownloadableVersion is unset (Hint: rebuild the binary with the upstream Makefile)")
}
shasha, err := version.SHASHA(ctx, version.DownloadableVersion)
if err != nil {
return fmt.Errorf("failed to get the URL of the SHA256SUMS file for version %q: %w", version.DownloadableVersion, err)
}

templateArgs := distro.DockerfileTemplateArgs{
BaseImage: resolvedWithDigest,
BaseImageOrig: baseImageOrig,
Packages: pkgs,
OCIArchDashVariant: archutil.OCIArchDashVariant(),
Providers: providers,
ReproGetVersion: version.DownloadableVersion,
ReproGetSHASHA: shasha,
ReproGetVersion: downloadable.Version,
ReproGetSHASHA: downloadable.SHASHA,
}
opts := distro.DockerfileOpts{
GenerateHash: len(pkgs) > 0,
Expand Down
81 changes: 75 additions & 6 deletions pkg/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,102 @@ package version
import (
"bytes"
"context"
"fmt"
"io"
"net/url"
"runtime/debug"
"strconv"
"strings"
"text/template"

"github.com/opencontainers/go-digest"
"github.com/reproducible-containers/repro-get/pkg/urlopener"
"github.com/sirupsen/logrus"
)

// Variables can be fulfilled on compilation time: -ldflags="-X github.com/reproducible-containers/repro-get/pkg/version.Version=v0.1.2"
var (
Version string
DownloadableVersion string // <= Version
Version string

SHA256SUMSDownloadURLTemplate = "https://github.com/reproducible-containers/repro-get/releases/download/{{.DownloadableVersion}}/SHA256SUMS"
SHA256SUMSDownloadURLTemplate = "https://github.com/reproducible-containers/repro-get/releases/download/{{.Version}}/SHA256SUMS"
LatestVersionURL = "https://github.com/reproducible-containers/repro-get/releases/latest/download/VERSION"
)

// SHASHA returns the sha256sum of the SHA256SUMS file.
func SHASHA(ctx context.Context, downloadableVersion string) (string, error) {
const (
Latest = "latest"
Auto = "auto" // current version or latest
)

type Downloadable struct {
Version string
SHASHA string // the sha256sum of the SHA256SUMS file
}

func DetectDownloadable(ctx context.Context, version string) (*Downloadable, error) {
var err error
switch version {
case Auto:
currentVersion := GetVersion()
rec, err := DetectDownloadable(ctx, currentVersion)
if err != nil {
logrus.WithError(err).Warnf("The current version %q does not seem downloadable, falling back to the latest version", currentVersion)
rec, err = DetectDownloadable(ctx, Latest)
if err != nil {
return nil, fmt.Errorf("failed to detect the latest version: %w", err)
}
}
logrus.Debugf("Automatically detected downloadable version: %+v", rec)
return rec, nil
case Latest:
version, err = DetectLatest(ctx)
if err != nil {
return nil, fmt.Errorf("failed to detect the latest version: %w", err)
}
logrus.Infof("Detected latest version %q", version)
default:
// NOP
}

if !strings.HasPrefix(version, "v") || strings.Contains(version, "-g") || strings.HasSuffix(version, ".m") {
return nil, fmt.Errorf("non-downloadable version: %q", version)
}
d := &Downloadable{
Version: version,
}
d.SHASHA, err = shasha(ctx, version)
if err != nil {
return nil, fmt.Errorf("failed to detect the sha256sum of the SHA256SUMS file for version %q: %w", version, err)
}
return d, nil
}

func DetectLatest(ctx context.Context) (string, error) {
u, err := url.Parse(LatestVersionURL)
if err != nil {
return "", err
}
uo := urlopener.New()
r, _, err := uo.Open(ctx, u, "")
if err != nil {
return "", err
}
defer r.Close()
b, err := io.ReadAll(r)
if err != nil {
return "", err
}
return strings.TrimSpace(string(b)), nil
}

// shasha returns the sha256sum of the SHA256SUMS file.
func shasha(ctx context.Context, version string) (string, error) {
tmpl, err := template.New("").Parse(SHA256SUMSDownloadURLTemplate)
if err != nil {
return "", err
}
var b bytes.Buffer
args := map[string]string{
"DownloadableVersion": downloadableVersion,
"Version": version,
}
if err = tmpl.Execute(&b, args); err != nil {
return "", err
Expand Down
27 changes: 27 additions & 0 deletions pkg/version/version_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package version

import (
"context"
"testing"

"gotest.tools/v3/assert"
)

func TestDetectDownloadable(t *testing.T) {
if testing.Short() {
t.Skip("slow test")
}
testCases := []string{
"v0.1.2",
Latest,
Auto,
}
for _, tc := range testCases {
tc := tc
t.Run(tc, func(t *testing.T) {
d, err := DetectDownloadable(context.TODO(), tc)
assert.NilError(t, err)
t.Logf("%+v", d)
})
}
}

0 comments on commit 8bc078f

Please sign in to comment.