diff --git a/.github/workflows/discussion-triage.yml b/.github/workflows/discussion-triage.yml deleted file mode 100644 index 9397e5103..000000000 --- a/.github/workflows/discussion-triage.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Discussion Triage -run-name: ${{ github.event.issue.title }} -on: - issues: - types: - - labeled -jobs: - create-discussion: - if: github.event.label.name == 'discuss' - runs-on: ubuntu-latest - steps: - - name: Create a discussion in github/cli - run: | - export DISCUSSION_TITLE="Triage: ${ISSUE_TITLE} (#${ISSUE_NUMBER})" - gh api graphql -f query=' - mutation($repositoryId: ID!, $categoryId: ID!, $title: String!, $body: String!) { - createDiscussion( - input: {repositoryId: $repositoryId, categoryId: $categoryId, title: $title, body: $body} - ) { - discussion { - id - } - } - }' -f repositoryId="${GITHUB_CLI_REPOSITORY_ID}" -f categoryId="${TRIAGE_CATEGORY_ID}" -f title="${DISCUSSION_TITLE}" -f body="@${LABELLER} added the discuss label to https://github.com/cli/cli/issues/${ISSUE_NUMBER}" - env: - GITHUB_TOKEN: ${{ secrets.CLI_DISCUSSION_TRIAGE_TOKEN }} - ISSUE_TITLE: ${{ github.event.issue.title }} - ISSUE_NUMBER: ${{ github.event.issue.number }} - LABELLER: ${{ github.event.sender.login }} - GITHUB_CLI_REPOSITORY_ID: "R_kgDODAqwpw" - TRIAGE_CATEGORY_ID: "DIC_kwDODAqwp84CajJa" - diff --git a/.github/workflows/triage.yml b/.github/workflows/triage.yml new file mode 100644 index 000000000..6cd9d981d --- /dev/null +++ b/.github/workflows/triage.yml @@ -0,0 +1,67 @@ +name: Discussion Triage +run-name: ${{ github.event_name == 'issues' && github.event.issue.title || github.event.pull_request.title }} +on: + issues: + types: + - labeled + pull_request_target: + types: + - labeled +env: + TARGET_REPO: github/cli +jobs: + issue: + runs-on: ubuntu-latest + if: github.event_name == 'issues' && github.event.action == 'labeled' && github.event.label.name == 'discuss' + steps: + - name: Create issue based on source issue + env: + BODY: ${{ github.event.issue.body }} + CREATED: ${{ github.event.issue.created_at }} + GH_TOKEN: ${{ secrets.CLI_DISCUSSION_TRIAGE_TOKEN }} + LINK: ${{ github.repository }}#${{ github.event.issue.number }} + TITLE: ${{ github.event.issue.title }} + TRIGGERED_BY: ${{ github.triggering_actor }} + run: | + # Markdown quote source body by replacing newlines for newlines and markdown quoting + BODY="${BODY//$'\n'/$'\n'> }" + + # Create issue using dynamically constructed body within heredoc + cat << EOF | gh issue create --title "Triage issue \"$TITLE\"" --body-file - --repo "$TARGET_REPO" --label triage + **Title:** $TITLE + **Issue:** $LINK + **Created:** $CREATED + **Triggered by:** @$TRIGGERED_BY + + --- + + > $BODY + EOF + + pull_request: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request_target' && github.event.action == 'labeled' && github.event.label.name == 'discuss' + steps: + - name: Create issue based on source pull request + env: + BODY: ${{ github.event.pull_request.body }} + CREATED: ${{ github.event.pull_request.created_at }} + GH_TOKEN: ${{ secrets.CLI_DISCUSSION_TRIAGE_TOKEN }} + LINK: ${{ github.repository }}#${{ github.event.pull_request.number }} + TITLE: ${{ github.event.pull_request.title }} + TRIGGERED_BY: ${{ github.triggering_actor }} + run: | + # Markdown quote source body by replacing newlines for newlines and markdown quoting + BODY="${BODY//$'\n'/$'\n'> }" + + # Create issue using dynamically constructed body within heredoc + cat << EOF | gh issue create --title "Triage PR \"$TITLE\"" --body-file - --repo "$TARGET_REPO" --label triage + **Title:** $TITLE + **Pull request:** $LINK + **Created:** $CREATED + **Triggered by:** @$TRIGGERED_BY + + --- + + > $BODY + EOF diff --git a/git/client.go b/git/client.go index d90990cc7..3ac6a4754 100644 --- a/git/client.go +++ b/git/client.go @@ -472,6 +472,39 @@ func (c *Client) SetRemoteBranches(ctx context.Context, remote string, refspec s return nil } +func (c *Client) AddRemote(ctx context.Context, name, urlStr string, trackingBranches []string) (*Remote, error) { + args := []string{"remote", "add"} + for _, branch := range trackingBranches { + args = append(args, "-t", branch) + } + args = append(args, name, urlStr) + cmd, err := c.Command(ctx, args...) + if err != nil { + return nil, err + } + if _, err := cmd.Output(); err != nil { + return nil, err + } + var urlParsed *url.URL + if strings.HasPrefix(urlStr, "https") { + urlParsed, err = url.Parse(urlStr) + if err != nil { + return nil, err + } + } else { + urlParsed, err = ParseURL(urlStr) + if err != nil { + return nil, err + } + } + remote := &Remote{ + Name: name, + FetchURL: urlParsed, + PushURL: urlParsed, + } + return remote, nil +} + // Below are commands that make network calls and need authentication credentials supplied from gh. func (c *Client) Fetch(ctx context.Context, remote string, refspec string, mods ...CommandModifier) error { @@ -541,42 +574,6 @@ func (c *Client) Clone(ctx context.Context, cloneURL string, args []string, mods return target, nil } -func (c *Client) AddRemote(ctx context.Context, name, urlStr string, trackingBranches []string, mods ...CommandModifier) (*Remote, error) { - args := []string{"remote", "add"} - for _, branch := range trackingBranches { - args = append(args, "-t", branch) - } - args = append(args, name, urlStr) - cmd, err := c.Command(ctx, args...) - if err != nil { - return nil, err - } - for _, mod := range mods { - mod(cmd) - } - if _, err := cmd.Output(); err != nil { - return nil, err - } - var urlParsed *url.URL - if strings.HasPrefix(urlStr, "https") { - urlParsed, err = url.Parse(urlStr) - if err != nil { - return nil, err - } - } else { - urlParsed, err = ParseURL(urlStr) - if err != nil { - return nil, err - } - } - remote := &Remote{ - Name: name, - FetchURL: urlParsed, - PushURL: urlParsed, - } - return remote, nil -} - func resolveGitPath() (string, error) { path, err := safeexec.LookPath("git") if err != nil { diff --git a/pkg/cmd/actions/actions.go b/pkg/cmd/actions/actions.go index f8087aa6d..663866844 100644 --- a/pkg/cmd/actions/actions.go +++ b/pkg/cmd/actions/actions.go @@ -26,36 +26,36 @@ func actionsExplainer(cs *iostreams.ColorScheme) string { header := cs.Bold("Welcome to GitHub Actions on the command line.") runHeader := cs.Bold("Interacting with workflow runs") workflowHeader := cs.Bold("Interacting with workflow files") - cacheHeader := cs.Bold("Interacting with the Actions cache") + cacheHeader := cs.Bold("Interacting with the GitHub Actions cache") return heredoc.Docf(` - %s + %[2]s - GitHub CLI integrates with Actions to help you manage runs and workflows. + GitHub CLI integrates with GitHub Actions to help you manage runs and workflows. - %s + %[3]s gh run list: List recent workflow runs gh run view: View details for a workflow run or one of its jobs gh run watch: Watch a workflow run while it executes gh run rerun: Rerun a failed workflow run gh run download: Download artifacts generated by runs - To see more help, run 'gh help run ' + To see more help, run %[1]sgh help run %[1]s - %s + %[4]s gh workflow list: List workflow files in your repository gh workflow view: View details for a workflow file gh workflow enable: Enable a workflow file gh workflow disable: Disable a workflow file gh workflow run: Trigger a workflow_dispatch run for a workflow file - To see more help, run 'gh help workflow ' + To see more help, run %[1]sgh help workflow %[1]s - %s - gh cache list: List all the caches saved in Actions for a repository - gh cache delete: Delete one or all saved caches in Actions for a repository + %[5]s + gh cache list: List all the caches saved in GitHub Actions for a repository + gh cache delete: Delete one or all saved caches in GitHub Actions for a repository - To see more help, run 'gh help cache ' + To see more help, run %[1]sgh help cache %[1]s - `, header, runHeader, workflowHeader, cacheHeader) + `, "`", header, runHeader, workflowHeader, cacheHeader) } diff --git a/pkg/cmd/alias/alias.go b/pkg/cmd/alias/alias.go index 713e7d1db..d91b4dc2d 100644 --- a/pkg/cmd/alias/alias.go +++ b/pkg/cmd/alias/alias.go @@ -14,11 +14,11 @@ func NewCmdAlias(f *cmdutil.Factory) *cobra.Command { cmd := &cobra.Command{ Use: "alias ", Short: "Create command shortcuts", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Aliases can be used to make shortcuts for gh commands or to compose multiple commands. - Run "gh help alias set" to learn more. - `), + Run %[1]sgh help alias set%[1]s to learn more. + `, "`"), } cmdutil.DisableAuthCheck(cmd) diff --git a/pkg/cmd/alias/imports/import.go b/pkg/cmd/alias/imports/import.go index ef2176d45..c70a150f3 100644 --- a/pkg/cmd/alias/imports/import.go +++ b/pkg/cmd/alias/imports/import.go @@ -34,7 +34,7 @@ func NewCmdImport(f *cmdutil.Factory, runF func(*ImportOptions) error) *cobra.Co cmd := &cobra.Command{ Use: "import [ | -]", Short: "Import aliases from a YAML file", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Import aliases from the contents of a YAML file. Aliases should be defined as a map in YAML, where the keys represent aliases and @@ -47,12 +47,12 @@ func NewCmdImport(f *cmdutil.Factory, runF func(*ImportOptions) error) *cobra.Co issue list --label=enhancement - Use "-" to read aliases (in YAML format) from standard input. + Use %[1]s-%[1]s to read aliases (in YAML format) from standard input. - The output from the gh command "alias list" can be used to produce a YAML file + The output from %[1]sgh alias list%[1]s can be used to produce a YAML file containing your aliases, which you can use to import them from one machine to - another. Run "gh help alias list" to learn more. - `), + another. Run %[1]sgh help alias list%[1]s to learn more. + `, "`"), Example: heredoc.Doc(` # Import aliases from a file $ gh alias import aliases.yml diff --git a/pkg/cmd/alias/set/set.go b/pkg/cmd/alias/set/set.go index 77de9ca5d..e2661b7f7 100644 --- a/pkg/cmd/alias/set/set.go +++ b/pkg/cmd/alias/set/set.go @@ -35,21 +35,21 @@ func NewCmdSet(f *cmdutil.Factory, runF func(*SetOptions) error) *cobra.Command cmd := &cobra.Command{ Use: "set ", Short: "Create a shortcut for a gh command", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Define a word that will expand to a full gh command when invoked. The expansion may specify additional arguments and flags. If the expansion includes - positional placeholders such as "$1", extra arguments that follow the alias will be + positional placeholders such as %[1]s$1%[1]s, extra arguments that follow the alias will be inserted appropriately. Otherwise, extra arguments will be appended to the expanded command. - Use "-" as expansion argument to read the expansion string from standard input. This + Use %[1]s-%[1]s as expansion argument to read the expansion string from standard input. This is useful to avoid quoting issues when defining expansions. - If the expansion starts with "!" or if "--shell" was given, the expansion is a shell - expression that will be evaluated through the "sh" interpreter when the alias is + If the expansion starts with %[1]s!%[1]s or if %[1]s--shell%[1]s was given, the expansion is a shell + expression that will be evaluated through the %[1]ssh%[1]s interpreter when the alias is invoked. This allows for chaining multiple commands via piping and redirection. - `), + `, "`"), Example: heredoc.Doc(` # note: Command Prompt on Windows requires using double quotes for arguments $ gh alias set pv 'pr view' diff --git a/pkg/cmd/api/api.go b/pkg/cmd/api/api.go index 610f2f830..6e366dfa7 100644 --- a/pkg/cmd/api/api.go +++ b/pkg/cmd/api/api.go @@ -71,43 +71,43 @@ func NewCmdApi(f *cmdutil.Factory, runF func(*ApiOptions) error) *cobra.Command Makes an authenticated HTTP request to the GitHub API and prints the response. The endpoint argument should either be a path of a GitHub API v3 endpoint, or - "graphql" to access the GitHub API v4. + %[1]sgraphql%[1]s to access the GitHub API v4. - Placeholder values "{owner}", "{repo}", and "{branch}" in the endpoint + Placeholder values %[1]s{owner}%[1]s, %[1]s{repo}%[1]s, and %[1]s{branch}%[1]s in the endpoint argument will get replaced with values from the repository of the current - directory or the repository specified in the GH_REPO environment variable. + directory or the repository specified in the %[1]sGH_REPO%[1]s environment variable. Note that in some shells, for example PowerShell, you may need to enclose - any value that contains "{...}" in quotes to prevent the shell from + any value that contains %[1]s{...}%[1]s in quotes to prevent the shell from applying special meaning to curly braces. - The default HTTP request method is "GET" normally and "POST" if any parameters + The default HTTP request method is %[1]sGET%[1]s normally and %[1]sPOST%[1]s if any parameters were added. Override the method with %[1]s--method%[1]s. - Pass one or more %[1]s-f/--raw-field%[1]s values in "key=value" format to add static string + Pass one or more %[1]s-f/--raw-field%[1]s values in %[1]skey=value%[1]s format to add static string parameters to the request payload. To add non-string or placeholder-determined values, see - %[1]s--field%[1]s below. Note that adding request parameters will automatically switch the - request method to POST. To send the parameters as a GET query string instead, use + %[1]s-F/--field%[1]s below. Note that adding request parameters will automatically switch the + request method to %[1]sPOST%[1]s. To send the parameters as a %[1]sGET%[1]s query string instead, use %[1]s--method GET%[1]s. The %[1]s-F/--field%[1]s flag has magic type conversion based on the format of the value: - - literal values "true", "false", "null", and integer numbers get converted to + - literal values %[1]strue%[1]s, %[1]sfalse%[1]s, %[1]snull%[1]s, and integer numbers get converted to appropriate JSON types; - - placeholder values "{owner}", "{repo}", and "{branch}" get populated with values + - placeholder values %[1]s{owner}%[1]s, %[1]s{repo}%[1]s, and %[1]s{branch}%[1]s get populated with values from the repository of the current directory; - - if the value starts with "@", the rest of the value is interpreted as a - filename to read the value from. Pass "-" to read from standard input. + - if the value starts with %[1]s@%[1]s, the rest of the value is interpreted as a + filename to read the value from. Pass %[1]s-%[1]s to read from standard input. - For GraphQL requests, all fields other than "query" and "operationName" are + For GraphQL requests, all fields other than %[1]squery%[1]s and %[1]soperationName%[1]s are interpreted as GraphQL variables. - To pass nested parameters in the request payload, use "key[subkey]=value" syntax when + To pass nested parameters in the request payload, use %[1]skey[subkey]=value%[1]s syntax when declaring fields. To pass nested values as arrays, declare multiple fields with the - syntax "key[]=value1", "key[]=value2". To pass an empty array, use "key[]" without a + syntax %[1]skey[]=value1%[1]s, %[1]skey[]=value2%[1]s. To pass an empty array, use %[1]skey[]%[1]s without a value. To pass pre-constructed JSON or payloads in other formats, a request body may be read - from file specified by %[1]s--input%[1]s. Use "-" to read from standard input. When passing the + from file specified by %[1]s--input%[1]s. Use %[1]s-%[1]s to read from standard input. When passing the request body this way, any parameters specified via field flags are added to the query string of the endpoint URL. diff --git a/pkg/cmd/auth/login/login.go b/pkg/cmd/auth/login/login.go index d02c28df4..ae793ae85 100644 --- a/pkg/cmd/auth/login/login.go +++ b/pkg/cmd/auth/login/login.go @@ -63,13 +63,13 @@ func NewCmdLogin(f *cmdutil.Factory, runF func(*LoginOptions) error) *cobra.Comm See %[1]sgh auth status%[1]s for its stored location. Alternatively, use %[1]s--with-token%[1]s to pass in a token on standard input. - The minimum required scopes for the token are: "repo", "read:org". + The minimum required scopes for the token are: %[1]srepo%[1]s, %[1]sread:org%[1]s, and %[1]sgist%[1]s. Alternatively, gh will use the authentication token found in environment variables. This method is most suitable for "headless" use of gh such as in automation. See %[1]sgh help environment%[1]s for more info. - To use gh in GitHub Actions, add %[1]sGH_TOKEN: ${{ github.token }}%[1]s to "env". + To use gh in GitHub Actions, add %[1]sGH_TOKEN: ${{ github.token }}%[1]s to %[1]senv%[1]s. `, "`"), Example: heredoc.Doc(` # start interactive setup diff --git a/pkg/cmd/auth/logout/logout.go b/pkg/cmd/auth/logout/logout.go index c871a5333..b2afc9a6c 100644 --- a/pkg/cmd/auth/logout/logout.go +++ b/pkg/cmd/auth/logout/logout.go @@ -33,11 +33,11 @@ func NewCmdLogout(f *cmdutil.Factory, runF func(*LogoutOptions) error) *cobra.Co Use: "logout", Args: cobra.ExactArgs(0), Short: "Log out of a GitHub host", - Long: heredoc.Doc(`Remove authentication for a GitHub host. + Long: heredoc.Docf(`Remove authentication for a GitHub host. This command removes the authentication configuration for a host either specified - interactively or via --hostname. - `), + interactively or via %[1]s--hostname%[1]s. + `, "`"), Example: heredoc.Doc(` $ gh auth logout # => select what host to log out of via a prompt diff --git a/pkg/cmd/auth/refresh/refresh.go b/pkg/cmd/auth/refresh/refresh.go index 870871284..2335a9952 100644 --- a/pkg/cmd/auth/refresh/refresh.go +++ b/pkg/cmd/auth/refresh/refresh.go @@ -60,19 +60,19 @@ func NewCmdRefresh(f *cmdutil.Factory, runF func(*RefreshOptions) error) *cobra. Use: "refresh", Args: cobra.ExactArgs(0), Short: "Refresh stored authentication credentials", - Long: heredoc.Doc(`Expand or fix the permission scopes for stored credentials. + Long: heredoc.Docf(`Expand or fix the permission scopes for stored credentials. - The --scopes flag accepts a comma separated list of scopes you want + The %[1]s--scopes%[1]s flag accepts a comma separated list of scopes you want your gh credentials to have. If no scopes are provided, the command maintains previously added scopes. - The --remove-scopes flag accepts a comma separated list of scopes you + The %[1]s--remove-scopes%[1]s flag accepts a comma separated list of scopes you want to remove from your gh credentials. Scope removal is idempotent. - The minimum set of scopes ("repo", "read:org" and "gist") cannot be removed. + The minimum set of scopes (%[1]srepo%[1]s, %[1]sread:org%[1]s, and %[1]sgist%[1]s) cannot be removed. - The --reset-scopes flag resets the scopes for your gh credentials to + The %[1]s--reset-scopes%[1]s flag resets the scopes for your gh credentials to the default set of scopes for your auth flow. - `), + `, "`"), Example: heredoc.Doc(` $ gh auth refresh --scopes write:org,read:public_key # => open a browser to add write:org and read:public_key scopes diff --git a/pkg/cmd/auth/setupgit/setupgit.go b/pkg/cmd/auth/setupgit/setupgit.go index a3c991f4f..8ba35a78c 100644 --- a/pkg/cmd/auth/setupgit/setupgit.go +++ b/pkg/cmd/auth/setupgit/setupgit.go @@ -33,7 +33,7 @@ func NewCmdSetupGit(f *cmdutil.Factory, runF func(*SetupGitOptions) error) *cobr Use: "setup-git", Short: "Setup git with GitHub CLI", Long: heredoc.Docf(` - This command configures git to use GitHub CLI as a credential helper. + This command configures %[1]sgit%[1]s to use GitHub CLI as a credential helper. For more information on git credential helpers please reference: https://git-scm.com/docs/gitcredentials. diff --git a/pkg/cmd/codespace/ssh.go b/pkg/cmd/codespace/ssh.go index 384b92bb8..8302e24d8 100644 --- a/pkg/cmd/codespace/ssh.go +++ b/pkg/cmd/codespace/ssh.go @@ -53,39 +53,39 @@ func newSSHCmd(app *App) *cobra.Command { sshCmd := &cobra.Command{ Use: "ssh [...] [-- ...] []", Short: "SSH into a codespace", - Long: heredoc.Doc(` - The 'ssh' command is used to SSH into a codespace. In its simplest form, you can - run 'gh cs ssh', select a codespace interactively, and connect. + Long: heredoc.Docf(` + The %[1]sssh%[1]s command is used to SSH into a codespace. In its simplest form, you can + run %[1]sgh cs ssh%[1]s, select a codespace interactively, and connect. - The 'ssh' command will automatically create a public/private ssh key pair in the - ~/.ssh directory if you do not have an existing valid key pair. When selecting the + The %[1]sssh%[1]s command will automatically create a public/private ssh key pair in the + %[1]s~/.ssh%[1]s directory if you do not have an existing valid key pair. When selecting the key pair to use, the preferred order is: - 1. Key specified by -i in + 1. Key specified by %[1]s-i%[1]s in %[1]s%[1]s 2. Automatic key, if it already exists - 3. First valid key pair in ssh config (according to ssh -G) + 3. First valid key pair in ssh config (according to %[1]sssh -G%[1]s) 4. Automatic key, newly created - The 'ssh' command also supports deeper integration with OpenSSH using a '--config' + The %[1]sssh%[1]s command also supports deeper integration with OpenSSH using a %[1]s--config%[1]s option that generates per-codespace ssh configuration in OpenSSH format. - Including this configuration in your ~/.ssh/config improves the user experience - of tools that integrate with OpenSSH, such as bash/zsh completion of ssh hostnames, - remote path completion for scp/rsync/sshfs, git ssh remotes, and so on. + Including this configuration in your %[1]s~/.ssh/config%[1]s improves the user experience + of tools that integrate with OpenSSH, such as Bash/Zsh completion of ssh hostnames, + remote path completion for %[1]sscp/rsync/sshfs%[1]s, %[1]sgit%[1]s ssh remotes, and so on. Once that is set up (see the second example below), you can ssh to codespaces as - if they were ordinary remote hosts (using 'ssh', not 'gh cs ssh'). + if they were ordinary remote hosts (using %[1]sssh%[1]s, not %[1]sgh cs ssh%[1]s). Note that the codespace you are connecting to must have an SSH server pre-installed. If the docker image being used for the codespace does not have an SSH server, - install it in your Dockerfile or, for codespaces that use Debian-based images, - you can add the following to your devcontainer.json: + install it in your %[1]sDockerfile%[1]s or, for codespaces that use Debian-based images, + you can add the following to your %[1]sdevcontainer.json%[1]s: - "features": { - "ghcr.io/devcontainers/features/sshd:1": { - "version": "latest" + "features": { + "ghcr.io/devcontainers/features/sshd:1": { + "version": "latest" + } } - } - `), + `, "`"), Example: heredoc.Doc(` $ gh codespace ssh @@ -693,7 +693,7 @@ func newCpCmd(app *App) *cobra.Command { Use: "cp [-e] [-r] [-- [...]] ... ", Short: "Copy files between local and remote file systems", Long: heredoc.Docf(` - The cp command copies files between the local and remote file systems. + The %[1]scp%[1]s command copies files between the local and remote file systems. As with the UNIX %[1]scp%[1]s command, the first argument specifies the source and the last specifies the destination; additional sources may be specified after the first, @@ -701,7 +701,7 @@ func newCpCmd(app *App) *cobra.Command { The %[1]s--recursive%[1]s flag is required if any source is a directory. - A "remote:" prefix on any file name argument indicates that it refers to + A %[1]sremote:%[1]s prefix on any file name argument indicates that it refers to the file system of the remote (Codespace) machine. It is resolved relative to the home directory of the remote user. @@ -711,8 +711,8 @@ func newCpCmd(app *App) *cobra.Command { environment variables, and backticks. For security, do not use this flag with arguments provided by untrusted users; see for discussion. - By default, the 'cp' command will create a public/private ssh key pair to authenticate with - the codespace inside the ~/.ssh directory. + By default, the %[1]scp%[1]s command will create a public/private ssh key pair to authenticate with + the codespace inside the %[1]s~/.ssh directory%[1]s. `, "`"), Example: heredoc.Doc(` $ gh codespace cp -e README.md 'remote:/workspaces/$RepositoryName/' diff --git a/pkg/cmd/extension/command.go b/pkg/cmd/extension/command.go index c2ed18985..ae0cc7703 100644 --- a/pkg/cmd/extension/command.go +++ b/pkg/cmd/extension/command.go @@ -38,14 +38,14 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command { Long: heredoc.Docf(` GitHub CLI extensions are repositories that provide additional gh commands. - The name of the extension repository must start with "gh-" and it must contain an + The name of the extension repository must start with %[1]sgh-%[1]s and it must contain an executable of the same name. All arguments passed to the %[1]sgh %[1]s invocation will be forwarded to the %[1]sgh-%[1]s executable of the extension. An extension cannot override any of the core gh commands. If an extension name conflicts - with a core gh command you can use %[1]sgh extension exec %[1]s. + with a core gh command, you can use %[1]sgh extension exec %[1]s. - See the list of available extensions at . + For the list of available extensions, see . `, "`"), Aliases: []string{"extensions", "ext"}, } @@ -93,36 +93,36 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command { cmd := &cobra.Command{ Use: "search []", Short: "Search extensions to the GitHub CLI", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Search for gh extensions. With no arguments, this command prints out the first 30 extensions available to install sorted by number of stars. More extensions can - be fetched by specifying a higher limit with the --limit flag. + be fetched by specifying a higher limit with the %[1]s--limit%[1]s flag. When connected to a terminal, this command prints out three columns. The first has a ✓ if the extension is already installed locally. The - second is the full name of the extension repository in NAME/OWNER + second is the full name of the extension repository in %[1]sOWNER/REPO%[1]s format. The third is the extension's description. When not connected to a terminal, the ✓ character is rendered as the word "installed" but otherwise the order and content of the columns - is the same. + are the same. - This command behaves similarly to 'gh search repos' but does not + This command behaves similarly to %[1]sgh search repos%[1]s but does not support as many search qualifiers. For a finer grained search of extensions, try using: gh search repos --topic "gh-extension" - and adding qualifiers as needed. See 'gh help search repos' to learn + and adding qualifiers as needed. See %[1]sgh help search repos%[1]s to learn more about repository search. For listing just the extensions that are already installed locally, see: gh ext list - `), + `, "`"), Example: heredoc.Doc(` # List the first 30 extensions sorted by star count, descending $ gh ext search @@ -297,17 +297,17 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command { cmd := &cobra.Command{ Use: "install ", Short: "Install a gh extension from a repository", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Install a GitHub repository locally as a GitHub CLI extension. - The repository argument can be specified in "owner/repo" format as well as a full URL. + The repository argument can be specified in %[1]sOWNER/REPO%[1]s format as well as a full URL. The URL format is useful when the repository is not hosted on github.com. - To install an extension in development from the current directory, use "." as the + To install an extension in development from the current directory, use %[1]s.%[1]s as the value of the repository argument. - See the list of available extensions at . - `), + For the list of available extensions, see . + `, "`"), Example: heredoc.Doc(` $ gh extension install owner/gh-extension $ gh extension install https://git.example.com/owner/gh-extension @@ -347,7 +347,11 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command { return err } - if err := m.Install(repo, pinFlag); err != nil { + io.StartProgressIndicator() + err = m.Install(repo, pinFlag) + io.StopProgressIndicator() + + if err != nil { if errors.Is(err, releaseNotFoundErr) { return fmt.Errorf("%s Could not find a release of %s for %s", cs.FailureIcon(), args[0], cs.Cyan(pinFlag)) @@ -431,17 +435,17 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command { cmd := &cobra.Command{ Use: "browse", Short: "Enter a UI for browsing, adding, and removing extensions", - Long: heredoc.Doc(` + Long: heredoc.Docf(` This command will take over your terminal and run a fully interactive interface for browsing, adding, and removing gh extensions. A terminal width greater than 100 columns is recommended. - To learn how to control this interface, press ? after running to see + To learn how to control this interface, press %[1]s?%[1]s after running to see the help text. - Press q to quit. + Press %[1]sq%[1]s to quit. - Running this command with --single-column should make this command + Running this command with %[1]s--single-column%[1]s should make this command more intelligible for users who rely on assistive technology like screen readers or high zoom. @@ -449,8 +453,8 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command { gh ext search - along with gh ext install, gh ext remove, and gh repo view. - `), + along with %[1]sgh ext install%[1]s, %[1]sgh ext remove%[1]s, and %[1]sgh repo view%[1]s. + `, "`"), Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { if !io.CanPrompt() { @@ -492,14 +496,14 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command { &cobra.Command{ Use: "exec [args]", Short: "Execute an installed extension", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Execute an extension using the short name. For example, if the extension repository is - "owner/gh-extension", you should pass "extension". You can use this command when + %[1]sowner/gh-extension%[1]s, you should pass %[1]sextension%[1]s. You can use this command when the short name conflicts with a core gh command. All arguments after the extension name will be forwarded to the executable of the extension. - `), + `, "`"), Example: heredoc.Doc(` # execute a label extension instead of the core gh label command $ gh extension exec label diff --git a/pkg/cmd/gist/clone/clone.go b/pkg/cmd/gist/clone/clone.go index d83560f40..f33ee13c6 100644 --- a/pkg/cmd/gist/clone/clone.go +++ b/pkg/cmd/gist/clone/clone.go @@ -40,15 +40,15 @@ func NewCmdClone(f *cmdutil.Factory, runF func(*CloneOptions) error) *cobra.Comm Use: "clone [] [-- ...]", Args: cmdutil.MinimumArgs(1, "cannot clone: gist argument required"), Short: "Clone a gist locally", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Clone a GitHub gist locally. A gist can be supplied as argument in either of the following formats: - - by ID, e.g. 5b0e0062eb8e9654adad7bb1d81cc75f - - by URL, e.g. "https://gist.github.com/OWNER/5b0e0062eb8e9654adad7bb1d81cc75f" + - by ID, e.g. %[1]s5b0e0062eb8e9654adad7bb1d81cc75f%[1]s + - by URL, e.g. %[1]shttps://gist.github.com/OWNER/5b0e0062eb8e9654adad7bb1d81cc75f%[1]s - Pass additional 'git clone' flags by listing them after '--'. - `), + Pass additional %[1]sgit clone%[1]s flags by listing them after %[1]s--%[1]s. + `, "`"), RunE: func(cmd *cobra.Command, args []string) error { opts.Gist = args[0] opts.GitArgs = args[1:] diff --git a/pkg/cmd/gist/create/create.go b/pkg/cmd/gist/create/create.go index 4154acf9c..5dec11cb7 100644 --- a/pkg/cmd/gist/create/create.go +++ b/pkg/cmd/gist/create/create.go @@ -50,14 +50,14 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co cmd := &cobra.Command{ Use: "create [... | -]", Short: "Create a new gist", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Create a new GitHub gist with given contents. - Gists can be created from one or multiple files. Alternatively, pass "-" as + Gists can be created from one or multiple files. Alternatively, pass %[1]s-%[1]s as file name to read from standard input. - By default, gists are secret; use '--public' to make publicly listed ones. - `), + By default, gists are secret; use %[1]s--public%[1]s to make publicly listed ones. + `, "`"), Example: heredoc.Doc(` # publish file 'hello.py' as a public gist $ gh gist create --public hello.py diff --git a/pkg/cmd/issue/create/create.go b/pkg/cmd/issue/create/create.go index 577f08728..9aa0fffa8 100644 --- a/pkg/cmd/issue/create/create.go +++ b/pkg/cmd/issue/create/create.go @@ -56,12 +56,12 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co cmd := &cobra.Command{ Use: "create", Short: "Create a new issue", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Create an issue on GitHub. - Adding an issue to projects requires authorization with the "project" scope. - To authorize, run "gh auth refresh -s project". - `), + Adding an issue to projects requires authorization with the %[1]sproject%[1]s scope. + To authorize, run %[1]sgh auth refresh -s project%[1]s. + `, "`"), Example: heredoc.Doc(` $ gh issue create --title "I found a bug" --body "Nothing works" $ gh issue create --label "bug,help wanted" diff --git a/pkg/cmd/issue/edit/edit.go b/pkg/cmd/issue/edit/edit.go index 53400fb63..1b775f88b 100644 --- a/pkg/cmd/issue/edit/edit.go +++ b/pkg/cmd/issue/edit/edit.go @@ -50,12 +50,12 @@ func NewCmdEdit(f *cmdutil.Factory, runF func(*EditOptions) error) *cobra.Comman cmd := &cobra.Command{ Use: "edit { | }", Short: "Edit issues", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Edit one or more issues within the same repository. - Editing issues' projects requires authorization with the "project" scope. - To authorize, run "gh auth refresh -s project". - `), + Editing issues' projects requires authorization with the %[1]sproject%[1]s scope. + To authorize, run %[1]sgh auth refresh -s project%[1]s. + `, "`"), Example: heredoc.Doc(` $ gh issue edit 23 --title "I found a bug" --body "Nothing works" $ gh issue edit 23 --add-label "bug,help wanted" --remove-label "core" diff --git a/pkg/cmd/issue/view/view.go b/pkg/cmd/issue/view/view.go index 83132291f..7a63f31e3 100644 --- a/pkg/cmd/issue/view/view.go +++ b/pkg/cmd/issue/view/view.go @@ -48,11 +48,11 @@ func NewCmdView(f *cmdutil.Factory, runF func(*ViewOptions) error) *cobra.Comman cmd := &cobra.Command{ Use: "view { | }", Short: "View an issue", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Display the title, body, and other information about an issue. - With '--web', open the issue in a web browser instead. - `), + With %[1]s--web%[1]s flag, open the issue in a web browser instead. + `, "`"), Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { // support `-R, --repo` override diff --git a/pkg/cmd/label/clone.go b/pkg/cmd/label/clone.go index 302de145a..81ab76958 100644 --- a/pkg/cmd/label/clone.go +++ b/pkg/cmd/label/clone.go @@ -34,7 +34,7 @@ func newCmdClone(f *cmdutil.Factory, runF func(*cloneOptions) error) *cobra.Comm cmd := &cobra.Command{ Use: "clone ", Short: "Clones labels from one repository to another", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Clones labels from a source repository to a destination repository on GitHub. By default, the destination repository is the current repository. @@ -44,8 +44,8 @@ func newCmdClone(f *cmdutil.Factory, runF func(*cloneOptions) error) *cobra.Comm Labels from the source repository that already exist in the destination repository will be skipped. You can overwrite existing labels in the - destination repository using the --force flag. - `), + destination repository using the %[1]s--force%[1]s flag. + `, "`"), Example: heredoc.Doc(` # clone and overwrite labels from cli/cli repository into the current repository $ gh label clone cli/cli --force diff --git a/pkg/cmd/label/create.go b/pkg/cmd/label/create.go index 0a88fbcab..414e9eb5e 100644 --- a/pkg/cmd/label/create.go +++ b/pkg/cmd/label/create.go @@ -57,14 +57,14 @@ func newCmdCreate(f *cmdutil.Factory, runF func(*createOptions) error) *cobra.Co cmd := &cobra.Command{ Use: "create ", Short: "Create a new label", - Long: heredoc.Doc(` - Create a new label on GitHub, or updates an existing one with --force. + Long: heredoc.Docf(` + Create a new label on GitHub, or update an existing one with %[1]s--force%[1]s. Must specify name for the label. The description and color are optional. If a color isn't provided, a random one will be chosen. The label color needs to be 6 character hex value. - `), + `, "`"), Example: heredoc.Doc(` # create new bug label $ gh label create bug --description "Something isn't working" --color E99695 diff --git a/pkg/cmd/pr/create/create.go b/pkg/cmd/pr/create/create.go index 890171860..21cb41964 100644 --- a/pkg/cmd/pr/create/create.go +++ b/pkg/cmd/pr/create/create.go @@ -118,8 +118,8 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co By default, users with write access to the base repository can push new commits to the head branch of the pull request. Disable this with %[1]s--no-maintainer-edit%[1]s. - Adding a pull request to projects requires authorization with the "project" scope. - To authorize, run "gh auth refresh -s project". + Adding a pull request to projects requires authorization with the %[1]sproject%[1]s scope. + To authorize, run %[1]sgh auth refresh -s project%[1]s. `, "`"), Example: heredoc.Doc(` $ gh pr create --title "The bug is fixed" --body "Everything works again" diff --git a/pkg/cmd/pr/diff/diff.go b/pkg/cmd/pr/diff/diff.go index ff09c6388..c837a530a 100644 --- a/pkg/cmd/pr/diff/diff.go +++ b/pkg/cmd/pr/diff/diff.go @@ -50,14 +50,14 @@ func NewCmdDiff(f *cmdutil.Factory, runF func(*DiffOptions) error) *cobra.Comman cmd := &cobra.Command{ Use: "diff [ | | ]", Short: "View changes in a pull request", - Long: heredoc.Doc(` + Long: heredoc.Docf(` View changes in a pull request. Without an argument, the pull request that belongs to the current branch is selected. - With '--web', open the pull request diff in a web browser instead. - `), + With %[1]s--web%[1]s flag, open the pull request diff in a web browser instead. + `, "`"), Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { opts.Finder = shared.NewFinder(f) diff --git a/pkg/cmd/pr/edit/edit.go b/pkg/cmd/pr/edit/edit.go index c606ae6bb..d0dbcfbc2 100644 --- a/pkg/cmd/pr/edit/edit.go +++ b/pkg/cmd/pr/edit/edit.go @@ -47,15 +47,15 @@ func NewCmdEdit(f *cmdutil.Factory, runF func(*EditOptions) error) *cobra.Comman cmd := &cobra.Command{ Use: "edit [ | | ]", Short: "Edit a pull request", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Edit a pull request. Without an argument, the pull request that belongs to the current branch is selected. - Editing a pull request's projects requires authorization with the "project" scope. - To authorize, run "gh auth refresh -s project". - `), + Editing a pull request's projects requires authorization with the %[1]sproject%[1]s scope. + To authorize, run %[1]sgh auth refresh -s project%[1]s. + `, "`"), Example: heredoc.Doc(` $ gh pr edit 23 --title "I found a bug" --body "Nothing works" $ gh pr edit 23 --add-label "bug,help wanted" --remove-label "core" diff --git a/pkg/cmd/pr/merge/merge.go b/pkg/cmd/pr/merge/merge.go index a23dc7390..4a3db447d 100644 --- a/pkg/cmd/pr/merge/merge.go +++ b/pkg/cmd/pr/merge/merge.go @@ -78,17 +78,17 @@ func NewCmdMerge(f *cmdutil.Factory, runF func(*MergeOptions) error) *cobra.Comm cmd := &cobra.Command{ Use: "merge [ | | ]", Short: "Merge a pull request", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Merge a pull request on GitHub. Without an argument, the pull request that belongs to the current branch is selected. When targeting a branch that requires a merge queue, no merge strategy is required. - If required checks have not yet passed, AutoMerge will be enabled. + If required checks have not yet passed, auto-merge will be enabled. If required checks have passed, the pull request will be added to the merge queue. - To bypass a merge queue and merge directly, pass the '--admin' flag. - `), + To bypass a merge queue and merge directly, pass the %[1]s--admin%[1]s flag. + `, "`"), Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { opts.Finder = shared.NewFinder(f) @@ -302,6 +302,8 @@ func (m *mergeContext) merge() error { return cmdutil.FlagErrorf("--merge, --rebase, or --squash required when not running interactively") } + _ = m.infof("Merging pull request #%d (%s)\n", m.pr.Number, m.pr.Title) + apiClient := api.NewClientFromHTTP(m.httpClient) r, err := api.GitHubRepo(apiClient, m.baseRepo) if err != nil { diff --git a/pkg/cmd/pr/merge/merge_test.go b/pkg/cmd/pr/merge/merge_test.go index 5055bf8f4..0eb6a81fb 100644 --- a/pkg/cmd/pr/merge/merge_test.go +++ b/pkg/cmd/pr/merge/merge_test.go @@ -1275,7 +1275,7 @@ func TestPRMergeTTY(t *testing.T) { t.Fatalf("Got unexpected error running `pr merge` %s", err) } - assert.Equal(t, "✓ Merged pull request #3 (It was the best of times)\n", output.Stderr()) + assert.Equal(t, "Merging pull request #3 (It was the best of times)\n✓ Merged pull request #3 (It was the best of times)\n", output.Stderr()) } func TestPRMergeTTY_withDeleteBranch(t *testing.T) { @@ -1346,6 +1346,7 @@ func TestPRMergeTTY_withDeleteBranch(t *testing.T) { assert.Equal(t, "", output.String()) assert.Equal(t, heredoc.Doc(` + Merging pull request #3 (It was the best of times) ✓ Merged pull request #3 (It was the best of times) ✓ Deleted local branch blueberries and switched to branch main ✓ Deleted remote branch blueberries @@ -1437,7 +1438,7 @@ func TestPRMergeTTY_squashEditCommitMsgAndSubject(t *testing.T) { assert.NoError(t, err) assert.Equal(t, "", stdout.String()) - assert.Equal(t, "✓ Squashed and merged pull request #123 (title)\n", stderr.String()) + assert.Equal(t, "Merging pull request #123 (title)\n✓ Squashed and merged pull request #123 (title)\n", stderr.String()) } func TestPRMergeEmptyStrategyNonTTY(t *testing.T) { @@ -1473,7 +1474,7 @@ func TestPRTTY_cancelled(t *testing.T) { shared.RunCommandFinder( "", - &api.PullRequest{ID: "THE-ID", Number: 123, MergeStateStatus: "CLEAN"}, + &api.PullRequest{ID: "THE-ID", Number: 123, Title: "title", MergeStateStatus: "CLEAN"}, ghrepo.New("OWNER", "REPO"), ) @@ -1516,7 +1517,7 @@ func TestPRTTY_cancelled(t *testing.T) { t.Fatalf("got error %v", err) } - assert.Equal(t, "Cancelled.\n", output.Stderr()) + assert.Equal(t, "Merging pull request #123 (title)\nCancelled.\n", output.Stderr()) } func Test_mergeMethodSurvey(t *testing.T) { @@ -1866,7 +1867,7 @@ func TestPrAddToMergeQueueAdmin(t *testing.T) { } assert.Equal(t, "", output.String()) - assert.Equal(t, "✓ Merged pull request #1 (The title of the PR)\n", output.Stderr()) + assert.Equal(t, "Merging pull request #1 (The title of the PR)\n✓ Merged pull request #1 (The title of the PR)\n", output.Stderr()) } func TestPrAddToMergeQueueAdminWithMergeStrategy(t *testing.T) { diff --git a/pkg/cmd/pr/ready/ready.go b/pkg/cmd/pr/ready/ready.go index ee0cfe2fd..0b98bb548 100644 --- a/pkg/cmd/pr/ready/ready.go +++ b/pkg/cmd/pr/ready/ready.go @@ -31,14 +31,14 @@ func NewCmdReady(f *cmdutil.Factory, runF func(*ReadyOptions) error) *cobra.Comm cmd := &cobra.Command{ Use: "ready [ | | ]", Short: "Mark a pull request as ready for review", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Mark a pull request as ready for review. Without an argument, the pull request that belongs to the current branch is marked as ready. - If supported by your plan, convert to draft with --undo - `), + If supported by your plan, convert to draft with %[1]s--undo%[1]s + `, "`"), Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { opts.Finder = shared.NewFinder(f) diff --git a/pkg/cmd/pr/view/view.go b/pkg/cmd/pr/view/view.go index 4a69de2f4..767e8836c 100644 --- a/pkg/cmd/pr/view/view.go +++ b/pkg/cmd/pr/view/view.go @@ -42,14 +42,14 @@ func NewCmdView(f *cmdutil.Factory, runF func(*ViewOptions) error) *cobra.Comman cmd := &cobra.Command{ Use: "view [ | | ]", Short: "View a pull request", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Display the title, body, and other information about a pull request. Without an argument, the pull request that belongs to the current branch is displayed. - With '--web', open the pull request in a web browser instead. - `), + With %[1]s--web%[1]s flag, open the pull request in a web browser instead. + `, "`"), Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { opts.Finder = shared.NewFinder(f) diff --git a/pkg/cmd/project/item-edit/item_edit.go b/pkg/cmd/project/item-edit/item_edit.go index c21548a4a..dcddac8f9 100644 --- a/pkg/cmd/project/item-edit/item_edit.go +++ b/pkg/cmd/project/item-edit/item_edit.go @@ -62,13 +62,13 @@ func NewCmdEditItem(f *cmdutil.Factory, runF func(config editItemConfig) error) editItemCmd := &cobra.Command{ Use: "item-edit", Short: "Edit an item in a project", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Edit either a draft issue or a project item. Both usages require the ID of the item to edit. For non-draft issues, the ID of the project is also required, and only a single field value can be updated per invocation. - Remove project item field value using "--clear" flag. - `), + Remove project item field value using %[1]s--clear%[1]s flag. + `, "`"), Example: heredoc.Doc(` # edit an item's text field value gh project item-edit --id --field-id --project-id --text "new text" diff --git a/pkg/cmd/release/create/create.go b/pkg/cmd/release/create/create.go index 6110d9c6a..8c8f58a61 100644 --- a/pkg/cmd/release/create/create.go +++ b/pkg/cmd/release/create/create.go @@ -94,11 +94,11 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co To create a release from an annotated git tag, first create one locally with git, push the tag to GitHub, then run this command. Use %[1]s--notes-from-tag%[1]s to automatically generate the release notes - from the annotated git tag. + from the annotated git tag. When using automatically generated release notes, a release title will also be automatically generated unless a title was explicitly passed. Additional release notes can be prepended to - automatically generated notes by using the notes parameter. + automatically generated notes by using the %[1]s--notes%[1]s flag. `, "`"), Example: heredoc.Doc(` Interactively create a release diff --git a/pkg/cmd/release/download/download.go b/pkg/cmd/release/download/download.go index 02519e146..56e6ac72a 100644 --- a/pkg/cmd/release/download/download.go +++ b/pkg/cmd/release/download/download.go @@ -46,13 +46,13 @@ func NewCmdDownload(f *cmdutil.Factory, runF func(*DownloadOptions) error) *cobr cmd := &cobra.Command{ Use: "download []", Short: "Download release assets", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Download assets from a GitHub release. Without an explicit tag name argument, assets are downloaded from the - latest release in the project. In this case, "--pattern" or "--archive" - is required. - `), + latest release in the project. In this case, %[1]s--pattern%[1]s or %[1]s--archive%[1]s + is required. + `, "`"), Example: heredoc.Doc(` # download all assets from a specific release $ gh release download v1.2.3 diff --git a/pkg/cmd/release/upload/upload.go b/pkg/cmd/release/upload/upload.go index 12cba4542..20d087a58 100644 --- a/pkg/cmd/release/upload/upload.go +++ b/pkg/cmd/release/upload/upload.go @@ -38,12 +38,12 @@ func NewCmdUpload(f *cmdutil.Factory, runF func(*UploadOptions) error) *cobra.Co cmd := &cobra.Command{ Use: "upload ...", Short: "Upload assets to a release", - Long: heredoc.Doc(` + Long: heredoc.Docf(` Upload asset files to a GitHub Release. - To define a display label for an asset, append text starting with '#' after the + To define a display label for an asset, append text starting with %[1]%#%[1]% after the file name. - `), + `, "`"), Args: cobra.MinimumNArgs(2), RunE: func(cmd *cobra.Command, args []string) error { // support `-R, --repo` override diff --git a/pkg/cmd/repo/clone/clone.go b/pkg/cmd/repo/clone/clone.go index b6def2edd..bac5727c8 100644 --- a/pkg/cmd/repo/clone/clone.go +++ b/pkg/cmd/repo/clone/clone.go @@ -44,14 +44,14 @@ func NewCmdClone(f *cmdutil.Factory, runF func(*CloneOptions) error) *cobra.Comm Short: "Clone a repository locally", Long: heredoc.Docf(` Clone a GitHub repository locally. Pass additional %[1]sgit clone%[1]s flags by listing - them after "--". + them after %[1]s--%[1]s. - If the "OWNER/" portion of the "OWNER/REPO" repository argument is omitted, it + If the %[1]sOWNER/%[1]s portion of the %[1]sOWNER/REPO%[1]s repository argument is omitted, it defaults to the name of the authenticating user. If the repository is a fork, its parent repository will be added as an additional - git remote called "upstream". The remote name can be configured using %[1]s--upstream-remote-name%[1]s. - The %[1]s--upstream-remote-name%[1]s option supports an "@owner" value which will name + git remote called %[1]supstream%[1]s. The remote name can be configured using %[1]s--upstream-remote-name%[1]s. + The %[1]s--upstream-remote-name%[1]s option supports an %[1]s@owner%[1]s value which will name the remote after the owner of the parent repository. If the repository is a fork, its parent repository will be set as the default remote repository. diff --git a/pkg/cmd/repo/edit/edit.go b/pkg/cmd/repo/edit/edit.go index 112aa5131..508dea06c 100644 --- a/pkg/cmd/repo/edit/edit.go +++ b/pkg/cmd/repo/edit/edit.go @@ -101,7 +101,7 @@ func NewCmdEdit(f *cmdutil.Factory, runF func(options *EditOptions) error) *cobr Long: heredoc.Docf(` Edit repository settings. - To toggle a setting off, use the %[1]s--flag=false%[1]s syntax. + To toggle a setting off, use the %[1]s--=false%[1]s syntax. Note that changing repository visibility to private will cause loss of stars and watchers. `, "`"), diff --git a/pkg/cmd/repo/fork/fork.go b/pkg/cmd/repo/fork/fork.go index 73fa906a6..fe59ab31f 100644 --- a/pkg/cmd/repo/fork/fork.go +++ b/pkg/cmd/repo/fork/fork.go @@ -88,13 +88,13 @@ func NewCmdFork(f *cmdutil.Factory, runF func(*ForkOptions) error) *cobra.Comman With no argument, creates a fork of the current repository. Otherwise, forks the specified repository. - By default, the new fork is set to be your "origin" remote and any existing - origin remote is renamed to "upstream". To alter this behavior, you can set + By default, the new fork is set to be your %[1]sorigin%[1]s remote and any existing + origin remote is renamed to %[1]supstream%[1]s. To alter this behavior, you can set a name for the new fork's remote with %[1]s--remote-name%[1]s. - The "upstream" remote will be set as the default remote repository. + The %[1]supstream%[1]s remote will be set as the default remote repository. - Additional git clone flags can be passed after %[1]s--%[1]s. + Additional %[1]sgit clone%[1]s flags can be passed after %[1]s--%[1]s. `, "`"), RunE: func(cmd *cobra.Command, args []string) error { promptOk := opts.IO.CanPrompt() diff --git a/pkg/cmd/repo/setdefault/setdefault.go b/pkg/cmd/repo/setdefault/setdefault.go index d5a03baf1..d54d3956a 100644 --- a/pkg/cmd/repo/setdefault/setdefault.go +++ b/pkg/cmd/repo/setdefault/setdefault.go @@ -29,7 +29,7 @@ func explainer() string { - viewing and creating pull requests - viewing and creating issues - viewing and creating releases - - working with Actions + - working with GitHub Actions - adding repository and environment secrets`) } diff --git a/pkg/cmd/repo/setdefault/setdefault_test.go b/pkg/cmd/repo/setdefault/setdefault_test.go index 58871f75b..a89effa14 100644 --- a/pkg/cmd/repo/setdefault/setdefault_test.go +++ b/pkg/cmd/repo/setdefault/setdefault_test.go @@ -379,7 +379,7 @@ func TestDefaultRun(t *testing.T) { } } }, - wantStdout: "This command sets the default remote repository to use when querying the\nGitHub API for the locally cloned repository.\n\ngh uses the default repository for things like:\n\n - viewing and creating pull requests\n - viewing and creating issues\n - viewing and creating releases\n - working with Actions\n - adding repository and environment secrets\n\n✓ Set OWNER2/REPO2 as the default repository for the current directory\n", + wantStdout: "This command sets the default remote repository to use when querying the\nGitHub API for the locally cloned repository.\n\ngh uses the default repository for things like:\n\n - viewing and creating pull requests\n - viewing and creating issues\n - viewing and creating releases\n - working with GitHub Actions\n - adding repository and environment secrets\n\n✓ Set OWNER2/REPO2 as the default repository for the current directory\n", }, { name: "interactive mode only one known host", @@ -453,7 +453,7 @@ func TestDefaultRun(t *testing.T) { } } }, - wantStdout: "This command sets the default remote repository to use when querying the\nGitHub API for the locally cloned repository.\n\ngh uses the default repository for things like:\n\n - viewing and creating pull requests\n - viewing and creating issues\n - viewing and creating releases\n - working with Actions\n - adding repository and environment secrets\n\n✓ Set OWNER2/REPO2 as the default repository for the current directory\n", + wantStdout: "This command sets the default remote repository to use when querying the\nGitHub API for the locally cloned repository.\n\ngh uses the default repository for things like:\n\n - viewing and creating pull requests\n - viewing and creating issues\n - viewing and creating releases\n - working with GitHub Actions\n - adding repository and environment secrets\n\n✓ Set OWNER2/REPO2 as the default repository for the current directory\n", }, } diff --git a/pkg/cmd/repo/sync/sync.go b/pkg/cmd/repo/sync/sync.go index 3c0201e43..94be50bbf 100644 --- a/pkg/cmd/repo/sync/sync.go +++ b/pkg/cmd/repo/sync/sync.go @@ -46,7 +46,7 @@ func NewCmdSync(f *cmdutil.Factory, runF func(*SyncOptions) error) *cobra.Comman Use: "sync []", Short: "Sync a repository", Long: heredoc.Docf(` - Sync destination repository from source repository. Syncing uses the main branch + Sync destination repository from source repository. Syncing uses the default branch of the source repository to update the matching branch on the destination repository so they are equal. A fast forward update will be used except when the %[1]s--force%[1]s flag is specified, then the two branches will @@ -83,7 +83,7 @@ func NewCmdSync(f *cmdutil.Factory, runF func(*SyncOptions) error) *cobra.Comman } cmd.Flags().StringVarP(&opts.SrcArg, "source", "s", "", "Source repository") - cmd.Flags().StringVarP(&opts.Branch, "branch", "b", "", "Branch to sync (default: main branch)") + cmd.Flags().StringVarP(&opts.Branch, "branch", "b", "", "Branch to sync (default: default branch)") cmd.Flags().BoolVarP(&opts.Force, "force", "", false, "Hard reset the branch of the destination repository to match the source repository") return cmd } diff --git a/pkg/cmd/root/help.go b/pkg/cmd/root/help.go index 860fb22c3..4eef641fd 100644 --- a/pkg/cmd/root/help.go +++ b/pkg/cmd/root/help.go @@ -171,9 +171,10 @@ func rootHelpFunc(f *cmdutil.Factory, command *cobra.Command, args []string) { if _, ok := command.Annotations["help:environment"]; ok { helpEntries = append(helpEntries, helpEntry{"ENVIRONMENT VARIABLES", command.Annotations["help:environment"]}) } - helpEntries = append(helpEntries, helpEntry{"LEARN MORE", ` -Use 'gh --help' for more information about a command. -Read the manual at https://cli.github.com/manual`}) + helpEntries = append(helpEntries, helpEntry{"LEARN MORE", heredoc.Docf(` + Use %[1]sgh --help%[1]s for more information about a command. + Read the manual at https://cli.github.com/manual + `, "`")}) out := f.IOStreams.Out for _, e := range helpEntries { diff --git a/pkg/cmd/root/help_topic.go b/pkg/cmd/root/help_topic.go index 7db694668..6c0ff8a00 100644 --- a/pkg/cmd/root/help_topic.go +++ b/pkg/cmd/root/help_topic.go @@ -21,7 +21,7 @@ var HelpTopics = []helpTopic{ { name: "mintty", short: "Information about using gh with MinTTY", - long: heredoc.Doc(` + long: heredoc.Docf(` MinTTY is the terminal emulator that comes by default with Git for Windows. It has known issues with gh's ability to prompt a user for input. @@ -31,75 +31,75 @@ var HelpTopics = []helpTopic{ - Reinstall Git for Windows, checking "Enable experimental support for pseudo consoles". - Use a different terminal emulator with Git for Windows like Windows Terminal. - You can run "C:\Program Files\Git\bin\bash.exe" from any terminal emulator to continue + You can run %[1]sC:\Program Files\Git\bin\bash.exe%[1]s from any terminal emulator to continue using all of the tooling in Git For Windows without MinTTY. - - Prefix invocations of gh with winpty, eg: "winpty gh auth login". + - Prefix invocations of gh with %[1]swinpty%[1]s, eg: %[1]swinpty gh auth login%[1]s. NOTE: this can lead to some UI bugs. - `), + `, "`"), }, { name: "environment", short: "Environment variables that can be used with gh", - long: heredoc.Doc(` - GH_TOKEN, GITHUB_TOKEN (in order of precedence): an authentication token for github.com + long: heredoc.Docf(` + %[1]sGH_TOKEN%[1]s, %[1]sGITHUB_TOKEN%[1]s (in order of precedence): an authentication token for github.com API requests. Setting this avoids being prompted to authenticate and takes precedence over previously stored credentials. - GH_ENTERPRISE_TOKEN, GITHUB_ENTERPRISE_TOKEN (in order of precedence): an authentication - token for API requests to GitHub Enterprise. When setting this, also set GH_HOST. + %[1]sGH_ENTERPRISE_TOKEN%[1]s, %[1]sGITHUB_ENTERPRISE_TOKEN%[1]s (in order of precedence): an authentication + token for API requests to GitHub Enterprise. When setting this, also set %[1]sGH_HOST%[1]s. - GH_HOST: specify the GitHub hostname for commands that would otherwise assume the + %[1]sGH_HOST%[1]s: specify the GitHub hostname for commands that would otherwise assume the "github.com" host when not in a context of an existing repository. When setting this, - also set GH_ENTERPRISE_TOKEN. + also set %[1]sGH_ENTERPRISE_TOKEN%[1]s. - GH_REPO: specify the GitHub repository in the "[HOST/]OWNER/REPO" format for commands + %[1]sGH_REPO%[1]s: specify the GitHub repository in the %[1]s[HOST/]OWNER/REPO%[1]s format for commands that otherwise operate on a local repository. - GH_EDITOR, GIT_EDITOR, VISUAL, EDITOR (in order of precedence): the editor tool to use + %[1]sGH_EDITOR%[1]s, %[1]sGIT_EDITOR%[1]s, %[1]sVISUAL%[1]s, %[1]sEDITOR%[1]s (in order of precedence): the editor tool to use for authoring text. - GH_BROWSER, BROWSER (in order of precedence): the web browser to use for opening links. + %[1]sGH_BROWSER%[1]s, %[1]sBROWSER%[1]s (in order of precedence): the web browser to use for opening links. - GH_DEBUG: set to a truthy value to enable verbose output on standard error. Set to "api" + %[1]sGH_DEBUG%[1]s: set to a truthy value to enable verbose output on standard error. Set to %[1]sapi%[1]s to additionally log details of HTTP traffic. - DEBUG (deprecated): set to "1", "true", or "yes" to enable verbose output on standard + %[1]sDEBUG%[1]s (deprecated): set to %[1]s1%[1]s, %[1]strue%[1]s, or %[1]syes%[1]s to enable verbose output on standard error. - GH_PAGER, PAGER (in order of precedence): a terminal paging program to send standard output - to, e.g. "less". + %[1]sGH_PAGER%[1]s, %[1]sPAGER%[1]s (in order of precedence): a terminal paging program to send standard output + to, e.g. %[1]sless%[1]s. - GLAMOUR_STYLE: the style to use for rendering Markdown. See + %[1]sGLAMOUR_STYLE%[1]s: the style to use for rendering Markdown. See - NO_COLOR: set to any value to avoid printing ANSI escape sequences for color output. + %[1]sNO_COLOR%[1]s: set to any value to avoid printing ANSI escape sequences for color output. - CLICOLOR: set to "0" to disable printing ANSI colors in output. + %[1]sCLICOLOR%[1]s: set to %[1]s0%[1]s to disable printing ANSI colors in output. - CLICOLOR_FORCE: set to a value other than "0" to keep ANSI colors in output + %[1]sCLICOLOR_FORCE%[1]s: set to a value other than %[1]s0%[1]s to keep ANSI colors in output even when the output is piped. - GH_FORCE_TTY: set to any value to force terminal-style output even when the output is + %[1]sGH_FORCE_TTY%[1]s: set to any value to force terminal-style output even when the output is redirected. When the value is a number, it is interpreted as the number of columns available in the viewport. When the value is a percentage, it will be applied against the number of columns available in the current viewport. - GH_NO_UPDATE_NOTIFIER: set to any value to disable update notifications. By default, gh + %[1]sGH_NO_UPDATE_NOTIFIER%[1]s: set to any value to disable update notifications. By default, gh checks for new releases once every 24 hours and displays an upgrade notice on standard error if a newer version was found. - GH_CONFIG_DIR: the directory where gh will store configuration files. If not specified, + %[1]sGH_CONFIG_DIR%[1]s: the directory where gh will store configuration files. If not specified, the default value will be one of the following paths (in order of precedence): - - "$XDG_CONFIG_HOME/gh" (if $XDG_CONFIG_HOME is set), - - "$AppData/GitHub CLI" (on Windows if $AppData is set), or - - "$HOME/.config/gh". + - %[1]s$XDG_CONFIG_HOME/gh%[1]s (if %[1]s$XDG_CONFIG_HOME%[1]s is set), + - %[1]s$AppData/GitHub CLI%[1]s (on Windows if %[1]s$AppData%[1]s is set), or + - %[1]s$HOME/.config/gh%[1]s. - GH_PROMPT_DISABLED: set to any value to disable interactive prompting in the terminal. + %[1]sGH_PROMPT_DISABLED%[1]s: set to any value to disable interactive prompting in the terminal. - GH_PATH: set the path to the gh executable, useful for when gh can not properly determine + %[1]sGH_PATH%[1]s: set the path to the gh executable, useful for when gh can not properly determine its own path such as in the cygwin terminal. - `), + `, "`"), }, { name: "reference", @@ -122,10 +122,10 @@ var HelpTopics = []helpTopic{ The %[1]s--jq%[1]s flag requires a string argument in jq query syntax, and will only print those JSON values which match the query. jq queries can be used to select elements from an - array, fields from an object, create a new array, and more. The jq utility does not need + array, fields from an object, create a new array, and more. The %[1]sjq%[1]s utility does not need to be installed on the system to use this formatting directive. When connected to a terminal, the output is automatically pretty-printed. To learn about jq query syntax, see: - + The %[1]s--template%[1]s flag requires a string argument in Go template syntax, and will only print those JSON values which match the query. @@ -138,7 +138,7 @@ var HelpTopics = []helpTopic{ - %[1]stablerow ...%[1]s: aligns fields in output vertically as a table - %[1]stablerender%[1]s: renders fields added by tablerow in place - %[1]stimeago