docs-stack-release
Original:🇺🇸 English
Translated
Coordinate Elastic Stack docs releases: classify versions, route 8.x vs 9.x PRs, edit elastic/dev tracking issues, handle same-GA supersession, draft Slack #docs reminders, and watch docs-internal-workflows deploys. Use when the user says "how's my release", "how's my release doing", or asks for release status; also when coordinating docs releases, opening coordinator PRs, editing elastic/dev issues, drafting release reminders, or working with assembler.yml, versions.yml, or conf.yaml.
7installs
Added on
NPX Install
npx skill4agent add elastic/elastic-docs-skills docs-stack-releaseTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →Docs release issue ( in ) is the source of truth -- not the eng issue. Create missing docs issues (§1.1) or collect dates from the user. Missing issue URLs: .
[Docs release] X.Y.Zelastic/dev[Release](issue TBD)| Line | Repo | Config files | Deploy watch |
|---|---|---|---|
| 9.x+ | | | |
| 8.x / 7.x | | | None -- do not use |
Invariants
- IDs, dates, PR URLs, @mentions: from , the docs issue, Slack, or the user. Never invent. Missing →
ghor(issue TBD)and ask.[@handle] - Never mix 8.x and 9.x in one PR. 8.x/7.x: only; no
elastic/docs.docs-internal-workflows - Checklist is the step index. Live-fetch only open work. RN merge is not a checkbox -- always blocking RN URLs.
gh pr view - A PR URL in the RN table is blocking until merged. Skip only /
No changes. Do not exempt Fleet, Agent, or any product by name.N/A - Check boxes this skill just completed. Do not check anyone else's work (including docs-eng). Do not wait to be asked.
- Slack: read slack-templates.md before drafting or sending. Confirm before send; thread follow-ups on the FF announcement.
- Live/released Slack only after the gate (§0.3) and a user eyeball of the site. Do not draft before the gate.
- Empty args / "how's my release": session state → active docs issue. Do not ask which version if one is in flight. After closed-issue cleanup leaves none, stop -- do not rediscover.
- Cleanup = docs issue only. 404 = drop that ID and rediscover. No TTL.
CLOSED - RC varies each release -- read from the coordination thread or eng issue. Never hardcode a name.
#mission-control - Do not offer a Slack ping or PR whose issue box is already checked, or that the user already said they sent.
Inputs
$ARGUMENTSelastic/dev9.4.0 9.3.4 8.19.15#1234 #1235"How's my release" / "how's my release doing" (no versions given): empty-args status. Load session state and run §0. Do not ask which version if an active release is in state. If cleanup left no versions, say the tracked issues are closed and stop.
Match the user's request to the relevant section (status, PRs, reminders) -- they may skip the full pipeline.
0. Check status (run on every invocation)
When versions or issue numbers are known (from or session state), check state before proposing actions.
$ARGUMENTS0.1 Session state (fast path)
Path: . Local coordinator cache -- never commit it.
~/.elastic-docs/stack-release-state.jsonOn every invocation:
- Read the file. Fall back to scratch if missing, unreadable, invalid JSON, no matching version, or the user says "start fresh".
- Cached IDs only skip discovery: ,
docsIssue,engIssue,coordinatorPrs.{repo:{number,sha,url}},rnPrs[].{product,url},slack.{docsChannelId,docsFfThreadTs,missionControlChannelId,coordinationThreadTs,beginPublishingTs,handles}(9.x only:deploys,configSha,stagingBumpPr,prodBumpPr,stagingRunId). AlsoprodRunId,line,type.anticipatedDate - Live-refresh only what the docs issue still has open (§0.2). Do not re-/
gh pr viewchecked lines. Always live-refresh RN PR merge state (the table stores URLs, not merge). Never trust cached JSON for merge/deploy conclusions; do trust a checked issue line that already cites a PR or run URL.gh run view - Cached ID 404 / missing message: drop that field and rediscover just that piece. Empty on a Buildkite/bot parent (
slack_read_thread,begin publishing) is not a 404.release build declared - End of §0: drop CLOSED docs issues, then write or delete the file.
deploysClosed-issue cleanup: Finished only if is . Report status this turn, then drop that version from and . while OPEN is not enough. A 404 is not finished -- drop and rediscover (step 4).
stateCLOSEDreleasesactiveannounceddocsIssue- Some versions still open: write remaining entries + now. Mention which version was dropped.
updatedAt - None remain: delete the file. Do not write . Mention that local state was cleared.
{ "active": [], "releases": {} }
0.2 Stage from the docs issue (do this before extra fetches)
After session state, the first GitHub call is . Parse checkboxes immediately. Jump to that stage. Do not walk §1–§5. Do not re-verify checked lines.
gh issue viewbash
gh issue view <N> -R elastic/dev --json body,state| If the issue shows | Stage | Live-fetch only |
|---|---|---|
| Docs issue CLOSED | done / cleanup | None. Report closed, then closed-issue cleanup (§0.1). |
| Day-before ping or coordinator-PR box unchecked | pre-release | Coordinator PR search (if no cached number) + RN table URLs. Skip |
| Coordinator PR checked, merge-RN ping unchecked | waiting to tell writers | RN PR states + (release day only) cached |
Config-merge / prod-bump (9.x) / | waiting on publish infra | That PR/deploy (§0.3 for 9.x) + RN PR states + cached |
Prod-bump line checked with a run URL (9.x), or | waiting on RNs / announce | RN PR merge states only. Skip coordinator |
Website-confirm and | announced | Report done. No extra fetches unless the user asks. |
RN merge is never a checkbox. Always each blocking RN URL.
gh pr viewIf a checked line's cited URL 404s, rediscover that line only.
Stakeholder resolution (§ below): run only when a row still has a placeholder, a "specify who's responsible" footnote, or 2+ named people. Skip the FF-thread search when every row already has a single named stakeholder.
#docsGitHub state
If session state has the docs issue number, it directly. Otherwise search . Do not by version if the issue or session state already has the coordinator PR URL.
gh issue view[Docs release] <version>gh pr listSearch coordinator PRs only when §0.2 still needs them, and only in the repo for that line (9.x → , 8.x → ). Never for a 9.x-only batch.
docs-builderdocsgh pr listelastic/docsbash
gh pr list -R elastic/docs-builder --search "<version>" --json number,title,state,url
gh pr list -R elastic/docs --search "<version>" --json number,title,state,url- Issue checkboxes: If an item is unchecked but this skill already completed it (a Slack message you sent, a PR you opened), check it now using §4. Do not ask. Do not check items for work this skill did not do.
- RN PR status: One shell loop over every PR URL in the Release Notes table:
bash
gh pr view <url> --json state,mergedAt,titleSkip vs blocking: Skip only / . A PR URL is blocking until merged -- do not exempt Fleet, Agent, or any other product by name. Named stakeholder is the owner; do not add on a named row.
No changesN/A?Report: X/Y merged (skipping N/A rows), Z outstanding. When all blocking RN PRs are merged: "All RN PRs merged."
Then, by line -- only if §0.2 says publish infra is still open:
- 9.x: After the coordinator PR is merged and the prod-bump issue line is still unchecked, continue to §0.3. If that line is already checked with a run URL, skip §0.3.
docs-builder - 8.x / 7.x: Skip §0.3. Config lives in . No
elastic/docsbump or deploy.docs-internal-workflows
Resolve stakeholder assignments
Run only when a row still needs it (§0.2). Cases: backtick placeholder (e.g. ) or "specify who's responsible" footnote; 2+ named people and one confirmed in thread; named stakeholder out and someone else confirmed covering.
`Beats point person`- FF announcement thread (for the version in
slack_search_public, then#docs).slack_read_thread - Scan replies: "I can handle [product]", "I'll do [product]", "I'm drafting the X.Y.Z [product] release notes", or explicit coverage.
- Reverse-map Slack display name → GitHub handle via the issue appendix lookup table. If missing, and ask the user for the GitHub handle.
slack_search_users - Update the issue body (§4): replace placeholder, narrow to the confirmed person, or swap in the covering person.
- Report: "Updated [Product] stakeholder: [old] → @new-handle (confirmed in thread)."
No confirmation: leave as-is and flag. Do not guess. Ambiguous ("I can help" with no product): ask.
#mission-control (release day only)
If session state has thread timestamps, those first.
slack_read_threadDo not the whole of . Do not for without a version and today's date.
slack_read_channel#mission-controlslack_search_public"begin publishing"after:Empty thread on / is expected for Buildkite bot posts. Treat the parent as the signal; do not rediscover.
beginPublishingTsreleaseBuildDeclaredTsOnly search when a needed cached ts is missing (not merely an empty thread): query like , limit 5.
slack_search_public9.5.2 in:#mission-control after:YYYY-MM-DDSignals matching tracked versions (link each thread in the status report):
- Coordination thread: "Coordination for ... release, scheduled on" -- timing, who's RC (never assume), schedule changes in replies.
- "release build declared": "We are officially declaring X.Y.Z as the release build".
- "begin publishing": "All pre-finalize steps for X.Y.Z are complete. Please begin the publishing process." -- docs action trigger. Read for go/hold from whoever is RC (step 1).
0.3 Watch docs-internal-workflows
(9.x only)
docs-internal-workflowsSkip this section for 8.x / 7.x. Do not search that repo, do not poll bump PRs or version-bump runs, and do not require a prod version-bump for 8.x live messages.
Skip §0.3 when the docs issue already checks the "Watch for the prod version-bump deploy" line (or equivalent) and cites a successful prod run URL. Do not re-list bump PRs or re-view runs.
For 9.x, after the coordinator PR merges and that issue line is still unchecked:
docs-builderThe coordinator merges docs-builder config PRs and watches the prod version-bump. Do not wait on docs engineering. Merging the coordinator PR (config SHA = merge commit short SHA) automatically opens:
[bump] [staging] docs-builder configuration: <sha>[bump] [prod] docs-builder configuration: <sha>
Those merges kick off and .
Staging / Docs / Deploy / version-bump / ...Prod / Docs / Deploy / version-bump / ...Care about two things only:
- Bump PRs merged -- staging and prod are
[bump] ... <sha>.MERGED - Prod version-bump deploy succeeded for that SHA. A failed staging version-bump blocks -- report immediately; do not treat prod as done.
Ignore unrelated workflows (edge, AI enrich, zizmor, dependabot, assembler ingest, link-index) unless the user asks. Do not wait on staging success once prod has succeeded, as long as staging did not fail.
bash
gh pr list -R elastic/docs-internal-workflows --state all \
--search "[bump] docs-builder configuration: <sha>" \
--json number,title,state,mergedAt,url
gh run list -R elastic/docs-internal-workflows --limit 20 \
--json name,conclusion,status,displayTitle,url,databaseId,createdAtMatch runs by in the name plus timing after the bump PR merge. Cache bump PR numbers and run IDs.
version-bumpWhen prod version-bump is and staging did not fail: "Prod deploy succeeded for <sha>."
completed/successGate -- do not draft "docs are live" / "docs released" until all required:
| Line | Gate |
|---|---|
| 9.x | All blocking RN PRs merged and prod version-bump succeeded (staging did not fail) |
| 8.x / 7.x | All blocking RN PRs merged and the |
Until the gate is met: do not draft those messages, do not ask "ready to send?", do not check website-confirm or boxes.
#mission-controlOnce the gate is met: ask the user to eyeball the website, then §6.5. Visual check is required before sending. 8.x "docs released" still includes the scrape line.
Propose next action
Summarize the §0.2 stage, what is still blocking, and the single next action. Do not offer a Slack ping or PR whose box is already checked / the user already sent.
1. Gather inputs
- Semver list.
- Docs release issue(s) -- , not the eng release issue.
[Docs release] X.Y.Z.gh issue list -R elastic/dev --search "[Docs release] <version>" --json number,title,url - Eng release issue -- RC's parent (,
[Release] X.Y.Z, etc.). Canonical schedule (FF, GA), often links to docs issues, identifies the RC. Use for dates when the docs issue does not exist yet, which versions share a GA, and RC name.X.Y.Z release - If docs issues don't exist yet, §1.1.
1.1 Create docs release issues (when they don't exist)
- Template: 9.x minor → ; 9.x patch →
docs-release.md; 8.x →docs-patch-release.md.docs-patch-release-8.x.md - Dates from the eng release issue (feature freeze, anticipated GA). If none, ask the user for those two only. Merge release notes by = the calendar day before anticipated GA (). Do not ask for merge-by or code freeze.
[DAY_BEFORE_RELEASE_DATE] gh issue create -R elastic/dev --template <template-file> --title "[Docs release] <version>"- Fill Overview (version, dates) and the release coordinator from the eng issue if listed. Leave the rest of the template as-is -- do not copy stakeholders from a previous release.
- Report: "Created #NNNN for X.Y.Z. Filled in dates from eng issue #MMMM. Please review."
- If the eng issue doesn't already reference the new docs issue:
gh issue comment <eng-issue> -R elastic/dev --body "Docs tracking: https://github.com/elastic/dev/issues/<new-docs-issue>"
User-provided schedule wins over the eng issue.
2. Classify each version
Patch if the patch number ; minor if ; major if (follow the dev issue + v8/v9 playbooks). Then route with §3.
> 0V.R.0V.0.03. Route PRs (decision)
8.x / 7.x (patch or minor)
Follow elastic-stack-v8.md. Coordinator PRs target only (, per template).
elastic/docsshared/versions*conf.yaml9.x -- isolated patch (only one 9.x in the batch, or no higher minor same GA)
- Patch: One PR: bump
elastic/docs-buildersoconfig/versions.ymlmatches the minor line you ship (e.g.versioning_systems.stack.current-> minor 9.3). Link on the9.3.4checklist line.versions.yml - Timing gate: Don't open this PR if more patch releases are expected on the same minor line before GA. If the current published version is more than one patch behind (e.g. current , shipping
9.3.2), an intermediate patch is likely first -- wait or confirm with the user.9.3.4
9.x -- minor (9.x.0
)
9.x.0Two separate draft PRs (two checklist lines):
| When | Branch / change | Link on dev issue |
|---|---|---|
| After FF | | Post-FF line -- PR or merge commit (shape) |
| Before GA (see timing below) | | Nested |
Timing for the versions.yml PR (minors): Don't open early -- many patches land between FF and GA. Open when no more patches are expected before GA (typically 1-2 days before). Check or ask if another patch is queued.
#mission-controlThe coordinator merges each docs-builder PR when it is time; bump PRs and deploys are automatic. Do not substitute one PR for both post-FF assembler and pre-GA versions.yml steps.
Same calendar GA: multiple 9.x (e.g. 9.3.4
+ 9.4.0
)
9.3.49.4.0Only one will be a minor -- the others are patches. There will not be two minors on the same day.
- Assembler PR: The minor still gets its own post-FF PR (
assembler.ymlbump).stack.next - versions.yml PR: Only one -- targets the highest version in the batch.
- Canonical issue = highest 9.x minor (owns the versions.yml PR).
- Lower-line issue = lower semver patch: still for RNs; do not duplicate the versions.yml bump -- supersede to canonical (§4).
4. Edit elastic/dev
issue bodies
elastic/dev- Main trail in the description, not comments.
- Do not delete template placeholders, footnotes, or stakeholder tables -- only add checkmarks, links, strikethrough, short cross-refs.
- Real / PR URLs from
#or the user -- never guess numbers.gh - Check off as you go. After any skill-flow action that matches a checklist item, check it immediately. Nested boxes for the same action get checked together. Do not wait to be asked. Do not report the item as pending.
- Do not check items you did not complete. Other teams' steps (including docs-eng), user-completed work outside this skill, and future release-day items stay unchecked.
- After each coordinator PR this skill opens: check the parent and nested lines and paste the PR URL (minors: post-FF vs version-bump have different URLs on different lines).
Match by checklist wording, not by assuming one template:
| Skill action | Checklist line |
|---|---|
Outstanding-RNs / day-before | Post in #docs to remind ... PRs that have not been opened and/or approved |
| Coordinator PR opened | Open a PR ... plus the nested versions.yml / assembler.yml / conf.yaml line |
Merge-RN | Post in #docs ... they can merge their release note PRs |
| Coordinator PR merged | Merge the docs-builder config PR (or the 8.x equivalent) |
| Prod version-bump deploy succeeded (9.x only) | Watch for the prod version-bump deploy -- check only after §0.3 prod deploy success (staging did not fail). Do not use this line for 8.x. |
| User confirmed website eyeball | Confirm that the updated docs appear on the website -- only after the gate (§0.3) and the user says the site looks right |
| Post in #mission-control that the docs are live -- only after the gate and website eyeball; still confirm before sending Slack |
bash
gh issue view <N> -R elastic/dev --json body -q .body > /tmp/dev-issue.md
gh issue edit <N> -R elastic/dev --body-file /tmp/dev-issue.mdSame-GA supersession (lower-line issue)
- Stakeholder blocks: (real number).
superseded by #<canonical> - Checklist blocks owned by canonical: wrap in , tag e.g.
~strikethrough~.[not needed: superseded by 9.4.0 -- #<canonical>] - Optional footer:
Crossed out instructions superseded by https://github.com/elastic/dev/issues/<canonical> - RN-only coordinator steps may stay open on the lower-line issue ("verify/publish this version's release notes"); strike only lines that duplicate canonical deploy work.
PR opened against the wrong issue's path: close with Superseded by .
owner/repo#N5. Open coordinator PRs (elastic/docs
/ elastic/docs-builder
)
elastic/docselastic/docs-builderBranch: (e.g. , , ) -- no prefix, no / "day before" in the name. Existing checkout if available; otherwise clone to a temp directory.
stack-<version>stack-9.5-post-ffstack-9.5stack-8.19.16docs/pre-gabash
gh pr create -R elastic/<repo> --draft --base main --head <branch> \
--title "<concise title -- no Draft prefix>" \
--body "## Refs\n\n- https://github.com/elastic/dev/issues/<N>"Mark ready only in the right window. Re-draft: .
gh pr ready <num> -R elastic/<repo> --undoImmediately after the PR exists: check the matching docs-issue lines and paste the PR URL (§4).
6. Reminders & messages (#docs
, Slack)
#docsCopy dates, issue links, products, and outstanding PR status from the docs issue (or user-provided schedule). Never invent versions, PR state, or @mentions.
If the body is not already in context from §0, . Parse: version from title/Overview; anticipated GA / FF / merge-by from Overview; stakeholders and RN PR column from the Release Notes table. Skip vs blocking as in §0. URL present = blocking until merged.
gh issue view <N> -R elastic/dev --json title,url,bodyGrouping: 8.x and 9.x tables often differ -- separate "Ping for ..." sections when they do; merge duplicate product lines when the same stakeholders apply to multiple versions.
Unresolved stakeholders and Slack send/preview: slack-templates.md.
Templates, mentions, send
Read slack-templates.md for templates, handle lookup, and OOO checks. If the user doesn't specify the reminder type, present options: feature freeze, outstanding RNs, docs released, or other.
Docs-released: one version → singular template ( / ); two or more → plural ( / ). Never "versions" / "all" for a single version. Omit the 8.x scrape line on a 9.x-only batch.
versionare releasedversionsare all releasedSend (do this even if you skip the templates file):
- Preview in a fenced code block (slack-templates.md) so line breaks are preserved. Then "Send?"
- Wait for confirmation. "Send it" / "looks good" counts. "Update the thread" / "check the boxes" does not.
- Payload mentions: people ; user groups
<@U…>. Never guess an ID.<!subteam^S…> - Follow-ups: thread on the FF announcement () and
docsFfThreadTs.reply_broadcast: true - After send: check the matching docs-issue item (§4).
6.5 Replying in #mission-control threads (release day)
Do not enter until the gate is met (§0.3): 9.x = blocking RNs merged + prod version-bump; 8.x = blocking RNs merged + coordinator PR merged. If not met, say what is outstanding and stop -- do not draft live/released messages.
elastic/docsOnce the gate is met:
- Ask the user to eyeball the website (9.x: current docs / this version's release notes; 8.x: v8 playbook pages).
- After they confirm: check the "docs appear on the website" box (§4). Draft the reply (
#mission-control) and theX.Y.Z docs are live."docs released" ping (8.x scrape line only when an 8.x version is in the batch). Show both; send only with confirmation (slack-templates.md).#docs - On confirm: reply in the begin-publishing thread (from §0), send the
thread_tsping, and check the#docsbox.#mission-control
7. Background poller (in-session)
When the user says "watch the PRs", "watch the deploy", or "let me know when they're all merged":
7.1 Release-note PRs
- Blocking RN PR URLs from the issue table (skip N/A / No changes only).
- Background shell () every 5 minutes:
block_until_ms: 0.gh pr view <url> --json state -q .state - All → emit
MERGED(ALL_RN_PRS_MERGED).notify_on_output - Report: "All RN PRs are merged." Persist to the session file.
7.2 docs-internal-workflows deploys (9.x only)
Skip for 8.x / 7.x.
After the 9.x coordinator PR is merged (or when the user asks to watch 9.x deploys):
docs-builder- Config SHA + staging/prod bump PRs + version-bump run IDs (§0.3). Prefer session state.
- Poll every 30s. Emit
gh run view <id>(blocks; alert immediately),DEPLOY_STAGING_FAILED,DEPLOY_PROD_FAILED(prodDEPLOY_PROD_DONEand staging did not fail).completed/success - On : "Prod deploy succeeded." If blocking RN PRs are still open, list them -- do not offer live/released Slack. If they are all merged, ask the user to eyeball, then §6.5.
DEPLOY_PROD_DONE - Write run IDs and conclusions to session state.
Pollers only run in the current session. Next session: §0.1 + §0, not full rediscovery.
For anything not specified here (API docs, Buildkite): follow the docs issue checklist and playbooks.