diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 8806f481f..aa8cb9f7e 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: go-version: '^1.24' - uses: actions/cache@v4 @@ -28,7 +28,7 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: go-version: '^1.24' - uses: actions/cache@v4 @@ -59,7 +59,7 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: go-version: '^1.24' - uses: actions/cache@v4 @@ -76,7 +76,7 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: go-version: '^1.24' - uses: actions/cache@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..9a09dee8c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,173 @@ +name: Release + +on: + push: + tags: + - 'v*.*.*' + +permissions: + contents: write + +jobs: + validate: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Verify tag is from main branch + run: | + git fetch origin main + if ! git merge-base --is-ancestor ${{ github.sha }} origin/main; then + echo "Error: Tag must be created from main branch" + exit 1 + fi + + test: + runs-on: ubuntu-24.04 + needs: validate + strategy: + matrix: + test-type: [unit, pact, integration] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: '^1.24' + - uses: actions/cache@v4 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + - name: Install pact + if: matrix.test-type == 'pact' + uses: replicatedhq/action-install-pact@v1 + - name: Run tests + run: make test-${{ matrix.test-type }} + + release: + runs-on: ubuntu-24.04 + needs: test + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/setup-go@v5 + with: + go-version: '^1.24' + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v6 + with: + distribution: goreleaser + version: v2.10.2 + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + docker: + runs-on: ubuntu-24.04 + needs: release + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USER }} + password: ${{ secrets.DOCKERHUB_PASSWORD }} + - name: Extract version + id: version + run: | + VERSION=${GITHUB_REF#refs/tags/v} + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "major=$(echo $VERSION | cut -d. -f1)" >> $GITHUB_OUTPUT + echo "minor=$(echo $VERSION | cut -d. -f1,2)" >> $GITHUB_OUTPUT + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: | + replicated/vendor-cli:latest + replicated/vendor-cli:${{ steps.version.outputs.major }} + replicated/vendor-cli:${{ steps.version.outputs.minor }} + replicated/vendor-cli:${{ steps.version.outputs.version }} + labels: | + com.replicated.vendor_cli=true + platforms: linux/amd64 + + docs: + runs-on: ubuntu-24.04 + needs: release + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/setup-go@v5 + with: + go-version: '^1.24' + - name: Generate CLI docs + run: go run ./docs/gen.go + - name: Checkout replicated-docs + uses: actions/checkout@v4 + with: + repository: replicatedhq/replicated-docs + path: replicated-docs + token: ${{ secrets.DOCS_REPO_TOKEN }} + - name: Update docs + run: | + set -euo pipefail + VERSION=${GITHUB_REF#refs/tags/} + BRANCH_NAME="update-cli-docs-${VERSION}-$(date +%Y-%m-%d-%H%M%S)" + WORKSPACE_ROOT=$(pwd) + + cd replicated-docs + git config user.name "Replicated Release Pipeline" + git config user.email "release@replicated.com" + git checkout -b "$BRANCH_NAME" + + # Configure git to use token from environment variable for authentication + # This avoids exposing the token in command strings or git config history + # The credential helper reads from GITHUB_TOKEN environment variable + git config credential.helper "!f() { echo \"username=x-access-token\"; echo \"password=${GITHUB_TOKEN}\"; }; f" + git remote set-url origin https://github.com/replicatedhq/replicated-docs.git + + # Remove existing CLI docs (except installing doc) + find docs/reference -name "replicated-cli-*.mdx" ! -name "replicated-cli-installing.mdx" -delete + rm -f docs/reference/replicated.mdx + + # Copy new docs + for file in "${WORKSPACE_ROOT}/gen/docs"/*.md; do + if [ -f "$file" ]; then + filename=$(basename "$file" .md) + newname=$(echo "$filename" | sed 's/replicated_/replicated-cli-/g' | sed 's/_/-/g') + + # Fix header level and internal links + sed 's/^## /# /' "$file" | \ + sed 's/\.md//' | \ + sed 's/replicated_/replicated-cli-/g' | \ + sed 's/_/-/g' > "docs/reference/${newname}.mdx" + fi + done + + # Update sidebar - this is a simplified version, may need manual adjustment + git add . + git commit -m "Update Replicated CLI docs for ${VERSION}" + git push origin "$BRANCH_NAME" + + # Create PR using GitHub CLI + gh pr create \ + --repo replicatedhq/replicated-docs \ + --base main \ + --head "$BRANCH_NAME" \ + --title "Update Replicated CLI docs for ${VERSION}" \ + --body "Automated update of CLI documentation for release ${VERSION}" + env: + GITHUB_TOKEN: ${{ secrets.DOCS_REPO_TOKEN }} + GH_TOKEN: ${{ secrets.DOCS_REPO_TOKEN }} diff --git a/Dockerfile b/Dockerfile index 94258ffaf..426305fd8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,34 @@ -FROM golang:1.24 +# Build stage +FROM golang:1.24-alpine AS builder -ENV PROJECTPATH=/go/src/github.com/replicatedhq/replicated +WORKDIR /build -RUN go get github.com/go-swagger/go-swagger/cmd/swagger +# Copy go mod files +COPY go.mod go.sum ./ +RUN go mod download -WORKDIR $PROJECTPATH +# Copy source code +COPY . . -ENV GO111MODULE=on +# Build the binary +RUN CGO_ENABLED=0 go build \ + -tags "containers_image_ostree_stub exclude_graphdriver_devicemapper exclude_graphdriver_btrfs containers_image_openpgp" \ + -o bin/replicated \ + cli/main.go -CMD ["/bin/bash"] +# Final stage +FROM alpine:latest + +RUN apk add --no-cache ca-certificates curl git && \ + update-ca-certificates + +ENV IN_CONTAINER=1 + +WORKDIR /out + +# Copy binary from builder stage +COPY --from=builder /build/bin/replicated /replicated + +LABEL com.replicated.vendor_cli=true + +ENTRYPOINT ["/replicated"] diff --git a/Makefile b/Makefile index c77db3ddc..3798448aa 100644 --- a/Makefile +++ b/Makefile @@ -93,18 +93,15 @@ build: .PHONY: release release: - dagger call release \ - --one-password-service-account-production env:OP_SERVICE_ACCOUNT_PRODUCTION \ - --version $(version) \ - --github-token env:GITHUB_TOKEN \ - --progress plain + @echo "Releases are now automated via GitHub Actions" + @echo "To create a release:" + @echo " 1. Ensure you are on the main branch with a clean working tree" + @echo " 2. Create and push a tag: git tag v1.2.3 && git push origin v1.2.3" + @echo " 3. GitHub Actions will automatically build, test, and release" @echo "" - @echo "✓ Release completed successfully" - @echo "Generating documentation PR..." - @$(MAKE) docs - -.PHONY: docs -docs: - dagger --progress plain call generate-docs \ - --github-token env:GITHUB_TOKEN \ - --progress plain + @echo "The workflow will:" + @echo " - Run all tests" + @echo " - Build multi-platform binaries with GoReleaser" + @echo " - Create a GitHub release with artifacts" + @echo " - Build and push Docker images" + @echo " - Generate and submit CLI documentation PR" diff --git a/dagger.json b/dagger.json deleted file mode 100644 index e2d249c1a..000000000 --- a/dagger.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "replicated", - "engineVersion": "v0.18.9", - "sdk": { - "source": "go" - }, - "dependencies": [ - { - "name": "goreleaser", - "source": "github.com/developer-guy/excoriate-daggerverse/goreleaser@b4bc20faec104b7f45c9a429b20f7d39d1531b79", - "pin": "b4bc20faec104b7f45c9a429b20f7d39d1531b79" - }, - { - "name": "onepassword", - "source": "github.com/replicatedhq/daggerverse/onepassword@0b03c8c560c2067f34dab800c92154abc3834841", - "pin": "0b03c8c560c2067f34dab800c92154abc3834841" - } - ], - "source": "dagger" -} diff --git a/dagger/.gitattributes b/dagger/.gitattributes deleted file mode 100644 index 3a454933c..000000000 --- a/dagger/.gitattributes +++ /dev/null @@ -1,4 +0,0 @@ -/dagger.gen.go linguist-generated -/internal/dagger/** linguist-generated -/internal/querybuilder/** linguist-generated -/internal/telemetry/** linguist-generated diff --git a/dagger/.gitignore b/dagger/.gitignore deleted file mode 100644 index 7ebabcc14..000000000 --- a/dagger/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/dagger.gen.go -/internal/dagger -/internal/querybuilder -/internal/telemetry diff --git a/dagger/compatibility.go b/dagger/compatibility.go deleted file mode 100644 index 457862adc..000000000 --- a/dagger/compatibility.go +++ /dev/null @@ -1,15 +0,0 @@ -package main - -import ( - "context" - "dagger/replicated/internal/dagger" -) - -func validateCompatibility( - ctx context.Context, - - // +defaultPath="./" - source *dagger.Directory, -) error { - return nil -} diff --git a/dagger/docs.go b/dagger/docs.go deleted file mode 100644 index d9c7f68f0..000000000 --- a/dagger/docs.go +++ /dev/null @@ -1,276 +0,0 @@ -package main - -import ( - "bufio" - "bytes" - "context" - "dagger/replicated/internal/dagger" - "encoding/json" - "fmt" - "io" - "net/http" - "path/filepath" - "strings" - "time" - - "github.com/pkg/errors" -) - -func (r *Replicated) GenerateDocs( - ctx context.Context, - - // +defaultPath="./" - source *dagger.Directory, - - githubToken *dagger.Secret, -) error { - err := checkGitTree(ctx, source, githubToken) - if err != nil { - return errors.Wrap(err, "failed to check git tree") - } - - latestVersion, err := getLatestVersion(ctx, githubToken) - if err != nil { - return errors.Wrap(err, "failed to get latest version") - } - - docsContainer := dag.Container(). - From("alpine/git:latest"). - WithWorkdir("/"). - With(CacheBustingExec([]string{"git", "clone", "--depth", "1", "https://github.com/replicatedhq/replicated-docs.git", "/replicated-docs"})) - - rootDocsDirectory := docsContainer.Directory("/replicated-docs") - docsDirectory := rootDocsDirectory.Directory("/docs/reference/") - - // Remove existing CLI docs - existingDocs, err := docsDirectory.Entries(ctx) - if err != nil { - return errors.Wrap(err, "failed to get existing docs") - } - - for _, existingDoc := range existingDocs { - // 'replicated-cli-installing.mdx' is a special file that's not a CLI doc - if existingDoc == "replicated-cli-installing.mdx" { - continue - } - if !strings.HasPrefix(existingDoc, "replicated-cli") { - continue - } - - docsDirectory = docsDirectory.WithoutFile(existingDoc) - } - - // Generate CLI new docs - goModCache := dag.CacheVolume("replicated-go-mod-122") - goBuildCache := dag.CacheVolume("replicated-go-build-121") - - // generate the docs from this current commit - docs := dag.Container(). - From("golang:1.24"). - WithMountedDirectory("/go/src/github.com/replicatedhq/replicated", source). - WithWorkdir("/go/src/github.com/replicatedhq/replicated"). - WithMountedCache("/go/pkg/mod", goModCache). - WithEnvVariable("GOMODCACHE", "/go/pkg/mod"). - WithMountedCache("/go/build-cache", goBuildCache). - WithEnvVariable("GOCACHE", "/go/build-cache"). - WithEnvVariable("CGO_ENABLED", "0"). - With(CacheBustingExec([]string{"go", "run", "./docs/gen.go"})) - - generatedDocs := docs.Directory("/go/src/github.com/replicatedhq/replicated/gen/docs") - - entries, err := generatedDocs.Entries(ctx) - if err != nil { - return errors.Wrap(err, "failed to get generated docs") - } - - // Add new CLI docs to the docs directory while updating file names and fixing up header level - newDocFilenames := []string{} - for _, entry := range entries { - file := generatedDocs.File(entry) - - content, err := file.Contents(ctx) - if err != nil { - return errors.Wrap(err, "failed to get generated doc contents") - } - - content = cleanContent(content, entries) - - destFilename := cobraFileNameToDocsFileName(entry) - - docsDirectory = docsDirectory.WithNewFile(destFilename, content) - newDocFilenames = append(newDocFilenames, destFilename) - } - - // Update sidebar config to include new CLI docs - sidebarFile := rootDocsDirectory.File("sidebars.js") - sidebarContent, err := sidebarFile.Contents(ctx) - if err != nil { - return errors.Wrap(err, "failed to get sidebar contents") - } - - sidebarContent, err = replaceFilenamesInSidebar(sidebarContent, newDocFilenames) - if err != nil { - return errors.Wrap(err, "failed to replace filenames in sidebar") - } - - rootDocsDirectory = rootDocsDirectory.WithNewFile("sidebars.js", sidebarContent) - - docsContainer = docsContainer. - WithMountedDirectory("/replicated-docs", rootDocsDirectory). - WithMountedDirectory("/replicated-docs/docs/reference", docsDirectory). - WithWorkdir("/replicated-docs"). - WithExec([]string{"git", "diff"}) - diffOut, err := docsContainer.Stdout(ctx) - if err != nil { - return errors.Wrap(err, "failed to get diff") - } - - if diffOut == "" { - return errors.New("diff is empty") - } - - githubTokenPlaintext, err := githubToken.Plaintext(ctx) - if err != nil { - return errors.Wrap(err, "failed to get github token plaintext") - } - - branchName := fmt.Sprintf("update-cli-docs-%s-%s", latestVersion, time.Now().Format("2006-01-02-150405")) - docsContainer = docsContainer. - WithExec([]string{"git", "config", "user.email", "release@replicated.com"}). - WithExec([]string{"git", "config", "user.name", "Replicated Release Pipeline"}). - WithExec([]string{"git", "remote", "add", "dagger", fmt.Sprintf("https://%s@github.com/replicatedhq/replicated-docs.git", githubTokenPlaintext)}). - WithExec([]string{"git", "checkout", "-b", branchName}). - WithExec([]string{"git", "add", "."}). - WithExec([]string{"git", "commit", "-m", fmt.Sprintf("Update Replicated CLI docs for %s", latestVersion)}). - WithExec([]string{"git", "push", "dagger", branchName}) - - _, err = docsContainer.Stdout(ctx) - if err != nil { - return errors.Wrap(err, "failed to get push output") - } - - err = createPullRequest(ctx, branchName, fmt.Sprintf("Update Replicated CLI docs for %s", latestVersion), "", githubTokenPlaintext) - if err != nil { - return errors.Wrap(err, "failed to create pull request") - } - - return nil -} - -// Change names like "replicated_channel_inspect.md" to "replicated-cli-channel-inspect.mdx" -func cobraFileNameToDocsFileName(filename string) string { - filename = strings.ReplaceAll(filename, "replicated_", "replicated-cli-") - filename = strings.ReplaceAll(filename, "_", "-") - if filepath.Ext(filename) == ".md" { - filename = strings.TrimSuffix(filename, filepath.Ext(filename)) + ".mdx" - } - return filename -} - -func cleanContent(content string, filenames []string) string { - // Header must be level 1 in order for white spaces to be rendered correctly ("replicated api get" vs "replicated_api_get") - if strings.HasPrefix(content, "## ") { - content = content[1:] - } - - // Replace all filenames in the content with the new filenames - for _, filename := range filenames { - topicLink := cobraFileNameToDocsFileName(filename) - topicLink = strings.TrimSuffix(topicLink, filepath.Ext(topicLink)) - content = strings.ReplaceAll(content, filename, topicLink) - } - - return content -} - -func replaceFilenamesInSidebar(sidebarContent string, newDocFilenames []string) (string, error) { - scanner := bufio.NewScanner(strings.NewReader(sidebarContent)) - - newDocLines := []string{} - foundCLILabel := false - wroteNewList := false - for scanner.Scan() { - line := scanner.Text() - - if strings.Contains(line, `reference/replicated-cli-`) { // CLI commands that are generated. - continue - } - - if strings.Contains(line, `'reference/replicated'`) { // CLI root command that is also generated. - continue - } - - if strings.Contains(line, `label: 'Replicated CLI'`) { - newDocLines = append(newDocLines, ` label: 'Replicated CLI', // This label is generated. Do not edit.`) - foundCLILabel = true - continue - } - - if foundCLILabel && !wroteNewList && strings.Contains(line, `items: [`) { - newDocLines = append(newDocLines, ` items: [ // This list is generated. Do not edit.`) - // 'reference/replicated-cli-installing' is a special file that's not a CLI doc and should at the top of the list - newDocLines = append(newDocLines, ` 'reference/replicated-cli-installing',`) - for _, newDocFilename := range newDocFilenames { - newDocLines = append(newDocLines, fmt.Sprintf(` 'reference/%s',`, strings.TrimSuffix(newDocFilename, filepath.Ext(newDocFilename)))) - } - wroteNewList = true - continue - } - - newDocLines = append(newDocLines, line) - } - - if !wroteNewList { - return "", fmt.Errorf("no CLI list found in sidebar") - } - - return strings.Join(newDocLines, "\n"), nil -} - -func createPullRequest(ctx context.Context, branchName string, title string, body string, githubTokenPlaintext string) error { - requestData := map[string]string{ - "title": title, - "body": body, - "head": branchName, - "base": "main", - } - - requestBody, err := json.Marshal(requestData) - if err != nil { - return errors.Wrap(err, "failed to marshal request data") - } - - req, err := http.NewRequestWithContext(ctx, "POST", "https://api.github.com/repos/replicatedhq/replicated-docs/pulls", bytes.NewReader(requestBody)) - if err != nil { - return errors.Wrap(err, "failed to create pull request") - } - - req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", githubTokenPlaintext)) - req.Header.Set("Accept", "application/vnd.github+json") - req.Header.Set("X-GitHub-Api-Version", "2022-11-28") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return errors.Wrap(err, "failed to do pull request") - } - - respBody, err := io.ReadAll(resp.Body) - if err != nil { - return errors.Wrap(err, "failed to read response body") - } - - if resp.StatusCode != http.StatusCreated { - return errors.Errorf("failed to create pull request: %s", string(respBody)) - } - - var pullRequest struct { - HTMLURL string `json:"html_url"` - } - if err := json.Unmarshal(respBody, &pullRequest); err != nil { - return errors.Wrap(err, "failed to unmarshal pull request") - } - - fmt.Printf("created pull request at: %s\n", pullRequest.HTMLURL) - - return nil -} diff --git a/dagger/exec_utils.go b/dagger/exec_utils.go deleted file mode 100644 index c03069979..000000000 --- a/dagger/exec_utils.go +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import ( - "dagger/replicated/internal/dagger" - "time" -) - -// CacheBustingExec is a helper function that will add a cache busting env var automatically -// to the container. This is useful when Exec target is a dynamic event acting on an entity outside -// of the container that you absolutely want to re-run every time. -// -// Temporary hack until cache controls are a thing: https://docs.dagger.io/cookbook/#invalidate-cache -func CacheBustingExec(args []string, opts ...dagger.ContainerWithExecOpts) dagger.WithContainerFunc { - return func(c *dagger.Container) *dagger.Container { - if c == nil { - panic("CacheBustingExec requires a container, but container was nil") - } - return c.WithEnvVariable("DAGGER_CACHEBUSTER_CBE", time.Now().String()).WithExec(args, opts...) - } -} diff --git a/dagger/functionality.go b/dagger/functionality.go deleted file mode 100644 index 3e7946616..000000000 --- a/dagger/functionality.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "context" - "dagger/replicated/internal/dagger" -) - -func validateFunctionality( - ctx context.Context, - - // +defaultPath="./" - source *dagger.Directory, -) error { - goModCache := dag.CacheVolume("replicated-go-mod-122") - goBuildCache := dag.CacheVolume("replicated-go-build-121") - - // unit tests - unitTest := dag.Container(). - From("golang:1.24"). - WithMountedDirectory("/go/src/github.com/replicatedhq/replicated", source). - WithWorkdir("/go/src/github.com/replicatedhq/replicated"). - WithMountedCache("/go/pkg/mod", goModCache). - WithEnvVariable("GOMODCACHE", "/go/pkg/mod"). - WithMountedCache("/go/build-cache", goBuildCache). - WithEnvVariable("GOCACHE", "/go/build-cache"). - With(CacheBustingExec([]string{"make", "test-unit"})) - - _, err := unitTest.Stderr(ctx) - if err != nil { - return err - } - - return nil -} diff --git a/dagger/go.mod b/dagger/go.mod deleted file mode 100644 index c73dbd1bb..000000000 --- a/dagger/go.mod +++ /dev/null @@ -1,52 +0,0 @@ -module dagger/replicated - -go 1.24 - -require ( - github.com/99designs/gqlgen v0.17.73 - github.com/Khan/genqlient v0.8.1 - github.com/pkg/errors v0.9.1 - github.com/vektah/gqlparser/v2 v2.5.27 - go.opentelemetry.io/otel v1.34.0 - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 - go.opentelemetry.io/otel/log v0.8.0 - go.opentelemetry.io/otel/sdk v1.34.0 - go.opentelemetry.io/otel/sdk/log v0.8.0 - go.opentelemetry.io/otel/trace v1.34.0 - go.opentelemetry.io/proto/otlp v1.3.1 - golang.org/x/sync v0.14.0 - google.golang.org/grpc v1.72.1 -) - -require ( - github.com/Masterminds/semver v1.5.0 - github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/go-logr/logr v1.4.2 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect - github.com/sosodev/duration v1.3.1 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 // indirect - go.opentelemetry.io/otel/metric v1.34.0 - go.opentelemetry.io/otel/sdk/metric v1.34.0 - golang.org/x/net v0.40.0 // indirect - golang.org/x/sys v0.33.0 // indirect - golang.org/x/text v0.25.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect - google.golang.org/protobuf v1.36.6 // indirect -) - -replace go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc => go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 - -replace go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp => go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 - -replace go.opentelemetry.io/otel/log => go.opentelemetry.io/otel/log v0.8.0 - -replace go.opentelemetry.io/otel/sdk/log => go.opentelemetry.io/otel/sdk/log v0.8.0 diff --git a/dagger/go.sum b/dagger/go.sum deleted file mode 100644 index 80e871621..000000000 --- a/dagger/go.sum +++ /dev/null @@ -1,89 +0,0 @@ -github.com/99designs/gqlgen v0.17.73 h1:A3Ki+rHWqKbAOlg5fxiZBnz6OjW3nwupDHEG15gEsrg= -github.com/99designs/gqlgen v0.17.73/go.mod h1:2RyGWjy2k7W9jxrs8MOQthXGkD3L3oGr0jXW3Pu8lGg= -github.com/Khan/genqlient v0.8.1 h1:wtOCc8N9rNynRLXN3k3CnfzheCUNKBcvXmVv5zt6WCs= -github.com/Khan/genqlient v0.8.1/go.mod h1:R2G6DzjBvCbhjsEajfRjbWdVglSH/73kSivC9TLWVjU= -github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= -github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= -github.com/sosodev/duration v1.3.1 h1:qtHBDMQ6lvMQsL15g4aopM4HEfOaYuhWBw3NPTtlqq4= -github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/vektah/gqlparser/v2 v2.5.27 h1:RHPD3JOplpk5mP5JGX8RKZkt2/Vwj/PZv0HxTdwFp0s= -github.com/vektah/gqlparser/v2 v2.5.27/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= -go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 h1:WzNab7hOOLzdDF/EoWCt4glhrbMPVMOO5JYTmpz36Ls= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0/go.mod h1:hKvJwTzJdp90Vh7p6q/9PAOd55dI6WA6sWj62a/JvSs= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 h1:S+LdBGiQXtJdowoJoQPEtI52syEP/JYBUpjO49EQhV8= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0/go.mod h1:5KXybFvPGds3QinJWQT7pmXf+TN5YIa7CNYObWRkj50= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 h1:t/Qur3vKSkUCcDVaSumWF2PKHt85pc7fRvFuoVT8qFU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0/go.mod h1:Rl61tySSdcOJWoEgYZVtmnKdA0GeKrSqkHC1t+91CH8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 h1:IJFEoHiytixx8cMiVAO+GmHR6Frwu+u5Ur8njpFO6Ac= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0/go.mod h1:3rHrKNtLIoS0oZwkY2vxi+oJcwFRWdtUyRII+so45p8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 h1:9kV11HXBHZAvuPUZxmMWrH8hZn/6UnHX4K0mu36vNsU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0/go.mod h1:JyA0FHXe22E1NeNiHmVp7kFHglnexDQ7uRWDiiJ1hKQ= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 h1:cMyu9O88joYEaI47CnQkxO1XZdpoTF9fEnW2duIddhw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0/go.mod h1:6Am3rn7P9TVVeXYG+wtcGE7IE1tsQ+bP3AuWcKt/gOI= -go.opentelemetry.io/otel/log v0.8.0 h1:egZ8vV5atrUWUbnSsHn6vB8R21G2wrKqNiDt3iWertk= -go.opentelemetry.io/otel/log v0.8.0/go.mod h1:M9qvDdUTRCopJcGRKg57+JSQ9LgLBrwwfC32epk5NX8= -go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= -go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= -go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= -go.opentelemetry.io/otel/sdk/log v0.8.0 h1:zg7GUYXqxk1jnGF/dTdLPrK06xJdrXgqgFLnI4Crxvs= -go.opentelemetry.io/otel/sdk/log v0.8.0/go.mod h1:50iXr0UVwQrYS45KbruFrEt4LvAdCaWWgIrsN3ZQggo= -go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= -go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= -go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= -go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= -go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= -go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= -google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a h1:nwKuGPlUAt+aR+pcrkfFRrTU1BVrSmYyYMxYbUIVHr0= -google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a/go.mod h1:3kWAYMk1I75K4vykHtKt2ycnOgpA6974V7bREqbsenU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ= -google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= -google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/dagger/main.go b/dagger/main.go deleted file mode 100644 index 75e60d1ed..000000000 --- a/dagger/main.go +++ /dev/null @@ -1,3 +0,0 @@ -package main - -type Replicated struct{} diff --git a/dagger/performance.go b/dagger/performance.go deleted file mode 100644 index 5a8132631..000000000 --- a/dagger/performance.go +++ /dev/null @@ -1,15 +0,0 @@ -package main - -import ( - "context" - "dagger/replicated/internal/dagger" -) - -func validatePerformance( - ctx context.Context, - - // +defaultPath="./" - source *dagger.Directory, -) error { - return nil -} diff --git a/dagger/release.go b/dagger/release.go deleted file mode 100644 index f0df52780..000000000 --- a/dagger/release.go +++ /dev/null @@ -1,361 +0,0 @@ -package main - -import ( - "context" - "dagger/replicated/internal/dagger" - "encoding/json" - "fmt" - "net/http" - "strings" - - "github.com/Masterminds/semver" - "github.com/pkg/errors" -) - -var goreleaserVersion = "v2.10.2" - -func (r *Replicated) Release( - ctx context.Context, - - // +defaultPath="./" - source *dagger.Directory, - - version string, - - // +default=false - snapshot bool, - - // +default=false - clean bool, - - onePasswordServiceAccountProduction *dagger.Secret, - - githubToken *dagger.Secret, -) error { - err := checkGitTree(ctx, source, githubToken) - if err != nil { - return errors.Wrap(err, "failed to check git tree") - } - - previousVersionTag, err := getLatestVersion(ctx, githubToken) - if err != nil { - return errors.Wrap(err, "failed to get latest version") - } - - previousReleaseBranchName, err := getReleaseBranchName(ctx, previousVersionTag) - if err != nil { - return errors.Wrap(err, "failed to get release branch name") - } - - major, minor, patch, err := getNextVersion(ctx, previousVersionTag, version) - if err != nil { - return errors.Wrap(err, "failed to get next version") - } - - 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 errors.Wrap(err, "failed to get build file contents") - } - 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) - - releaseBranchName := fmt.Sprintf("release-%d.%d.%d", major, minor, patch) - githubTokenPlaintext, err := githubToken.Plaintext(ctx) - if err != nil { - return errors.Wrap(err, "failed to get github token plaintext") - } - - // 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", updatedSource). - WithWorkdir("/go/src/github.com/replicatedhq/replicated"). - WithExec([]string{"git", "config", "user.email", "release@replicated.com"}). - WithExec([]string{"git", "config", "user.name", "Replicated Release Pipeline"}). - WithExec([]string{"git", "remote", "add", "dagger", fmt.Sprintf("https://%s@github.com/replicatedhq/replicated.git", githubTokenPlaintext)}). - WithExec([]string{"git", "checkout", "-b", releaseBranchName}). - WithExec([]string{"git", "add", "pkg/version/build.go"}). - WithExec([]string{"git", "commit", "-m", fmt.Sprintf("Set version to %d.%d.%d", major, minor, patch)}). - WithExec([]string{"git", "push", "dagger", releaseBranchName}) - _, err = gitCommitContainer.Stdout(ctx) - if err != nil { - return errors.Wrap(err, "failed to get git commit stdout") - } - updatedSource = gitCommitContainer.Directory("/go/src/github.com/replicatedhq/replicated") - - nextVersionTag := fmt.Sprintf("v%d.%d.%d", major, minor, patch) - - tagContainer := dag.Container(). - From("alpine/git:latest"). - WithMountedDirectory("/go/src/github.com/replicatedhq/replicated", updatedSource). - WithWorkdir("/go/src/github.com/replicatedhq/replicated"). - With(CacheBustingExec([]string{"git", "tag", nextVersionTag})). - With(CacheBustingExec([]string{"git", "push", "dagger", nextVersionTag})). - With(CacheBustingExec([]string{"git", "fetch", "dagger", previousReleaseBranchName})). - With(CacheBustingExec([]string{"git", "fetch", "dagger", "--tags"})) - _, err = tagContainer.Stdout(ctx) - if err != nil { - return errors.Wrap(err, "failed to get tag stdout") - } - - // 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.24"). - WithMountedDirectory("/go/src/github.com/replicatedhq/replicated", updatedSource). - WithoutFile("/go/src/github.com/replicatedhq/replicated/bin/replicated"). - WithWorkdir("/go/src/github.com/replicatedhq/replicated"). - 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(dagger.ContainerOpts{ - Platform: "linux/amd64", - }). - From("alpine:latest"). - WithExec([]string{"apk", "add", "--no-cache", "ca-certificates", "curl", "git", "nodejs", "npm"}). - WithExec([]string{"update-ca-certificates"}). - WithExec([]string{"npm", "install", "-g", "replicated-lint"}). - WithEnvVariable("IN_CONTAINER", "1"). - WithLabel("com.replicated.vendor_cli", "true"). - WithWorkdir("/out"). - WithEntrypoint([]string{"/replicated"}). - WithFile("/replicated", replicatedBinary) - _, err = dockerContainer.Stdout(ctx) - if err != nil { - return errors.Wrap(err, "failed to get docker container stdout") - } - - username, err := dag.Onepassword().FindSecret( - onePasswordServiceAccountProduction, - "Developer Automation Production", - "Docker Hub Release Account", - "username", - ).Plaintext(ctx) - if err != nil { - return errors.Wrap(err, "failed to get docker hub username") - } - password := dag.Onepassword().FindSecret( - onePasswordServiceAccountProduction, - "Developer Automation Production", - "Docker Hub Release Account", - "password", - ) - - dockerContainer = dockerContainer.WithRegistryAuth("", username, password) - if _, err := dockerContainer.Publish(ctx, "replicated/vendor-cli:latest"); err != nil { - return errors.Wrap(err, "failed to publish latest docker container") - } - if _, err := dockerContainer.Publish(ctx, fmt.Sprintf("replicated/vendor-cli:%d", major)); err != nil { - return errors.Wrap(err, "failed to publish major docker container") - } - if _, err := dockerContainer.Publish(ctx, fmt.Sprintf("replicated/vendor-cli:%d.%d", major, minor)); err != nil { - return errors.Wrap(err, "failed to publish minor docker container") - } - if _, err := dockerContainer.Publish(ctx, fmt.Sprintf("replicated/vendor-cli:%d.%d.%d", major, minor, patch)); err != nil { - return errors.Wrap(err, "failed to publish patch docker container") - } - - goreleaserContainer := dag.Goreleaser(dagger.GoreleaserOpts{ - Version: goreleaserVersion, - }).Ctr(). - WithSecretVariable("GITHUB_TOKEN", githubToken). - WithEnvVariable("GORELEASER_CURRENT_TAG", nextVersionTag). - WithEnvVariable("GORELEASER_PREVIOUS_TAG", previousVersionTag) - - if snapshot { - _, err := dag. - Goreleaser(dagger.GoreleaserOpts{ - Version: goreleaserVersion, - Ctr: goreleaserContainer, - }). - WithSource(updatedSource). - Snapshot(ctx, dagger.GoreleaserSnapshotOpts{ - Clean: clean, - }) - if err != nil { - return errors.Wrap(err, "failed to snapshot goreleaser") - } - } else { - _, err := dag. - Goreleaser(dagger.GoreleaserOpts{ - Version: goreleaserVersion, - Ctr: goreleaserContainer, - }). - WithSource(updatedSource). - Release(ctx, dagger.GoreleaserReleaseOpts{ - Clean: clean, - }) - if err != nil { - return errors.Wrap(err, "failed to release goreleaser") - } - } - - return nil -} - -func getNextVersion(ctx context.Context, latestVersion string, version string) (int64, int64, int64, error) { - parsedLatestVersion, err := semver.NewVersion(latestVersion) - if err != nil { - return 0, 0, 0, err - } - - switch version { - case "major": - return parsedLatestVersion.Major() + 1, 0, 0, nil - case "minor": - return parsedLatestVersion.Major(), parsedLatestVersion.Minor() + 1, 0, nil - case "patch": - return parsedLatestVersion.Major(), parsedLatestVersion.Minor(), parsedLatestVersion.Patch() + 1, nil - default: - v, err := semver.NewVersion(version) - if err != nil { - return 0, 0, 0, err - } - return v.Major(), v.Minor(), v.Patch(), nil - } -} - -func getReleaseBranchName(ctx context.Context, latestVersion string) (string, error) { - parsedLatestVersion, err := semver.NewVersion(latestVersion) - if err != nil { - return "", err - } - - return fmt.Sprintf("release-%d.%d.%d", parsedLatestVersion.Major(), parsedLatestVersion.Minor(), parsedLatestVersion.Patch()), nil -} - -func getLatestVersion(ctx context.Context, githubToken *dagger.Secret) (string, error) { - req, err := http.NewRequest("GET", "https://api.github.com/repos/replicatedhq/replicated/releases/latest", nil) - if err != nil { - return "", err - } - - githubTokenPlaintext, err := githubToken.Plaintext(ctx) - if err != nil { - return "", errors.Wrap(err, "failed to get github token plaintext") - } - - req.Header.Set("Authorization", fmt.Sprintf("token %s", githubTokenPlaintext)) - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return "", errors.Wrap(err, "failed to do github request") - } - - defer resp.Body.Close() - - var release struct { - TagName string `json:"tag_name"` - } - if err := json.NewDecoder(resp.Body).Decode(&release); err != nil { - return "", err - } - - 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 nil if the local git tree is clean or an error if it's not -func checkGitTree(ctx context.Context, source *dagger.Directory, githubToken *dagger.Secret) error { - container := dag.Container(). - From("alpine/git:latest"). - WithMountedDirectory("/go/src/github.com/replicatedhq/replicated", source). - WithWorkdir("/go/src/github.com/replicatedhq/replicated"). - With(CacheBustingExec([]string{"git", "status", "--porcelain"})) - - gitStatusOutput, err := container.Stdout(ctx) - if err != nil { - return errors.Wrap(err, "failed to get git status") - } - - gitStatusOutput = strings.TrimSpace(gitStatusOutput) - - if len(gitStatusOutput) > 0 { - fmt.Printf("output: %s\n", gitStatusOutput) - return fmt.Errorf("error: dirty tree: %q", gitStatusOutput) - } - - container = dag.Container(). - From("alpine/git:latest"). - WithMountedDirectory("/go/src/github.com/replicatedhq/replicated", source). - WithWorkdir("/go/src/github.com/replicatedhq/replicated"). - With(CacheBustingExec([]string{"git", "branch"})) - - gitBranchOutput, err := container.Stdout(ctx) - if err != nil { - return errors.Wrap(err, "failed to get git branch") - } - - gitBranchOutput = strings.TrimSpace(gitBranchOutput) - - if !strings.Contains(gitBranchOutput, "* main") { - return ErrMainBranch - } - - container = dag.Container(). - From("alpine/git:latest"). - WithMountedDirectory("/go/src/github.com/replicatedhq/replicated", source). - WithWorkdir("/go/src/github.com/replicatedhq/replicated"). - With(CacheBustingExec([]string{"git", "rev-parse", "HEAD"})) - - commit, err := container.Stdout(ctx) - if err != nil { - return errors.Wrap(err, "failed to get git commit") - } - - commit = strings.TrimSpace(commit) - - req, err := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/repos/replicatedhq/replicated/commits/%s", commit), nil) - if err != nil { - return errors.Wrap(err, "failed to create github request") - } - - githubTokenPlaintext, err := githubToken.Plaintext(ctx) - if err != nil { - return errors.Wrap(err, "failed to get github token plaintext") - } - - req.Header.Set("Authorization", fmt.Sprintf("token %s", githubTokenPlaintext)) - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return errors.Wrap(err, "failed to do github request") - } - 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 errors.Wrap(err, "failed to decode github response") - } - - if ghResp.Status == "422" { - return ErrCommitNotInGitHub - } - - return nil -} diff --git a/dagger/security.go b/dagger/security.go deleted file mode 100644 index 55cdd06c3..000000000 --- a/dagger/security.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "context" - "dagger/replicated/internal/dagger" -) - -func validateSecurity( - ctx context.Context, - - // +defaultPath="./" - source *dagger.Directory, -) error { - goModCache := dag.CacheVolume("replicated-go-mod-122") - goBuildCache := dag.CacheVolume("replicated-go-build-121") - - // run semgrep - semgrep := dag.Container(). - From("returntocorp/semgrep"). - WithMountedDirectory("/go/src/github.com/replicatedhq/replicated", source). - WithWorkdir("/go/src/github.com/replicatedhq/replicated"). - WithMountedCache("/go/pkg/mod", goModCache). - WithEnvVariable("GOMODCACHE", "/go/pkg/mod"). - WithMountedCache("/go/build-cache", goBuildCache). - WithEnvVariable("GOCACHE", "/go/build-cache"). - With(CacheBustingExec([]string{"semgrep", "scan", "--config=p/golang", "."})) - - _, err := semgrep.Stderr(ctx) - if err != nil { - return err - } - - return nil -} diff --git a/dagger/validate.go b/dagger/validate.go deleted file mode 100644 index e1807e55f..000000000 --- a/dagger/validate.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "context" - "dagger/replicated/internal/dagger" -) - -func (r *Replicated) Validate( - ctx context.Context, - - // +defaultPath="./" - source *dagger.Directory, -) error { - if err := validateSecurity(ctx, source); err != nil { - return err - } - - if err := validateFunctionality(ctx, source); err != nil { - return err - } - - if err := validateCompatibility(ctx, source); err != nil { - return err - } - - if err := validatePerformance(ctx, source); err != nil { - return err - } - - return nil -}