Skip to content

Commit

Permalink
Add option to host the chart package files in the GitHub Pages branch (
Browse files Browse the repository at this point in the history
…#123)

* add packages-with-index flag

Signed-off-by: Steven Barnes <Steven.Barnes@topgolf.com>

* Add unit tests

Signed-off-by: Steven Barnes <Steven.Barnes@topgolf.com>

* delete files created by test

Signed-off-by: Steven Barnes <Steven.Barnes@topgolf.com>

* Authenticate to get existing index.yaml

Signed-off-by: Steven Barnes <Steven.Barnes@topgolf.com>

* update docs

Signed-off-by: cpanato <ctadeu@gmail.com>

* fix lints

Signed-off-by: cpanato <ctadeu@gmail.com>

* add git pull function

Signed-off-by: cpanato <ctadeu@gmail.com>

* update help text for upload command

Signed-off-by: cpanato <ctadeu@gmail.com>

---------

Signed-off-by: Steven Barnes <Steven.Barnes@topgolf.com>
Signed-off-by: cpanato <ctadeu@gmail.com>
Co-authored-by: cpanato <ctadeu@gmail.com>
  • Loading branch information
annabarnes1138 and cpanato authored Jun 20, 2023
1 parent 9630f42 commit 378f527
Show file tree
Hide file tree
Showing 9 changed files with 267 additions and 91 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ Flags:
--skip-existing Skip upload if release exists
-t, --token string GitHub Auth Token
--make-release-latest bool Mark the created GitHub release as 'latest' (default "true")
--packages-with-index Host the package files in the GitHub Pages branch

Global Flags:
--config string Config file (default is $HOME/.cr.yaml)
Expand Down Expand Up @@ -118,6 +119,7 @@ Flags:
--release-name-template string Go template for computing release names, using chart metadata (default "{{ .Name }}-{{ .Version }}")
--remote string The Git remote used when creating a local worktree for the GitHub Pages branch (default "origin")
-t, --token string GitHub Auth Token (only needed for private repos)
--packages-with-index Host the package files in the GitHub Pages branch

Global Flags:
--config string Config file (default is $HOME/.cr.yaml)
Expand Down
1 change: 1 addition & 0 deletions cr/cmd/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,5 @@ func init() {
flags.Bool("push", false, "Push index.yaml to the GitHub Pages branch (must not be set if --pr is set)")
flags.Bool("pr", false, "Create a pull request for index.yaml against the GitHub Pages branch (must not be set if --push is set)")
flags.String("release-name-template", "{{ .Name }}-{{ .Version }}", "Go template for computing release names, using chart metadata")
flags.Bool("packages-with-index", false, "Host the package files in the GitHub Pages branch")
}
5 changes: 5 additions & 0 deletions cr/cmd/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,9 @@ func init() {
"If it is set to empty string, or the file is not found, the chart description will be used instead. The file is read from the chart package")
uploadCmd.Flags().Bool("generate-release-notes", false, "Whether to automatically generate the name and body for this release. See https://docs.github.com/en/rest/releases/releases")
uploadCmd.Flags().Bool("make-release-latest", true, "Mark the created GitHub release as 'latest'")
uploadCmd.Flags().String("pages-branch", "gh-pages", "The GitHub pages branch")
uploadCmd.Flags().String("remote", "origin", "The Git remote used when creating a local worktree for the GitHub Pages branch")
uploadCmd.Flags().Bool("push", false, "Push the chart package to the GitHub Pages branch (must not be set if --pr is set)")
uploadCmd.Flags().Bool("pr", false, "Create a pull request for the chart package against the GitHub Pages branch (must not be set if --push is set)")
uploadCmd.Flags().Bool("packages-with-index", false, "Host the package files in the GitHub Pages branch")
}
1 change: 1 addition & 0 deletions doc/cr_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ cr index [flags]
-i, --index-path string Path to index file (default ".cr-index/index.yaml")
-o, --owner string GitHub username or organization
-p, --package-path string Path to directory with chart packages (default ".cr-release-packages")
--packages-with-index Host the package files in the GitHub Pages branch
--pages-branch string The GitHub pages branch (default "gh-pages")
--pages-index-path string The GitHub pages index path (default "index.yaml")
--pr Create a pull request for index.yaml against the GitHub Pages branch (must not be set if --push is set)
Expand Down
5 changes: 5 additions & 0 deletions doc/cr_upload.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,13 @@ cr upload [flags]
--make-release-latest Mark the created GitHub release as 'latest' (default true)
-o, --owner string GitHub username or organization
-p, --package-path string Path to directory with chart packages (default ".cr-release-packages")
--packages-with-index Host the package files in the GitHub Pages branch
--pages-branch string The GitHub pages branch (default "gh-pages")
--pr Create a pull request for the chart package against the GitHub Pages branch (must not be set if --push is set)
--push Push the chart package to the GitHub Pages branch (must not be set if --pr is set)
--release-name-template string Go template for computing release names, using chart metadata (default "{{ .Name }}-{{ .Version }}")
--release-notes-file string Markdown file with chart release notes. If it is set to empty string, or the file is not found, the chart description will be used instead. The file is read from the chart package
--remote string The Git remote used when creating a local worktree for the GitHub Pages branch (default "origin")
--skip-existing Skip upload if release exists
-t, --token string GitHub Auth Token
```
Expand Down
1 change: 1 addition & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ type Options struct {
ReleaseNotesFile string `mapstructure:"release-notes-file"`
GenerateReleaseNotes bool `mapstructure:"generate-release-notes"`
MakeReleaseLatest bool `mapstructure:"make-release-latest"`
PackagesWithIndex bool `mapstructure:"packages-with-index"`
}

func LoadConfiguration(cfgFile string, cmd *cobra.Command, requiredFlags []string) (*Options, error) {
Expand Down
8 changes: 8 additions & 0 deletions pkg/git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ func (g *Git) Commit(workingDir string, message string) error {
return runCommand(workingDir, command)
}

// UpdateBranch runs 'git pull' with the given args.
func (g *Git) Pull(workingDir string, args ...string) error {
pullArgs := []string{"pull"}
pullArgs = append(pullArgs, args...)
command := exec.Command("git", pullArgs...)
return runCommand(workingDir, command)
}

// Push runs 'git push' with the given args.
func (g *Git) Push(workingDir string, args ...string) error {
pushArgs := []string{"push"}
Expand Down
91 changes: 69 additions & 22 deletions pkg/releaser/releaser.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type GitHub interface {

type HTTPClient interface {
Get(url string) (*http.Response, error)
GetWithToken(url string, token string) (*http.Response, error)
}

type Git interface {
Expand All @@ -63,6 +64,7 @@ type Git interface {
Add(workingDir string, args ...string) error
Commit(workingDir string, message string) error
Push(workingDir string, args ...string) error
Pull(workingDir string, args ...string) error
GetPushURL(remote string, token string) (string, error)
}

Expand Down Expand Up @@ -213,36 +215,21 @@ func (r *Releaser) UpdateIndexFile() (bool, error) {
if err := copyFile(r.config.IndexPath, indexYamlPath); err != nil {
return false, err
}
if err := r.git.Add(worktree, indexYamlPath); err != nil {

if err := r.git.Pull(worktree, r.config.Remote, r.config.PagesBranch); err != nil {
return false, err
}
if err := r.git.Commit(worktree, fmt.Sprintf("Update %s", r.config.PagesIndexPath)); err != nil {

if err := r.git.Add(worktree, indexYamlPath); err != nil {
return false, err
}

pushURL, err := r.git.GetPushURL(r.config.Remote, r.config.Token)
if err != nil {
if err := r.git.Commit(worktree, fmt.Sprintf("Update %s", r.config.PagesIndexPath)); err != nil {
return false, err
}

if r.config.Push {
fmt.Printf("Pushing to branch %q\n", r.config.PagesBranch)
if err := r.git.Push(worktree, pushURL, "HEAD:refs/heads/"+r.config.PagesBranch); err != nil {
return false, err
}
} else if r.config.PR {
branch := fmt.Sprintf("chart-releaser-%s", randomString(16))

fmt.Printf("Pushing to branch %q\n", branch)
if err := r.git.Push(worktree, pushURL, "HEAD:refs/heads/"+branch); err != nil {
return false, err
}
fmt.Printf("Creating pull request against branch %q\n", r.config.PagesBranch)
prURL, err := r.github.CreatePullRequest(r.config.Owner, r.config.GitRepo, "Update index.yaml", branch, r.config.PagesBranch)
if err != nil {
return false, err
}
fmt.Println("Pull request created:", prURL)
if err := r.pushToPagesBranch(worktree); err != nil {
return false, err
}

return true, nil
Expand Down Expand Up @@ -302,6 +289,12 @@ func (r *Releaser) addToIndexFile(indexFile *repo.IndexFile, url string) error {
s := strings.Split(url, "/")
s = s[:len(s)-1]

if r.config.PackagesWithIndex {
// the chart will be stored in the same repo as
// the index file so let's make the path relative
s = s[:0]
}

// Add to index
if err := indexFile.MustAdd(c.Metadata, filepath.Base(arch), strings.Join(s, "/"), hash); err != nil {
return err
Expand Down Expand Up @@ -354,6 +347,31 @@ func (r *Releaser) CreateReleases() error {
if err := r.github.CreateRelease(context.TODO(), release); err != nil {
return errors.Wrapf(err, "error creating GitHub release %s", releaseName)
}

if r.config.PackagesWithIndex {
worktree, err := r.git.AddWorktree("", r.config.Remote+"/"+r.config.PagesBranch)
if err != nil {
return err
}
defer r.git.RemoveWorktree("", worktree) //nolint: errcheck

pkgTargetPath := filepath.Join(worktree, filepath.Base(p))
if err := copyFile(p, pkgTargetPath); err != nil {
return err
}

if err := r.git.Add(worktree, pkgTargetPath); err != nil {
return err
}

if err := r.git.Commit(worktree, fmt.Sprintf("Publishing chart package for %s", releaseName)); err != nil {
return err
}

if err := r.pushToPagesBranch(worktree); err != nil {
return err
}
}
}

return nil
Expand All @@ -363,6 +381,35 @@ func (r *Releaser) getListOfPackages(dir string) ([]string, error) {
return filepath.Glob(filepath.Join(dir, "*.tgz"))
}

func (r *Releaser) pushToPagesBranch(worktree string) error {
pushURL, err := r.git.GetPushURL(r.config.Remote, r.config.Token)
if err != nil {
return err
}

if r.config.Push {
fmt.Printf("Pushing to branch %q\n", r.config.PagesBranch)
if err := r.git.Push(worktree, pushURL, "HEAD:refs/heads/"+r.config.PagesBranch); err != nil {
return err
}
} else if r.config.PR {
branch := fmt.Sprintf("chart-releaser-%s", randomString(16))

fmt.Printf("Pushing to branch %q\n", branch)
if err := r.git.Push(worktree, pushURL, "HEAD:refs/heads/"+branch); err != nil {
return err
}
fmt.Printf("Creating pull request against branch %q\n", r.config.PagesBranch)
prURL, err := r.github.CreatePullRequest(r.config.Owner, r.config.GitRepo, "Update index.yaml", branch, r.config.PagesBranch)
if err != nil {
return err
}
fmt.Println("Pull request created:", prURL)
}

return nil
}

func copyFile(srcFile string, dstFile string) error {
source, err := os.Open(srcFile)
if err != nil {
Expand Down
Loading

0 comments on commit 378f527

Please sign in to comment.