Skip to content

Commit b2cde14

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

File tree

7 files changed

+512
-17
lines changed

7 files changed

+512
-17
lines changed
Lines changed: 283 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,305 @@
11
name: Publish Documentation
22
on:
33
push:
4-
branches:
5-
- main
4+
branches: [main]
5+
workflow_dispatch:
6+
inputs:
7+
deploy_as_release:
8+
description: 'Deploy as release version (e.g., v1.2.3) - will deploy the docs as if this is a release with this version'
9+
required: false
10+
type: string
11+
default: ''
12+
force_deploy:
13+
description: 'Force deployment even on non-main branches (for testing)'
14+
required: false
15+
type: boolean
16+
default: false
17+
skip_build:
18+
description: 'Skip build-and-test job (use existing artifacts)'
19+
required: false
20+
type: boolean
21+
default: false
22+
workflow_call:
23+
inputs:
24+
deploy_as_release:
25+
description: 'Deploy as release version (e.g., v1.2.3) - will deploy the docs as if this is a release with this version'
26+
required: false
27+
type: string
28+
default: ''
29+
skip_build:
30+
description: 'Skip build-and-test job (assumes artifacts already exist)'
31+
required: false
32+
type: boolean
33+
default: false
34+
secrets:
35+
SIEMENS_NPM_TOKEN:
36+
required: false
37+
SIEMENS_NPM_USER:
38+
required: false
39+
MAPTILER_KEY:
40+
required: false
41+
42+
env:
43+
PYTHON_VERSION: '3.11'
44+
NODE_VERSION: '20'
45+
VERSIONED_BUCKET_NAME: simpl-element-release
46+
CLOUDFRONT_DOMAIN: d2uqfzn4lxgtwv.cloudfront.net
647

748
jobs:
849
build-and-test:
50+
if: ${{ !inputs.skip_build && github.event.inputs.skip_build != 'true' }}
951
uses: ./.github/workflows/build-and-test.yaml
1052
secrets:
1153
SIEMENS_NPM_TOKEN: ${{ secrets.SIEMENS_NPM_TOKEN }}
1254
SIEMENS_NPM_USER: ${{ secrets.SIEMENS_NPM_USER }}
1355
MAPTILER_KEY: ${{ secrets.MAPTILER_KEY }}
1456

15-
publish-documentation:
57+
# Simple deployment for main branch (no versioning)
58+
publish-documentation-main:
1659
runs-on: ubuntu-24.04
60+
needs:
61+
- build-and-test
62+
if: >-
63+
${{
64+
needs.build-and-test.result == 'success' &&
65+
github.ref == format('refs/heads/{0}', github.event.repository.default_branch) &&
66+
!inputs.deploy_as_release
67+
}}
1768
permissions:
69+
contents: write
1870
pages: write
1971
id-token: write
20-
needs:
21-
- build-and-test
2272
steps:
23-
- uses: actions/configure-pages@v5
24-
- uses: actions/download-artifact@v7
73+
- name: Download documentation artifact
74+
uses: actions/download-artifact@v7
2575
with:
2676
name: pages
2777
path: dist/design
28-
- uses: actions/upload-pages-artifact@v4
78+
79+
- name: Setup Pages
80+
uses: actions/configure-pages@v5
81+
82+
- name: Upload Pages artifact
83+
uses: actions/upload-pages-artifact@v4
2984
with:
3085
path: 'dist/design'
31-
- uses: actions/deploy-pages@v4
86+
87+
- name: Deploy to GitHub Pages
88+
uses: actions/deploy-pages@v4
89+
90+
# Versioned deployment for releases (S3 only, not GitHub Pages)
91+
publish-documentation-release:
92+
runs-on: ubuntu-24.04
93+
needs:
94+
- build-and-test
95+
if: ${{ always() && (needs.build-and-test.result == 'success' || inputs.skip_build) && inputs.deploy_as_release }}
96+
permissions:
97+
contents: write
98+
id-token: write
99+
steps:
100+
- name: Checkout
101+
uses: actions/checkout@v4
102+
with:
103+
fetch-depth: 0
104+
105+
- name: Determine deployment targets
106+
id: deploy
107+
run: |
108+
# Initialize all outputs
109+
DEPLOY_MAJOR="false"
110+
MAJOR_VERSION=""
111+
VERSION=""
112+
SHOULD_DEPLOY="false"
113+
114+
DEPLOY_AS_RELEASE="${{ github.event.inputs.deploy_as_release || inputs.deploy_as_release }}"
115+
116+
# Validate and extract version info
117+
if [[ -n "$DEPLOY_AS_RELEASE" ]]; then
118+
# Ensure version starts with 'v'
119+
if [[ ! "$DEPLOY_AS_RELEASE" =~ ^v[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then
120+
echo "Error: Deploy as release version must be in format 'v1.2.3' or 'v1.2.3-suffix'"
121+
echo "Provided: '$DEPLOY_AS_RELEASE'"
122+
exit 1
123+
fi
124+
125+
VERSION="${DEPLOY_AS_RELEASE#v}"
126+
MAJOR_VERSION="v$(echo "$VERSION" | cut -d. -f1)"
127+
128+
# Check if it's a pre-release (contains -, like v1.0.0-rc1)
129+
IS_PRERELEASE="false"
130+
if [[ "$VERSION" =~ -.*$ ]]; then
131+
IS_PRERELEASE="true"
132+
fi
133+
134+
# Deploy to major version except for pre/next/rc releases
135+
if [[ "$IS_PRERELEASE" == "false" ]]; then
136+
DEPLOY_MAJOR="true"
137+
SHOULD_DEPLOY="true"
138+
fi
139+
fi
140+
141+
echo "deploy_major=$DEPLOY_MAJOR" >> $GITHUB_OUTPUT
142+
echo "major_version=$MAJOR_VERSION" >> $GITHUB_OUTPUT
143+
echo "version=$VERSION" >> $GITHUB_OUTPUT
144+
echo "should_deploy=$SHOULD_DEPLOY" >> $GITHUB_OUTPUT
145+
146+
echo "DEPLOYMENT PLAN"
147+
echo "==============="
148+
echo "Branch: ${{ github.ref }}"
149+
echo "Trigger: ${{ github.event_name }}"
150+
echo "Major ($MAJOR_VERSION): $DEPLOY_MAJOR"
151+
152+
# Exit early if we should not deploy
153+
if [[ "$SHOULD_DEPLOY" != "true" ]]; then
154+
echo "Skipping deployment (pre-release version)"
155+
exit 1
156+
fi
157+
158+
- name: Download documentation artifact
159+
uses: actions/download-artifact@v7
160+
with:
161+
name: pages
162+
path: new-docs
163+
164+
- name: Configure AWS credentials
165+
uses: aws-actions/configure-aws-credentials@v5.1.1
166+
with:
167+
role-to-assume: arn:aws:iam::974483672234:role/simpl-element-release
168+
role-session-name: element-release-docs
169+
aws-region: eu-west-1
170+
171+
- name: List existing versions from S3
172+
run: |
173+
mkdir -p deploy-site
174+
175+
# List existing version directories from S3 (no download needed)
176+
echo "Listing existing versions from S3..."
177+
aws s3 ls s3://${{ env.VERSIONED_BUCKET_NAME }}/ || echo "No existing versions found"
178+
179+
- name: Update with new version(s)
180+
run: |
181+
# Deploy to major version directory
182+
MAJOR_VERSION="${{ steps.deploy.outputs.major_version }}"
183+
184+
echo "Updating /$MAJOR_VERSION/..."
185+
# Remove old version to ensure clean deployment
186+
rm -rf "deploy-site/$MAJOR_VERSION"
187+
mkdir -p "deploy-site/$MAJOR_VERSION"
188+
cp -r new-docs/* "deploy-site/$MAJOR_VERSION/"
189+
190+
# Add base tag to docs HTML files only (exclude element-examples, dashboards-demo, coverage)
191+
find "deploy-site/$MAJOR_VERSION" -name "*.html" -type f \
192+
! -path "*/element-examples/*" \
193+
! -path "*/dashboards-demo/*" \
194+
! -path "*/coverage/*" \
195+
-exec sed -i.bak "s|<head>|<head>\n <base href=\"/$MAJOR_VERSION/\">|" {} \;
196+
197+
find "deploy-site/$MAJOR_VERSION" -name "*.bak" -type f -delete
198+
199+
- name: Generate versions.json
200+
run: |
201+
# Generate versions.json from S3 directory listing (no download needed)
202+
echo "Generating versions.json from S3 directory listing..."
203+
204+
# Collect all versions from S3
205+
ALL_VERSIONS=()
206+
207+
# List all existing version-specific folders from S3 (v1, v2, v48, etc.)
208+
# aws s3 ls lists directories with trailing slashes, e.g., "PRE v1/"
209+
aws s3 ls s3://${{ env.VERSIONED_BUCKET_NAME }}/ | grep "PRE v" | awk '{print $2}' | sed 's/\/$//' > s3-versions.txt || true
210+
211+
# Add the currently deploying version to ensure it's included
212+
MAJOR_VERSION="${{ steps.deploy.outputs.major_version }}"
213+
echo "$MAJOR_VERSION" >> s3-versions.txt
214+
215+
# Read all versions and remove duplicates
216+
while IFS= read -r version_name; do
217+
if [[ -n "$version_name" ]]; then
218+
ALL_VERSIONS+=("$version_name")
219+
fi
220+
done < s3-versions.txt
221+
222+
# Remove duplicates and sort versions in descending order
223+
SORTED_VERSIONS=($(printf '%s\n' "${ALL_VERSIONS[@]}" | sort -u -t 'v' -k 2 -n -r))
224+
225+
# Find the highest version for "Latest"
226+
LATEST_VERSION="${SORTED_VERSIONS[0]}"
227+
echo "Latest version: $LATEST_VERSION"
228+
229+
# Build versions.json with correct order:
230+
# 1. Latest (empty version string)
231+
# 2. All versions in descending order (v48, v18, v17, etc.)
232+
# 3. Preview (redirect to element.siemens.io)
233+
234+
VERSIONS='[]'
235+
236+
# Add Latest first (empty version string points to root)
237+
latest_num=$(echo "$LATEST_VERSION" | sed 's/^v//')
238+
echo "Adding: Latest (${latest_num}.x)"
239+
VERSIONS=$(echo "$VERSIONS" | jq '. += [{"version": "", "title": "Latest"}]')
240+
241+
# Add all versions in descending order
242+
for version_name in "${SORTED_VERSIONS[@]}"; do
243+
version_num=$(echo "$version_name" | sed 's/^v//')
244+
echo "Adding: $version_name (${version_num}.x)"
245+
VERSIONS=$(echo "$VERSIONS" | jq --arg version "$version_name" --arg title "${version_num}.x" '. += [{"version": $version, "title": $title}]')
246+
done
247+
248+
# Add Preview last
249+
echo "Adding: Preview (redirect to https://element.siemens.io)"
250+
VERSIONS=$(echo "$VERSIONS" | jq '. += [{"version": "https://element.siemens.io", "title": "Preview"}]')
251+
252+
# Write to deploy-site/versions.json
253+
mkdir -p deploy-site
254+
echo "$VERSIONS" | jq '.' > deploy-site/versions.json
255+
256+
echo "Generated versions.json:"
257+
cat deploy-site/versions.json
258+
259+
- name: Update canonical URLs
260+
run: |
261+
SITE_URL="https://element.siemens.io/"
262+
263+
# Update canonical URLs for version directories
264+
MAJOR_VERSION="${{ steps.deploy.outputs.major_version }}"
265+
VERSION_URL="${SITE_URL}${MAJOR_VERSION}/"
266+
267+
find "deploy-site/$MAJOR_VERSION" -name "*.html" -type f -exec sed -i.bak \
268+
-e "s|<link rel=\"canonical\" href=\"https://element.siemens.io/|<link rel=\"canonical\" href=\"${VERSION_URL}|g" \
269+
{} \;
270+
271+
# Clean up backup files
272+
find deploy-site -name "*.bak" -type f -delete 2>/dev/null || true
273+
274+
- name: Upload to S3
275+
run: |
276+
echo "Uploading versioned documentation to S3..."
277+
278+
MAJOR_VERSION="${{ steps.deploy.outputs.major_version }}"
279+
280+
# Upload versioned directory
281+
echo "Uploading /$MAJOR_VERSION/..."
282+
if [[ ! -d "deploy-site/$MAJOR_VERSION" ]]; then
283+
echo "Error: deploy-site/$MAJOR_VERSION directory does not exist"
284+
exit 1
285+
fi
286+
aws s3 sync --quiet --no-progress --delete "deploy-site/$MAJOR_VERSION/" "s3://${{ env.VERSIONED_BUCKET_NAME }}/$MAJOR_VERSION/"
287+
288+
# If on main branch, also copy to root (without version prefix in path)
289+
if [[ "${{ github.ref }}" == "refs/heads/${{ github.event.repository.default_branch }}" ]]; then
290+
echo "On main branch - copying /$MAJOR_VERSION/ to root..."
291+
# Delete old files but exclude version directories and versions.json from sync and deletion
292+
aws s3 sync --quiet --no-progress --delete "deploy-site/$MAJOR_VERSION/" "s3://${{ env.VERSIONED_BUCKET_NAME }}/" \
293+
--exclude "v*" \
294+
--exclude "versions.json"
295+
fi
296+
297+
# Upload versions.json with short cache-control for quick updates
298+
if [[ ! -f "deploy-site/versions.json" ]]; then
299+
echo "Error: deploy-site/versions.json file does not exist"
300+
exit 1
301+
fi
302+
aws s3 cp deploy-site/versions.json s3://${{ env.VERSIONED_BUCKET_NAME }}/versions.json \
303+
--cache-control "max-age=60,public"
304+
305+
echo "Uploaded versioned documentation to S3 at s3://${{ env.VERSIONED_BUCKET_NAME }}/"

.github/workflows/release.yaml

Lines changed: 35 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,13 @@ jobs:
3033
name: dist
3134
path: dist
3235
- run: npm ci --prefer-offline --no-audit
36+
37+
- name: Get tag before semantic-release
38+
id: before_release
39+
run: |
40+
BEFORE_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
41+
echo "before_tag=$BEFORE_TAG" >> $GITHUB_OUTPUT
42+
3343
- run: npx semantic-release
3444
env:
3545
SKIP_COMMIT: ${{ github.ref_name == 'next' && 'true' || '' }}
@@ -38,3 +48,28 @@ jobs:
3848
GIT_COMMITTER_NAME: 'Siemens Element Bot'
3949
GIT_COMMITTER_EMAIL: 'simpl.si@siemens.com'
4050
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_GITHUB_TOKEN }}
51+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
52+
53+
- name: Check if new release was created
54+
id: check_release
55+
run: |
56+
AFTER_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
57+
BEFORE_TAG="${{ steps.before_release.outputs.before_tag }}"
58+
59+
if [[ -n "$AFTER_TAG" && "$AFTER_TAG" != "$BEFORE_TAG" ]]; then
60+
echo "release_tag=$AFTER_TAG" >> $GITHUB_OUTPUT
61+
echo "new_release=true" >> $GITHUB_OUTPUT
62+
else
63+
echo "new_release=false" >> $GITHUB_OUTPUT
64+
echo "release_tag=" >> $GITHUB_OUTPUT
65+
fi
66+
67+
trigger-documentation:
68+
uses: ./.github/workflows/publish-documentation.yaml
69+
needs:
70+
- publish
71+
- build-and-test
72+
if: success() && needs.publish.outputs.new_release == 'true'
73+
with:
74+
deploy_as_release: ${{ needs.publish.outputs.release_tag }}
75+
skip_build: true

0 commit comments

Comments
 (0)