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

Add init package downloader #506

Merged
merged 7 commits into from
Jun 9, 2022
Merged
Show file tree
Hide file tree
Changes from 4 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
43 changes: 41 additions & 2 deletions src/cmd/initialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"path"
"path/filepath"

"github.com/AlecAivazis/survey/v2"
"github.com/Masterminds/semver/v3"
"github.com/defenseunicorns/zarf/src/config"
"github.com/defenseunicorns/zarf/src/internal/message"
"github.com/defenseunicorns/zarf/src/internal/packager"
Expand All @@ -28,16 +30,53 @@ var initCmd = &cobra.Command{
initPackageName := fmt.Sprintf("zarf-init-%s.tar.zst", config.GetArch())
config.DeployOptions.PackagePath = initPackageName

// Use an init-package in the executable directory if none exist in current working directory
// Try to use an init-package in the executable directory if none exist in current working directory
if utils.InvalidPath(config.DeployOptions.PackagePath) {
executablePath, err := utils.GetFinalExecutablePath()
if err != nil {
message.Fatal(err, "Unable to get the directory where the zarf cli executable lives")
message.Error(err, "Unable to get the directory where the zarf cli executable lives")
}

executableDir := path.Dir(executablePath)
config.DeployOptions.PackagePath = filepath.Join(executableDir, initPackageName)

// If the init-package doesn't exist in the executable directory, suggest trying to download
if utils.InvalidPath(config.DeployOptions.PackagePath) {

// If no CLI version exists (should only occur in dev or CI), try to get the latest release tag from Githhub
if _, err := semver.StrictNewVersion(config.CLIVersion); err != nil {
config.CLIVersion, err = utils.GetLatestReleaseTag(config.GithubProject)
if err != nil {
message.Fatal(err, "No CLI version found and unable to get the latest release tag for the zarf cli.")
}
}

confirmDownload := config.DeployOptions.Confirm
url := fmt.Sprintf("https://github.com/%s/releases/download/%s/%s", config.GithubProject, config.CLIVersion, initPackageName)

// Give the user the choice to download the init-package and note that this does require an internet connection
message.Question("It seems the init package could not be found locally, Zarf can download this for you if you still have internet connectivity.")
message.Question(url)

// Prompt the user if --confirm not specified
YrrepNoj marked this conversation as resolved.
Show resolved Hide resolved
if !confirmDownload {
prompt := &survey.Confirm{
Message: "Do you want to download this init package?",
}
_ = survey.AskOne(prompt, &confirmDownload)
}

// If the user wants to download the init-package, download it
if confirmDownload {
utils.DownloadToFile(url, config.DeployOptions.PackagePath, "")
} else {
// Otherwise, exit and tell the user to manually download the init-package
message.Warn("You must download the init package manually and place it in the current working directory")
os.Exit(0)
}
}
}

// Run everything
packager.Deploy()
},
Expand Down
1 change: 1 addition & 0 deletions src/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
)

const (
GithubProject = "defenseunicorns/zarf"
IPV4Localhost = "127.0.0.1"

PackagePrefix = "zarf-package"
Expand Down
34 changes: 34 additions & 0 deletions src/internal/utils/github.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package utils

import (
"encoding/json"
"fmt"
"net/http"

"github.com/defenseunicorns/zarf/src/internal/message"
)

// GetLatestReleaseTag returns the latest release tag for the given github project
func GetLatestReleaseTag(project string) (string, error) {
message.Debugf("utils.GetLatestReleaseTag(%s)", project)

// We only need the tag from the JSON response
// See https://github.com/google/go-github/blob/v45.1.0/github/repos_releases.go#L21 for complete reference
ghRelease := struct {
TagName string `json:"tag_name"`
}{}

// Get the latest release from the GitHub API for the given project
resp, err := http.Get(fmt.Sprintf("https://api.github.com/repos/%s/releases/latest", project))
if err != nil {
return "", err
}
defer resp.Body.Close()

// Decode the JSON response into the ghRelease struct
if err := json.NewDecoder(resp.Body).Decode(&ghRelease); err != nil {
return "", err
}

return ghRelease.TagName, nil
}