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 option to host the chart package files in the GitHub Pages branch #123

Merged
merged 8 commits into from
Jun 20, 2023
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
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
Comment on lines +352 to +372
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this won't work if there are more than one packages to release as this can cause push failure because of conflict.

annabarnes1138/yet-another-chart-releaser#3

We might move L352-L356 outside of this for loop.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And also it would be great to push only once so that we can apply a complete patch to the remote repository or fail completely.

}
}
}

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