docs: add release process runbook and openapi refresh automation - #112
docs: add release process runbook and openapi refresh automation#112marekdano wants to merge 5 commits into
Conversation
… test coverage Signed-off-by: Marek Dano <mk.dano@gmail.com>
Signed-off-by: Marek Dano <mk.dano@gmail.com>
Signed-off-by: Marek Dano <mk.dano@gmail.com>
Signed-off-by: Marek Dano <mk.dano@gmail.com>
gcgoncalves
left a comment
There was a problem hiding this comment.
The RELEASE.md instructions are clear and simple, I like it! :)
A few considerations about the script:
- The script leans on
gh, supposing the user has it installed on the first place. Can we replace it withgit? - The script ends pushing the changes by default. Do we actually want that?
When running the script locally, I got the following error:
==> Updating ~/Projects/mcp-context-forge
==> Generating openapi.json from 63d69a
2026-09-08T13:23:22 - mcpgateway.config - INFO - Using SQLite database. Consider PostgreSQL for production.
2026-09-08T13:23:22 - mcpgateway.config - INFO - SIEM URL allowlist is empty — all outbound destination URLs are permitted
Traceback (most recent call last):
...
File "~/Projects/mcp-context-forge/mcpgateway/config.py", line 1671, in _enforce_secret_strength
raise SecurityConfigurationError(f"{field_name}: unset placeholder (__REPLACE_ME__) rejected. {remediation}{hint}")
mcpgateway.config.SecurityConfigurationError: jwt_secret_key: unset placeholder (__REPLACE_ME__) rejected. Run 'python -m mcpgateway.scripts.init_secrets' to generate strong values, or use 'make init-secrets-patch-env' to write them directly into .env.
ELIFECYCLE Command failed with exit code 1.This means that .env has no JWT secret set. I think we need to document this and, ideally, handle this error on the script and instruct the user on how to proceed.
| REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" | ||
| API_DIR="${API_DIR_ARG:-${OPENAPI_SOURCE_DIR:-$(dirname "$REPO_ROOT")/mcp-context-forge}}" | ||
|
|
||
| if [[ ! -d "$API_DIR/.git" ]]; then |
There was a problem hiding this comment.
Thanks for adding the dirty-tree guard. Could we also verify this checkout has the canonical IBM/mcp-context-forge remote before checking it out, pulling it, and importing its Python app? Right now any local .git path supplied through the argument or environment variable is trusted and its code runs in the release operator environment.
| f.write("\n") | ||
| PY | ||
|
|
||
| if diff -q "$TMP_SPEC" "$REPO_ROOT/openapi.json" >/dev/null 2>&1; then |
There was a problem hiding this comment.
Nice idempotency check. Could README synchronization happen before this early return, or be evaluated separately? If openapi.json already matches while its README version references are stale, the command reports nothing to do and skips the advertised README update.
|
|
||
| BRANCH="chore/openapi-${API_VERSION}-${API_COMMIT_SHORT}" | ||
| echo "==> Creating branch $BRANCH" | ||
| git -C "$REPO_ROOT" checkout -B "$BRANCH" |
There was a problem hiding this comment.
Could we base this branch explicitly on origin/main? checkout -B uses whichever commit the caller currently has checked out; running from a clean feature or stale branch would make the generated PR include unrelated commits.
- Verify the sibling checkout's remote points at IBM/mcp-context-forge before pulling and importing its Python app - Check README references for staleness independently of the openapi.json idempotency check, so a stale README alone still updates - Base the new branch explicitly on origin/main instead of whatever is currently checked out - Require --push to push/open a PR instead of doing it by default, with gh now optional - Fail fast with a clear message when the sibling repo's .env still has unset secret placeholders Signed-off-by: Marek Dano <mk.dano@gmail.com>
Summary
RELEASE.md, documenting the end-to-end release process: refreshing the pinned API contract, bumping the UI version, taggingmain, and publishing the GitHub release.scripts/refresh-openapi.sh(wired up asnpm run openapi:refresh), automating the "regenerate openapi.json from a sibling mcp-context-forge checkout" step: pulls upstreammain, regenerates the spec, pinsinfo.versionto<API version>+<commit hash>, updates the two README references to that version, regenerates the API client, and opens a signed-off PR with the result. Supports--dry-runto inspect the diff before anything is committed.No application code changes — docs and release tooling only.