Skip to content

Commit c592c9c

Browse files
committed
chore(docs): add versioned documentation with auto-detection
Close #675
1 parent 222283c commit c592c9c

File tree

7 files changed

+447
-12
lines changed

7 files changed

+447
-12
lines changed

.github/workflows/publish-documentation.yaml

Lines changed: 221 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,246 @@ on:
33
push:
44
branches:
55
- main
6+
workflow_call:
7+
inputs:
8+
deploy_as_release:
9+
description: 'Deploy as release version (e.g., v1.2.3) - will deploy the docs as if this is a release with this version'
10+
required: false
11+
type: string
12+
default: ''
13+
skip_build:
14+
description: 'Skip build-and-test job (assumes artifacts already exist)'
15+
required: false
16+
type: boolean
17+
default: false
18+
secrets:
19+
SIEMENS_NPM_TOKEN:
20+
required: false
21+
SIEMENS_NPM_USER:
22+
required: false
23+
MAPTILER_KEY:
24+
required: false
25+
26+
env:
27+
VERSIONED_BUCKET_NAME: simpl-element-release
28+
CLOUDFRONT_DOMAIN: d2uqfzn4lxgtwv.cloudfront.net
629

730
jobs:
831
build-and-test:
32+
if: ${{ !inputs.skip_build && github.event.inputs.skip_build != 'true' }}
933
uses: ./.github/workflows/build-and-test.yaml
1034
secrets:
1135
SIEMENS_NPM_TOKEN: ${{ secrets.SIEMENS_NPM_TOKEN }}
1236
SIEMENS_NPM_USER: ${{ secrets.SIEMENS_NPM_USER }}
1337
MAPTILER_KEY: ${{ secrets.MAPTILER_KEY }}
1438

15-
publish-documentation:
39+
# Simple deployment for main branch (no versioning)
40+
publish-documentation-main:
1641
runs-on: ubuntu-24.04
42+
needs:
43+
- build-and-test
44+
if: >-
45+
${{
46+
needs.build-and-test.result == 'success' &&
47+
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
48+
!inputs.deploy_as_release
49+
}}
1750
permissions:
1851
pages: write
1952
id-token: write
20-
needs:
21-
- build-and-test
2253
steps:
23-
- uses: actions/configure-pages@v5
2454
- uses: actions/download-artifact@v7
2555
with:
2656
name: pages
2757
path: dist/design
58+
59+
- uses: actions/configure-pages@v5
60+
2861
- uses: actions/upload-pages-artifact@v4
2962
with:
3063
path: 'dist/design'
64+
3165
- uses: actions/deploy-pages@v4
66+
67+
# Versioned deployment for releases (S3 only, not GitHub Pages)
68+
publish-documentation-release:
69+
runs-on: ubuntu-24.04
70+
needs:
71+
- build-and-test
72+
if: ${{ always() && (needs.build-and-test.result == 'success' || inputs.skip_build) && inputs.deploy_as_release }}
73+
permissions:
74+
id-token: write
75+
steps:
76+
- uses: actions/checkout@v4
77+
with:
78+
fetch-depth: 0
79+
80+
- id: deploy
81+
uses: actions/github-script@v7
82+
with:
83+
script: |
84+
const deployAsRelease = "${{ inputs.deploy_as_release }}";
85+
86+
if (!deployAsRelease) {
87+
core.setFailed("deploy_as_release input is required");
88+
return;
89+
}
90+
91+
const versionRegex = /^v[0-9]+\.[0-9]+\.[0-9]+.*$/;
92+
if (!versionRegex.test(deployAsRelease)) {
93+
core.setFailed(`Error: Deploy as release version must be in format 'v1.2.3' or 'v1.2.3-suffix'\nProvided: '${deployAsRelease}'`);
94+
return;
95+
}
96+
97+
const version = deployAsRelease.substring(1);
98+
const majorVersion = `v${version.split('.')[0]}`;
99+
const isPrerelease = version.includes('-');
100+
101+
const deployMajor = !isPrerelease;
102+
const shouldDeploy = deployMajor;
103+
104+
core.setOutput('deploy_major', deployMajor);
105+
core.setOutput('major_version', majorVersion);
106+
core.setOutput('version', version);
107+
core.setOutput('should_deploy', shouldDeploy);
108+
109+
console.log('DEPLOYMENT PLAN');
110+
console.log('===============');
111+
console.log(`Branch: ${{ github.ref }}`);
112+
console.log(`Trigger: ${{ github.event_name }}`);
113+
console.log(`Major (${majorVersion}): ${deployMajor}`);
114+
115+
if (!shouldDeploy) {
116+
core.setFailed("Skipping deployment (pre-release version)");
117+
}
118+
119+
- uses: actions/download-artifact@v7
120+
with:
121+
name: pages
122+
path: new-docs
123+
124+
- uses: aws-actions/configure-aws-credentials@v5.1.1
125+
with:
126+
role-to-assume: arn:aws:iam::974483672234:role/simpl-element-release
127+
role-session-name: element-release-docs
128+
aws-region: eu-west-1
129+
130+
- run: |
131+
mkdir -p deploy-site
132+
133+
# List existing version directories from S3 (no download needed)
134+
echo "Listing existing versions from S3..."
135+
aws s3 ls s3://${{ env.VERSIONED_BUCKET_NAME }}/ || echo "No existing versions found"
136+
137+
- run: |
138+
MAJOR_VERSION="${{ steps.deploy.outputs.major_version }}"
139+
140+
echo "Updating /$MAJOR_VERSION/..."
141+
rm -rf "deploy-site/$MAJOR_VERSION"
142+
mkdir -p "deploy-site/$MAJOR_VERSION"
143+
cp -r new-docs/* "deploy-site/$MAJOR_VERSION/"
144+
145+
- run: |
146+
# Generate versions.json from S3 directory listing (no download needed)
147+
echo "Generating versions.json from S3 directory listing..."
148+
149+
# Collect all versions from S3
150+
ALL_VERSIONS=()
151+
152+
# List all existing version-specific folders from S3 (v1, v2, v48, etc.)
153+
# aws s3 ls lists directories with trailing slashes, e.g., "PRE v1/"
154+
aws s3 ls s3://${{ env.VERSIONED_BUCKET_NAME }}/ | grep "PRE v" | awk '{print $2}' | sed 's/\/$//' > s3-versions.txt || true
155+
156+
# Add the currently deploying version to ensure it's included
157+
MAJOR_VERSION="${{ steps.deploy.outputs.major_version }}"
158+
echo "$MAJOR_VERSION" >> s3-versions.txt
159+
160+
# Read all versions and remove duplicates
161+
while IFS= read -r version_name; do
162+
if [[ -n "$version_name" ]]; then
163+
ALL_VERSIONS+=("$version_name")
164+
fi
165+
done < s3-versions.txt
166+
167+
# Remove duplicates and sort versions in descending order
168+
SORTED_VERSIONS=($(printf '%s\n' "${ALL_VERSIONS[@]}" | sort -u -t 'v' -k 2 -n -r))
169+
170+
# Find the highest version for "Latest"
171+
LATEST_VERSION="${SORTED_VERSIONS[0]}"
172+
echo "Latest version: $LATEST_VERSION"
173+
174+
# Build versions.json with correct order:
175+
# 1. Latest (empty version string)
176+
# 2. All versions in descending order (v48, v18, v17, etc.)
177+
# 3. Preview (redirect to element.siemens.io)
178+
179+
VERSIONS='[]'
180+
181+
# Add Latest first (empty version string points to root)
182+
latest_num=$(echo "$LATEST_VERSION" | sed 's/^v//')
183+
echo "Adding: Latest (${latest_num}.x)"
184+
VERSIONS=$(echo "$VERSIONS" | jq '. += [{"version": "", "title": "Latest"}]')
185+
186+
# Add all versions in descending order
187+
for version_name in "${SORTED_VERSIONS[@]}"; do
188+
version_num=$(echo "$version_name" | sed 's/^v//')
189+
echo "Adding: $version_name (${version_num}.x)"
190+
VERSIONS=$(echo "$VERSIONS" | jq --arg version "$version_name" --arg title "${version_num}.x" '. += [{"version": $version, "title": $title}]')
191+
done
192+
193+
# Add Preview last
194+
echo "Adding: Preview (redirect to https://element.siemens.io)"
195+
VERSIONS=$(echo "$VERSIONS" | jq '. += [{"version": "https://element.siemens.io", "title": "Preview"}]')
196+
197+
# Write to deploy-site/versions.json
198+
mkdir -p deploy-site
199+
echo "$VERSIONS" | jq '.' > deploy-site/versions.json
200+
201+
echo "Generated versions.json:"
202+
cat deploy-site/versions.json
203+
204+
- run: |
205+
SITE_URL="https://element.siemens.io/"
206+
207+
# Update canonical URLs for version directories
208+
MAJOR_VERSION="${{ steps.deploy.outputs.major_version }}"
209+
VERSION_URL="${SITE_URL}${MAJOR_VERSION}/"
210+
211+
find "deploy-site/$MAJOR_VERSION" -name "*.html" -type f -exec sed -i.bak \
212+
-e "s|<link rel=\"canonical\" href=\"https://element.siemens.io/|<link rel=\"canonical\" href=\"${VERSION_URL}|g" \
213+
{} \;
214+
215+
# Clean up backup files
216+
find deploy-site -name "*.bak" -type f -delete 2>/dev/null || true
217+
218+
- run: |
219+
echo "Uploading versioned documentation to S3..."
220+
221+
MAJOR_VERSION="${{ steps.deploy.outputs.major_version }}"
222+
223+
# Upload versioned directory
224+
echo "Uploading /$MAJOR_VERSION/..."
225+
if [[ ! -d "deploy-site/$MAJOR_VERSION" ]]; then
226+
echo "Error: deploy-site/$MAJOR_VERSION directory does not exist"
227+
exit 1
228+
fi
229+
aws s3 sync --quiet --no-progress --delete "deploy-site/$MAJOR_VERSION/" "s3://${{ env.VERSIONED_BUCKET_NAME }}/$MAJOR_VERSION/"
230+
231+
# If on main branch, also copy to root (without version prefix in path)
232+
if [[ "${{ github.ref }}" == "refs/heads/${{ github.event.repository.default_branch }}" ]]; then
233+
echo "On main branch - copying /$MAJOR_VERSION/ to root..."
234+
# Delete old files but exclude version directories and versions.json from sync and deletion
235+
aws s3 sync --quiet --no-progress --delete "deploy-site/$MAJOR_VERSION/" "s3://${{ env.VERSIONED_BUCKET_NAME }}/" \
236+
--exclude "v*" \
237+
--exclude "versions.json"
238+
fi
239+
240+
# Upload versions.json with short cache-control for quick updates
241+
if [[ ! -f "deploy-site/versions.json" ]]; then
242+
echo "Error: deploy-site/versions.json file does not exist"
243+
exit 1
244+
fi
245+
aws s3 cp deploy-site/versions.json s3://${{ env.VERSIONED_BUCKET_NAME }}/versions.json \
246+
--cache-control "max-age=60,public"
247+
248+
echo "Uploaded versioned documentation to S3 at s3://${{ env.VERSIONED_BUCKET_NAME }}/"

.github/workflows/release.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ jobs:
1616
- build-and-test
1717
permissions:
1818
id-token: write
19+
outputs:
20+
new_release: ${{ steps.check_release.outputs.new_release }}
21+
release_tag: ${{ steps.check_release.outputs.release_tag }}
1922
steps:
2023
- uses: actions/checkout@v6
2124
with:
@@ -30,6 +33,12 @@ jobs:
3033
name: dist
3134
path: dist
3235
- run: npm ci --prefer-offline --no-audit
36+
37+
- id: before_release
38+
run: |
39+
BEFORE_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
40+
echo "before_tag=$BEFORE_TAG" >> $GITHUB_OUTPUT
41+
3342
- run: npx semantic-release
3443
env:
3544
SKIP_COMMIT: ${{ github.ref_name == 'next' && 'true' || '' }}
@@ -38,3 +47,26 @@ jobs:
3847
GIT_COMMITTER_NAME: 'Siemens Element Bot'
3948
GIT_COMMITTER_EMAIL: 'simpl.si@siemens.com'
4049
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_GITHUB_TOKEN }}
50+
51+
- id: check_release
52+
run: |
53+
AFTER_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
54+
BEFORE_TAG="${{ steps.before_release.outputs.before_tag }}"
55+
56+
if [[ -n "$AFTER_TAG" && "$AFTER_TAG" != "$BEFORE_TAG" ]]; then
57+
echo "release_tag=$AFTER_TAG" >> $GITHUB_OUTPUT
58+
echo "new_release=true" >> $GITHUB_OUTPUT
59+
else
60+
echo "new_release=false" >> $GITHUB_OUTPUT
61+
echo "release_tag=" >> $GITHUB_OUTPUT
62+
fi
63+
64+
trigger-documentation:
65+
uses: ./.github/workflows/publish-documentation.yaml
66+
needs:
67+
- publish
68+
- build-and-test
69+
if: success() && needs.publish.outputs.new_release == 'true' && github.ref_name != 'next'
70+
with:
71+
deploy_as_release: ${{ needs.publish.outputs.release_tag }}
72+
skip_build: true

0 commit comments

Comments
 (0)