From 976b4b621377c5236874e4a13938cb3953fcb8ed Mon Sep 17 00:00:00 2001 From: Carolyn Van Slyck Date: Tue, 15 Jun 2021 11:36:04 -0500 Subject: [PATCH] Skip publish for v1 canary and latest (#1641) * Change permalinks to prefix with canary/latest I was running into conflict with how we detect versions with the other tagging scheme (v1-latest would get flagged as a real release). Switching the order so that it's latest-v1 will help avoid a bunch of false positives and workarounds. * Only publish v*, latest and canary Do not publish latest-* or canary-* for simplicity Signed-off-by: Carolyn Van Slyck --- build/azure-pipelines.release.yml | 9 +- .../content/project/version-strategy/index.md | 2 +- mage/git.go | 15 ++-- mage/releases/publish.go | 33 ++++--- magefile.go | 86 ++++++++++++++++--- pkg/pkgmgmt/feed/generate.go | 5 +- pkg/pkgmgmt/feed/generate_test.go | 16 +--- pkg/pkgmgmt/feed/testdata/atom-existing.xml | 11 --- pkg/pkgmgmt/feed/testdata/atom.xml | 10 --- scripts/build-images.sh | 14 --- scripts/publish-images.sh | 20 ----- 11 files changed, 120 insertions(+), 101 deletions(-) delete mode 100755 scripts/build-images.sh delete mode 100755 scripts/publish-images.sh diff --git a/build/azure-pipelines.release.yml b/build/azure-pipelines.release.yml index bc275f42b..7118d2151 100644 --- a/build/azure-pipelines.release.yml +++ b/build/azure-pipelines.release.yml @@ -1,7 +1,12 @@ trigger: - branches: + tags: include: - - refs/tags/v* + - "v*" + exclude: + # We tag a release for canary-v1 or latest-v1 because of how we host our binaries with GitHub releases. + # Do not trigger another release when we create these tags during the release process, preventing an infinite recursion of release builds. + - "latest*" + - "canary*" # Do not run on pull requests pr: none diff --git a/docs/content/project/version-strategy/index.md b/docs/content/project/version-strategy/index.md index 2711823e8..0d6b160d7 100644 --- a/docs/content/project/version-strategy/index.md +++ b/docs/content/project/version-strategy/index.md @@ -38,6 +38,6 @@ Porter v1 will include a number of breaking changes that we are grouping togethe The final release from the v1 branch will be v1.0.0. * The release/v1 branch will be merged into main, and then the v1.0.0 release is cut. * The latest and canary builds continue to be based on builds of the main branch only. - We may provide v1-latest and v1-canary builds at a later date. + We may provide latest-v1 and canary-v1 builds at a later date. [semver v2]: https://semver.org/spec/v2.0.0.html diff --git a/mage/git.go b/mage/git.go index b8115ac58..e92644c2c 100644 --- a/mage/git.go +++ b/mage/git.go @@ -31,6 +31,11 @@ type GitMetadata struct { IsTaggedRelease bool } +func (m GitMetadata) ShouldPublishPermalink() bool { + // For now don't publish canary-v1 or latest-v1 to keep things simpler + return m.Permalink == "canary" || m.Permalink == "latest" +} + // LoadMetadata populates the status of the current working copy: current version, tag and permalink func LoadMetadata() GitMetadata { loadMetadata.Do(func() { @@ -96,21 +101,21 @@ func getBranchName() string { func getPermalink() (string, bool) { // Use latest for tagged commits taggedRelease := false - permalinkSuffix := "canary" + permalinkPrefix := "canary" err := shx.RunS("git", "describe", "--tags", "--match=v*", "--exact") if err == nil { - permalinkSuffix = "latest" + permalinkPrefix = "latest" taggedRelease = true } // Get the current branch name, or the name of the branch we tagged from branch := getBranchName() - // Build a permalink such as "canary", "latest", "v1-latest", etc + // Build a permalink such as "canary", "latest", "latest-v1", or "canary-v1" switch branch { case "main": - return permalinkSuffix, taggedRelease + return permalinkPrefix, taggedRelease default: - return fmt.Sprintf("%s-%s", strings.TrimPrefix(branch, "release/"), permalinkSuffix), taggedRelease + return fmt.Sprintf("%s-%s", permalinkPrefix, strings.TrimPrefix(branch, "release/")), taggedRelease } } diff --git a/mage/releases/publish.go b/mage/releases/publish.go index 170843ec3..2afedd4b3 100644 --- a/mage/releases/publish.go +++ b/mage/releases/publish.go @@ -6,6 +6,7 @@ import ( "log" "os" "path/filepath" + "strings" "get.porter.sh/porter/mage" "get.porter.sh/porter/mage/tools" @@ -95,15 +96,19 @@ func publishPackage(pkgType string, name string) { remote := fmt.Sprintf("https://%s.git", repo) versionDir := filepath.Join("bin", pkgType+"s", name, info.Version) - // Move the permalink tag. The existing release automatically points to the tag. - must.RunV("git", "tag", info.Permalink, info.Version+"^{}", "-f") - must.RunV("git", "push", "-f", remote, info.Permalink) - // Create or update GitHub release for the permalink (canary/latest) with the version's binaries - AddFilesToRelease(repo, info.Permalink, versionDir) + if info.ShouldPublishPermalink() { + // Move the permalink tag. The existing release automatically points to the tag. + must.RunV("git", "tag", info.Permalink, info.Version+"^{}", "-f") + must.RunV("git", "push", "-f", remote, info.Permalink) + + AddFilesToRelease(repo, info.Permalink, versionDir) + } else { + fmt.Println("Skipping publish package for permalink", info.Permalink) + } + // Create GitHub release for the exact version (v1.2.3) and attach assets if info.IsTaggedRelease { - // Create GitHub release for the exact version (v1.2.3) and attach assets AddFilesToRelease(repo, info.Version, versionDir) } } @@ -116,12 +121,16 @@ func PublishMixin(mixin string) { // Publish a plugin's binaries. func PublishPlugin(plugin string) { publishPackage("plugin", plugin) - } func publishPackageFeed(pkgType string, name string) { info := mage.LoadMetadata() + if !info.ShouldPublishPermalink() { + fmt.Println("Skipping publish package feed for permalink", info.Permalink) + return + } + // Clone the packages repository if _, err := os.Stat(packagesRepo); !os.IsNotExist(err) { os.RemoveAll(packagesRepo) @@ -168,20 +177,20 @@ func GeneratePluginFeed() { // AddFilesToRelease uploads the files in the specified directory to a GitHub release. // If the release does not exist already, it will be created with empty release notes. -func AddFilesToRelease(repo string, version string, dir string) { +func AddFilesToRelease(repo string, tag string, dir string) { files := listFiles(dir) // Mark canary releases as a draft draft := "" - if version == "canary" { + if strings.HasPrefix(tag, "canary") { draft = "-p" } - if releaseExists(repo, version) { - must.Command("gh", "release", "upload", "--clobber", "-R", repo, version). + if releaseExists(repo, tag) { + must.Command("gh", "release", "upload", "--clobber", "-R", repo, tag). Args(files...).RunV() } else { - must.Command("gh", "release", "create", "-R", repo, "-t", version, "--notes=", draft, version). + must.Command("gh", "release", "create", "-R", repo, "-t", tag, "--notes=", draft, tag). CollapseArgs().Args(files...).RunV() } } diff --git a/magefile.go b/magefile.go index e2d23e8e1..5ed0d1d52 100644 --- a/magefile.go +++ b/magefile.go @@ -148,24 +148,86 @@ func getDualPublish() bool { func BuildImages() { info := mage.LoadMetadata() + registry := getRegistry() - must.Command("./scripts/build-images.sh").Env("VERSION="+info.Version, "PERMALINK="+info.Permalink, "REGISTRY="+getRegistry()).RunV() + buildImages(registry, info) if getDualPublish() { - must.Command("./scripts/build-images.sh").Env("VERSION="+info.Version, "PERMALINK="+info.Permalink, "REGISTRY=ghcr.io/getporter").RunV() + buildImages("ghcr.io/getporter", info) } } +func buildImages(registry string, info mage.GitMetadata) { + var g errgroup.Group + + g.Go(func() error { + img := fmt.Sprintf("%s/porter:%s", registry, info.Version) + err := shx.RunV("docker", "build", "-t", img, "-f", "build/images/client/Dockerfile", ".") + if err != nil { + return err + } + + err = shx.Run("docker", "tag", img, fmt.Sprintf("%s/porter:%s", registry, info.Permalink)) + if err != nil { + return err + } + + // porter-agent does a FROM porter so they can't go in parallel + img = fmt.Sprintf("%s/porter-agent:%s", registry, info.Version) + err = shx.RunV("docker", "build", "-t", img, "--build-arg", "PORTER_VERSION="+info.Version, "--build-arg", "REGISTRY="+registry, "-f", "build/images/agent/Dockerfile", "build/images/agent") + if err != nil { + return err + } + + return shx.Run("docker", "tag", img, fmt.Sprintf("%s/porter-agent:%s", registry, info.Permalink)) + }) + + g.Go(func() error { + img := fmt.Sprintf("%s/workshop:%s", registry, info.Version) + err := shx.RunV("docker", "build", "-t", img, "-f", "build/images/workshop/Dockerfile", ".") + if err != nil { + return err + } + + return shx.Run("docker", "tag", img, fmt.Sprintf("%s/workshop:%s", registry, info.Permalink)) + }) + + mgx.Must(g.Wait()) +} + func PublishImages() { mg.Deps(BuildImages) info := mage.LoadMetadata() - must.Command("./scripts/publish-images.sh").Env("VERSION="+info.Version, "PERMALINK="+info.Permalink, "REGISTRY="+getRegistry()).RunV() + pushImagesTo(getRegistry(), info) if getDualPublish() { - must.Command("./scripts/publish-images.sh").Env("VERSION="+info.Version, "PERMALINK="+info.Permalink, "REGISTRY=ghcr.io/getporter").RunV() + pushImagesTo("ghcr.io/getporter", info) } } +// Only push tagged versions, canary and latest +func pushImagesTo(registry string, info mage.GitMetadata) { + if info.IsTaggedRelease { + pushImages(registry, info.Version) + } + + if info.ShouldPublishPermalink() { + pushImages(registry, info.Permalink) + } else { + fmt.Println("Skipping image publish for permalink", info.Permalink) + } +} + +func pushImages(registry string, tag string) { + pushImage(fmt.Sprintf("%s/porter:%s", registry, tag)) + pushImage(fmt.Sprintf("%s/porter-agent:%s", registry, tag)) + pushImage(fmt.Sprintf("%s/workshop:%s", registry, tag)) +} + +func pushImage(img string) { + must.RunV("docker", "push", img) +} + // Publish the porter binaries and install scripts. func PublishPorter() { mg.Deps(tools.EnsureGitHubClient, releases.ConfigureGitBot) @@ -183,13 +245,17 @@ func PublishPorter() { } remote := fmt.Sprintf("https://%s.git", repo) - // Move the permalink tag. The existing release automatically points to the tag. - must.RunV("git", "tag", info.Permalink, info.Version+"^{}", "-f") - must.RunV("git", "push", "-f", remote, info.Permalink) - // Create or update GitHub release for the permalink (canary/latest) with the version's assets (porter binaries, exec binaries and install scripts) - releases.AddFilesToRelease(repo, info.Permalink, porterVersionDir) - releases.AddFilesToRelease(repo, info.Permalink, execVersionDir) + if info.ShouldPublishPermalink() { + // Move the permalink tag. The existing release automatically points to the tag. + must.RunV("git", "tag", info.Permalink, info.Version+"^{}", "-f") + must.RunV("git", "push", "-f", remote, info.Permalink) + + releases.AddFilesToRelease(repo, info.Permalink, porterVersionDir) + releases.AddFilesToRelease(repo, info.Permalink, execVersionDir) + } else { + fmt.Println("Skipping publish binaries for permalink", info.Permalink) + } if info.IsTaggedRelease { // Create GitHub release for the exact version (v1.2.3) and attach assets diff --git a/pkg/pkgmgmt/feed/generate.go b/pkg/pkgmgmt/feed/generate.go index dc9397187..5a44aee95 100644 --- a/pkg/pkgmgmt/feed/generate.go +++ b/pkg/pkgmgmt/feed/generate.go @@ -5,7 +5,6 @@ import ( "os" "regexp" "sort" - "strings" "time" "get.porter.sh/porter/pkg/context" @@ -127,8 +126,8 @@ var versionRegex = regexp.MustCompile(`\d+-g[a-z0-9]+`) // As a safety measure, skip versions that shouldn't be put in the feed, we only want canary and tagged releases. func shouldPublishVersion(version string) bool { - if strings.HasSuffix(version, "canary") { - // Publish canary permalinks + // Publish canary permalinks, for now ignore canary-v1 + if version == "canary" { return true } diff --git a/pkg/pkgmgmt/feed/generate_test.go b/pkg/pkgmgmt/feed/generate_test.go index e02a469e8..b2c52c554 100644 --- a/pkg/pkgmgmt/feed/generate_test.go +++ b/pkg/pkgmgmt/feed/generate_test.go @@ -63,12 +63,9 @@ func TestGenerate(t *testing.T) { tc.FileSystem.Create("bin/latest/helm-linux-amd64") tc.FileSystem.Create("bin/latest/helm-windows-amd64.exe") - tc.FileSystem.Create("bin/v2-latest/helm-darwin-amd64") - tc.FileSystem.Create("bin/v2-latest/helm-linux-amd64") - tc.FileSystem.Create("bin/v2-latest/helm-windows-amd64.exe") - tc.FileSystem.Chtimes("bin/v2-latest/helm-darwin-amd64", up4, up4) - tc.FileSystem.Chtimes("bin/v2-latest/helm-linux-amd64", up4, up4) - tc.FileSystem.Chtimes("bin/v2-latest/helm-windows-amd64.exe", up4, up4) + tc.FileSystem.Create("bin/canary-v1/exec-darwin-amd64") + tc.FileSystem.Create("bin/canary-v1/exec-linux-amd64") + tc.FileSystem.Create("bin/canary-v1/exec-windows-amd64.exe") opts := GenerateOptions{ AtomFile: "atom.xml", @@ -230,13 +227,6 @@ func TestGenerate_RegenerateDoesNotCreateDuplicates(t *testing.T) { tc.FileSystem.Chtimes("bin/canary/exec-linux-amd64", up10, up10) tc.FileSystem.Chtimes("bin/canary/exec-windows-amd64.exe", up10, up10) - tc.FileSystem.Create("bin/v2-latest/helm-darwin-amd64") - tc.FileSystem.Create("bin/v2-latest/helm-linux-amd64") - tc.FileSystem.Create("bin/v2-latest/helm-windows-amd64.exe") - tc.FileSystem.Chtimes("bin/v2-latest/helm-darwin-amd64", up4, up4) - tc.FileSystem.Chtimes("bin/v2-latest/helm-linux-amd64", up4, up4) - tc.FileSystem.Chtimes("bin/v2-latest/helm-windows-amd64.exe", up4, up4) - opts := GenerateOptions{ AtomFile: "atom.xml", SearchDirectory: "bin", diff --git a/pkg/pkgmgmt/feed/testdata/atom-existing.xml b/pkg/pkgmgmt/feed/testdata/atom-existing.xml index c7f8facc3..643e5203d 100644 --- a/pkg/pkgmgmt/feed/testdata/atom-existing.xml +++ b/pkg/pkgmgmt/feed/testdata/atom-existing.xml @@ -8,17 +8,6 @@ https://porter.sh/mixins - - - https://cdn.porter.sh/mixins/v2-latest/helm - helm @ v2-latest - 2013-02-4T00:00:00Z - - v2-latest - - - - https://cdn.porter.sh/mixins/canary/exec exec @ canary diff --git a/pkg/pkgmgmt/feed/testdata/atom.xml b/pkg/pkgmgmt/feed/testdata/atom.xml index b9d7ca474..af35a4363 100644 --- a/pkg/pkgmgmt/feed/testdata/atom.xml +++ b/pkg/pkgmgmt/feed/testdata/atom.xml @@ -19,16 +19,6 @@ - - https://cdn.porter.sh/mixins/v2-latest/helm - helm @ v2-latest - 2013-02-04T00:00:00Z - - v2-latest - - - - https://cdn.porter.sh/mixins/v1.2.4/helm helm @ v1.2.4 diff --git a/scripts/build-images.sh b/scripts/build-images.sh deleted file mode 100755 index 0d692a683..000000000 --- a/scripts/build-images.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - - -# REGISTRY, PERMALINK and VERSION must be set before calling this script -# It is intended to only be executed by make publish - -docker build -t $REGISTRY/porter:$VERSION -f build/images/client/Dockerfile . -docker build -t $REGISTRY/porter-agent:$VERSION --build-arg PORTER_VERSION=$VERSION --build-arg REGISTRY=$REGISTRY -f build/images/agent/Dockerfile build/images/agent -docker build -t $REGISTRY/workshop:$VERSION -f build/images/workshop/Dockerfile . - -docker tag $REGISTRY/porter:$VERSION $REGISTRY/porter:$PERMALINK -docker tag $REGISTRY/porter-agent:$VERSION $REGISTRY/porter-agent:$PERMALINK -docker tag $REGISTRY/workshop:$VERSION $REGISTRY/workshop:$PERMALINK diff --git a/scripts/publish-images.sh b/scripts/publish-images.sh deleted file mode 100755 index 2bd1975d7..000000000 --- a/scripts/publish-images.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - - -# REGISTRY, PERMALINK and VERSION must be set before calling this script -# It is intended to only be executed by make publish - -if [[ "$PERMALINK" == *latest ]]; then - docker push $REGISTRY/porter:$VERSION - docker push $REGISTRY/porter-agent:$VERSION - docker push $REGISTRY/workshop:$VERSION - - docker push $REGISTRY/porter:$PERMALINK - docker push $REGISTRY/porter-agent:$PERMALINK - docker push $REGISTRY/workshop:$PERMALINK -else - docker push $REGISTRY/porter:$PERMALINK - docker push $REGISTRY/porter-agent:$PERMALINK - docker push $REGISTRY/workshop:$PERMALINK -fi