Skip to content

Commit

Permalink
feat(release): force-replace existing asset files by default
Browse files Browse the repository at this point in the history
The file-size check is obviously not a very reliable way to determine if
the local and remote files are different. Hence we now default to always
uploading all given asset files, replacing any existing ones with the
same file name.

The size check logic is still available via the --asset-size-check flag.
  • Loading branch information
jimeh committed Oct 10, 2021
1 parent 7118ed8 commit e7a991e
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 58 deletions.
19 changes: 13 additions & 6 deletions pkg/cli/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,12 @@ func releasePublishCmd() *cli2.Command {
"specified",
Value: "",
},
&cli2.BoolFlag{
Name: "asset-size-check",
Usage: "Do not replace existing asset files if local and " +
"remote file sizes match.",
Value: false,
},
},
Action: releaseActionWrapper(releasePublishAction),
}
Expand All @@ -164,12 +170,13 @@ func releasePublishAction(
rOpts *releaseOptions,
) error {
rlsOpts := &release.PublishOptions{
Repository: rOpts.Repository,
CommitRef: c.String("release-sha"),
ReleaseName: rOpts.Name,
ReleaseTitle: c.String("title"),
AssetFiles: c.Args().Slice(),
GithubToken: rOpts.GithubToken,
Repository: rOpts.Repository,
CommitRef: c.String("release-sha"),
ReleaseName: rOpts.Name,
ReleaseTitle: c.String("title"),
AssetFiles: c.Args().Slice(),
AssetSizeCheck: c.Bool("asset-size-check"),
GithubToken: rOpts.GithubToken,
}

rlsType := c.String("type")
Expand Down
130 changes: 78 additions & 52 deletions pkg/release/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,17 @@ type PublishOptions struct {
// the check to pass.
AssetFiles []string

// AssetSizeCheck causes a file size check for any existing asset files on a
// release which have the same filename as a asset we want to upload. If the
// size of the local and remote files are the same, the existing asset file
// is left in place. When this is false, given asset files will always be
// uploaded, replacing any asset files with the same filename.
AssetSizeCheck bool

// GitHubToken is the OAuth token used to talk to the GitHub API.
GithubToken string
}

//nolint:funlen,gocyclo
// Publish creates and publishes a GitHub release.
func Publish(ctx context.Context, opts *PublishOptions) error {
logger := hclog.FromContext(ctx).Named("release")
Expand Down Expand Up @@ -112,16 +118,73 @@ func Publish(ctx context.Context, opts *PublishOptions) error {
}
}

for _, fileName := range files {
fileIO, err2 := os.Open(fileName)
if err2 != nil {
return err2
err = uploadReleaseAssets(ctx, gh, release, files, opts)
if err != nil {
return err
}

changed := false
if release.GetName() != name {
release.Name = &name
changed = true
}

if body != "" && release.GetBody() != body {
release.Body = &body
changed = true
}

if release.GetDraft() != draft {
release.Draft = &draft
changed = true
}

if !draft && release.GetPrerelease() != prerelease {
release.Prerelease = &prerelease
changed = true
}

if changed {
logger.Info("updating release attributes", "url", release.GetHTMLURL())
release, _, err = gh.Repositories.EditRelease(
ctx, opts.Repository.Owner(), opts.Repository.Name(),
release.GetID(), release,
)
if err != nil {
return err
}
}

if created {
logger.Info("release created", "url", release.GetHTMLURL())
} else {
logger.Info("release updated", "url", release.GetHTMLURL())
}

return nil
}

func uploadReleaseAssets(
ctx context.Context,
gh *github.Client,
release *github.RepositoryRelease,
fileNames []string,
opts *PublishOptions,
) error {
logger := hclog.FromContext(ctx).Named("release")

for _, fileName := range fileNames {
logger.Debug("processing asset", "file", filepath.Base(fileName))

fileIO, err := os.Open(fileName)
if err != nil {
return err
}
defer fileIO.Close()

fileInfo, err2 := fileIO.Stat()
if err2 != nil {
return err2
fileInfo, err := fileIO.Stat()
if err != nil {
return err
}

fileBaseName := filepath.Base(fileName)
Expand All @@ -132,24 +195,24 @@ func Publish(ctx context.Context, opts *PublishOptions) error {
continue
}

if a.GetSize() == int(fileInfo.Size()) {
if opts.AssetSizeCheck && a.GetSize() == int(fileInfo.Size()) {
logger.Info("asset exists with correct size",
"file", fileBaseName,
"local_size", byteCountIEC(fileInfo.Size()),
"remote_size", byteCountIEC(int64(a.GetSize())),
)
assetExists = true
} else {
logger.Info(
"deleting existing asset", "file", fileBaseName,
)
_, err = gh.Repositories.DeleteReleaseAsset(
ctx, opts.Repository.Owner(), opts.Repository.Name(),
a.GetID(),
)
if err != nil {
return err
}
logger.Info(
"deleted asset with wrong size", "file", fileBaseName,
)
}
}

Expand All @@ -158,55 +221,18 @@ func Publish(ctx context.Context, opts *PublishOptions) error {
"file", fileBaseName,
"size", byteCountIEC(fileInfo.Size()),
)
_, _, err2 = gh.Repositories.UploadReleaseAsset(
_, _, err = gh.Repositories.UploadReleaseAsset(
ctx, opts.Repository.Owner(), opts.Repository.Name(),
release.GetID(),
&github.UploadOptions{Name: fileBaseName},
fileIO,
)
if err2 != nil {
return err2
if err != nil {
return err
}
}
}

changed := false
if release.GetName() != name {
release.Name = &name
changed = true
}

if body != "" && release.GetBody() != body {
release.Body = &body
changed = true
}

if release.GetDraft() != draft {
release.Draft = &draft
changed = true
}

if !draft && release.GetPrerelease() != prerelease {
release.Prerelease = &prerelease
changed = true
}

if changed {
release, _, err = gh.Repositories.EditRelease(
ctx, opts.Repository.Owner(), opts.Repository.Name(),
release.GetID(), release,
)
if err != nil {
return err
}
}

if created {
logger.Info("release created", "url", release.GetHTMLURL())
} else {
logger.Info("release updated", "url", release.GetHTMLURL())
}

return nil
}

Expand Down

0 comments on commit e7a991e

Please sign in to comment.