|
| 1 | +# Library Maintainer Guide |
| 2 | + |
| 3 | +This guide is aimed at maintainers of libraries using Librarian, where the |
| 4 | +library contains hand-written code. (Fully-generated libraries are automated |
| 5 | +for both generation and release.) |
| 6 | + |
| 7 | +This guide is task-oriented, specifically for core/handwritten/hybrid library |
| 8 | +maintainers. See the |
| 9 | +[generated CLI documentation](https://pkg.go.dev/github.com/googleapis/librarian/cmd/librarian) |
| 10 | +for a more comprehensive list of commands and flags. |
| 11 | + |
| 12 | +This guide uses the term Librarian (capital L, regular font) for the overall |
| 13 | +Librarian system, and `librarian` (lower case L, code font) for the CLI. |
| 14 | + |
| 15 | +## Prerequisites |
| 16 | + |
| 17 | +`librarian` requires: |
| 18 | + |
| 19 | +- Linux |
| 20 | +- Go (or a prebuilt binary) |
| 21 | +- sudoless Docker |
| 22 | +- git (if you wish to build it locally) |
| 23 | +- gcloud (to set up Docker access to conatiner images) |
| 24 | +- [gh](https://github.com/cli/cli) for GitHub access tokens |
| 25 | + |
| 26 | +While in theory `librarian` can be run in non-Linux environments that support |
| 27 | +Linux Docker containers, Google policies make this at least somewhat infeasible |
| 28 | +(while staying conformant), so `librarian` is not tested other than on Linux. |
| 29 | + |
| 30 | +See go/docker for instructions on how to install Docker, ensuring that you |
| 31 | +follow the sudoless part. |
| 32 | + |
| 33 | +> Note that installing Docker will cause gLinux to warn you that Docker is |
| 34 | +> unsupported and discouraged. Within Cloud, support for Docker is a core |
| 35 | +> expectation (e.g. for Cloud Run and Cloud Build). Using Docker is the most |
| 36 | +> practical way of abstracting away language details. We are confident that |
| 37 | +> there are enough Googlers who require Docker to work on gLinux that it won't |
| 38 | +> actually go away any time soon. We may investigate using podman instead if |
| 39 | +> necessary. |
| 40 | +
|
| 41 | +## Running `librarian` |
| 42 | + |
| 43 | +There are various options for running `librarian`. We recommend using `go run` |
| 44 | +(the first option) unless you're developing `librarian`. You may wish to use |
| 45 | +a bash alias for simplicity. For example, using the first option below you might |
| 46 | +use: |
| 47 | + |
| 48 | +```sh |
| 49 | +$ alias librarian='go run github.com/googleapis/librarian/cmd/librarian@latest' |
| 50 | +``` |
| 51 | + |
| 52 | +In this guide, we just assume that `librarian` is either a binary in your path, |
| 53 | +or a suitable alias. |
| 54 | + |
| 55 | +### Using `go run` |
| 56 | + |
| 57 | +The latest released version of `librarian` can be run directly without cloning |
| 58 | +using: |
| 59 | + |
| 60 | +```sh |
| 61 | +$ go run github.com/googleapis/librarian/cmd/librarian@latest |
| 62 | +``` |
| 63 | + |
| 64 | +### Using `go install` |
| 65 | + |
| 66 | +To install a binary locally, and then run it (assuming the `$GOBIN` directory |
| 67 | +is in your path): |
| 68 | + |
| 69 | +```sh |
| 70 | +$ go install github.com/googleapis/librarian/cmd/librarian@latest |
| 71 | +``` |
| 72 | + |
| 73 | +Note that while this makes it easier to run `librarian`, you'll need to know |
| 74 | +to install a new version when it's released. |
| 75 | + |
| 76 | +### Building locally |
| 77 | + |
| 78 | +Clone the source code, then run it: |
| 79 | + |
| 80 | +```sh |
| 81 | +$ git clone https://github.com/googleapis/librarian |
| 82 | +$ cd librarian |
| 83 | +$ go run ./cmd/librarian |
| 84 | +``` |
| 85 | + |
| 86 | +## Obtaining a GitHub access token |
| 87 | + |
| 88 | +`librarian` commands which perform write operations on GitHub require |
| 89 | +a GitHub access token to be specified via the `LIBRARIAN_GITHUB_TOKEN` |
| 90 | +environment variable. While access tokens can be generated manually |
| 91 | +and then stored in environment variables in other ways, it's simplest |
| 92 | +to use the [`gh` tool](https://github.com/cli/cli). |
| 93 | + |
| 94 | +Once installed, use `gh auth login` to log into GitHub. After that, |
| 95 | +when running `librarian` you can use `gh auth token` to obtain an access |
| 96 | +token and set it in the environment variable just for that invocation: |
| 97 | + |
| 98 | +```sh |
| 99 | +$ LIBRARIAN_GITHUB_TOKEN=$(gh auth token) librarian ... |
| 100 | +``` |
| 101 | + |
| 102 | +The examples below assume include this for convenience; if you have |
| 103 | +set the environment variable in a different way, just remove the |
| 104 | +`LIBRARIAN_GITHUB_TOKEN=$(gh auth token)` part from the command. |
| 105 | + |
| 106 | +## Repository and library options |
| 107 | + |
| 108 | +`librarian` can either operate on a local clone of the library repo, |
| 109 | +or it can clone the repo itself. Unless you have a particular need to use a |
| 110 | +local clone (e.g. to the impact of a local change) we recommend you let |
| 111 | +`librarian` clone the library repo itself, using the `-repo` flag - just specify |
| 112 | +the GitHub repository, e.g. |
| 113 | +`-repo=https://github.com/googleapis/google-cloud-go`. This avoids any |
| 114 | +risk of unwanted local changes accidentally becoming part of a generation/release |
| 115 | +PR. |
| 116 | + |
| 117 | +If you wish to use a local clone, you can specify the directory in the `-repo` |
| 118 | +flag, or just run `librarian` from the root directory of the clone and omit the |
| 119 | +`-repo` flag entirely. |
| 120 | + |
| 121 | +The commands in this guide are specifically for generating/releasing a single |
| 122 | +library, specified with the `library` flag. This is typically the name of the |
| 123 | +package or module, e.g. `bigtable` or `google-cloud-bigtable`. Consult the |
| 124 | +state file (`.librarian/state.yaml`) in the library repository to find the |
| 125 | +library IDs in use (and ideally record this in a team-specific playbook). |
| 126 | + |
| 127 | +The remainder of this guide uses |
| 128 | +`https://github.com/googleapis/google-cloud-go` as the repository and `bigtable` |
| 129 | +as the library ID, in order to provide concrete examples. |
| 130 | + |
| 131 | +## Initiating a release |
| 132 | + |
| 133 | +The release process consists of four steps (at a high level; there are more |
| 134 | +details which aren't relevant to this guide): |
| 135 | + |
| 136 | +1. Creating a release PR using `librarian` |
| 137 | +2. Reviewing/merging the release PR |
| 138 | +3. Creating a tag for the commit created by the merged release PR |
| 139 | +4. Running a release job (to build, test, publish) on the tagged commit |
| 140 | + |
| 141 | +Step 1 is described in this section. |
| 142 | + |
| 143 | +Step 2 is simply the normal process of reviewing and merging a PR. |
| 144 | + |
| 145 | +Steps 3 and 4 are automated; step 3 should occur within about 5 minutes of the |
| 146 | +release PR being merged, and this will trigger step 4. The instructions for the |
| 147 | +remainder of this section are about step 1. |
| 148 | + |
| 149 | +### Hands-off release PR creation |
| 150 | + |
| 151 | +If you are reasonably confident that the release notes won't need editing, the |
| 152 | +simplest way to initiate a release is to ask `librarian` to create the release |
| 153 | +PR for you: |
| 154 | + |
| 155 | +```sh |
| 156 | +$ LIBRARIAN_GITHUB_TOKEN=$(gh auth token) librarian release init -push \ |
| 157 | + -repo=https://github.com/googleapis/google-cloud-go -library=bigtable |
| 158 | +``` |
| 159 | + |
| 160 | +This will use the conventional commits since the last release to populate |
| 161 | +any release notes in both the PR and the relevant changelog file in the repo. |
| 162 | + |
| 163 | +If you want to release a version other than the one inferred by the conventional |
| 164 | +commits (e.g. for a prerelease or a patch), you can use the `-library-version` |
| 165 | +flag: |
| 166 | + |
| 167 | +```sh |
| 168 | +$ LIBRARIAN_GITHUB_TOKEN=$(gh auth token) librarian release init -push \ |
| 169 | + -repo=https://github.com/googleapis/google-cloud-go -library=bigtable \ |
| 170 | + -library-version=1.2.3 |
| 171 | +``` |
| 172 | + |
| 173 | +Note that if `librarian` doesn't detect any conventional commits that would |
| 174 | +trigger a release, you *must* specify the `-library-version` flag. |
| 175 | + |
| 176 | +### Manual release PR creation |
| 177 | + |
| 178 | +If you expect to need to edit the release notes, it's simplest to run |
| 179 | +`librarian` *without* the `-push` flag (and using a local repo), |
| 180 | +then create the pull request yourself: |
| 181 | + |
| 182 | +1. Make sure your local clone is up-to-date |
| 183 | +2. Create a new branch for the release (e.g. `git checkout -b release-bigtable-1.2.3`) |
| 184 | +3. Run `librarian`, specifying `-library-version` if you want/need to, as above: |
| 185 | + ```sh |
| 186 | + $ librarian release init -library=bigtable -library-version=1.2.3 |
| 187 | + ``` |
| 188 | +4. Note the line of the `librarian` output near the end, which tells you where |
| 189 | + it has written a `pr-body.txt` file (split by key below, but all on one line |
| 190 | + in the output): |
| 191 | + ```text |
| 192 | + time=2025-09-26T15:35:23.124Z |
| 193 | + level=INFO |
| 194 | + msg="Wrote body of pull request that might have been created" |
| 195 | + file=/tmp/librarian-837968205/pr-body.txt |
| 196 | + ``` |
| 197 | +5. Perform any edits to the release notes, and commit the change using a "chore" |
| 198 | + conventional commit, e.g. `git commit -a -m "chore: create release"` |
| 199 | +6. Push your change to GitHub *in the main fork* (rather than any personal fork you may use), |
| 200 | + and create a PR from the branch. Use the content of the `pr-body.txt` file as the body |
| 201 | + of the PR, editing it to be consistent with any changes you've made in the release notes. |
| 202 | +7. Add the "release:pending" label to the PR. |
| 203 | +8. Ask a colleague to review and merge the PR. |
| 204 | + |
| 205 | +## Updating generated code |
| 206 | + |
| 207 | +Librarian automation updates GAPIC/proto-generated code on a weekly basis on a |
| 208 | +Wednesday, but generation can be run manually if an API change urgently needs |
| 209 | +to be included in client libraries. |
| 210 | + |
| 211 | +### Create a PR with updated code |
| 212 | + |
| 213 | +In the common case where you just need to expedite generation, `librarian` can |
| 214 | +create the generation PR for you: |
| 215 | + |
| 216 | +```sh |
| 217 | +$ LIBRARIAN_GITHUB_TOKEN=$(gh auth token) librarian generate -push \ |
| 218 | + -repo=https://github.com/googleapis/google-cloud-go -library=bigtable |
| 219 | +``` |
| 220 | + |
| 221 | +Ask a colleague to review and merge the PR. |
| 222 | + |
| 223 | +### Test a local API change |
| 224 | + |
| 225 | +If you need to test the potential impact of an API change which isn't yet in the |
| 226 | +`googleapis` repository, you can use the `-api-source` flag to specify a local |
| 227 | +clone of `googleapis`. You should *not* push this to GitHub other than for |
| 228 | +sharing purposes. |
| 229 | + |
| 230 | +Typical flow, assuming a directory structure of `~/github/googleapis` containing |
| 231 | +clones of `googleapis` and `google-cloud-go` (and assuming they're up-to-date): |
| 232 | + |
| 233 | +```sh |
| 234 | +$ cd ~/github/googleapis/googleapis |
| 235 | +$ git checkout -b test-api-changes |
| 236 | +# Make changes here |
| 237 | +$ git commit -a -m "Test API changes" |
| 238 | +$ cd ../google-cloud-go |
| 239 | +$ git checkout -b test-generated-api-changes |
| 240 | +$ librarian generate -api-source=../googleapis -library=bigtable |
| 241 | +``` |
0 commit comments