Commit 2eafbe03 authored by xuwang's avatar xuwang
Browse files

feat(release): GITLAB_TOKEN auth, RELEASE_BRANCH auto-detect; uppercase docs



Release module refinements:
- Authenticate with GITLAB_TOKEN / GITLAB_TOKEN_FILE (default ~/.gitlab-token)
  instead of OTICA_SERVER_TOKEN, so a consumer releasing on its own GitLab needs
  no release-specific token var. OTICA's own release points GITLAB_TOKEN_FILE at
  ~/.otica-token via its Makefile. OTICA_SERVER_TOKEN stays the agentic knob.
- RELEASE_BRANCH defaults to "default", which auto-detects the repo's remote
  default branch (main or master) — no per-repo setting needed.

Docs:
- Uppercase docs/ filenames for consistency (HEADLAMP, GKE-IAP-AUTH, RENOVATE,
  GITLAB-RELEASE) and update all references.
- Add a Documentation index to the README and embed the architecture diagram, so
  no doc is orphaned. Add a token-creation reference to GITLAB-RELEASE.md.

Changelog: changed
Co-Authored-By: default avatarClaude Opus 4.8 <noreply@anthropic.com>
parent 05432660
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -115,7 +115,7 @@ Ground every answer in **working examples**, not just prose. Reference corpus:

- **This framework** (`~/.otica`):
  - `docs/` — the prose documentation: `OTICA_TECHNICAL_REFERENCE.md` (deep reference),
    `MIGRATION-EXEC-BRIEFING.md`, `Headlamp.md`, and anything else under `docs/`.
    `MIGRATION-EXEC-BRIEFING.md`, `HEADLAMP.md`, and anything else under `docs/`.
    **Consult `docs/` first** for conceptual / how-does-it-work questions.
  - `makefiles/*.mk` (target definitions + `## descriptions`) and `makefiles/README.md`,
    `scripts/*.sh`, `README.md`, `CONTRIBUTING.md`, `CLAUDE.md`, `envs/` templates.
+2 −2
Original line number Diff line number Diff line
@@ -75,11 +75,11 @@ The `MAKELEVEL` guard prevents re-running on recursive make calls. There is **no

### Releases & Versioning

`VERSION` (repo root) is the semver source of truth; releases are git tags `vX.Y.Z` with a generated `CHANGELOG.md` and a GitLab Release. `makefiles/gitlab-release.mk` (included by the top-level `Makefile`) drives `version` / `release-preview` / `release` / `release-{patch,minor,major}` via the `release-version.sh`, `gitlab-changelog.sh`, `gitlab-release.sh` scripts. The module is GitLab-specific but repo-agnostic: it operates on `RELEASE_REPO_DIR` (default: the dir `make` runs in, so OTICA releases itself), with `VERSION_FILE` / `CHANGELOG_FILE` / `RELEASE_CHANGELOG_MARKER` / `RELEASE_VALIDATE_CMD` overridable — so any GitLab repo (e.g. a docker-xxxx project) can include it. OTICA's top Makefile sets `RELEASE_VALIDATE_CMD = tests/validate.sh all` to gate its own releases. Releases publish to the canonical remote (`RELEASE_REMOTE`, default `origin` = code.stanford.edu; legacy `OTICA_RELEASE_REMOTE` still honored) and authenticate to the **release host** with `OTICA_SERVER_TOKEN[_FILE]` (falls back to `GITLAB_TOKEN`).
`VERSION` (repo root) is the semver source of truth; releases are git tags `vX.Y.Z` with a generated `CHANGELOG.md` and a GitLab Release. `makefiles/gitlab-release.mk` (included by the top-level `Makefile`) drives `version` / `release-preview` / `release` / `release-{patch,minor,major}` via the `release-version.sh`, `gitlab-changelog.sh`, `gitlab-release.sh` scripts. The module is GitLab-specific but repo-agnostic: it operates on `RELEASE_REPO_DIR` (default: the dir `make` runs in, so OTICA releases itself), with `VERSION_FILE` / `CHANGELOG_FILE` / `RELEASE_CHANGELOG_MARKER` / `RELEASE_VALIDATE_CMD` overridable — so any GitLab repo (e.g. a docker-xxxx project) can include it. OTICA's top Makefile sets `RELEASE_VALIDATE_CMD = tests/validate.sh all` to gate its own releases. Releases publish to the canonical remote (`RELEASE_REMOTE`, default `origin` = code.stanford.edu; legacy `OTICA_RELEASE_REMOTE` still honored) and authenticate with `GITLAB_TOKEN`/`GITLAB_TOKEN_FILE` (default `~/.gitlab-token`); OTICA's own release points `GITLAB_TOKEN_FILE` at `~/.otica-token` via its top Makefile. (`OTICA_SERVER_TOKEN[_FILE]` remains the agentic-workflow knob, not the release one.)

**Mirroring:** code.stanford.edu is canonical; gitlab.med is an automatic **push mirror** (branches + tags), so a release pushed to `origin` reaches med on the next mirror sync (GitLab rate-limits push mirrors to about once every 5 minutes). Never release to or push directly at med — it's overwritten to match code. GitLab Release *objects* aren't mirrored (only tags), which is all consumers need to pin.

`CHANGELOG.md` is generated from `Changelog:` git trailers (config in `.gitlab/changelog_config.yml`). Consumers move to a release with `make update-otica` and are nudged to upgrade by `otica-upgrade-check.sh` (release-tag-aware). See the [README](README.md) "Releases & Versioning", [docs/gitlab-release.md](docs/gitlab-release.md) (full module reference: targets, variables, `make gitlab-release-onboarding`, `RELEASE_NOTES_EXTRA_CMD`, docker CI integration), and [CONTRIBUTING.md](CONTRIBUTING.md).
`CHANGELOG.md` is generated from `Changelog:` git trailers (config in `.gitlab/changelog_config.yml`). Consumers move to a release with `make update-otica` and are nudged to upgrade by `otica-upgrade-check.sh` (release-tag-aware). See the [README](README.md) "Releases & Versioning", [docs/GITLAB-RELEASE.md](docs/GITLAB-RELEASE.md) (full module reference: targets, variables, `make gitlab-release-onboarding`, `RELEASE_NOTES_EXTRA_CMD`, docker CI integration), and [CONTRIBUTING.md](CONTRIBUTING.md).

### Agentic Workflow (developer)

+6 −0
Original line number Diff line number Diff line
@@ -11,6 +11,12 @@ OTICA_REPO ?= $(shell git -C $(OTICA_DIR) config --get remote.origin.url 2>/dev/
# this in the repo before tagging; consumers without a validator leave it unset.
export RELEASE_VALIDATE_CMD ?= tests/validate.sh all

# OTICA releases to its hosting server (code.stanford.edu), which differs from a
# consumer's default GITLAB_TOKEN host. gitlab.sh defaults GITLAB_TOKEN_FILE to
# ~/.gitlab-token; point it at OTICA's own token instead. (Consumers releasing on
# their own GitLab just use GITLAB_TOKEN / ~/.gitlab-token — no override needed.)
export GITLAB_TOKEN_FILE ?= $(HOME)/.otica-token

include $(OTICA_DIR)/makefiles/help.mk
include $(OTICA_DIR)/makefiles/gitlab-release.mk

+26 −8
Original line number Diff line number Diff line
@@ -97,16 +97,19 @@ for anything that can change consumer behavior — it is rendered first.

### Cutting a release (maintainers)

From a clean `main` checkout of `~/.otica`, with a token for the **OTICA hosting
server** configured. This is a dedicated variable — `OTICA_SERVER_TOKEN` or
`OTICA_SERVER_TOKEN_FILE` (default `~/.otica-token`) — separate from any consumer
project's `GITLAB_TOKEN`, because the server hosting OTICA may not be the GitLab
server a consumer project deploys against:
From a clean `main` checkout of `~/.otica`, with an api-scoped token for the
**OTICA hosting server** (code.stanford.edu) saved at `~/.otica-token`. OTICA's
top-level `Makefile` points the release at it via `GITLAB_TOKEN_FILE ?=
~/.otica-token` — distinct from a consumer's `~/.gitlab-token`, because the server
hosting OTICA isn't the GitLab server a consumer project deploys against:

```bash
echo '<api-scoped-token-for-otica-server>' > ~/.otica-token && chmod 600 ~/.otica-token
umask 077 && printf '%s' '<api-scoped-token-for-otica-server>' > ~/.otica-token
```

(Consumer repos that include `gitlab-release.mk` need no such override — they
release on their own GitLab using `GITLAB_TOKEN` / `~/.gitlab-token`.)

then:

```bash
@@ -140,7 +143,7 @@ set `RELEASE_NOTES_EXTRA_CMD` to a command whose stdout is appended under the
release header (flows into the preview, `CHANGELOG.md`, and the GitLab Release).

Full module reference (targets, variables, docker CI integration, onboarding):
[docs/gitlab-release.md](docs/gitlab-release.md).
[docs/GITLAB-RELEASE.md](docs/GITLAB-RELEASE.md).

### Mirroring topology

@@ -244,7 +247,7 @@ authoritative, always-current list of targets and descriptions. For per-module i
A few modules have dedicated guides:

- **Renovate** (automated dependency updates) — `renovate.mk` / `renovate-admin.mk` and a
  schedulable GitLab CI template: see **[docs/renovate.md](docs/renovate.md)**.
  schedulable GitLab CI template: see **[docs/RENOVATE.md](docs/RENOVATE.md)**.

## Common Workflows

@@ -386,3 +389,18 @@ my-target: ## Description for help
  `## description`, so it never goes stale.
- **Scripts:** `ls scripts/`, or the
  [Technical Reference — Script Reference](docs/OTICA_TECHNICAL_REFERENCE.md#script-reference).

### Documentation

All long-form docs live in [`docs/`](docs/):

| Doc | What it covers |
|-----|----------------|
| [GUIDE.md](docs/GUIDE.md) | OTICA usage guide — getting started and day-to-day use |
| [WORKFLOWS.md](docs/WORKFLOWS.md) | Common end-to-end workflows |
| [OTICA_TECHNICAL_REFERENCE.md](docs/OTICA_TECHNICAL_REFERENCE.md) | Internal architecture, variable contracts, extension patterns |
| [GITLAB-RELEASE.md](docs/GITLAB-RELEASE.md) | Releases & versioning module (`gitlab-release.mk`) |
| [RENOVATE.md](docs/RENOVATE.md) | Automated dependency updates with Renovate |
| [GKE-IAP-AUTH.md](docs/GKE-IAP-AUTH.md) | Protecting GKE apps with Identity-Aware Proxy |
| [HEADLAMP.md](docs/HEADLAMP.md) | Headlamp Kubernetes dashboard |
| [MIGRATION-EXEC-BRIEFING.md](docs/MIGRATION-EXEC-BRIEFING.md) | Executive briefing: migrating to OTICA |
+35 −15
Original line number Diff line number Diff line
@@ -72,11 +72,13 @@ Key ideas:
   | `CHANGELOG.md` | generated changelog, with the prepend marker line |
   | `.gitlab/changelog_config.yml` | category map + render template for trailers |

3. If your default branch isn't `main`, set it in `env.mk` (the onboarding
   target reminds you):
3. Nothing to configure for the branch: `RELEASE_BRANCH` defaults to `default`,
   which resolves to the repo's **remote default branch** (`main` or `master`)
   at release time. Override only for an unusual setup (e.g. releasing off a
   `release/*` branch):

   ```makefile
   RELEASE_BRANCH=master
   RELEASE_BRANCH=release/3.x   # optional; default = the repo's default branch
   ```

4. Review, commit, and push the scaffolding. Then cut a release:
@@ -112,7 +114,7 @@ above the latest `vX.Y.Z` tag, an optional validation hook, and a confirm prompt
|----------|---------|---------|
| `RELEASE_REPO_DIR` | `$(CURDIR)` | repo to release |
| `RELEASE_REMOTE` | `origin` (legacy `OTICA_RELEASE_REMOTE` honored) | canonical git remote |
| `RELEASE_BRANCH` | `main` | release branch |
| `RELEASE_BRANCH` | `default` → the repo's remote default branch (`main`/`master`) | release branch |
| `VERSION_FILE` | `<repo>/VERSION` | version file |
| `CHANGELOG_FILE` | `<repo>/CHANGELOG.md` | changelog file |
| `RELEASE_CHANGELOG_MARKER` | `<!-- New release sections are prepended below this line` | line after which notes are inserted |
@@ -198,22 +200,40 @@ before releasing.
## Authentication

The release talks to the GitLab REST API (changelog + Release object) and needs
an **api-scoped token for the release host**. Resolution order
([`otica-server-token.sh`](../scripts/otica-server-token.sh)):
an **api-scoped token for the release host**.

1. `OTICA_SERVER_TOKEN` (env)
2. `OTICA_SERVER_TOKEN_FILE` (default `~/.otica-token`)
3. `GITLAB_TOKEN`
**Create one and save it locally.** Generate a Personal Access Token with the
`api` scope (Developer role or higher) on your GitLab server — for med that's
[`https://gitlab.med.stanford.edu/-/profile/personal_access_tokens`](https://gitlab.med.stanford.edu/-/profile/personal_access_tokens)
(see GitLab's [Personal Access Tokens docs](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html))
— then save it to a local file with no trailing newline:

> **Host-shadowing gotcha.** Because the default file `~/.otica-token` usually
> exists (the OTICA-host token), a consumer releasing on a *different* GitLab
> host who sets only `GITLAB_TOKEN` gets it **shadowed** → `401`. On a consumer
> host, set the token explicitly:
```bash
umask 077 && printf '%s' '<your-api-token>' > ~/.gitlab-token   # no trailing newline
```

> **No newline.** A trailing `\n` in the token file produces a malformed header
> and a `401`. Use `printf '%s'` (not `echo`).

Resolution ([`gitlab.sh`](../scripts/gitlab.sh)):

1. `GITLAB_TOKEN` (env)
2. `GITLAB_TOKEN_FILE` (default `~/.gitlab-token`)

So on your own GitLab, `make release-*` just works once `~/.gitlab-token` exists —
no release-specific variable needed.

> **Releasing on a non-default host.** To release a repo on a GitLab host other
> than your usual `~/.gitlab-token`, point `GITLAB_TOKEN_FILE` at that host's
> token:
>
> ```bash
> export OTICA_SERVER_TOKEN_FILE=~/.gitlab-token   # or OTICA_SERVER_TOKEN=…
> make release-patch
> make release-patch GITLAB_TOKEN_FILE=~/.other-host-token
> ```
>
> OTICA itself does this for its own releases: its top-level `Makefile` sets
> `GITLAB_TOKEN_FILE ?= ~/.otica-token` (code.stanford.edu), distinct from a
> consumer's `~/.gitlab-token`.

---

Loading