Skip to content

Commit

Permalink
feat: refactor ref to update-ref
Browse files Browse the repository at this point in the history
  • Loading branch information
isometry committed Sep 23, 2024
1 parent 895bdef commit f402afc
Show file tree
Hide file tree
Showing 10 changed files with 383 additions and 297 deletions.
60 changes: 31 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ A GitHub API client for managing tags and repository content from third-party au

* Create and update tags, both lightweight and annotated.
* Add, update and delete content idempotently.
* Idempotent ref copying (e.g. fast-forward merge and mutable tag updates).
* Idempotent update of git refs (e.g. fast-forward merge and mutable tags).
* GitHub-verified commits (when using a GitHub App-derived token), facilitating the enforcement of commit signing.
* Configuration defaults inferred from local context (e.g. git clone and environment).
* Completely self-contained: no external dependencies.
Expand Down Expand Up @@ -80,7 +80,7 @@ Unless `--force` is used, content that already matches the remote repository sta

Note: Due to limitations in the GitHub V4 API, when the target branch does not exist, branch creation and content push will trigger two distinct "push" events.

#### Content Example
#### Content Examples

##### Idempotent file add/update

Expand Down Expand Up @@ -137,7 +137,7 @@ Global Flags:
-v, --verbosity count verbosity
```

#### Tagging Example
#### Tagging Examples

##### Create lightweight tag

Expand All @@ -157,47 +157,49 @@ $ ghup -o nexthink-oss -r ghup -b main tag v1.0 -m "Release v1.0!"
https://github.com/nexthink-oss/ghup/releases/tag/v1.0
```

### Ref Copying
### Update Refs

The `ref` verb is used to update an arbitrary number `head` or `tag` references to match a source reference.
The `update-ref` verb is used to update an arbitrary number `head` or `tag` references to match a source reference.

The `source_ref` may take the form of a partial commit hash, or of a fully- or partially-qualified reference, defaulting to a branch reference (`heads/…`; overrideable via `--source-type=tags`).
The `target_ref`(s) must take the form of fully- or partially-qualified references, defaulting to tag references, defaulting to tag references (`tags/…`; overrideable via `--target-type=heads`). The `--force` flag will override standard fast-forward-only protection on branch updates.
The `source` may take the form of a partial commit hash, or of a fully- or partially-qualified reference, defaulting to a branch reference (`heads/…`; overrideable via `--source-type=tags`).
The `target`(s) must take the form of fully- or partially-qualified references, defaulting to tag references, defaulting to tag references (`tags/…`; overrideable via `--target-type=heads`).
The `--force` flag will override standard fast-forward-only protection on branch updates.

```console
$ ghup ref --help
Update target_refs to match source_ref
$ ghup update-ref --help
Update target refs to match source

Usage:
ghup ref [flags] <source_ref> <target_ref>...
ghup update-ref [flags] -s <source> <target> ...

Flags:
-S, --source-type string default source ref type (choices: [heads, tags]) (default "heads")
-T, --target-type string default target ref type (choices: [tags, heads]) (default "tags")
-h, --help help for ref
-s, --source ref-or-commit source ref-or-commit
-S, --source-type heads|tags unqualified source ref type (default heads)
-T, --target-type heads|tags unqualified target ref type (default tags)
-h, --help help for update-ref

Global Flags:
--author.trailer string key for commit author trailer (blank to disable) (default "Co-Authored-By")
-b, --branch string target branch name (default "feature/ref")
-f, --force force action
-m, --message string message (default "Commit via API")
-o, --owner string repository owner (default "isometry")
-r, --repo string repository name (default "ghup")
--token string GitHub Token or path/to/token-file
--trailer stringToString additional commit trailer (key=value; JSON via environment) (default [])
--user.email string email for commit author trailer (default "robin@isometry.net")
--user.name string name for commit author trailer (default "Robin Breathe")
-v, --verbosity count verbosity
--author.trailer key key for commit author trailer (blank to disable) (default "Co-Authored-By")
-b, --branch name target branch name (default "feature/ref")
-f, --force force action
-m, --message string message (default "Commit via API")
-o, --owner name repository owner name (default "isometry")
-r, --repo name repository name (default "ghup")
--token string GitHub Token or path/to/token-file
--trailer key=value extra key=value commit trailers (default [])
--user.email email email for commit author trailer (default "robin[email protected]")
--user.name name name for commit author trailer (default "Robin Breathe")
-v, --verbosity count verbosity
```

Note: the `--branch`, `--message` and `--trailer.*` flags are not used by the `ref` verb.
Note: the `--branch`, `--message` and trailer-related flags are not used by the `ref` verb.

#### Ref Copying Example
#### Updated Refs Examples

##### Fast-forward production branch to match staging

```console
$ ghup ref staging heads/production
$ ghup update-ref -s staging heads/production
source:
ref: heads/staging
sha: 206e1a484f03cd320a2125a50aa73bd8a2b045dc
Expand All @@ -211,7 +213,7 @@ target:
##### Create a lightweight tag pointing at a specific commit

```console
$ ghup ref b7ccc4d example
$ ghup update-ref -s b7ccc4d example
source:
ref: b7ccc4d
sha: b7ccc4db9bc43551fd3571c260869f4c69aa2fd4
Expand All @@ -224,7 +226,7 @@ target:
##### Update GitHub Actions-style major and minor tags following patch release:

```console
$ ghup ref tags/v1.1.7 v1.1 v1
$ ghup update-ref -s tags/v1.1.7 v1.1 v1
source:
ref: tags/v1.1.7
sha: b7ccc4db9bc43551fd3571c260869f4c69aa2fd4
Expand Down
26 changes: 13 additions & 13 deletions cmd/content.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,33 +25,33 @@ var contentCmd = &cobra.Command{
}

func init() {
contentCmd.PersistentFlags().Bool("create-branch", true, "create missing target branch")
viper.BindPFlag("create-branch", contentCmd.PersistentFlags().Lookup("create-branch"))
contentCmd.Flags().Bool("create-branch", true, "create missing target branch")
viper.BindPFlag("create-branch", contentCmd.Flags().Lookup("create-branch"))
viper.BindEnv("create-branch", "GHUP_CREATE_BRANCH")

contentCmd.PersistentFlags().String("pr-title", "", "create pull request iff target branch is created and title is specified")
viper.BindPFlag("pr-title", contentCmd.PersistentFlags().Lookup("pr-title"))
contentCmd.Flags().String("pr-title", "", "create pull request iff target branch is created and title is specified")
viper.BindPFlag("pr-title", contentCmd.Flags().Lookup("pr-title"))
viper.BindEnv("pr-title", "GHUP_PR_TITLE")

contentCmd.PersistentFlags().String("pr-body", "", "pull request body")
viper.BindPFlag("pr-body", contentCmd.PersistentFlags().Lookup("pr-body"))
contentCmd.Flags().String("pr-body", "", "pull request body")
viper.BindPFlag("pr-body", contentCmd.Flags().Lookup("pr-body"))
viper.BindEnv("pr-body", "GHUP_PR_BODY")

contentCmd.PersistentFlags().Bool("pr-draft", false, "create pull request in draft mode")
viper.BindPFlag("pr-draft", contentCmd.PersistentFlags().Lookup("pr-draft"))
contentCmd.Flags().Bool("pr-draft", false, "create pull request in draft mode")
viper.BindPFlag("pr-draft", contentCmd.Flags().Lookup("pr-draft"))
viper.BindEnv("pr-draft", "GHUP_PR_DRAFT")

contentCmd.PersistentFlags().String("base-branch", "", `base branch name (default: "[remote-default-branch])"`)
viper.BindPFlag("base-branch", contentCmd.PersistentFlags().Lookup("base-branch"))
contentCmd.Flags().String("base-branch", "", `base branch `+"`name`"+` (default: "[remote-default-branch])"`)
viper.BindPFlag("base-branch", contentCmd.Flags().Lookup("base-branch"))
viper.BindEnv("base-branch", "GHUP_BASE_BRANCH")

contentCmd.Flags().StringP("separator", "s", ":", "file-spec separator")
viper.BindPFlag("separator", contentCmd.Flags().Lookup("separator"))

contentCmd.Flags().StringSliceP("update", "u", []string{}, "file-spec to update")
contentCmd.Flags().StringSliceP("update", "u", []string{}, "`file-spec` to update")
viper.BindPFlag("update", contentCmd.Flags().Lookup("update"))

contentCmd.Flags().StringSliceP("delete", "d", []string{}, "file-path to delete")
contentCmd.Flags().StringSliceP("delete", "d", []string{}, "`file-path` to delete")
viper.BindPFlag("delete", contentCmd.Flags().Lookup("delete"))

contentCmd.Flags().SortFlags = false
Expand Down Expand Up @@ -172,7 +172,7 @@ func runContentCmd(cmd *cobra.Command, args []string) (err error) {
}
log.Debugf("CreateCommitOnBranchInput: %+v", input)

_, commitUrl, err := client.CommitOnBranchV4(input)
_, commitUrl, err := client.CreateCommitOnBranchV4(input)
if err != nil {
return errors.Wrap(err, "CommitOnBranchV4")
}
Expand Down
177 changes: 0 additions & 177 deletions cmd/ref.go

This file was deleted.

15 changes: 8 additions & 7 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,39 +72,40 @@ func init() {
viper.BindPFlag("token", rootCmd.PersistentFlags().Lookup("token"))
viper.BindEnv("token", "GHUP_TOKEN", "GITHUB_TOKEN")

rootCmd.PersistentFlags().StringP("owner", "o", defaultOwner, "repository owner")
rootCmd.PersistentFlags().StringP("owner", "o", defaultOwner, "repository owner `name`")
viper.BindPFlag("owner", rootCmd.PersistentFlags().Lookup("owner"))
viper.BindEnv("owner", "GHUP_OWNER", "GITHUB_OWNER")

rootCmd.PersistentFlags().StringP("repo", "r", defaultRepo, "repository name")
rootCmd.PersistentFlags().StringP("repo", "r", defaultRepo, "repository `name`")
viper.BindPFlag("repo", rootCmd.PersistentFlags().Lookup("repo"))

rootCmd.PersistentFlags().StringP("branch", "b", defaultBranch, "target branch name")
rootCmd.PersistentFlags().StringP("branch", "b", defaultBranch, "target branch `name`")
viper.BindPFlag("branch", rootCmd.PersistentFlags().Lookup("branch"))
viper.BindEnv("branch", "GHUP_BRANCH", "CHANGE_BRANCH", "BRANCH_NAME", "GIT_BRANCH")

rootCmd.PersistentFlags().StringP("message", "m", "Commit via API", "message")
viper.BindPFlag("message", rootCmd.PersistentFlags().Lookup("message"))

rootCmd.PersistentFlags().String("author.trailer", "Co-Authored-By", "key for commit author trailer (blank to disable)")
rootCmd.PersistentFlags().String("author.trailer", "Co-Authored-By", "`key` for commit author trailer (blank to disable)")
viper.BindPFlag("author.trailer", rootCmd.PersistentFlags().Lookup("author.trailer"))
viper.BindEnv("author.trailer", "GHUP_TRAILER_KEY")

rootCmd.PersistentFlags().String("user.name", defaultUserName, "name for commit author trailer")
rootCmd.PersistentFlags().String("user.name", defaultUserName, "`name` for commit author trailer")
viper.BindPFlag("user.name", rootCmd.PersistentFlags().Lookup("user.name"))
viper.BindEnv("user.name", "GHUP_TRAILER_NAME", "GIT_COMMITTER_NAME", "GIT_AUTHOR_NAME")

rootCmd.PersistentFlags().String("user.email", defaultUserEmail, "email for commit author trailer")
rootCmd.PersistentFlags().String("user.email", defaultUserEmail, "`email` for commit author trailer")
viper.BindPFlag("user.email", rootCmd.PersistentFlags().Lookup("user.email"))
viper.BindEnv("user.email", "GHUP_TRAILER_EMAIL", "GIT_COMMITTER_EMAIL", "GIT_AUTHOR_EMAIL")

rootCmd.PersistentFlags().StringToString("trailer", nil, "additional commit trailer (key=value; JSON via environment)")
rootCmd.PersistentFlags().StringToString("trailer", nil, "extra `key=value` commit trailers")
viper.BindPFlag("trailer", rootCmd.PersistentFlags().Lookup("trailer"))

rootCmd.PersistentFlags().BoolVarP(&force, "force", "f", false, "force action")
viper.BindPFlag("force", rootCmd.PersistentFlags().Lookup("force"))

rootCmd.Flags().SortFlags = false
rootCmd.PersistentFlags().SortFlags = false
}

// initViper initializes Viper to load config from the environment
Expand Down
Loading

0 comments on commit f402afc

Please sign in to comment.