Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/nexthink-oss/ghup
A tool for managing GitHub repository tags and content from third-party automation systems
https://github.com/nexthink-oss/ghup
git-commit git-tag github-api github-token
Last synced: about 2 hours ago
JSON representation
A tool for managing GitHub repository tags and content from third-party automation systems
- Host: GitHub
- URL: https://github.com/nexthink-oss/ghup
- Owner: nexthink-oss
- License: other
- Created: 2022-11-11T17:35:39.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2024-11-11T21:02:29.000Z (4 days ago)
- Last Synced: 2024-11-11T22:18:16.115Z (4 days ago)
- Topics: git-commit, git-tag, github-api, github-token
- Language: Go
- Homepage:
- Size: 242 KB
- Stars: 10
- Watchers: 4
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[![CodeQL](https://github.com/nexthink-oss/ghup/actions/workflows/codeql.yml/badge.svg)](https://github.com/nexthink-oss/ghup/actions/workflows/codeql.yml)
[![Go Report Card](https://goreportcard.com/badge/github.com/nexthink-oss/ghup)](https://goreportcard.com/report/github.com/nexthink-oss/ghup)# ghup
A GitHub API client for managing tags and repository content from third-party automation systems (e.g. Jenkins).
## Features
* Create and update tags, both lightweight and annotated.
* Add, update and delete content idempotently.
* 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.## Requirements
* A GitHub Token, preferably derived from GitHub App credentials (for verified commits), with `contents=write` and `metadata=read` permissions on target repository. In addition, `workflows=write` is also needed if used to manage `.github/workflows` content.
Note: works well with [vault-plugin-secrets-github](https://github.com/martinbaillie/vault-plugin-secrets-github)!
## Configuration
If the current working directory is a git repository, its first GitHub remote (if there is one) is used to infer default repository owner (`--owner`) and name (`--repo`), the current branch is used to set the default branch (`--branch`), and resolved git config is used to set a default author for a generated `Co-Authored-By` commit message trailer to help distinguish between different systems sharing common GitHub App credentials (override components with `--author.trailer`, `--user.name` and `--user.email`, or disable with `--author.trailer=` or `export GHUP_AUTHOR_TRAILER=`). Additional commit trailers can be specified with `--trailer key=value` flags.
If run outside a GitHub repository, then the `--owner` and `--repo` flags are required, with `--branch` defaulting to `main`.
All configuration may be passed via environment variable rather than flag. The environment variable associated with each flag is `GHUP_[UPPERCASED_FLAG_NAME]`, e.g. `GHUP_TOKEN`, `GHUP_OWNER`, `GHUP_REPO`, `GHUP_BRANCH`, `GHUP_AUTHOR_TRAILER`, etc.
In addition, various fallback environment variables are supported for better integration with Jenkins and similar CI tools: `GITHUB_TOKEN`, `GITHUB_OWNER`, `GITHUB_REPO`, `CHANGE_BRANCH`, `BRANCH_NAME`, `GIT_BRANCH`, `GIT_COMMITTER_NAME`, `GIT_COMMITTER_EMAIL`, etc.
The environment variable `GITHUB_REPOSITORY`, always set in GitHub Actions workflow context in the form `/`, is only used to set initial defaults for `--owner` and `--repo`, but will be overridden by local repository context and more specific configuration.
If `GITHUB_REPOSITORY` is set, then `--branch` will also default from `GITHUB_HEAD_REF` in pull request context, or `GITHUB_REF_NAME` otherwise.For security, it is strongly recommended that the GitHub Token by passed via environment (`GHUP_TOKEN` or `GITHUB_TOKEN`) or file path (`--token /path/to/token-file`, `--token <(gh auth token)` or `export GHUP_TOKEN=/path/to/token-file ghup …`)
## Installation
### Generic
Binaries for all supported platforms and architectures are available from [GitHub Releases](https://github.com/nexthink-oss/ghup/releases/latest).
Alternatively, install to `$GOBIN` with a local Go toolchain:
```sh
go install github.com/nexthink-oss/ghup@latest
```### Homebrew
```sh
brew install isometry/tap/ghup
```### GitHub Actions
The [`nexthink-oss/ghup/actions/setup`](actions/setup/) action is available to make the `ghup` tool available in GitHub Actions.
## Usage
### Content
The `content` verb is used to generate arbitrary (verified) commits via the GitHub V4 API.
An arbitrary number of content adds, removes and deletes can be committed without the need for a local signing key or for checking out the target repository.```console
$ ghup content --help
Manage content via the GitHub V4 APIUsage:
ghup content [flags] [ ...]Flags:
--create-branch create missing target branch (default true)
--pr-title string create pull request iff target branch is created and title is specified
--pr-body string pull request body
--pr-draft create pull request in draft mode
--base-branch name base branch name (default: "[remote-default-branch])"
-s, --separator string file-spec separator (default ":")
-u, --update file-spec file-spec to update
-d, --delete file-path file-path to delete
-h, --help help for contentGlobal Flags:
--author.trailer key key for commit author trailer (blank to disable) (default "Co-Authored-By")
-b, --branch name target branch name (default "[local-branch-or-main]")
-f, --force force action
-m, --message string message (default "Commit via API")
-o, --owner name repository owner name (default "[owner-of-first-github-remote-or-required]")
-r, --repo name repository name (default "[repo-of-first-github-remote-or-required]")
--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 "[user.email]")
--user.name name name for commit author trailer (default "[user.name]")
-v, --verbosity count verbosity
```Each `file-spec` provided as a positional argument or explicitly via the `--update` flag takes the form `[:]`. Content is read from the local file `` and written to `` (defaulting to `` if not specified).
Each `file-path` provided to the `--delete` flag is a ``: the path to a file on the target repository:branch that should be deleted.
Unless `--force` is used, content that already matches the remote repository state is ignored.
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 Examples
##### Idempotent file add/update
Update `.zshrc` in my `dotfiles` repo, adding if's missing and updating if-and-only-if changed:
```console
$ ghup content --owner=isometry --repo=dotfiles ~/.zshrc:.zshrc -m "chore: update zshrc"
https://github.com/isometry/dotfiles/commit/15b8630c81a051c2b128c94e5796c5d9c2bc8846
$ ghup content --owner=isometry --repo=dotfiles ~/.zshrc:.zshrc -m "chore: update zshrc"
nothing to do
```##### Idempotent file deletion
Delete `.tcshrc` from my `dotfiles` repo:
```console
$ ghup content --owner=isometry --repo=dotfiles --delete .tcshrc -m "chore: remove tcshrc"
https://github.com/isometry/dotfiles/commit/bf120a96c65cb482eacc3c9e27d2d0935d108eca
$ ghup content --owner=isometry --repo=dotfiles --delete .tcshrc -m "chore: remove tcshrc"
nothing to do
```### Tagging
The `tag` verb is used to create lightweight or annotated tags without the need to checkout the target repository.
Note: annotated tags are the default, but only lightweight tags (i.e. `--lightweight`), which simply point at an existing commit, are "verified".
```console
$ ghup tag --helpManage tags via the GitHub V3 API
Usage:
ghup tag [flags] []Flags:
-h, --help help for tag
-l, --lightweight force lightweight tag
--tag string tag nameGlobal Flags:
--author.trailer key key for commit author trailer (blank to disable) (default "Co-Authored-By")
-b, --branch name target branch name (default "[local-branch-or-main]")
-f, --force force action
-m, --message string message (default "Commit via API")
-o, --owner name repository owner name (default "[owner-of-first-github-remote-or-required]")
-r, --repo name repository name (default "[repo-of-first-github-remote-or-required]")
--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 "[user.email]")
--user.name name name for commit author trailer (default "[user.name]")
-v, --verbosity count verbosity
```#### Tagging Examples
##### Create lightweight tag
Create lightweight tag `v1.0.0` pointing at the head of the local repository's checked out branch:
```console
$ ghup tag v1.0.0
https://github.com/nexthink-oss/ghup/releases/tag/v1.0.0
```##### Create annotated tag
Create an annotated repo `v1.0` pointed at the head of the `main` branch of the `ghup` repo owned by `nexthink-oss`:
```console
$ 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
```### Update Refs
The `update-ref` verb is used to update an arbitrary number `head` or `tag` references to match a source reference.
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 update-ref --help
Update target refs to match sourceUsage:
ghup update-ref [flags] -s ...Flags:
-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-refGlobal Flags:
--author.trailer key key for commit author trailer (blank to disable) (default "Co-Authored-By")
-b, --branch name target branch name (default "[local-branch-or-main]")
-f, --force force action
-m, --message string message (default "Commit via API")
-o, --owner name repository owner name (default "[owner-of-first-github-remote-or-required]")
-r, --repo name repository name (default "[repo-of-first-github-remote-or-required]")
--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 "[user.email]")
--user.name name name for commit author trailer (default "[user.name]")
-v, --verbosity count verbosity
```Note: the `--branch`, `--message` and trailer-related flags are not used by the `ref` verb.
#### Updated Refs Examples
##### Fast-forward production branch to match staging
```console
$ ghup update-ref -s staging heads/production
{"source":{"ref":"heads/staging","sha":"206e1a484f03cd320a2125a50aa73bd8a2b045dc"},"target":[{"ref":"heads/production","updated":true,"old_sha":"b7ccc4db9bc43551fd3571c260869f4c69aa2fd4","sha":"206e1a484f03cd320a2125a50aa73bd8a2b045dc"}]}
```##### Create a lightweight tag pointing at a specific commit
```console
$ ghup update-ref -s b7ccc4d example
{"source":{"ref":"b7ccc4d","sha":"b7ccc4db9bc43551fd3571c260869f4c69aa2fd4"},"target":[{"ref":"tags/example","updated":true,"sha":"b7ccc4db9bc43551fd3571c260869f4c69aa2fd4"}]}
```##### Update GitHub Actions-style major and minor tags following patch release:
```console
$ ghup update-ref -s tags/v1.1.7 v1.1 v1
{"source":{"ref":"tags/v1.1.7","sha":"b7ccc4db9bc43551fd3571c260869f4c69aa2fd4"},"target":[{"ref":"tags/v1.1","updated":true,"sha":"b7ccc4db9bc43551fd3571c260869f4c69aa2fd4"},{"ref":"tags/v1","updated":true,"sha":"b7ccc4db9bc43551fd3571c260869f4c69aa2fd4"}]}
```### Debug Info
In order to better validate the configuration derived from context (working directory, environment variables and global flags), the `info` verb is available:
```console
$ ghup info
{
"has_token": true,
"owner": "nexthink-oss",
"repository": "ghup",
"branch": "feature/branch",
"commit": "5e1692253399bd9ea6077dba27e4cdc8a15b9720",
"clean": false,
"message": {
"headline": "Commit via API",
"body": "Co-Authored-By: Example User "
}
"trailers": [
"Co-Authored-By: Example User "
],
}
```