Skip to content

Commit 5d2263b

Browse files
committed
Merge main into feat/docs-read-edit
Resolve conflicts between branch's DocsReadCmd/DocsEditCmd additions and main's refactoring of docs code into separate files. Branch's new commands are placed into main's file structure (docs_read.go, docs_edit.go). Updated DocsEditCmd tests to match new field names.
2 parents aef903e + 8677685 commit 5d2263b

281 files changed

Lines changed: 26029 additions & 7972 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,43 @@ on:
44
push:
55
pull_request:
66

7+
concurrency:
8+
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
9+
cancel-in-progress: true
10+
711
jobs:
812
test:
9-
runs-on: blacksmith-16vcpu-ubuntu-2404
13+
runs-on: ubuntu-latest
1014
steps:
11-
- uses: actions/checkout@v4
12-
- uses: actions/setup-go@v5
15+
- uses: actions/checkout@v6
16+
- uses: actions/setup-go@v6
1317
with:
1418
go-version-file: go.mod
1519
cache: true
20+
- uses: actions/cache@v5
21+
with:
22+
path: .tools
23+
key: ${{ runner.os }}-tools-${{ hashFiles('Makefile') }}
1624
- name: Install tools
1725
run: make tools
1826
- name: Format check
1927
run: make fmt-check
2028
- name: Test
21-
run: go test ./...
29+
run: make test
2230
- name: Lint
2331
run: make lint
2432

2533
worker:
26-
runs-on: blacksmith-16vcpu-ubuntu-2404
34+
runs-on: ubuntu-latest
2735
steps:
28-
- uses: actions/checkout@v4
29-
- uses: actions/setup-node@v4
36+
- uses: actions/checkout@v6
37+
- uses: actions/setup-node@v6
3038
with:
31-
node-version: "20"
39+
node-version: "24"
3240
- name: Enable Corepack (pnpm)
3341
run: |
3442
corepack enable
35-
corepack prepare pnpm@10.27.0 --activate
43+
corepack prepare pnpm@10.30.3 --activate
3644
- name: Install dependencies
3745
run: pnpm -C internal/tracking/worker install --frozen-lockfile
3846
- name: Lint
@@ -42,28 +50,48 @@ jobs:
4250
- name: Test
4351
run: pnpm -C internal/tracking/worker test
4452

45-
darwin-cgo-build:
46-
runs-on: macos-latest
53+
windows:
54+
runs-on: windows-latest
4755
steps:
48-
- uses: actions/checkout@v4
49-
- uses: actions/setup-go@v5
56+
- uses: actions/checkout@v6
57+
- uses: actions/setup-go@v6
5058
with:
5159
go-version-file: go.mod
5260
cache: true
61+
- uses: actions/cache@v5
62+
with:
63+
path: .tools
64+
key: ${{ runner.os }}-tools-${{ hashFiles('Makefile') }}
65+
- name: Install tools
66+
run: make tools
67+
shell: bash
68+
- name: Format check
69+
run: make fmt-check
70+
shell: bash
5371
- name: Test
54-
run: go test ./...
55-
- name: Build (Keychain / cgo)
56-
run: CGO_ENABLED=1 go build ./cmd/gog
72+
# Skip tests that depend on macOS Keychain / Linux keyring or Unix path semantics.
73+
# These are covered by ubuntu-latest and macos-latest jobs.
74+
# See https://github.com/steipete/gogcli/issues/395
75+
run: make test
76+
shell: bash
77+
env:
78+
TEST_FLAGS: >-
79+
-skip 'TestAuth|TestListClientCredentials|TestReadClientCredentials|TestConfigExists|TestExpandPath|TestResolveKeyringBackendInfo|TestLoadSecrets_LegacyFallback'
80+
- name: Lint
81+
run: make lint
82+
shell: bash
83+
- name: Build
84+
run: go build ./cmd/gog
5785

58-
windows-build:
59-
runs-on: blacksmith-16vcpu-windows-2025
86+
darwin-cgo-build:
87+
runs-on: macos-latest
6088
steps:
61-
- uses: actions/checkout@v4
62-
- uses: actions/setup-go@v5
89+
- uses: actions/checkout@v6
90+
- uses: actions/setup-go@v6
6391
with:
6492
go-version-file: go.mod
6593
cache: true
6694
- name: Test
67-
run: go test ./...
68-
- name: Build
69-
run: go build ./cmd/gog
95+
run: make test
96+
- name: Build (Keychain / cgo)
97+
run: CGO_ENABLED=1 go build ./cmd/gog

.github/workflows/release.yml

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,37 @@ jobs:
1919
runs-on: macos-latest
2020
steps:
2121
- name: Checkout
22-
uses: actions/checkout@v4
22+
uses: actions/checkout@v6
2323
with:
2424
fetch-depth: 0
2525

2626
- name: Setup Go
27-
uses: actions/setup-go@v5
27+
uses: actions/setup-go@v6
2828
with:
2929
go-version-file: go.mod
3030
cache: true
3131

3232
- name: Stash GoReleaser config
3333
run: cp .goreleaser.yaml /tmp/.goreleaser.yaml
3434

35+
- name: Validate release tag
36+
if: ${{ github.event_name == 'workflow_dispatch' }}
37+
env:
38+
RELEASE_TAG: ${{ inputs.tag }}
39+
run: |
40+
if ! echo "$RELEASE_TAG" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$'; then
41+
echo "::error::Invalid tag format: $RELEASE_TAG"
42+
exit 1
43+
fi
44+
3545
- name: Checkout release tag
3646
if: ${{ github.event_name == 'workflow_dispatch' }}
37-
run: git checkout ${{ inputs.tag }}
47+
env:
48+
RELEASE_TAG: ${{ inputs.tag }}
49+
run: git checkout "$RELEASE_TAG"
3850

3951
- name: GoReleaser
40-
uses: goreleaser/goreleaser-action@v6
52+
uses: goreleaser/goreleaser-action@v7
4153
with:
4254
distribution: goreleaser
4355
version: latest

CHANGELOG.md

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,96 @@
11
# Changelog
22

3-
## 0.12.0 - Unreleased
3+
## 0.12.0 - 2026-03-09
4+
5+
### Highlights
6+
- Admin: full Workspace Admin users/groups coverage for common directory operations. (#403) — thanks @dl-alexandre.
7+
- Auth: new headless/cloud auth paths with ADC, direct access tokens, custom callbacks, proxy-safe loopback settings, and extra-scope controls. (#357, #419, #227, #398, #421) — thanks @tengis617, @mmkal, @cyberfox, @salmonumbrella, and @peteradams2026.
8+
- Docs: much stronger document editing and export flow with tab targeting, richer find-replace, pageless mode, and native Markdown/HTML export. (#330, #305, #300, #282, #141) — thanks @ignacioreyna, @chparsons, @shohei-majima, @fprochazka, and @in-liberty420.
9+
- Sheets: spreadsheet editing/formatting expands significantly with named ranges, tab management, notes, find-replace, formatting controls, inserts, links, and format inspection. (#278, #309, #430, #341, #320, #203, #374, #284) — thanks @TheCrazyLex, @JulienMalige, @andybergon, @Shehryar, @omothm, and @nilzzzzzz.
10+
- Calendar: aliases, subscribe, and selector parity make multi-calendar workflows much easier. (#393, #327, #319) — thanks @salmonumbrella and @cdthompson.
11+
- Forms/Slides/Keep: forms management + watches, slides from templates, and first write/delete coverage for Keep. (#274, #273, #413) — thanks @alexknowshtml, @penguinco, and @jgwesterlund.
412

513
### Added
14+
- Admin: add Workspace Admin Directory commands for users and groups, including user list/get/create/suspend and group membership list/add/remove. (#403) — thanks @dl-alexandre.
15+
- Auth: add Application Default Credentials mode via `GOG_AUTH_MODE=adc` for Workload Identity, Cloud Run, and local `gcloud` ADC flows without stored OAuth refresh tokens. (#357) — thanks @tengis617.
16+
- Auth: add `--access-token` / `GOG_ACCESS_TOKEN` for direct access-token auth in headless or CI flows, bypassing stored refresh tokens. (#419) — thanks @mmkal.
17+
- Auth: add `auth add|manage --listen-addr` plus `--redirect-host` for browser OAuth behind proxies or remote loopback forwarding. (#227) — thanks @cyberfox.
18+
- Auth: add `auth add --redirect-uri` for manual/remote OAuth flows, so custom callback hosts can be reused across the printed auth URL, state cache, and code exchange. (#398) — thanks @salmonumbrella.
19+
- Auth: add `--extra-scopes` to `auth add` for appending custom OAuth scope URIs beyond the built-in service scopes. (#421) — thanks @peteradams2026.
20+
- Docs: add `--tab-id` to editing commands so write/update/insert/delete/find-replace can target a specific Google Docs tab. (#330) — thanks @ignacioreyna.
21+
- Docs: extend `docs find-replace` with `--first`, `--content-file`, Markdown replacement, inline image insertion, and image sizing syntax. (#305) — thanks @chparsons.
22+
- Docs: add `--pageless` to `docs create`, `docs write`, and `docs update` to switch documents into pageless mode after writes. (#300) — thanks @shohei-majima.
23+
- Docs: add native Google Docs Markdown export via `docs export --format md`. (#282) — thanks @fprochazka.
24+
- Docs: add native Google Docs HTML export via `docs export --format html`. (#141) — thanks @in-liberty420.
25+
- Sheets: add named range management (`sheets named-ranges`) and let range-based Sheets commands accept named range names where GridRange-backed operations are needed. (#278) — thanks @TheCrazyLex.
26+
- Sheets: add `add-tab`, `rename-tab`, and `delete-tab` commands for managing spreadsheet tabs, with delete dry-run/confirmation guardrails. (#309) — thanks @JulienMalige.
27+
- Sheets: add `merge`, `unmerge`, `number-format`, `freeze`, `resize-columns`, and `resize-rows` commands for spreadsheet layout/format control. (#320) — thanks @Shehryar.
28+
- Sheets: add `sheets update-note` / `set-note` to write or clear cell notes across a range. (#430) — thanks @andybergon.
29+
- Sheets: add `sheets find-replace` to replace text across a spreadsheet or a specific tab, with exact-match, regex, and formula search options. (#341) — thanks @Shehryar.
630
- Sheets: add `sheets insert` to insert rows/columns into a sheet. (#203) — thanks @andybergon.
31+
- Sheets: add `sheets create --parent` to place new spreadsheets in a Drive folder. (#424) — thanks @ManManavadaria.
32+
- Sheets: add `sheets read-format` to inspect `userEnteredFormat` / `effectiveFormat` per cell. (#284) — thanks @nilzzzzzz.
733
- Sheets: add `sheets links` (alias `hyperlinks`) to list cell links from ranges, including rich-text links. (#374) — thanks @omothm.
34+
- Forms: add form update/question-management commands plus response watch create/list/delete/renew, with delete-question validation and confirmation guardrails. (#274) — thanks @alexknowshtml.
35+
- Slides: add `create-from-template` with `--replace` / `--replacements`, dry-run support, and template placeholder replacement stats. (#273) — thanks @penguinco.
36+
- Calendar: add `calendar alias list|set|unset`, and let calendar commands resolve configured aliases before API/name lookup. (#393) — thanks @salmonumbrella.
37+
- Calendar: let `calendar freebusy` / `calendar conflicts` accept `--cal`, names, indices, and `--all` like `calendar events`. (#319) — thanks @salmonumbrella.
38+
- Calendar: add `calendar subscribe` (aliases `sub`, `add-calendar`) to add a shared calendar to the current account’s calendar list. (#327) — thanks @cdthompson.
839
- Gmail: add `watch serve --history-types` filtering (`messageAdded|messageDeleted|labelAdded|labelRemoved`) and include `deletedMessageIds` in webhook payloads. (#168) — thanks @salmonumbrella.
40+
- Gmail: add `gmail labels rename` to rename user labels by ID or exact name, with system-label guards and wrong-case ID safety. (#391) — thanks @adam-zethraeus.
41+
- Gmail: add `gmail messages modify` for single-message label changes, complementing thread- and batch-level modify flows. (#281) — thanks @zerone0x.
42+
- Gmail: add `gmail filters export` to dump filter definitions as JSON to stdout or a file for backup/script workflows. (#119) — thanks @Jeswang.
43+
- Keep: add `keep create` for text/checklist notes and `keep delete` for note removal. (#413) — thanks @jgwesterlund.
944
- Contacts: support `--org`, `--title`, `--url`, `--note`, and `--custom` on create/update; include custom fields in get output with deterministic ordering. (#199) — thanks @phuctm97.
45+
- Contacts: add `--relation type=person` to contact create/update, include relations in text `contacts get`, and cover relation payload updates. (#351) — thanks @karbassi.
46+
- Contacts: add `--address` to contact create/update and include addresses in text `contacts get`. (#148) — thanks @beezly.
1047
- Drive: add `drive ls --all` (alias `--global`) to list across all accessible files; make `--all` and `--parent` mutually exclusive. (#107) — thanks @struong.
48+
- Chat: add `chat messages reactions create|list|delete` to manage emoji reactions on messages; `chat messages react <message> <emoji>` as a shorthand for creating reactions; `reaction` is an alias for `reactions`. (#426) — thanks @fernandopps.
49+
- Tasks: add `--recur` / `--recur-rrule` aliases for repeat materialization, including RRULE `INTERVAL` support for generated occurrences. (#408) — thanks @salmonumbrella.
1150

1251
### Fixed
13-
- Calendar: respond patches only attendees to avoid custom reminders validation errors. (#265) — thanks @sebasrodriguez.
14-
- Secrets: respect empty `GOG_KEYRING_PASSWORD` (treat set-to-empty as intentional; avoids headless prompts). (#269) — thanks @zerone0x.
52+
- Google API: use transport-level response-header timeouts for API clients while keeping token exchanges bounded, so large downloads are not cut short by `http.Client.Timeout`. (#425) — thanks @laihenyi.
53+
- Timezone: embed the IANA timezone database so Windows builds can resolve calendar timezones correctly. (#388) — thanks @visionik.
54+
- Auth: persist rotated OAuth refresh tokens returned during API calls so later commands keep working without re-auth. (#373) — thanks @joshp123.
55+
- Auth: allow pure service-account mode when the configured subject matches the service account itself, instead of forcing domain-wide delegation impersonation. (#399) — thanks @carrotRakko.
56+
- Auth: keep Keep-only service-account fallback isolated to Keep commands so other Google services do not accidentally pick it up. (#414) — thanks @jgwesterlund.
57+
- Auth: add `--gmail-scope full|readonly`, and disable `include_granted_scopes` for readonly/limited auth requests to avoid Drive/Gmail scope accumulation. (#113) — thanks @salmonumbrella.
58+
- Auth: preserve scope-shaping flags in the remote step-2 replay guidance for `auth add --remote`. (#427) — thanks @doodaaatimmy-creator.
59+
- Calendar: preserve full RRULE values and recurring-event timezones during updates so recurrence edits don’t lose BYDAY lists or hit missing-timezone API errors. (#392) — thanks @salmonumbrella.
60+
- Calendar: let recurring `calendar update --scope=future` and `calendar delete --scope=future` start from an instance event ID by resolving the parent series first. (#319) — thanks @salmonumbrella.
61+
- Calendar: use `Calendars.Get` for timezone lookups so service-account flows don’t 404 on `calendarList/primary`. (#325) — thanks @markwatson.
62+
- Calendar: hide cancelled/deleted events from `calendar events` list output by explicitly setting `showDeleted=false`. (#362) — thanks @sharukh010.
1563
- Calendar: reject ambiguous calendar-name selectors for `calendar events` instead of guessing. (#131) — thanks @salmonumbrella.
64+
- Calendar: respond patches only attendees to avoid custom reminders validation errors. (#265) — thanks @sebasrodriguez.
65+
- Calendar: force-send `minutes=0` for `--reminder popup:0m` so zero-minute popup reminders survive Google Calendar API JSON omission rules. (#316) — thanks @salmonumbrella.
66+
- Calendar: clarify that RFC3339 `--from/--to` timestamps must include a timezone while keeping date and relative-time help intact. (#409) — thanks @dbhurley.
67+
- Gmail: add a fetch delay in `watch serve` so History API reads don't race message indexing. (#397) — thanks @salmonumbrella.
68+
- Gmail: preserve the selected `--client` during `watch serve` push handling instead of falling back to the default client. (#411) — thanks @chrysb.
69+
- Gmail: allow Workspace-managed send-as aliases with empty verification status in `send` and `drafts create`. (#407) — thanks @salmonumbrella.
70+
- Gmail: fall back to `MimeType` charset hints when `Content-Type` headers are missing so GBK/GB2312 message bodies decode correctly. (#428) — thanks @WinnCook.
1671
- Gmail: `drafts update --quote` now picks a non-draft, non-self message from thread fallback (or errors clearly), avoiding self-quote loops and wrong reply headers. (#394) — thanks @salmonumbrella.
17-
- Auth: add `--gmail-scope full|readonly`, and disable `include_granted_scopes` for readonly/limited auth requests to avoid Drive/Gmail scope accumulation. (#113) — thanks @salmonumbrella.
72+
- Gmail: preserve `Cc` metadata output in plain `gmail get --format metadata` even when Gmail returns uppercase `CC` headers. (#343) — thanks @salmonumbrella.
1873
- Gmail: `gmail archive|read|unread|trash` convenience commands now honor `--dry-run` and emit action-specific dry-run ops. (#385) — thanks @yeager.
74+
- Sheets: harden `sheets format` against `boarders` typo (JSON and field mask), with clearer error messages. (#284) — thanks @nilzzzzzz.
75+
- Sheets: force-send empty note values so `sheets update-note --note ''` reliably clears notes via the API. (#341) — thanks @Shehryar.
76+
- Contacts: send the required `copyMask` when deleting "other contacts", avoiding People API 400 errors. (#384) — thanks @rbansal42.
77+
- Groups: include required label filters in transitive group searches so `groups list` doesn’t 400 on Cloud Identity. (#315) — thanks @salmonumbrella.
78+
- Sheets: make `sheets metadata --plain` emit real TSV tab delimiters, with regression coverage for plain tabular sheet output. (#298) — thanks @mahsumaktas.
79+
- CLI: show root help instead of a parse error when `gog` is run with no arguments. (#342) — thanks @cstenglein.
80+
- CLI: include the current partial token in fish shell completion so `gog __complete` sees the active word under the cursor. (#123) — thanks @GiGurra.
81+
82+
### Security & Reliability
83+
- Secrets: verify keyring token writes by reading them back, so macOS headless Keychain failures return an actionable error instead of silently storing 0 bytes. (#270) — thanks @zerone0x.
84+
- Secrets: respect empty `GOG_KEYRING_PASSWORD` (treat set-to-empty as intentional; avoids headless prompts). (#269) — thanks @zerone0x.
85+
- Security: require confirmation before public Drive shares, Gmail forwarding filters, and Gmail delegate grants in no-input/agent flows. (#317) — thanks @salmonumbrella.
86+
- Security: redact stored Gmail watch webhook bearer tokens in `gmail watch status` text and JSON output unless `--show-secrets` is set. (#136) — thanks @paveg.
87+
88+
### Tooling & Docs
89+
- Docs: update install docs to use the official Homebrew core formula (`brew install gogcli`). (#361) — thanks @zeldrisho.
90+
- Contacts: fix grouped parameter types in CRUD helpers to restore builds on newer Go toolchains. (#355) — thanks @laihenyi.
91+
- CI: validate release tags and quote the checkout ref in the release workflow to block tag-script injection on manual releases. (#299) — thanks @salmonumbrella.
92+
- Build: refresh the dependency stack to Go 1.26.1, current Go indirects, GitHub Actions v6/v7 pins, and current Cloudflare worker dependencies.
93+
- Keep: request the writable Keep service-account scope now that note create/delete is supported. (#413) — thanks @jgwesterlund.
1994

2095
## 0.11.0 - 2026-02-15
2196

Makefile

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,17 @@ VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo dev)
1414
COMMIT := $(shell git rev-parse --short=12 HEAD 2>/dev/null || echo "")
1515
DATE := $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
1616
LDFLAGS := -X github.com/steipete/gogcli/internal/cmd.version=$(VERSION) -X github.com/steipete/gogcli/internal/cmd.commit=$(COMMIT) -X github.com/steipete/gogcli/internal/cmd.date=$(DATE)
17+
# `make lint` already covers vet-equivalent checks; skip duplicate work in `make test`.
18+
GO_TEST_FLAGS ?= -vet=off
19+
TEST_FLAGS ?=
20+
TEST_PKGS ?= ./...
1721

1822
TOOLS_DIR := $(CURDIR)/.tools
1923
GOFUMPT := $(TOOLS_DIR)/gofumpt
2024
GOIMPORTS := $(TOOLS_DIR)/goimports
2125
GOLANGCI_LINT := $(TOOLS_DIR)/golangci-lint
26+
TOOLS_STAMP := $(TOOLS_DIR)/.versions
27+
TOOLS_VERSION := gofumpt=v0.9.2;goimports=v0.42.0;golangci-lint=v2.10.1
2228

2329
# Allow passing CLI args as extra "targets":
2430
# make gogcli -- --help
@@ -60,9 +66,14 @@ help: gog-help
6066

6167
tools:
6268
@mkdir -p $(TOOLS_DIR)
63-
@GOBIN=$(TOOLS_DIR) go install mvdan.cc/gofumpt@v0.9.2
64-
@GOBIN=$(TOOLS_DIR) go install golang.org/x/tools/cmd/goimports@v0.42.0
65-
@GOBIN=$(TOOLS_DIR) go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.10.1
69+
@if [ -x "$(GOFUMPT)" ] && [ -x "$(GOIMPORTS)" ] && [ -x "$(GOLANGCI_LINT)" ] && [ "$$(cat $(TOOLS_STAMP) 2>/dev/null)" = "$(TOOLS_VERSION)" ]; then \
70+
echo "tools up to date"; \
71+
else \
72+
GOBIN=$(TOOLS_DIR) go install mvdan.cc/gofumpt@v0.9.2; \
73+
GOBIN=$(TOOLS_DIR) go install golang.org/x/tools/cmd/goimports@v0.42.0; \
74+
GOBIN=$(TOOLS_DIR) go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.10.1; \
75+
printf '%s\n' "$(TOOLS_VERSION)" > "$(TOOLS_STAMP)"; \
76+
fi
6677

6778
fmt: tools
6879
@$(GOIMPORTS) -local github.com/steipete/gogcli -w .
@@ -84,7 +95,7 @@ pnpm-gate:
8495
fi
8596

8697
test:
87-
@go test ./...
98+
@go test $(GO_TEST_FLAGS) $(TEST_FLAGS) $(TEST_PKGS)
8899

89100
ci: pnpm-gate fmt-check lint test
90101

0 commit comments

Comments
 (0)