Skip to content
Draft
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
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

- package-ecosystem: "npm"
directory: "/docs"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
10 changes: 5 additions & 5 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
# fetch all commits to get last updated time or other git log info
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v3
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
# choose node.js version to use
node-version: 24

- name: Install dependencies
run: cd docs && npm ci

Expand All @@ -32,7 +32,7 @@ jobs:
# please check out the docs of the workflow for more details
# @see https://github.com/crazy-max/ghaction-github-pages
- name: Deploy to GitHub Pages
uses: crazy-max/ghaction-github-pages@v4
uses: crazy-max/ghaction-github-pages@df5cc2bfa78282ded844b354faee141f06b41865 # v4.2.0
with:
# deploy to gh-pages branch
target_branch: gh-pages
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1

- name: Setup Node.js
uses: actions/setup-node@v3
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
# choose node.js version to use
node-version: 24

- name: Install dependencies
run: cd docs && npm ci

Expand Down
10 changes: 5 additions & 5 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@
"@vuepress/plugin-markdown-math": "2.0.0-rc.121",
"@vuepress/plugin-markdown-tab": "2.0.0-rc.121",
"@vuepress/plugin-slimsearch": "2.0.0-rc.121",
"katex": "^0.16.28",
"sass-embedded": "^1.97.3",
"sass-loader": "^16.0.7",
"vue": "^3.5.28",
"katex": "0.16.28",
"sass-embedded": "1.97.3",
"sass-loader": "16.0.7",
"vue": "3.5.28",
"vuepress": "2.0.0-rc.26",
"vuepress-theme-hope": "2.0.0-rc.102"
},
"optionalDependencies": {
"@rollup/rollup-linux-x64-gnu": "^4.57.1"
"@rollup/rollup-linux-x64-gnu": "4.59.0"
}
}
4 changes: 2 additions & 2 deletions docs/src/.vuepress/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import Layout from './layouts/PageLayout.vue'
import NotFoundLayout from './layouts/NotFoundLayout.vue'
import BlogLayout from './layouts/BlogLayout.vue';


import OldVersions from './components/OldVersions.vue';

export default defineClientConfig({
enhance({ app }) {

app.component('OldVersions', OldVersions);
},
layouts: {
ParentLayout,
Expand Down
19 changes: 19 additions & 0 deletions docs/src/.vuepress/components/OldVersions.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<template>
<div>
<h2>DSF v2</h2>
<ul>
<li v-for="v in v2" :key="v.tag"><a :href="'./v' + v.tag + '/'">{{ v.tag }}</a></li>
</ul>
<h2>DSF v1</h2>
<ul>
<li v-for="v in v1" :key="v.tag"><a :href="'./v' + v.tag + '/'">{{ v.tag }}</a></li>
</ul>
</div>
</template>

<script setup lang="ts">
import { allVersions } from '../data/releases';

const v2 = allVersions.filter(v => v.tag.startsWith('2.'));
const v1 = allVersions.filter(v => v.tag.startsWith('1.'));
</script>
32 changes: 32 additions & 0 deletions docs/src/.vuepress/data/releases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,38 @@ export const releases: Record<string, Release> = {
},
};

// --- Version registry (single source of truth) ---
// Sidebar keys reference generator functions by name; mapped in theme.ts.
// Ordered newest-first.
export type SidebarKey = 'v2_latest' | 'v2_0_0' | 'v1_latest' | 'v1_gte_1_7' | 'v1_gte_1_5' | 'v1_gte_1_0';

export interface VersionEntry {
tag: string;
sidebar: SidebarKey;
}

export const allVersions: VersionEntry[] = [
{ tag: '2.1.0', sidebar: 'v2_latest' },
{ tag: '2.0.2', sidebar: 'v2_0_0' },
{ tag: '2.0.1', sidebar: 'v2_0_0' },
{ tag: '2.0.0', sidebar: 'v2_0_0' },
{ tag: '1.9.0', sidebar: 'v1_latest' },
{ tag: '1.8.0', sidebar: 'v1_gte_1_7' },
{ tag: '1.7.1', sidebar: 'v1_gte_1_7' },
{ tag: '1.7.0', sidebar: 'v1_gte_1_7' },
{ tag: '1.6.0', sidebar: 'v1_gte_1_5' },
{ tag: '1.5.2', sidebar: 'v1_gte_1_5' },
{ tag: '1.5.1', sidebar: 'v1_gte_1_5' },
{ tag: '1.5.0', sidebar: 'v1_gte_1_5' },
{ tag: '1.4.0', sidebar: 'v1_gte_1_0' },
{ tag: '1.3.2', sidebar: 'v1_gte_1_0' },
{ tag: '1.3.1', sidebar: 'v1_gte_1_0' },
{ tag: '1.3.0', sidebar: 'v1_gte_1_0' },
{ tag: '1.2.0', sidebar: 'v1_gte_1_0' },
{ tag: '1.1.0', sidebar: 'v1_gte_1_0' },
{ tag: '1.0.0', sidebar: 'v1_gte_1_0' },
];

export const latestVersion = '2.1.0';

export function getReleaseFromPath(path: string): Release | undefined {
Expand Down
36 changes: 8 additions & 28 deletions docs/src/.vuepress/layouts/PageLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,27 @@
import { Layout as ParentLayout, PageContent } from 'vuepress-theme-hope/client'
import { useRoute, useRouter } from "vue-router";
import { ref, onMounted } from 'vue'
import { allVersions, latestVersion } from '../data/releases'

const version = ref("");
const latestVersion = "v2.1.0";

const latestTag = `v${latestVersion}`;

function setVersionBasedOnCurrentPath() : void {
if (route.path.startsWith('/operations/')) {
const input = route.path.substring('/operations/'.length);
const firstSlash = input.indexOf("/");
var result = firstSlash !== -1 ? input.slice(0, firstSlash) : input;
if (result === "latest") {
result = latestVersion;
result = latestTag;
}
version.value = result;


} else {
version.value = "";
}
}

const route = useRoute();


const router = useRouter();
router.afterEach((_to, _from) => {
setVersionBasedOnCurrentPath();
Expand All @@ -39,11 +36,10 @@ function navigateToNewVersion() {
const input = route.path.substring('/operations/'.length);
const firstSlash = input.indexOf("/");
const result = firstSlash !== -1 ? input.slice(firstSlash + 1) : "";
if (version.value === latestVersion) {
if (version.value === latestTag) {
router.push('/operations/' + "latest" + "/" + result);
} else {
router.push('/operations/' + version.value + "/" + result);

}
}

Expand All @@ -55,25 +51,9 @@ function navigateToNewVersion() {
<div class="version-selector" v-if="route.path.startsWith('/operations/')">
<label class="vp-sidebar-header" for="version-select"><strong>Version:</strong> </label>
<select id="version-select" class="vp-sidebar-header" v-model="version" @change="navigateToNewVersion">
<option value="v2.1.0">latest (2.1.0)</option>
<option value="v2.0.2">2.0.2</option>
<option value="v2.0.1">2.0.1</option>
<option value="v2.0.0">2.0.0</option>
<option value="v1.9.0">1.9.0</option>
<option value="v1.8.0">1.8.0</option>
<option value="v1.7.1">1.7.1</option>
<option value="v1.7.0">1.7.0</option>
<option value="v1.6.0">1.6.0</option>
<option value="v1.5.2">1.5.2</option>
<option value="v1.5.1">1.5.1</option>
<option value="v1.5.0">1.5.0</option>
<option value="v1.4.0">1.4.0</option>
<option value="v1.3.2">1.3.2</option>
<option value="v1.3.1">1.3.1</option>
<option value="v1.3.0">1.3.0</option>
<option value="v1.2.0">1.2.0</option>
<option value="v1.1.0">1.1.0</option>
<option value="v1.0.0">1.0.0</option>
<option v-for="v in allVersions" :key="v.tag" :value="'v' + v.tag">
{{ v.tag === latestVersion ? `latest (${v.tag})` : v.tag }}
</option>
</select></div>
</template>
<PageContent id="main-content" class="vp-page"/>
Expand All @@ -84,4 +64,4 @@ function navigateToNewVersion() {
.version-selector {
margin-top: 20px;
}
</style>
</style>
115 changes: 115 additions & 0 deletions docs/src/.vuepress/scripts/create-version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#!/usr/bin/env npx tsx
// Creates a new DSF documentation version.
//
// Usage: npx tsx docs/src/.vuepress/scripts/create-version.ts <new-version>
// Example: npx tsx docs/src/.vuepress/scripts/create-version.ts 2.2.0
//
// What it does:
// 1. Copies the current latest version folder to operations/v<new-version>/
// 2. Updates releases.ts: adds new entry to allVersions, updates latestVersion,
// adds a releases entry with TODO digests
// 3. Updates the latest symlink to point to v<new-version>/
// 4. Runs fetch-versioned-release-notes.ts if a GitHub release exists

import { cpSync, existsSync, readFileSync, writeFileSync, unlinkSync, symlinkSync, realpathSync } from 'fs';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';
import { execSync } from 'child_process';

const __dirname = dirname(fileURLToPath(import.meta.url));
const OPERATIONS_DIR = resolve(__dirname, '../../operations');
const RELEASES_FILE = resolve(__dirname, '../data/releases.ts');

function die(msg: string): never {
console.error(`Error: ${msg}`);
process.exit(1);
}

function parseVersion(v: string): [number, number, number] {
const m = v.match(/^(\d+)\.(\d+)\.(\d+)$/);
if (!m) die(`Invalid version format: "${v}". Expected X.Y.Z`);
return [parseInt(m![1]), parseInt(m![2]), parseInt(m![3])];
}

function main() {
const newVersion = process.argv[2];
if (!newVersion) die('Usage: npx tsx create-version.ts <new-version>\n Example: npx tsx create-version.ts 2.2.0');

parseVersion(newVersion); // validate format

const newDir = resolve(OPERATIONS_DIR, `v${newVersion}`);
if (existsSync(newDir)) die(`Directory ${newDir} already exists.`);

// --- 1. Determine current latest and copy ---
const latestLink = resolve(OPERATIONS_DIR, 'latest');
const currentLatestDir = realpathSync(latestLink);
const currentLatestVersion = currentLatestDir.match(/v(\d+\.\d+\.\d+)$/)?.[1];
if (!currentLatestVersion) die(`Could not determine current latest version from symlink: ${currentLatestDir}`);

console.log(`Copying v${currentLatestVersion}/ → v${newVersion}/...`);
cpSync(currentLatestDir, newDir, { recursive: true });

// --- 2. Update releases.ts ---
console.log('Updating releases.ts...');
let src = readFileSync(RELEASES_FILE, 'utf-8');

// Determine sidebar key from previous latest
const prevSidebarMatch = src.match(new RegExp(`\\{\\s*tag:\\s*'${currentLatestVersion}'\\s*,\\s*sidebar:\\s*'([^']+)'`));
const sidebarKey = prevSidebarMatch?.[1] ?? 'v2_latest';

// Add new entry at the top of allVersions
const allVersionsMarker = 'export const allVersions: VersionEntry[] = [';
const newEntry = ` { tag: '${newVersion}', sidebar: '${sidebarKey}' },`;
src = src.replace(allVersionsMarker, `${allVersionsMarker}\n${newEntry}`);

// Update latestVersion
src = src.replace(
/export const latestVersion = '[^']+';/,
`export const latestVersion = '${newVersion}';`
);

// Add releases entry with TODO digests (if major >= 2)
const [major] = parseVersion(newVersion);
if (major >= 2) {
const releasesClosingBrace = /^};$/m;
const newRelease = ` '${newVersion}': {
tag: '${newVersion}',
previousTag: '${currentLatestVersion}',
images: {
fhir: { digest: 'sha256:TODO' },
fhir_proxy: { digest: 'sha256:TODO' },
bpe: { digest: 'sha256:TODO' },
bpe_proxy: { digest: 'sha256:TODO' },
},
},\n`;
src = src.replace(releasesClosingBrace, `${newRelease}};`);
}

writeFileSync(RELEASES_FILE, src, 'utf-8');

// --- 3. Update latest symlink ---
console.log(`Updating latest symlink → v${newVersion}/...`);
unlinkSync(latestLink);
symlinkSync(`v${newVersion}`, latestLink);

// --- 4. Fetch release notes (if release exists) ---
const fetchScript = resolve(__dirname, '../sidebar/fetch-versioned-release-notes.ts');
if (existsSync(fetchScript)) {
console.log('Fetching release notes...');
try {
execSync(`npx tsx "${fetchScript}"`, { stdio: 'inherit' });
} catch {
console.log('(Release notes fetch had warnings — may not exist on GitHub yet)');
}
}

// --- Done ---
console.log(`\n✓ Version ${newVersion} created successfully.\n`);
console.log('Remaining manual steps:');
console.log(` 1. Update image digests in releases.ts (replace sha256:TODO)`);
console.log(` 2. Review/edit release-specific content in operations/v${newVersion}/`);
console.log(` (release-notes.md, upgrade-from-*.md if upgrade steps differ)`);
console.log(` 3. Run: cd docs && npm run docs:build`);
}

main();
Loading
Loading