Skip to content

Commit 7849ecf

Browse files
milldrclaude
andcommitted
feat: add documentation versioning with GitHub release automation
- Add version dropdown to navbar for switching between doc versions - Create GitHub Actions workflow to auto-create doc versions on major releases (v1, v2, etc.) - Initialize v1 as the first versioned snapshot of current docs - Configure Docusaurus versioning with "Latest" label for current docs The workflow triggers on GitHub releases matching ^v[0-9]+$ pattern and: - Creates versioned_docs/version-{version}/ snapshot - Updates versions.json - Commits changes back to the repo 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 6ac3d15 commit 7849ecf

579 files changed

Lines changed: 53108 additions & 2 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
name: "Create Doc Version on Major Release"
2+
3+
on:
4+
release:
5+
types:
6+
- published
7+
8+
workflow_dispatch:
9+
inputs:
10+
version:
11+
description: 'Version to create (e.g., v1, v2). Leave empty to use latest release tag.'
12+
required: false
13+
type: string
14+
15+
permissions:
16+
contents: write
17+
18+
jobs:
19+
create-version:
20+
runs-on: ubuntu-latest
21+
# Only run on major version releases (v1, v2, v3, etc.) or manual dispatch
22+
if: |
23+
github.event_name == 'workflow_dispatch' ||
24+
(github.event_name == 'release' && github.event.release.tag_name matches '^v[0-9]+$')
25+
26+
steps:
27+
- name: Checkout Repository
28+
uses: actions/checkout@v4
29+
with:
30+
fetch-depth: 0
31+
token: ${{ secrets.GITHUB_TOKEN }}
32+
33+
- name: Setup Node.js
34+
uses: actions/setup-node@v4
35+
with:
36+
node-version-file: '.nvmrc'
37+
cache: 'npm'
38+
39+
- name: Install Dependencies
40+
run: npm ci
41+
42+
- name: Determine Version
43+
id: version
44+
run: |
45+
if [ -n "${{ github.event.inputs.version }}" ]; then
46+
VERSION="${{ github.event.inputs.version }}"
47+
else
48+
VERSION="${{ github.event.release.tag_name }}"
49+
fi
50+
echo "version=$VERSION" >> $GITHUB_OUTPUT
51+
echo "Creating doc version: $VERSION"
52+
53+
- name: Check if Version Already Exists
54+
id: check
55+
run: |
56+
if [ -f "versions.json" ]; then
57+
if jq -e --arg v "${{ steps.version.outputs.version }}" '.[] | select(. == $v)' versions.json > /dev/null 2>&1; then
58+
echo "exists=true" >> $GITHUB_OUTPUT
59+
echo "Version ${{ steps.version.outputs.version }} already exists in versions.json"
60+
else
61+
echo "exists=false" >> $GITHUB_OUTPUT
62+
fi
63+
else
64+
echo "exists=false" >> $GITHUB_OUTPUT
65+
fi
66+
67+
- name: Create Doc Version
68+
if: steps.check.outputs.exists != 'true'
69+
run: |
70+
VERSION="${{ steps.version.outputs.version }}"
71+
72+
# Create versioned docs directory (Docusaurus requires version- prefix)
73+
mkdir -p "versioned_docs/version-${VERSION}"
74+
cp -r docs/* "versioned_docs/version-${VERSION}/"
75+
76+
# Create versioned sidebar (Docusaurus requires version- prefix)
77+
mkdir -p versioned_sidebars
78+
node -e "const s = require('./sidebars.js'); console.log(JSON.stringify(s, null, 2));" > "versioned_sidebars/version-${VERSION}-sidebars.json"
79+
80+
# Update versions.json (prepend new version to maintain order)
81+
if [ -f "versions.json" ]; then
82+
jq --arg v "$VERSION" '. = [$v] + .' versions.json > versions.json.tmp && mv versions.json.tmp versions.json
83+
else
84+
echo "[\"$VERSION\"]" > versions.json
85+
fi
86+
87+
echo "Created version $VERSION"
88+
89+
- name: Commit and Push Version
90+
if: steps.check.outputs.exists != 'true'
91+
run: |
92+
git config --local user.email "github-actions[bot]@users.noreply.github.com"
93+
git config --local user.name "github-actions[bot]"
94+
git add versions.json versioned_docs/ versioned_sidebars/
95+
git commit -m "docs: create version ${{ steps.version.outputs.version }}
96+
97+
Automatically created from release ${{ github.event.release.tag_name || steps.version.outputs.version }}
98+
99+
[skip ci]"
100+
git push origin HEAD:${{ github.ref_name }}
101+
102+
- name: Summary
103+
run: |
104+
VERSION="${{ steps.version.outputs.version }}"
105+
if [ "${{ steps.check.outputs.exists }}" == "true" ]; then
106+
echo "## Version Already Exists" >> $GITHUB_STEP_SUMMARY
107+
echo "Version **${VERSION}** already exists. No changes made." >> $GITHUB_STEP_SUMMARY
108+
else
109+
echo "## Doc Version Created" >> $GITHUB_STEP_SUMMARY
110+
echo "Successfully created documentation version **${VERSION}**" >> $GITHUB_STEP_SUMMARY
111+
echo "" >> $GITHUB_STEP_SUMMARY
112+
echo "### Files Created" >> $GITHUB_STEP_SUMMARY
113+
echo "- \`versioned_docs/version-${VERSION}/\`" >> $GITHUB_STEP_SUMMARY
114+
echo "- \`versioned_sidebars/version-${VERSION}-sidebars.json\`" >> $GITHUB_STEP_SUMMARY
115+
echo "- Updated \`versions.json\`" >> $GITHUB_STEP_SUMMARY
116+
fi

docusaurus.config.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ async function createConfig() {
147147
routeBasePath: '/',
148148
sidebarPath: require.resolve('./sidebars.js'),
149149
editUrl: ({ versionDocsDirPath, docPath, locale }) => {
150-
return `https://github.com/cloudposse/docs/edit/master/docs/${docPath}`;
150+
return `https://github.com/cloudposse/docs/edit/master/${versionDocsDirPath}/${docPath}`;
151151
},
152152
exclude: ['README.md'],
153153
showLastUpdateTime: true,
@@ -156,7 +156,18 @@ async function createConfig() {
156156
// There are many from components and GHA, it's too much noise without being helpful
157157
onInlineTags: 'ignore',
158158
tags: 'tags.yml',
159-
include: ['**/*.md', '**/*.mdx']
159+
include: ['**/*.md', '**/*.mdx'],
160+
// Versioning configuration - versions are created automatically on major releases
161+
// See .github/workflows/docs-version-on-release.yml
162+
includeCurrentVersion: true,
163+
// Custom paths for versioned docs
164+
path: 'docs',
165+
versions: {
166+
current: {
167+
label: 'Latest',
168+
path: '',
169+
},
170+
},
160171
},
161172
blog: {
162173
showReadingTime: false,
@@ -225,6 +236,11 @@ async function createConfig() {
225236
label: 'Blog',
226237
position: 'left',
227238
},
239+
{
240+
type: 'docsVersionDropdown',
241+
position: 'right',
242+
dropdownActiveClassDisabled: true,
243+
},
228244
{
229245
type: 'search',
230246
position: 'right',
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
title: Best Practices
3+
sidebar_label: Best Practices
4+
sidebar_class_name: hidden
5+
sidebar_position: 0
6+
description: Cloud Posse's Opinionated Reference Architecture Best Practices
7+
tags:
8+
- best-practices
9+
---
10+
11+
> <q>
12+
> Physics is the law, everything else is a recommendation.
13+
> Anyone can break laws created by people, but I have yet to see anyone break the laws of physics.
14+
> <p className="author">— **Elon Musk**</p>
15+
> </q>
16+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
title: "Developer Best Practices"
3+
sidebar_label: Developer
4+
description: "We've written thousands of lines of code. These are our best practices from the trenches."
5+
tags:
6+
- best-practices
7+
- developer
8+
---
9+
import DocCardList from '@theme/DocCardList';
10+
import Intro from '@site/src/components/Intro';
11+
12+
### Recommendations
13+
14+
<DocCardList/>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
---
2+
title: Editor Config Best Practices
3+
sidebar_label: Editor Config
4+
description: "Enforce consistent formatting using a `.editorconfig`"
5+
tags:
6+
- best-practices
7+
- developer
8+
---
9+
import Intro from '@site/src/components/Intro';
10+
11+
<Intro>
12+
The EditorConfig enables developers to define and maintain consistent coding styles between different editors and IDEs. It consists of a simple file format (`.editorconfig`) for defining coding styles such as tabs vs spaces. Most text editors support the format and adhere to defined styles. The config files are easily readable and they work nicely with version control systems.
13+
</Intro>
14+
15+
## Example
16+
17+
Place this file in the root of your git repository.
18+
19+
### `.editorconfig`
20+
21+
```ini
22+
# top-most EditorConfig file
23+
root = true
24+
25+
# Unix-style newlines with a newline ending every file
26+
[*]
27+
end_of_line = lf
28+
insert_final_newline = true
29+
30+
# Matches multiple files with brace expansion notation
31+
# Set default charset
32+
[*.{js,py}]
33+
charset = utf-8
34+
35+
# 4 space indentation
36+
[*.py]
37+
indent_style = space
38+
indent_size = 4
39+
40+
# Override for Makefile
41+
[{Makefile, makefile, GNUmakefile}]
42+
indent_style = tab
43+
indent_size = 4
44+
45+
[Makefile.*]
46+
indent_style = tab
47+
indent_size = 4
48+
49+
50+
# Indentation override for all JS under lib directory
51+
[lib/**.js]
52+
indent_style = space
53+
indent_size = 2
54+
55+
# Matches the exact files either package.json or .travis.yml
56+
[{package.json,.travis.yml}]
57+
indent_style = space
58+
indent_size = 2
59+
60+
[shell]
61+
indent_style = tab
62+
indent_size = 4
63+
64+
[*.sh]
65+
indent_style = tab
66+
indent_size = 4
67+
```
68+
69+
## Editor Plugins
70+
71+
Find all plugins here: http://editorconfig.org/#download
72+
73+
- [Vim](https://github.com/editorconfig/editorconfig-vim#readme)
74+
- [Visual Studio](https://marketplace.visualstudio.com/items?itemName=EditorConfigTeam.EditorConfig)
75+
76+
## References
77+
78+
- http://editorconfig.org/
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
---
2+
title: "Sign Your GitHub Commits with SSH"
3+
sidebar_label: "Sign GitHub Commits"
4+
description: Sign all your git commits
5+
tags:
6+
- best-practices
7+
- developer
8+
- github
9+
---
10+
11+
If you are already using SSH to authenticate to GitHub, it is very easy to sign all your commits as well, as long as you have already installed Git 2.34.0 or later. (Note, there may be problems with OpenSSH 8.7. Use an earlier or later version. I have this working with OpenSSH 8.1p1.)
12+
13+
### Configure git to sign all your commits with an SSH key
14+
15+
```bash
16+
git config --global gpg.format ssh
17+
git config --global commit.gpgsign true
18+
git config --global tag.gpgsign true
19+
```
20+
21+
### Configure git with the public key to use when signing
22+
23+
Set `KEY_FILE` to the file containing your SSH public key
24+
25+
```bash
26+
KEY_FILE=~/.ssh/id_ed25519.pub
27+
git config --global user.signingKey "$(head -1 $KEY_FILE)"
28+
```
29+
30+
Add your SSH public key to GitHub as a signing key, much the same way you added it as an authentication key, but choose "Signing Key" instead of "Authentication Key" under "Key type", even if you already have it uploaded as an authentication key. Detailed instructions are available [here](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account#adding-a-new-ssh-key-to-your-account).
31+
32+
We suggest using the same key you use to authenticate with, so that signing is the same as pulling and pushing, but you can use a different key if you want to be prompted for a password with every commit.

0 commit comments

Comments
 (0)