Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .claude/docs-guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,32 @@ Documentation follows the Diátaxis framework:
- When referencing alternatives in other docs, maintain this order: "Homebrew, shell script, ..." (e.g., "See the Installation Guide for Homebrew, shell script, or other options")
- Both `icp-cli` and `ic-wasm` are available as official Homebrew formulas: `brew install icp-cli` and `brew install ic-wasm`

## Docs-Only Fixes for Released Versions

Versioned docs deployments (e.g. `/0.2/`) are controlled by `docs/vX.Y` tags. To fix or improve docs for an already-released version without cutting a new code release:

**Rule: always merge the change to `main` first.** The `docs/vX.Y` tag is only for immediate deployment — when the next patch release is tagged, `sync-docs-tag.yml` resets `docs/vX.Y` to the new release commit. Any commit that exists only on the tag (not in `main`) will be silently lost at that point.

**Workflow:**

```bash
# 1. Merge the fix to main via a normal PR (always required)

# 2. To immediately deploy the fix to /X.Y/ without waiting for a release:
git fetch --tags
git checkout -b temp/docs-fix-vX.Y docs/vX.Y # start from current tag state
git cherry-pick <commit-sha-from-main> # pick the merged commit(s)

git tag -f docs/vX.Y HEAD
git push origin refs/tags/docs/vX.Y --force # triggers re-deploy of /X.Y/

git branch -D temp/docs-fix-vX.Y # local branch no longer needed
```

The commits remain reachable via the tag — no remote branch is needed.

**On the next release:** `sync-docs-tag.yml` resets `docs/vX.Y` to the release commit. Because the fix was already merged to `main`, the release will contain it, and the reset preserves it automatically.

## Writing Guidelines

- Use "canister environment variables" (not just "environment variables") when referring to runtime variables stored in canister settings — this distinguishes them from shell/build environment variables
Expand Down
14 changes: 13 additions & 1 deletion .claude/skills/release/rollback.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,20 @@ If something fails mid-release, here's how to clean up depending on how far you
git tag -d v$ARGUMENTS
```
If a GitHub Release was already created, delete it first via `gh release delete v$ARGUMENTS --yes`, then delete the tag.
Also revert the `docs/vX.Y` tag that `sync-docs-tag.yml` moved automatically. If a previous patch existed (e.g. rolling back v0.2.3 means docs/v0.2 should revert to v0.2.2), force-move it back:
```bash
MINOR=$(echo "$ARGUMENTS" | sed 's/\.[0-9]*$//')
git tag -f docs/v${MINOR} v${MINOR}.$(( $(echo "$ARGUMENTS" | sed 's/.*\.//') - 1 ))
git push origin refs/tags/docs/v${MINOR} --force
```
If this was the first release of the minor (no previous patch), delete the docs tag instead:
```bash
MINOR=$(echo "$ARGUMENTS" | sed 's/\.[0-9]*$//')
git push origin --delete refs/tags/docs/v${MINOR}
git tag -d docs/v${MINOR}
```
- **Task 3 failed (Release workflow)**: Investigate the failure. The tag still exists. Once fixed, you can re-run the workflow from the GitHub Actions UI. Do **not** delete and re-push the tag — that creates duplicate runs.
- **Task 4 failed (NPM publish)**: NPM publishes are not easily reversible. If the publish partially succeeded, check `npm info @icp-sdk/icp-cli versions` and coordinate with the team. The workflow can be re-triggered from the GitHub Actions UI.
- **Task 5 failed (homebrew-tap)**: If the workflow failed, it can be re-triggered. If the PR was created but has issues, close it and delete the branch `update/icp-cli-beta-$ARGUMENTS` on `dfinity/homebrew-tap` via the GitHub UI. No packages were published.
- **Task 6 failed (docs versions)**: Close the PR and delete the branch. The versioned docs are deployed independently and are unaffected.
- **Task 6 failed (docs versions)**: Close the versions.json PR and delete the branch. The versioned docs at `/X.Y/` are deployed independently by the tag push and are unaffected. The `docs/vX.Y` tag was already moved by `sync-docs-tag.yml` as part of Task 2 — no additional cleanup needed for the tag unless you are also rolling back Task 2.
- **Task 7 (homebrew-core check)**: This task is read-only — no cleanup needed. If it fails, just check manually.
7 changes: 6 additions & 1 deletion .claude/skills/release/task6-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

*Skip if `$ARGUMENTS` is a beta release. Requires Task 2. Runs concurrently with Task 3.*

The tag push triggers a docs deployment workflow that builds and publishes the versioned docs to `/X.Y/` on the `docs-deployment` branch (served at `https://cli.internetcomputer.org/X.Y/`). The `versions.json` PR must not be merged until that deployment succeeds, otherwise the root redirect will point to a path that does not exist yet.
The tag push triggers two automated workflows:

1. **`docs.yml` (`publish-versioned-docs` job):** Builds and publishes the versioned docs to `/X.Y/` on the `docs-deployment` branch (served at `https://cli.internetcomputer.org/X.Y/`). The `versions.json` PR must not be merged until that deployment succeeds, otherwise the root redirect will point to a path that does not exist yet.

2. **`sync-docs-tag.yml`:** Creates or moves the `docs/vX.Y` tag to the new release commit — no manual action required. This keeps the docs-override tag in sync with the latest patch. Because the tag is moved via `GITHUB_TOKEN`, the push does not re-trigger `docs.yml` (GitHub prevents recursive workflow runs from `GITHUB_TOKEN` pushes).
- The reset overwrites any docs-only commits that were on `docs/vX.Y` but not in the release. This is safe as long as the "merge to main first" rule was followed — those commits will be in the release itself. See `.claude/docs-guidelines.md` → "Docs-Only Fixes for Released Versions".

Once the `versions.json` PR merges to `main`, the `publish-root-files` CI job runs automatically and copies `og-image.png`, `llms.txt`, `llms-full.txt`, and `feed.xml` from the new version's folder to the deployment root — no manual step needed.

Expand Down
21 changes: 10 additions & 11 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ on:
tags:
- 'v*'
- '!v*-*' # exclude pre-release tags (e.g. v0.2.0-beta.0)
- 'docs/v*' # docs-only overrides for specific minor versions (e.g. docs/v0.2)
- '!docs/v*-*' # exclude pre-release doc-override tags
branches:
- main
- 'docs/v*'
- '!docs/v*-*' # exclude pre-release doc branches
paths:
- 'docs/**'
- 'docs-site/**'
Expand Down Expand Up @@ -255,9 +255,9 @@ jobs:
destination_dir: main
keep_files: true

# Publish versioned docs - runs on tags (v*) or docs branches (docs/v*)
# Publish versioned docs - runs on release tags (v*) or docs-override tags (docs/v*)
publish-versioned-docs:
if: github.event_name == 'push' && (startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/heads/docs/v'))
if: github.event_name == 'push' && (startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/tags/docs/v'))
needs: build
runs-on: ubuntu-latest
steps:
Expand All @@ -277,22 +277,21 @@ jobs:
working-directory: ./docs-site
run: npm ci

- name: Extract version from tag or branch
- name: Extract version from tag
run: |
if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
# Tag: v0.1.0 -> extract major.minor -> 0.1
# Release tag: v0.1.0 -> extract major.minor -> 0.1
VERSION=${GITHUB_REF#refs/tags/v}
# Strip patch version (0.1.0 -> 0.1)
VERSION=${VERSION%.*}
echo "DOCS_VERSION=${VERSION}" >> $GITHUB_ENV
echo "DOCS_BASE_PATH=/${VERSION}/" >> $GITHUB_ENV
elif [[ "${GITHUB_REF}" == refs/heads/docs/v* ]]; then
# Branch: docs/v0.1 -> extract version -> 0.1
VERSION=${GITHUB_REF#refs/heads/docs/v}
elif [[ "${GITHUB_REF}" == refs/tags/docs/v* ]]; then
# Docs-override tag: docs/v0.1 -> extract version -> 0.1
VERSION=${GITHUB_REF#refs/tags/docs/v}
echo "DOCS_VERSION=${VERSION}" >> $GITHUB_ENV
echo "DOCS_BASE_PATH=/${VERSION}/" >> $GITHUB_ENV
else
echo "❌ Docs should only be published for version tags (v*) or docs branches (docs/v*)"
echo "❌ Docs should only be published for release tags (v*) or docs-override tags (docs/v*)"
echo "Current ref: ${GITHUB_REF}"
exit 1
fi
Expand Down
59 changes: 59 additions & 0 deletions .github/workflows/sync-docs-tag.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Sync docs tag after release

# When a release tag is pushed, create or force-move the docs/vX.Y tag to that
# same commit. This keeps the docs-override tag in sync with the latest patch
# and prevents stale content from being served if someone later moves the tag
# for a docs-only fix on top of an outdated base.
#
# docs/vX.Y tags are the stable mechanism for docs-only updates to an older
# minor version without cutting a new code release. Moving them is intentional
# and requires explicit force-push — unlike branches, they cannot drift by
# accident.
#
# Note: pushes via GITHUB_TOKEN do not trigger other workflow runs, so moving
# the docs/vX.Y tag here will NOT re-trigger publish-versioned-docs in
# docs.yml. Only a human explicitly pushing the tag triggers a re-deploy.

on:
push:
tags:
- 'v*'
- '!v*-*' # exclude pre-release tags (e.g. v0.2.0-beta.0)

permissions:
contents: write

jobs:
sync-docs-tag:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0

- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Extract version info
run: |
TAG=${GITHUB_REF_NAME} # e.g. v0.2.3
PATCH=${TAG#v} # e.g. 0.2.3
MINOR=${PATCH%.*} # e.g. 0.2
echo "TAG=${TAG}" >> $GITHUB_ENV
echo "MINOR=${MINOR}" >> $GITHUB_ENV
echo "DOCS_TAG=docs/v${MINOR}" >> $GITHUB_ENV

- name: Create or move docs tag to release commit
run: |
if git ls-remote --exit-code --tags origin "refs/tags/${DOCS_TAG}" > /dev/null 2>&1; then
git tag -f "${DOCS_TAG}" "${TAG}"
git push origin "refs/tags/${DOCS_TAG}" --force
echo "Moved ${DOCS_TAG} to ${TAG}"
else
git tag "${DOCS_TAG}" "${TAG}"
git push origin "refs/tags/${DOCS_TAG}"
echo "Created ${DOCS_TAG} at ${TAG}"
fi
9 changes: 7 additions & 2 deletions docs-site/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,13 @@ The site is hosted on an IC asset canister and served at `https://cli.internetco
### Triggers

- **Push to `main`**: Rebuilds `/main/` docs and root files (`index.html`, `versions.json`, `robots.txt`, `sitemap.xml`, IC config). Also copies `og-image.png`, `llms.txt`, `llms-full.txt`, and `feed.xml` from the latest versioned deployment to the root.
- **Tags (`v*`)**: Builds versioned docs (e.g., `v0.2.0` → `/0.2/`)
- **Branches (`docs/v*`)**: Updates versioned docs (e.g., `docs/v0.1` → `/0.1/`)
- **Release tags (`v*`)**: Builds and deploys versioned docs (e.g., `v0.2.0` → `/0.2/`). Also triggers `sync-docs-tag.yml` which automatically creates or moves the `docs/v0.2` tag to that same commit — no manual step needed.
- **Docs-override tags (`docs/v*`)**: Redeploys versioned docs for a specific minor version without cutting a new code release (e.g., `docs/v0.1` → `/0.1/`). To trigger a re-deploy, force-move the tag to the desired commit:
```bash
git tag -f docs/v0.2 <commit-sha>
git push origin refs/tags/docs/v0.2 --force
```
Note: `sync-docs-tag.yml` uses `GITHUB_TOKEN` to move the tag after each release, which does **not** re-trigger `docs.yml` (GitHub prevents recursive workflow runs from `GITHUB_TOKEN` pushes). Only a human explicitly pushing the tag triggers a re-deploy.

### Root-level files

Expand Down
Loading