Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup from first release with dagger #440

Merged
merged 1 commit into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '^1.20'
go-version: '^1.22'
- uses: replicatedhq/action-install-pact@v1
- run: make test
- if: github.event_name == 'push' || ( github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository )
Expand All @@ -31,6 +31,6 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '^1.20'
go-version: '^1.22'
- name: make build
run: make build
4 changes: 2 additions & 2 deletions .github/workflows/working.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '^1.20'
go-version: '^1.22'
- uses: replicatedhq/action-install-pact@v1
- name: make test
run: make test
Expand All @@ -27,6 +27,6 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '^1.20'
go-version: '^1.22'
- name: make build
run: make build
53 changes: 0 additions & 53 deletions .goreleaser-nodocker.yaml

This file was deleted.

8 changes: 1 addition & 7 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,4 @@ archives:
- CHANGELOG*
snapshot:
version_template: SNAPSHOT-{{ .Commit }}
dockers:
- dockerfile: deploy/Dockerfile
image_templates:
- "replicated/vendor-cli:latest"
- "replicated/vendor-cli:{{ .Major }}"
- "replicated/vendor-cli:{{ .Major }}.{{ .Minor }}"
- "replicated/vendor-cli:{{ .Major }}.{{ .Minor }}.{{ .Patch }}"

35 changes: 6 additions & 29 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,37 +1,10 @@
API_PKGS=apps channels releases

VERSION=$(shell git describe)
ABBREV_VERSION=$(shell git describe --abbrev=0)
VERSION_PACKAGE = github.com/replicatedhq/replicated/pkg/version
DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"`
BUILDTAGS = containers_image_ostree_stub exclude_graphdriver_devicemapper exclude_graphdriver_btrfs containers_image_openpgp

export GO111MODULE=on

GIT_TREE = $(shell git rev-parse --is-inside-work-tree 2>/dev/null)
ifneq "$(GIT_TREE)" ""
define GIT_UPDATE_INDEX_CMD
git update-index --assume-unchanged
endef
define GIT_SHA
`git rev-parse HEAD`
endef
else
define GIT_UPDATE_INDEX_CMD
echo "Not a git repo, skipping git update-index"
endef
define GIT_SHA
""
endef
endif

define LDFLAGS
-ldflags "\
-X ${VERSION_PACKAGE}.version=${VERSION} \
-X ${VERSION_PACKAGE}.gitSHA=${GIT_SHA} \
-X ${VERSION_PACKAGE}.buildTime=${DATE} \
"
endef
export CGO_ENABLED=0

.PHONY: test-unit
test-unit:
Expand Down Expand Up @@ -138,4 +111,8 @@ docs:

.PHONE: release
release:
dagger call release --one-password-service-account env:OP_SERVICE_ACCOUNT_PRODUCTION --version $(version)
dagger call release \
--one-password-service-account-production env:OP_SERVICE_ACCOUNT_PRODUCTION \
--version $(version) \
--github-token env:GITHUB_TOKEN \
--progress plain
167 changes: 147 additions & 20 deletions dagger/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import (
"context"
"dagger/replicated/internal/dagger"
"encoding/json"
"errors"
"fmt"
"net/http"
"strings"

"github.com/Masterminds/semver"
)
Expand All @@ -27,32 +29,86 @@ func (r *Replicated) Release(
clean bool,

onePasswordServiceAccountProduction *dagger.Secret,

githubToken *dagger.Secret,
) error {
gitTreeOK, err := checkGitTree(ctx, source)
gitTreeOK, err := checkGitTree(ctx, source, githubToken)
if err != nil {
return err
}
if !gitTreeOK {
return fmt.Errorf("git tree is not clean")
return fmt.Errorf("Your git tree is not clean. You cannot release what's not commited.")
}

latestVersion, err := getLatestVersion(ctx)
if err != nil {
return err
}

major, minor, patch, err := parseVersion(ctx, version)
major, minor, patch, err := parseVersion(ctx, latestVersion, version)
if err != nil {
return err
}

_ = dag.Container().
fmt.Printf("Releasing as version %d.%d.%d\n", major, minor, patch)

// replace the version in the Makefile
buildFileContent, err := source.File("./pkg/version/build.go").Contents(ctx)
if err != nil {
return err
}
buildFileContent = strings.ReplaceAll(buildFileContent, "const version = \"unknown\"", fmt.Sprintf("const version = \"%d.%d.%d\"", major, minor, patch))
updatedSource := source.WithNewFile("./pkg/version/build.go", buildFileContent)

// mount that and commit the updated build.go to git (don't push)
// so that goreleaser won't have a dirty git tree error
gitCommitContainer := dag.Container().
From("alpine/git:latest").
WithMountedDirectory("/go/src/github.com/replicatedhq/replicated", source).
WithMountedDirectory("/go/src/github.com/replicatedhq/replicated", updatedSource).
WithWorkdir("/go/src/github.com/replicatedhq/replicated").
WithExec([]string{"git", "config", "user.email", "[email protected]"}).
WithExec([]string{"git", "config", "user.name", "Replicated Release Pipeline"}).
WithExec([]string{"git", "add", "pkg/version/build.go"}).
WithExec([]string{"git", "commit", "-m", fmt.Sprintf("Set version to %d.%d.%d", major, minor, patch)})
_, err = gitCommitContainer.Stdout(ctx)
if err != nil {
return err
}
updatedSource = gitCommitContainer.Directory("/go/src/github.com/replicatedhq/replicated")

githubTokenPlaintext, err := githubToken.Plaintext(ctx)
if err != nil {
return err
}
tagContainer := dag.Container().
From("alpine/git:latest").
WithMountedDirectory("/go/src/github.com/replicatedhq/replicated", updatedSource).
WithWorkdir("/go/src/github.com/replicatedhq/replicated").
WithExec([]string{"git", "tag", fmt.Sprintf("v%d.%d.%d", major, minor, patch)}).
WithExec([]string{"git", "push", "origin", fmt.Sprintf("v%d.%d.%d", major, minor, patch)})
WithExec([]string{"git", "remote", "add", "tag", fmt.Sprintf("https://%[email protected]/replicatedhq/replicated.git", githubTokenPlaintext)}).
With(CacheBustingExec([]string{"git", "tag", fmt.Sprintf("v%d.%d.%d", major, minor, patch)})).
With(CacheBustingExec([]string{"git", "push", "tag", fmt.Sprintf("v%d.%d.%d", major, minor, patch)}))
_, err = tagContainer.Stdout(ctx)
if err != nil {
return err
}

replicatedBinary := dag.Container().
// copy the source that has the tag included in it
updatedSource = tagContainer.Directory("/go/src/github.com/replicatedhq/replicated")

goModCache := dag.CacheVolume("replicated-go-mod-122")
goBuildCache := dag.CacheVolume("replicated-go-build-121")

replicatedBinary := dag.Container(dagger.ContainerOpts{
Platform: "linux/amd64",
}).
From("golang:1.22").
WithMountedDirectory("/go/src/github.com/replicatedhq/replicated", source).
WithMountedDirectory("/go/src/github.com/replicatedhq/replicated", updatedSource).
WithWorkdir("/go/src/github.com/replicatedhq/replicated").
WithExec([]string{"make", "build"}).
WithMountedCache("/go/pkg/mod", goModCache).
WithEnvVariable("GOMODCACHE", "/go/pkg/mod").
WithMountedCache("/go/build-cache", goBuildCache).
WithEnvVariable("GOCACHE", "/go/build-cache").
With(CacheBustingExec([]string{"make", "build"})).
File("/go/src/github.com/replicatedhq/replicated/bin/replicated")

dockerContainer := dag.Container().
Expand All @@ -65,6 +121,10 @@ func (r *Replicated) Release(
WithWorkdir("/out").
WithEntrypoint([]string{"/replicated"}).
WithFile("/replicated", replicatedBinary)
_, err = dockerContainer.Stdout(ctx)
if err != nil {
return err
}

username, err := dag.Onepassword().FindSecret(
onePasswordServiceAccountProduction,
Expand Down Expand Up @@ -96,12 +156,17 @@ func (r *Replicated) Release(
panic(err)
}

goreleaserContainer := dag.Goreleaser(dagger.GoreleaserOpts{
Version: goreleaserVersion,
}).Ctr().WithSecretVariable("GITHUB_TOKEN", githubToken)

if snapshot {
_, err := dag.
Goreleaser(dagger.GoreleaserOpts{
Version: goreleaserVersion,
Ctr: goreleaserContainer,
}).
WithSource(source).
WithSource(updatedSource).
Snapshot(ctx, dagger.GoreleaserSnapshotOpts{
Clean: clean,
})
Expand All @@ -112,8 +177,9 @@ func (r *Replicated) Release(
_, err := dag.
Goreleaser(dagger.GoreleaserOpts{
Version: goreleaserVersion,
Ctr: goreleaserContainer,
}).
WithSource(source).
WithSource(updatedSource).
Release(ctx, dagger.GoreleaserReleaseOpts{
Clean: clean,
})
Expand All @@ -125,11 +191,7 @@ func (r *Replicated) Release(
return nil
}

func parseVersion(ctx context.Context, version string) (int64, int64, int64, error) {
latestVersion, err := getLatestVersion(ctx)
if err != nil {
return 0, 0, 0, err
}
func parseVersion(ctx context.Context, latestVersion string, version string) (int64, int64, int64, error) {
parsedLatestVersion, err := semver.NewVersion(latestVersion)
if err != nil {
return 0, 0, 0, err
Expand Down Expand Up @@ -168,8 +230,14 @@ func getLatestVersion(ctx context.Context) (string, error) {
return release.TagName, nil
}

var (
ErrGitTreeNotClean = errors.New("Your git tree is not clean. You cannot release what's not commited.")
ErrMainBranch = errors.New("You must be on the main branch to release")
ErrCommitNotInGitHub = errors.New("You must merge your changes into the main branch before releasing")
)

// checkGitTree will return true if the local git tree is clean
func checkGitTree(ctx context.Context, source *dagger.Directory) (bool, error) {
func checkGitTree(ctx context.Context, source *dagger.Directory, githubToken *dagger.Secret) (bool, error) {
container := dag.Container().
From("alpine/git:latest").
WithMountedDirectory("/go/src/github.com/replicatedhq/replicated", source).
Expand All @@ -181,8 +249,67 @@ func checkGitTree(ctx context.Context, source *dagger.Directory) (bool, error) {
return false, err
}

if len(output) == 0 {
return true, nil
if len(output) > 0 {
return false, ErrGitTreeNotClean
}

container = dag.Container().
From("alpine/git:latest").
WithMountedDirectory("/go/src/github.com/replicatedhq/replicated", source).
WithWorkdir("/go/src/github.com/replicatedhq/replicated").
WithExec([]string{"git", "branch"})

output, err = container.Stdout(ctx)
if err != nil {
return false, err
}

if !strings.Contains(output, "* main") {
return false, ErrMainBranch
}

container = dag.Container().
From("alpine/git:latest").
WithMountedDirectory("/go/src/github.com/replicatedhq/replicated", source).
WithWorkdir("/go/src/github.com/replicatedhq/replicated").
WithExec([]string{"git", "rev-parse", "HEAD"})

commit, err := container.Stdout(ctx)
if err != nil {
return false, err
}

req, err := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/repos/replicatedhq/replicated/commits/%s", commit), nil)
if err != nil {
return false, err
}

githubTokenPlaintext, err := githubToken.Plaintext(ctx)
if err != nil {
return false, err
}

req.Header.Set("Authorization", fmt.Sprintf("token %s", githubTokenPlaintext))

resp, err := http.DefaultClient.Do(req)
if err != nil {
return false, err
}
defer resp.Body.Close()

type GitHubResponse struct {
SHA string `json:"sha"`
NodeID string `json:"node_id"`
Status string `json:"status"`
}

var ghResp GitHubResponse
if err := json.NewDecoder(resp.Body).Decode(&ghResp); err != nil {
return false, err
}

if ghResp.Status == "422" {
return false, ErrCommitNotInGitHub
}

return false, nil
Expand Down
Loading
Loading