Skip to content

Commit 356da43

Browse files
authored
Flip docs default to released + support doc-only releases (#177)
* Flip docs default to released + support doc-only releases Add a private @salesforce/b2c-dx-docs workspace package to enable: - Doc-only releases via changesets without bumping CLI/SDK/MCP versions - Automatic docs rebuild when SDK changes (via updateInternalDependencies cascade) - Changelog tracking for documentation changes Flip the docs deployment so released/stable docs are served at the root URL and dev docs live at /dev/. Previously dev was at root and released docs were at /release/. Update deploy-docs workflow to build stable docs at root from the latest tag (matching both @salesforce/* and docs@* patterns) and nest dev docs under /dev/. Update publish workflow to create docs@<version> tags and trigger docs deployment on stable releases. * Update AGENTS.md with docs workspace package details Document the docs workspace package in the monorepo package listing, Documentation section (build modes, URL structure, doc-only releases, SDK cascade), and Changesets section. * Add docs CI workflow to verify docs build on PRs Runs on PRs that touch docs/ or SDK source (which affects TypeDoc API docs generation). Catches broken docs builds before merge. * Move docs build check into main CI workflow Add a docs build step to ci.yml after package builds instead of a separate docs-ci workflow. Reuses the existing checkout, install, and build steps — more efficient than spinning up a separate runner. * Move docs build deps and config into docs workspace package Move vitepress, typedoc, and typedoc plugins from root devDependencies into docs/package.json. Move typedoc.json into docs/ with adjusted relative paths. Root package.json scripts now proxy to the docs package via pnpm --filter. * List docs as valid changeset package and start at 0.1.0 Add explicit list of valid changeset packages to AGENTS.md and note doc-only changeset guidance. Set docs package version to 0.1.0 to align with the pre-GA versioning of the other packages.
1 parent 556f916 commit 356da43

11 files changed

Lines changed: 196 additions & 81 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ jobs:
5858
- name: Build packages
5959
run: pnpm -r run build
6060

61+
- name: Build documentation
62+
run: pnpm run docs:build
63+
6164
- name: Run SDK tests
6265
id: sdk-test
6366
working-directory: packages/b2c-tooling-sdk

.github/workflows/deploy-docs.yml

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ permissions:
1212

1313
concurrency:
1414
group: pages
15-
cancel-in-progress: false
15+
cancel-in-progress: true
1616

1717
jobs:
1818
build:
@@ -54,20 +54,44 @@ jobs:
5454
- name: Get latest release tag
5555
id: release
5656
run: |
57-
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
57+
# Find the most recent package tag and docs tag
58+
PKG_TAG=$(git describe --tags --abbrev=0 --match '@salesforce/*' 2>/dev/null || echo "")
59+
DOCS_TAG=$(git describe --tags --abbrev=0 --match 'docs@*' 2>/dev/null || echo "")
60+
61+
# Pick whichever tag is closer to HEAD (fewer commits behind)
62+
LATEST_TAG=""
63+
if [[ -n "$PKG_TAG" && -n "$DOCS_TAG" ]]; then
64+
PKG_DISTANCE=$(git rev-list --count "${PKG_TAG}..HEAD")
65+
DOCS_DISTANCE=$(git rev-list --count "${DOCS_TAG}..HEAD")
66+
if [[ "$DOCS_DISTANCE" -le "$PKG_DISTANCE" ]]; then
67+
LATEST_TAG="$DOCS_TAG"
68+
else
69+
LATEST_TAG="$PKG_TAG"
70+
fi
71+
elif [[ -n "$PKG_TAG" ]]; then
72+
LATEST_TAG="$PKG_TAG"
73+
elif [[ -n "$DOCS_TAG" ]]; then
74+
LATEST_TAG="$DOCS_TAG"
75+
fi
76+
5877
echo "tag=$LATEST_TAG" >> $GITHUB_OUTPUT
5978
echo "exists=$([[ -n $LATEST_TAG ]] && echo true || echo false)" >> $GITHUB_OUTPUT
6079
61-
- name: Build main documentation
62-
run: pnpm run docs:build
63-
env:
64-
RELEASE_VERSION: ${{ steps.release.outputs.tag }}
80+
- name: Read CLI version for display
81+
id: cli-version
82+
run: |
83+
CLI_VERSION=$(node -p "require('./packages/b2c-cli/package.json').version")
84+
echo "version=$CLI_VERSION" >> $GITHUB_OUTPUT
6585
66-
- name: Build release documentation
86+
- name: Build dev documentation
87+
run: |
88+
IS_DEV_BUILD=true RELEASE_VERSION=${{ steps.cli-version.outputs.version }} pnpm run docs:build
89+
mv docs/.vitepress/dist docs/.vitepress/dist-dev
90+
91+
- name: Build stable documentation from release tag
6792
if: steps.release.outputs.exists == 'true'
6893
run: |
69-
# Save main build and config (config has version dropdown code)
70-
mv docs/.vitepress/dist docs/.vitepress/dist-main
94+
# Save config from main (has version dropdown and dynamic base path)
7195
cp docs/.vitepress/config.mts /tmp/config.mts
7296
7397
# Remove S3-extracted uxstudio files before checkout to avoid conflicts
@@ -87,14 +111,17 @@ jobs:
87111
# Restore config from main (has version dropdown and dynamic base path)
88112
cp /tmp/config.mts docs/.vitepress/config.mts
89113
90-
# Build at release tag with main's config
114+
# Build at release tag with main's config (no IS_DEV_BUILD = stable at root)
91115
pnpm install --frozen-lockfile
92116
pnpm -r run build
93-
RELEASE_VERSION=${{ steps.release.outputs.tag }} IS_RELEASE_BUILD=true pnpm run docs:build
117+
RELEASE_VERSION=${{ steps.cli-version.outputs.version }} pnpm run docs:build
118+
119+
# Combine: stable at root, dev in /dev/
120+
mv docs/.vitepress/dist-dev docs/.vitepress/dist/dev
94121
95-
# Combine: main at root, release in /release/
96-
mv docs/.vitepress/dist docs/.vitepress/dist-main/release
97-
mv docs/.vitepress/dist-main docs/.vitepress/dist
122+
- name: Use dev as root when no release exists
123+
if: steps.release.outputs.exists != 'true'
124+
run: mv docs/.vitepress/dist-dev docs/.vitepress/dist
98125

99126
- name: Upload artifact
100127
uses: actions/upload-pages-artifact@v3

.github/workflows/publish.yml

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ jobs:
2727
steps:
2828
- name: Checkout
2929
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
30+
with:
31+
fetch-depth: 0 # Needed for docs tag detection
3032

3133
- name: Determine release type
3234
id: release-type
@@ -81,6 +83,16 @@ jobs:
8183
check_package "@salesforce/b2c-cli" "packages/b2c-cli" "cli"
8284
check_package "@salesforce/b2c-dx-mcp" "packages/b2c-dx-mcp" "mcp"
8385
86+
# Check if docs version changed (private package — not published to npm, uses git tag)
87+
DOCS_VERSION=$(node -p "require('./docs/package.json').version")
88+
if git rev-parse "docs@${DOCS_VERSION}" >/dev/null 2>&1; then
89+
echo "publish_docs=false" >> $GITHUB_OUTPUT
90+
else
91+
echo "publish_docs=true" >> $GITHUB_OUTPUT
92+
echo "version_docs=${DOCS_VERSION}" >> $GITHUB_OUTPUT
93+
fi
94+
echo "@salesforce/b2c-docs: version=${DOCS_VERSION}"
95+
8496
- name: Create snapshot versions
8597
if: steps.release-type.outputs.type == 'nightly'
8698
run: |
@@ -147,6 +159,14 @@ jobs:
147159
echo "No tags to create"
148160
fi
149161
162+
- name: Create docs tag if version changed
163+
if: steps.release-type.outputs.type == 'stable' && steps.packages.outputs.publish_docs == 'true'
164+
run: |
165+
DOCS_TAG="docs@${{ steps.packages.outputs.version_docs }}"
166+
git tag "$DOCS_TAG"
167+
git push origin "$DOCS_TAG"
168+
echo "Created docs tag: $DOCS_TAG"
169+
150170
- name: Extract changelogs for release
151171
if: steps.release-type.outputs.type == 'stable'
152172
run: |
@@ -180,6 +200,13 @@ jobs:
180200
extract_latest packages/b2c-tooling-sdk/CHANGELOG.md
181201
echo ""
182202
fi
203+
204+
if [[ "${{ steps.packages.outputs.publish_docs }}" == "true" && -f docs/CHANGELOG.md ]]; then
205+
echo "## Documentation"
206+
echo ""
207+
extract_latest docs/CHANGELOG.md
208+
echo ""
209+
fi
183210
} > /tmp/release-notes.md
184211
185212
- name: Create GitHub Release
@@ -192,6 +219,8 @@ jobs:
192219
RELEASE_TAG="@salesforce/b2c-tooling-sdk@${{ steps.packages.outputs.version_sdk }}"
193220
elif [[ "${{ steps.packages.outputs.publish_mcp }}" == "true" ]]; then
194221
RELEASE_TAG="@salesforce/b2c-dx-mcp@${{ steps.packages.outputs.version_mcp }}"
222+
elif [[ "${{ steps.packages.outputs.publish_docs }}" == "true" ]]; then
223+
RELEASE_TAG="docs@${{ steps.packages.outputs.version_docs }}"
195224
else
196225
echo "No packages published, skipping release"
197226
exit 0
@@ -224,10 +253,16 @@ jobs:
224253
elif [[ "${{ steps.packages.outputs.publish_mcp }}" == "true" ]]; then
225254
RELEASE_TAG="@salesforce/b2c-dx-mcp@${{ steps.packages.outputs.version_mcp }}"
226255
else
227-
echo "No release to upload to"
256+
echo "No package release to upload to"
228257
exit 0
229258
fi
230259
231260
gh release upload "$RELEASE_TAG" b2c-skills.zip b2c-cli-skills.zip
232261
env:
233262
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
263+
264+
- name: Trigger documentation deployment
265+
if: steps.release-type.outputs.type == 'stable'
266+
run: gh workflow run deploy-docs.yml
267+
env:
268+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

AGENTS.md

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ This is a monorepo project with the following packages:
44
- `./packages/b2c-cli` - the command line interface built with oclif
55
- `./packages/b2c-tooling-sdk` - the SDK/library for B2C Commerce operations; supports the CLI and can be used standalone
66
- `./packages/b2c-dx-mcp` - Model Context Protocol server; also built with oclif
7+
- `./docs` - documentation site (private `@salesforce/b2c-dx-docs` workspace package; not published to npm)
78

89
## Common Commands
910

@@ -97,10 +98,33 @@ See [documentation skill](./.claude/skills/documentation/SKILL.md) for details o
9798
# Run docs dev server (from project root)
9899
pnpm run docs:dev
99100

100-
# Build docs for production
101+
# Build docs for production (stable mode — root base path)
101102
pnpm run docs:build
103+
104+
# Build docs in dev mode (/dev/ base path)
105+
IS_DEV_BUILD=true pnpm run docs:build
106+
```
107+
108+
### Docs workspace package
109+
110+
The `./docs` directory is a private workspace package (`@salesforce/b2c-dx-docs`) with a dependency on `@salesforce/b2c-tooling-sdk`. This exists to support doc-only releases and changelog tracking via changesets, not for npm publishing. It has no build script — `pnpm -r run build` skips it.
111+
112+
**Deployed URL structure:** stable/released docs are served at the root URL, dev docs (from `main`) live at `/dev/`.
113+
114+
**Doc-only releases:** to release documentation changes without bumping CLI/SDK/MCP, create a changeset that targets only the docs package:
115+
116+
```md
117+
---
118+
'@salesforce/b2c-dx-docs': patch
119+
---
120+
121+
Improved authentication guide with step-by-step examples
102122
```
103123

124+
This produces a `docs@<version>` tag and triggers a docs rebuild on merge of the version PR.
125+
126+
**Automatic cascade:** because the docs package depends on the SDK, when the SDK version is bumped by a changeset, `updateInternalDependencies: "patch"` auto-bumps the docs version too — triggering a docs rebuild (correct since API docs are generated from the SDK).
127+
104128
## Logging
105129

106130
- when logging use the logger instance from `@salesforce/b2c-tooling-sdk/logger` package
@@ -142,8 +166,9 @@ This project uses [Changesets](https://github.com/changesets/changesets) for ver
142166

143167
**How it works:**
144168
- A changeset affecting only the SDK bumps only the SDK version
145-
- Packages that depend on a bumped package get an automatic patch bump (via `updateInternalDependencies: "patch"`) — e.g., if SDK bumps, CLI and MCP auto-get a patch bump because they depend on it
146-
- Only packages with a newer version than what's on npm get published
169+
- Packages that depend on a bumped package get an automatic patch bump (via `updateInternalDependencies: "patch"`) — e.g., if SDK bumps, CLI, MCP, and Docs all auto-get a patch bump
170+
- Only packages with a newer version than what's on npm get published (docs package is private and uses git tags instead)
171+
- A changeset targeting only `@salesforce/b2c-dx-docs` triggers a doc-only release — no npm packages are published, just a `docs@<version>` tag and docs rebuild
147172

148173
Changeset guidelines:
149174
- Create a changeset for any user-facing changes (features, bug fixes); typically in new pull requests
@@ -157,7 +182,9 @@ Changeset guidelines:
157182
- HOW a consumer should update their code
158183
- Good changesets are brief and user-focused (not contributor); they are generally 1 line or two; The content of the changeset is used in CHANGELOG and release notes. You do not need to list internal implementation details or all details of commands; just the high level summary for users.
159184

160-
create a changeset file directly in `.changeset/` with a unique filename (e.g., `descriptive-change-name.md`):
185+
Valid changeset packages: `@salesforce/b2c-cli`, `@salesforce/b2c-tooling-sdk`, `@salesforce/b2c-dx-mcp`, `@salesforce/b2c-dx-docs`
186+
187+
Create a changeset file directly in `.changeset/` with a unique filename (e.g., `descriptive-change-name.md`):
161188

162189
```md
163190
---
@@ -169,3 +196,4 @@ Description of the change explaining WHAT, WHY, and HOW to update
169196
```
170197

171198
- Include only the packages that were directly modified
199+
- For doc-only changes, target `@salesforce/b2c-dx-docs` instead of the CLI/SDK/MCP packages

docs/.vitepress/config.mts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import typedocSidebar from '../api/typedoc-sidebar.json';
33

44
// Version configuration from environment
55
const releaseVersion = process.env.RELEASE_VERSION || 'unreleased';
6-
const isReleaseBuild = process.env.IS_RELEASE_BUILD === 'true';
6+
const isDevBuild = process.env.IS_DEV_BUILD === 'true';
77

8-
// Base paths - release build lives in /release/ subdirectory
8+
// Base paths - dev build lives in /dev/ subdirectory, stable/release is at root
99
const siteBase = '/b2c-developer-tooling';
10-
const basePath = isReleaseBuild ? `${siteBase}/release/` : `${siteBase}/`;
10+
const basePath = isDevBuild ? `${siteBase}/dev/` : `${siteBase}/`;
1111

1212
// Build version dropdown items
1313
// VitePress prepends base path to links starting with /, so we use relative paths
@@ -18,19 +18,19 @@ function getVersionItems() {
1818
return [{text: 'Development (main)', link: '/'}];
1919
}
2020

21-
if (isReleaseBuild) {
22-
// Release build: base is /b2c-developer-tooling/release/
23-
// Use ../ to navigate up to main docs
21+
if (isDevBuild) {
22+
// Dev build: base is /b2c-developer-tooling/dev/
23+
// Use ../ to navigate up to stable docs at root
2424
return [
25-
{text: 'Development (main)', link: '../'},
26-
{text: 'Latest Release', link: '/'},
25+
{text: 'Latest Release', link: '../'},
26+
{text: 'Development (main)', link: '/'},
2727
];
2828
}
2929

30-
// Main build: base is /b2c-developer-tooling/
30+
// Stable build: base is /b2c-developer-tooling/
3131
return [
32-
{text: 'Development (main)', link: '/'},
33-
{text: 'Latest Release', link: '/release/'},
32+
{text: 'Latest Release', link: '/'},
33+
{text: 'Development (main)', link: '/dev/'},
3434
];
3535
}
3636

@@ -99,15 +99,15 @@ document.addEventListener('click', (e) => {
9999
if (!link) return;
100100
const href = link.getAttribute('href');
101101
// Check if this is a version switch link
102-
if (href && (href.includes('/release/') || href === '../')) {
102+
if (href && (href.includes('/dev/') || href === '../')) {
103103
e.preventDefault();
104104
e.stopPropagation();
105105
if (href === '../') {
106-
// Navigate from /release/ back to main - construct path explicitly
106+
// Navigate from /dev/ back to stable root - construct path explicitly
107107
// to avoid relative path issues with trailing slashes
108108
const path = window.location.pathname;
109-
const mainPath = path.replace(/\\/release\\/.*$/, '/').replace(/\\/release$/, '/');
110-
window.location.href = mainPath;
109+
const stablePath = path.replace(/\\/dev\\/.*$/, '/').replace(/\\/dev$/, '/');
110+
window.location.href = stablePath;
111111
} else {
112112
window.location.href = link.href;
113113
}
@@ -140,7 +140,7 @@ export default defineConfig({
140140
{text: 'CLI Reference', link: '/cli/'},
141141
{text: 'API Reference', link: '/api/'},
142142
{
143-
text: isReleaseBuild ? 'Latest Release' : 'dev',
143+
text: isDevBuild ? 'dev' : `v${releaseVersion}`,
144144
items: getVersionItems(),
145145
},
146146
],

docs/package.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "@salesforce/b2c-dx-docs",
3+
"version": "0.1.0",
4+
"private": true,
5+
"description": "Documentation for B2C Developer Tooling",
6+
"scripts": {
7+
"docs:api": "typedoc",
8+
"docs:dev": "pnpm run docs:api && vitepress dev",
9+
"docs:build": "pnpm run docs:api && vitepress build",
10+
"docs:preview": "vitepress preview"
11+
},
12+
"devDependencies": {
13+
"@salesforce/b2c-tooling-sdk": "workspace:*",
14+
"typedoc": "^0.28.14",
15+
"typedoc-plugin-markdown": "^4.9.0",
16+
"typedoc-vitepress-theme": "^1.1.2",
17+
"vitepress": "^1.6.4"
18+
}
19+
}

docs/typedoc.json

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"$schema": "https://typedoc.org/schema.json",
3+
"entryPoints": [
4+
"../packages/b2c-tooling-sdk/src/config/index.ts",
5+
"../packages/b2c-tooling-sdk/src/auth/index.ts",
6+
"../packages/b2c-tooling-sdk/src/clients/index.ts",
7+
"../packages/b2c-tooling-sdk/src/instance/index.ts",
8+
"../packages/b2c-tooling-sdk/src/logging/index.ts",
9+
"../packages/b2c-tooling-sdk/src/operations/code/index.ts",
10+
"../packages/b2c-tooling-sdk/src/operations/cip/index.ts",
11+
"../packages/b2c-tooling-sdk/src/operations/jobs/index.ts",
12+
"../packages/b2c-tooling-sdk/src/operations/logs/index.ts",
13+
"../packages/b2c-tooling-sdk/src/operations/mrt/index.ts",
14+
"../packages/b2c-tooling-sdk/src/operations/ods/index.ts",
15+
"../packages/b2c-tooling-sdk/src/scaffold/index.ts",
16+
"../packages/b2c-tooling-sdk/src/docs/index.ts",
17+
"../packages/b2c-tooling-sdk/src/schemas/index.ts",
18+
"../packages/b2c-tooling-sdk/src/cli/index.ts",
19+
"../packages/b2c-tooling-sdk/src/i18n/index.ts"
20+
],
21+
"exclude": ["**/*.generated.ts"],
22+
"out": "./api",
23+
"plugin": ["typedoc-plugin-markdown", "typedoc-vitepress-theme"],
24+
"tsconfig": "../packages/b2c-tooling-sdk/tsconfig.json",
25+
"readme": "./api-readme.md",
26+
"excludePrivate": true,
27+
"excludeProtected": true,
28+
"excludeInternal": true,
29+
"hideGenerator": true,
30+
"githubPages": false,
31+
"entryPointStrategy": "resolve",
32+
"docsRoot": ".",
33+
"navigation": {
34+
"includeCategories": true,
35+
"includeGroups": true
36+
}
37+
}

0 commit comments

Comments
 (0)