build: add container labels and annotations (#4071)
This adds a new helper which retrieves the build metadata, uses it to generate container labels, and refactors XFlags uses to utilize the same machinery. Co-authored-by: James Elliott <james-d-elliott@users.noreply.github.com>pull/4079/head
parent
a7a217a036
commit
e3f5a574fe
|
@ -40,7 +40,7 @@ func cmdBuildRun(cobraCmd *cobra.Command, args []string) {
|
|||
|
||||
cmdCleanRun(cobraCmd, args)
|
||||
|
||||
xflags, err := getXFlags(branch, os.Getenv("BUILDKITE_BUILD_NUMBER"), "")
|
||||
buildMetaData, err := getBuild(branch, os.Getenv("BUILDKITE_BUILD_NUMBER"), "")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -62,11 +62,11 @@ func cmdBuildRun(cobraCmd *cobra.Command, args []string) {
|
|||
if buildkite {
|
||||
log.Info("Building Authelia Go binaries with gox...")
|
||||
|
||||
buildAutheliaBinaryGOX(xflags)
|
||||
buildAutheliaBinaryGOX(buildMetaData.XFlags())
|
||||
} else {
|
||||
log.Info("Building Authelia Go binary...")
|
||||
|
||||
buildAutheliaBinaryGO(xflags)
|
||||
buildAutheliaBinaryGO(buildMetaData.XFlags())
|
||||
}
|
||||
|
||||
cleanAssets()
|
||||
|
|
|
@ -13,15 +13,17 @@ import (
|
|||
|
||||
var container string
|
||||
|
||||
var containers = []string{"dev", "coverage"}
|
||||
var defaultContainer = "dev"
|
||||
var ciBranch = os.Getenv("BUILDKITE_BRANCH")
|
||||
var ciPullRequest = os.Getenv("BUILDKITE_PULL_REQUEST")
|
||||
var ciTag = os.Getenv("BUILDKITE_TAG")
|
||||
var dockerTags = regexp.MustCompile(`v(?P<Patch>(?P<Minor>(?P<Major>\d+)\.\d+)\.\d+.*)`)
|
||||
var ignoredSuffixes = regexp.MustCompile("alpha|beta")
|
||||
var publicRepo = regexp.MustCompile(`.*:.*`)
|
||||
var tags = dockerTags.FindStringSubmatch(ciTag)
|
||||
var (
|
||||
containers = []string{"dev", "coverage"}
|
||||
defaultContainer = "dev"
|
||||
ciBranch = os.Getenv("BUILDKITE_BRANCH")
|
||||
ciPullRequest = os.Getenv("BUILDKITE_PULL_REQUEST")
|
||||
ciTag = os.Getenv("BUILDKITE_TAG")
|
||||
dockerTags = regexp.MustCompile(`v(?P<Patch>(?P<Minor>(?P<Major>\d+)\.\d+)\.\d+.*)`)
|
||||
ignoredSuffixes = regexp.MustCompile("alpha|beta")
|
||||
publicRepo = regexp.MustCompile(`.*:.*`)
|
||||
tags = dockerTags.FindStringSubmatch(ciTag)
|
||||
)
|
||||
|
||||
func newDockerCmd() (cmd *cobra.Command) {
|
||||
cmd = &cobra.Command{
|
||||
|
@ -143,13 +145,12 @@ func dockerBuildOfficialImage(arch string) error {
|
|||
filename := "Dockerfile"
|
||||
dockerfile := fmt.Sprintf("%s.%s", filename, arch)
|
||||
|
||||
flags, err := getXFlags(ciBranch, os.Getenv("BUILDKITE_BUILD_NUMBER"), "")
|
||||
buildMetaData, err := getBuild(ciBranch, os.Getenv("BUILDKITE_BUILD_NUMBER"), "")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return docker.Build(IntermediateDockerImageName, dockerfile, ".",
|
||||
strings.Join(flags, " "))
|
||||
return docker.Build(IntermediateDockerImageName, dockerfile, ".", buildMetaData)
|
||||
}
|
||||
|
||||
func login(docker *Docker, registry string) {
|
||||
|
|
|
@ -2,66 +2,63 @@ package cmd
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/authelia/authelia/v4/internal/utils"
|
||||
)
|
||||
|
||||
func getXFlags(branch, build, extra string) (flags []string, err error) {
|
||||
if branch == "" {
|
||||
out, _, err := utils.RunCommandAndReturnOutput("git rev-parse --abbrev-ref HEAD")
|
||||
if err != nil {
|
||||
return flags, fmt.Errorf("error getting branch with git rev-parse: %w", err)
|
||||
func getBuild(branch, buildNumber, extra string) (b *Build, err error) {
|
||||
var out string
|
||||
|
||||
b = &Build{
|
||||
Branch: branch,
|
||||
Extra: extra,
|
||||
}
|
||||
|
||||
if buildNumber != "" {
|
||||
if b.Number, err = strconv.Atoi(buildNumber); err != nil {
|
||||
return nil, fmt.Errorf("error parsing provided build number: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if b.Branch == "" {
|
||||
if out, _, err = utils.RunCommandAndReturnOutput("git rev-parse --abbrev-ref HEAD"); err != nil {
|
||||
return nil, fmt.Errorf("error getting branch with git rev-parse: %w", err)
|
||||
}
|
||||
|
||||
if out == "" {
|
||||
branch = "master"
|
||||
b.Branch = "master"
|
||||
} else {
|
||||
branch = out
|
||||
b.Branch = out
|
||||
}
|
||||
}
|
||||
|
||||
gitTagCommit, _, err := utils.RunCommandAndReturnOutput("git rev-list --tags --max-count=1")
|
||||
if err != nil {
|
||||
return flags, fmt.Errorf("error getting tag commit with git rev-list: %w", err)
|
||||
var (
|
||||
gitTagCommit string
|
||||
)
|
||||
|
||||
if gitTagCommit, _, err = utils.RunCommandAndReturnOutput("git rev-list --tags --max-count=1"); err != nil {
|
||||
return nil, fmt.Errorf("error getting tag commit with git rev-list: %w", err)
|
||||
}
|
||||
|
||||
tag, _, err := utils.RunCommandAndReturnOutput(fmt.Sprintf("git describe --tags --abbrev=0 %s", gitTagCommit))
|
||||
if err != nil {
|
||||
return flags, fmt.Errorf("error getting tag with git describe: %w", err)
|
||||
if b.Tag, _, err = utils.RunCommandAndReturnOutput(fmt.Sprintf("git describe --tags --abbrev=0 %s", gitTagCommit)); err != nil {
|
||||
return nil, fmt.Errorf("error getting tag with git describe: %w", err)
|
||||
}
|
||||
|
||||
commit, _, err := utils.RunCommandAndReturnOutput("git rev-parse HEAD")
|
||||
if err != nil {
|
||||
return flags, fmt.Errorf("error getting commit with git rev-parse: %w", err)
|
||||
if b.Commit, _, err = utils.RunCommandAndReturnOutput("git rev-parse HEAD"); err != nil {
|
||||
return nil, fmt.Errorf("error getting commit with git rev-parse: %w", err)
|
||||
}
|
||||
|
||||
var states []string
|
||||
|
||||
if gitTagCommit == commit {
|
||||
states = append(states, "tagged")
|
||||
} else {
|
||||
states = append(states, "untagged")
|
||||
if gitTagCommit == b.Commit {
|
||||
b.Tagged = true
|
||||
}
|
||||
|
||||
if _, exitCode, _ := utils.RunCommandAndReturnOutput("git diff --quiet"); exitCode != 0 {
|
||||
states = append(states, "dirty")
|
||||
} else {
|
||||
states = append(states, "clean")
|
||||
if _, exitCode, _ := utils.RunCommandAndReturnOutput("git diff --quiet"); exitCode == 0 {
|
||||
b.Clean = true
|
||||
}
|
||||
|
||||
if build == "" {
|
||||
build = "manual"
|
||||
}
|
||||
b.Date = time.Now()
|
||||
|
||||
return []string{
|
||||
fmt.Sprintf(fmtLDFLAGSX, "BuildBranch", branch),
|
||||
fmt.Sprintf(fmtLDFLAGSX, "BuildTag", tag),
|
||||
fmt.Sprintf(fmtLDFLAGSX, "BuildCommit", commit),
|
||||
fmt.Sprintf(fmtLDFLAGSX, "BuildDate", time.Now().Format("Mon, 02 Jan 2006 15:04:05 -0700")),
|
||||
fmt.Sprintf(fmtLDFLAGSX, "BuildState", strings.Join(states, " ")),
|
||||
fmt.Sprintf(fmtLDFLAGSX, "BuildExtra", extra),
|
||||
fmt.Sprintf(fmtLDFLAGSX, "BuildNumber", build),
|
||||
}, nil
|
||||
return b, nil
|
||||
}
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/authelia/authelia/v4/internal/utils"
|
||||
)
|
||||
|
||||
|
@ -8,11 +15,20 @@ import (
|
|||
type Docker struct{}
|
||||
|
||||
// Build build a docker image.
|
||||
func (d *Docker) Build(tag, dockerfile, target, ldflags string) error {
|
||||
return utils.CommandWithStdout(
|
||||
"docker", "build", "-t", tag, "-f", dockerfile,
|
||||
"--progress=plain", "--build-arg", "LDFLAGS_EXTRA="+ldflags,
|
||||
target).Run()
|
||||
func (d *Docker) Build(tag, dockerfile, target string, buildMetaData *Build) error {
|
||||
args := []string{"build", "-t", tag, "-f", dockerfile, "--progress=plain"}
|
||||
|
||||
for label, value := range buildMetaData.ContainerLabels() {
|
||||
if value == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
args = append(args, "--label", fmt.Sprintf("%s=%s", label, value))
|
||||
}
|
||||
|
||||
args = append(args, "--build-arg", "LDFLAGS_EXTRA="+strings.Join(buildMetaData.XFlags(), " "), target)
|
||||
|
||||
return utils.CommandWithStdout("docker", args...).Run()
|
||||
}
|
||||
|
||||
// Tag tag a docker image.
|
||||
|
@ -27,10 +43,101 @@ func (d *Docker) Login(username, password, registry string) error {
|
|||
|
||||
// Manifest push a docker manifest to dockerhub.
|
||||
func (d *Docker) Manifest(tag1, tag2 string) error {
|
||||
return utils.CommandWithStdout("docker", "build", "-t", tag1, "-t", tag2, "--platform", "linux/amd64,linux/arm/v7,linux/arm64", "--builder", "buildx", "--push", ".").Run()
|
||||
args := []string{"build", "-t", tag1, "-t", tag2}
|
||||
annotations := ""
|
||||
|
||||
buildMetaData, err := getBuild(ciBranch, os.Getenv("BUILDKITE_BUILD_NUMBER"), "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for label, value := range buildMetaData.ContainerLabels() {
|
||||
if value == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
annotations += fmt.Sprintf("annotation.%s=%s,", label, value)
|
||||
args = append(args, "--label", fmt.Sprintf("%s=%s", label, value))
|
||||
}
|
||||
|
||||
var baseImageTag string
|
||||
|
||||
from, err := getDockerfileDirective("Dockerfile", "FROM")
|
||||
if err == nil {
|
||||
baseImageTag = from[strings.IndexRune(from, ':')+1:]
|
||||
args = append(args, "--label", "org.opencontainers.image.base.name=docker.io/library/alpine:"+baseImageTag)
|
||||
}
|
||||
|
||||
resp, err := http.Get("https://hub.docker.com/v2/repositories/library/alpine/tags/" + baseImageTag + "/images")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
images := DockerImages{}
|
||||
|
||||
if err = json.NewDecoder(resp.Body).Decode(&images); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
digestAMD64, digestARM, digestARM64 string
|
||||
)
|
||||
|
||||
for _, platform := range []string{"linux/amd64", "linux/arm/v7", "linux/arm64"} {
|
||||
for _, image := range images {
|
||||
if !image.Match(platform) {
|
||||
continue
|
||||
}
|
||||
|
||||
switch platform {
|
||||
case "linux/amd64":
|
||||
digestAMD64 = image.Digest
|
||||
case "linux/arm/v7":
|
||||
digestARM = image.Digest
|
||||
case "linux/arm64":
|
||||
digestARM64 = image.Digest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finalArgs := make([]string, len(args))
|
||||
|
||||
copy(finalArgs, args)
|
||||
|
||||
finalArgs = append(finalArgs, "--output", "type=image,\"name="+dockerhub+"/"+DockerImageName+","+ghcr+"/"+DockerImageName+"\","+annotations+"annotation.org.opencontainers.image.base.name=docker.io/library/alpine:"+baseImageTag+",annotation[linux/amd64].org.opencontainers.image.base.digest="+digestAMD64+",annotation[linux/arm/v7].org.opencontainers.image.base.digest="+digestARM+",annotation[linux/arm64].org.opencontainers.image.base.digest="+digestARM64, "--platform", "linux/amd64,linux/arm/v7,linux/arm64", "--builder", "buildx", "--push", ".")
|
||||
|
||||
if err = utils.CommandWithStdout("docker", finalArgs...).Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// PublishReadme push README.md to dockerhub.
|
||||
func (d *Docker) PublishReadme() error {
|
||||
return utils.CommandWithStdout("bash", "-c", `token=$(curl -fs --retry 3 -H "Content-Type: application/json" -X "POST" -d '{"username": "'$DOCKER_USERNAME'", "password": "'$DOCKER_PASSWORD'"}' https://hub.docker.com/v2/users/login/ | jq -r .token) && jq -n --arg msg "$(cat README.md | sed -r 's/(\<img\ src\=\")(\.\/)/\1https:\/\/github.com\/authelia\/authelia\/raw\/master\//' | sed 's/\.\//https:\/\/github.com\/authelia\/authelia\/blob\/master\//g' | sed '/start \[contributing\]/ a <a href="https://github.com/authelia/authelia/graphs/contributors"><img src="https://opencollective.com/authelia-sponsors/contributors.svg?width=890" /></a>' | sed '/Thanks goes to/,/### Backers/{/### Backers/!d}')" '{"registry":"registry-1.docker.io","full_description": $msg }' | curl -fs --retry 3 -o /dev/null -L -X "PATCH" -H "Content-Type: application/json" -H "Authorization: JWT $token" -d @- https://hub.docker.com/v2/repositories/authelia/authelia/`).Run()
|
||||
}
|
||||
|
||||
func getDockerfileDirective(filePath, directive string) (from string, err error) {
|
||||
var f *os.File
|
||||
|
||||
if f, err = os.Open(filePath); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
s := bufio.NewScanner(f)
|
||||
|
||||
for s.Scan() {
|
||||
data := s.Text()
|
||||
|
||||
if strings.HasPrefix(data, directive+" ") {
|
||||
return data[5:], nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
|
|
@ -1,7 +1,130 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/authelia/authelia/v4/internal/utils"
|
||||
)
|
||||
|
||||
// HostEntry represents an entry in /etc/hosts.
|
||||
type HostEntry struct {
|
||||
Domain string
|
||||
IP string
|
||||
}
|
||||
|
||||
// DockerImages represents some of the data from the docker images API.
|
||||
type DockerImages []DockerImage
|
||||
|
||||
// DockerImage represents some of the data from the docker images API.
|
||||
type DockerImage struct {
|
||||
Architecture string `json:"architecture"`
|
||||
Variant interface{} `json:"variant"`
|
||||
Digest string `json:"digest"`
|
||||
OS string `json:"os"`
|
||||
}
|
||||
|
||||
// Match returns true if this image matches the platform.
|
||||
func (d DockerImage) Match(platform string) bool {
|
||||
parts := []string{d.OS, d.Architecture}
|
||||
|
||||
if strings.Join(parts, "/") == platform {
|
||||
return true
|
||||
}
|
||||
|
||||
if d.Variant == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
parts = append(parts, d.Variant.(string))
|
||||
|
||||
return strings.Join(parts, "/") == platform
|
||||
}
|
||||
|
||||
// Build represents a builds metadata.
|
||||
type Build struct {
|
||||
Branch string
|
||||
Tag string
|
||||
Commit string
|
||||
Tagged bool
|
||||
Clean bool
|
||||
Extra string
|
||||
Number int
|
||||
Date time.Time
|
||||
}
|
||||
|
||||
// States returns the state tags for this Build.
|
||||
func (b Build) States() []string {
|
||||
var states []string
|
||||
|
||||
if b.Tagged {
|
||||
states = append(states, "tagged")
|
||||
} else {
|
||||
states = append(states, "untagged")
|
||||
}
|
||||
|
||||
if b.Clean {
|
||||
states = append(states, "clean")
|
||||
} else {
|
||||
states = append(states, "dirty")
|
||||
}
|
||||
|
||||
return states
|
||||
}
|
||||
|
||||
// State returns the state tags string for this Build.
|
||||
func (b Build) State() string {
|
||||
return strings.Join(b.States(), " ")
|
||||
}
|
||||
|
||||
// XFlags returns the XFlags for this Build.
|
||||
func (b Build) XFlags() []string {
|
||||
return []string{
|
||||
fmt.Sprintf(fmtLDFLAGSX, "BuildBranch", b.Branch),
|
||||
fmt.Sprintf(fmtLDFLAGSX, "BuildTag", b.Tag),
|
||||
fmt.Sprintf(fmtLDFLAGSX, "BuildCommit", b.Commit),
|
||||
fmt.Sprintf(fmtLDFLAGSX, "BuildDate", b.Date.Format("Mon, 02 Jan 2006 15:04:05 -0700")),
|
||||
fmt.Sprintf(fmtLDFLAGSX, "BuildState", b.State()),
|
||||
fmt.Sprintf(fmtLDFLAGSX, "BuildExtra", b.Extra),
|
||||
fmt.Sprintf(fmtLDFLAGSX, "BuildNumber", strconv.Itoa(b.Number)),
|
||||
}
|
||||
}
|
||||
|
||||
// ContainerLabels returns the container labels for this Build.
|
||||
func (b Build) ContainerLabels() (labels map[string]string) {
|
||||
var version string
|
||||
|
||||
switch {
|
||||
case b.Clean && b.Tagged:
|
||||
version = utils.VersionAdv(b.Tag, b.State(), b.Commit, b.Branch, b.Extra)
|
||||
case b.Clean:
|
||||
version = fmt.Sprintf("%s-pre+%s.%s", b.Tag, b.Branch, b.Commit)
|
||||
case b.Tagged:
|
||||
version = fmt.Sprintf("%s-dirty", b.Tag)
|
||||
default:
|
||||
version = fmt.Sprintf("%s-dirty+%s.%s", b.Tag, b.Branch, b.Commit)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(version, "v") && len(version) > 1 {
|
||||
version = version[1:]
|
||||
}
|
||||
|
||||
labels = map[string]string{
|
||||
"org.opencontainers.image.created": b.Date.Format(time.RFC3339),
|
||||
"org.opencontainers.image.authors": "",
|
||||
"org.opencontainers.image.url": "https://github.com/authelia/authelia/pkgs/container/authelia",
|
||||
"org.opencontainers.image.documentation": "https://www.authelia.com",
|
||||
"org.opencontainers.image.source": fmt.Sprintf("https://github.com/authelia/authelia/tree/%s", b.Commit),
|
||||
"org.opencontainers.image.version": version,
|
||||
"org.opencontainers.image.revision": b.Commit,
|
||||
"org.opencontainers.image.vendor": "Authelia",
|
||||
"org.opencontainers.image.licenses": "Apache-2.0",
|
||||
"org.opencontainers.image.ref.name": "",
|
||||
"org.opencontainers.image.title": "authelia",
|
||||
"org.opencontainers.image.description": "Authelia is an open-source authentication and authorization server providing two-factor authentication and single sign-on (SSO) for your applications via a web portal.",
|
||||
}
|
||||
|
||||
return labels
|
||||
}
|
||||
|
|
|
@ -37,10 +37,10 @@ func cmdXFlagsRun(cobraCmd *cobra.Command, _ []string) {
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
flags, err := getXFlags("", build, extra)
|
||||
buildMetaData, err := getBuild("", build, extra)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(strings.Join(flags, " "))
|
||||
fmt.Println(strings.Join(buildMetaData.XFlags(), " "))
|
||||
}
|
||||
|
|
|
@ -35,10 +35,11 @@ var BuildNumber = "0"
|
|||
// BuildTag i.e. v1.0.0. If dirty and tagged are present it returns <BuildTag>-dirty. Otherwise, the following is the
|
||||
// format: untagged-<BuildTag>-dirty-<BuildExtra> (<BuildBranch>, <BuildCommit>).
|
||||
func Version() (versionString string) {
|
||||
return version(BuildTag, BuildState, BuildCommit, BuildBranch, BuildExtra)
|
||||
return VersionAdv(BuildTag, BuildState, BuildCommit, BuildBranch, BuildExtra)
|
||||
}
|
||||
|
||||
func version(tag, state, commit, branch, extra string) (version string) {
|
||||
// VersionAdv takes inputs to generate the version.
|
||||
func VersionAdv(tag, state, commit, branch, extra string) (version string) {
|
||||
b := strings.Builder{}
|
||||
|
||||
states := strings.Split(state, " ")
|
||||
|
|
|
@ -15,27 +15,27 @@ func TestVersionDefault(t *testing.T) {
|
|||
func TestVersion(t *testing.T) {
|
||||
var v string
|
||||
|
||||
v = version("v4.90.0", "tagged clean", "50d8b4a941c26b89482c94ab324b5a274f9ced66", "master", "")
|
||||
v = VersionAdv("v4.90.0", "tagged clean", "50d8b4a941c26b89482c94ab324b5a274f9ced66", "master", "")
|
||||
assert.Equal(t, "v4.90.0", v)
|
||||
|
||||
v = version("v4.90.0", "tagged clean", "50d8b4a941c26b89482c94ab324b5a274f9ced66", "master", "freshports")
|
||||
v = VersionAdv("v4.90.0", "tagged clean", "50d8b4a941c26b89482c94ab324b5a274f9ced66", "master", "freshports")
|
||||
assert.Equal(t, "v4.90.0-freshports", v)
|
||||
|
||||
v = version("v4.90.0", "tagged dirty", "50d8b4a941c26b89482c94ab324b5a274f9ced66", "master", "")
|
||||
v = VersionAdv("v4.90.0", "tagged dirty", "50d8b4a941c26b89482c94ab324b5a274f9ced66", "master", "")
|
||||
assert.Equal(t, "v4.90.0-dirty", v)
|
||||
|
||||
v = version("v4.90.0", "untagged dirty", "50d8b4a941c26b89482c94ab324b5a274f9ced66", "master", "")
|
||||
v = VersionAdv("v4.90.0", "untagged dirty", "50d8b4a941c26b89482c94ab324b5a274f9ced66", "master", "")
|
||||
assert.Equal(t, "untagged-v4.90.0-dirty (master, 50d8b4a)", v)
|
||||
|
||||
v = version("v4.90.0", "untagged clean", "50d8b4a941c26b89482c94ab324b5a274f9ced66", "master", "")
|
||||
v = VersionAdv("v4.90.0", "untagged clean", "50d8b4a941c26b89482c94ab324b5a274f9ced66", "master", "")
|
||||
assert.Equal(t, "untagged-v4.90.0 (master, 50d8b4a)", v)
|
||||
|
||||
v = version("v4.90.0", "untagged clean", "50d8b4a941c26b89482c94ab324b5a274f9ced66", "master", "freshports")
|
||||
v = VersionAdv("v4.90.0", "untagged clean", "50d8b4a941c26b89482c94ab324b5a274f9ced66", "master", "freshports")
|
||||
assert.Equal(t, "untagged-v4.90.0-freshports (master, 50d8b4a)", v)
|
||||
|
||||
v = version("v4.90.0", "untagged clean", "", "master", "")
|
||||
v = VersionAdv("v4.90.0", "untagged clean", "", "master", "")
|
||||
assert.Equal(t, "untagged-v4.90.0 (master, unknown)", v)
|
||||
|
||||
v = version("v4.90.0", "", "50d8b4a941c26b89482c94ab324b5a274f9ced66", "master", "")
|
||||
v = VersionAdv("v4.90.0", "", "50d8b4a941c26b89482c94ab324b5a274f9ced66", "master", "")
|
||||
assert.Equal(t, "untagged-v4.90.0-dirty (master, 50d8b4a)", v)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue