Skip to content

Commit cc291cb

Browse files
committed
update release notes and release note generation
1 parent e369f28 commit cc291cb

4 files changed

Lines changed: 208 additions & 97 deletions

File tree

‎docs/src/.vuepress/scripts/create-version.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ function main() {
9797
if (existsSync(fetchScript)) {
9898
console.log('Fetching release notes...');
9999
try {
100-
execSync(`npx tsx "${fetchScript}"`, { stdio: 'inherit' });
100+
execSync(`npx tsx "${fetchScript}" ${newVersion}`, { stdio: 'inherit' });
101101
} catch {
102102
console.log('(Release notes fetch had warnings — may not exist on GitHub yet)');
103103
}

‎docs/src/.vuepress/sidebar/fetch-versioned-release-notes.ts‎

Lines changed: 77 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
#!/usr/bin/env npx tsx
2-
// Fetches GitHub release notes for all versions in releases.ts and writes them
3-
// as Markdown files into the corresponding operations/v<tag>/ directories.
2+
// Fetches GitHub release notes for DSF versions and writes them as Markdown
3+
// files into the corresponding operations/v<tag>/ directories.
44
//
5-
// Usage: npx tsx fetch-versioned-release-notes.ts
5+
// Usage: npx tsx fetch-versioned-release-notes.ts 2.1.0 [2.1.1 ...]
6+
// npx tsx fetch-versioned-release-notes.ts --all
67
// Docs: https://wiki.gecko.hs-heilbronn.de/doc/dokumentation-release-notes-script-45Ex3hoxjB
8+
//
9+
// --all regenerates every version and overwrites edits made to a release-notes.md
10+
// after it was generated, so pass explicit versions unless that is intended.
711

812
import { writeFileSync, existsSync } from 'fs';
913
import { resolve, dirname } from 'path';
@@ -22,45 +26,90 @@ interface GitHubRelease {
2226
body: string;
2327
}
2428

25-
async function fetchAllReleases(): Promise<GitHubRelease[]> {
26-
const url = `https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/releases?per_page=100`;
27-
console.log('Fetching all releases...');
28-
const res = await fetch(url, {
29-
headers: { Accept: 'application/vnd.github+json' },
30-
});
29+
async function fetchRelease(version: string): Promise<GitHubRelease | null> {
30+
const url = `https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/releases/tags/${version}`;
31+
const headers: Record<string, string> = { Accept: 'application/vnd.github+json' };
32+
// optional, only needed to avoid the rate limit for unauthenticated requests
33+
if (process.env.GITHUB_TOKEN) headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`;
34+
35+
const res = await fetch(url, { headers });
36+
if (res.status === 404) return null;
3137
if (!res.ok) throw new Error(`GitHub API error: ${res.status} ${res.statusText}`);
32-
return res.json() as Promise<GitHubRelease[]>;
38+
return res.json() as Promise<GitHubRelease>;
39+
}
40+
41+
// Rewriting must skip code, otherwise config samples and image digests
42+
// (ghcr.io/...@sha256:...) get mangled.
43+
const CODE_SEGMENT = /(```[\s\S]*?```|~~~[\s\S]*?~~~|`[^`\n]+`)/;
44+
// Inside links and bare URLs, #123 and @name are part of the target, not a reference.
45+
const LINK_SEGMENT = /(\[[^\]]*\]\([^)]*\)|<[^>\s]+>|https?:\/\/\S+)/;
46+
47+
// split() keeps the captured separators at the odd indices, so only the even
48+
// ones are handed to the callback
49+
function mapUnmatched(text: string, separator: RegExp, fn: (part: string) => string): string {
50+
return text.split(separator).map((part, i) => (i % 2 === 0 ? fn(part) : part)).join('');
51+
}
52+
53+
function normalize(body: string): string {
54+
return body
55+
// the GitHub API returns CRLF, every other file in this repo uses LF
56+
.replace(/\r\n/g, '\n')
57+
// drop a single trailing space but keep 2+, those are markdown hard breaks
58+
.replace(/[^\S\n]+$/gm, (spaces) => (spaces.length > 1 ? spaces : ''))
59+
.trimEnd();
60+
}
61+
62+
// Link targets pointing at our own site must be relative, otherwise VuePress
63+
// treats them as external links and cannot check or route them. Only https
64+
// targets are rewritten, http://dsf.dev/fhir/... are FHIR canonical URLs.
65+
function relativizeSiteLinks(body: string): string {
66+
return mapUnmatched(body, CODE_SEGMENT, (text) =>
67+
text.replace(/\]\(https:\/\/(?:www\.)?dsf\.dev(\/[^)]*)\)/g, ']($1)')
68+
);
3369
}
3470

3571
function linkify(body: string): string {
36-
// Convert #123 to GitHub issue link
37-
body = body.replace(/#(\d+)/g, `[#$1](https://github.com/${REPO_OWNER}/${REPO_NAME}/issues/$1)`);
38-
// Convert @username to GitHub user link
39-
body = body.replace(/@([a-zA-Z0-9_-]+)/g, '[@$1](https://github.com/$1)');
40-
return body;
72+
return mapUnmatched(body, CODE_SEGMENT, (text) =>
73+
mapUnmatched(text, LINK_SEGMENT, (plain) =>
74+
plain
75+
// #123 to GitHub issue link
76+
.replace(/(^|[^\w&#])#(\d+)\b/g, `$1[#$2](https://github.com/${REPO_OWNER}/${REPO_NAME}/issues/$2)`)
77+
// @username to GitHub user link, a leading word character means it is an email address
78+
.replace(/(^|[^\w.@/-])@([A-Za-z\d](?:-?[A-Za-z\d]){0,38})\b/g, '$1[@$2](https://github.com/$2)')
79+
)
80+
);
4181
}
4282

43-
async function main() {
44-
const releases = await fetchAllReleases();
45-
const releaseByTag = new Map(releases.map(r => [r.tag_name, r]));
83+
function usage(): never {
84+
console.error('Usage: npx tsx fetch-versioned-release-notes.ts <version>... | --all');
85+
console.error(' Example: npx tsx fetch-versioned-release-notes.ts 2.1.0');
86+
process.exit(1);
87+
}
4688

47-
for (const { tag } of allVersions) {
48-
const version = `v${tag}`;
49-
const release = releaseByTag.get(version);
89+
async function main() {
90+
const args = process.argv.slice(2);
91+
const versions = args.includes('--all')
92+
? allVersions.map(({ tag }) => `v${tag}`)
93+
: args.map((arg) => (arg.startsWith('v') ? arg : `v${arg}`));
5094

51-
if (!release) {
52-
console.log(`No release found for version ${version}`);
53-
continue;
54-
}
95+
if (versions.length === 0) usage();
5596

97+
for (const version of versions) {
5698
const versionDir = resolve(OUTPUT_BASE, version);
5799
if (!existsSync(versionDir)) {
58100
console.log(`Directory ${versionDir} does not exist. Skipping ${version}.`);
101+
process.exitCode = 1;
59102
continue;
60103
}
61104

62-
const outputFile = resolve(versionDir, 'release-notes.md');
63-
const body = linkify(release.body ?? '');
105+
const release = await fetchRelease(version);
106+
if (!release) {
107+
console.log(`No release found for version ${version}`);
108+
process.exitCode = 1;
109+
continue;
110+
}
111+
112+
const body = linkify(relativizeSiteLinks(normalize(release.body ?? '')));
64113

65114
const content = `---
66115
title: Release Notes (${version})
@@ -77,6 +126,7 @@ You can access all release notes on our [GitHub](https://github.com/datasharingf
77126
${body}
78127
`;
79128

129+
const outputFile = resolve(versionDir, 'release-notes.md');
80130
writeFileSync(outputFile, content, 'utf-8');
81131
console.log(`Release notes for version ${version} saved to ${outputFile}`);
82132
}

‎docs/src/operations/v2.1.0/release-notes.md‎

Lines changed: 68 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -10,72 +10,72 @@ You can access all release notes on our [GitHub](https://github.com/datasharingf
1010
:::
1111

1212
### 2.1.0 - Security and Performance
13-
General remarks:
14-
15-
- This is a feature update for DSF 2.x with security and performance improvements.
16-
- To Update from an existing 2.x installation, please see the [2.x -> 2.1.0 Upgrade Guide](https://dsf.dev/operations/v2.1.0/upgrade-from-2.html).
17-
- For a fresh deployment, follow the [installation instructions](https://dsf.dev/operations/v2.1.0/install.html).
18-
19-
Security Advisories:
20-
- Missing Session Timeout for OIDC Sessions: [GHSA-gj7p-595x-qwf5](https://github.com/datasharingframework/dsf/security/advisories/GHSA-gj7p-595x-qwf5)
21-
- Inverted Time Comparison in OIDC JWKS and Token Cache: [GHSA-xmj9-7625-f634](https://github.com/datasharingframework/dsf/security/advisories/GHSA-xmj9-7625-f634)
22-
23-
Bug Fixes:
24-
- In previous versions starting processes via the FHIR server front-end failed, if `Task` resources used input parameter codes (`Task.input.type`) that were substrings of other input parameter codes ([#442](https://github.com/datasharingframework/dsf/issues/442)). The front-end code was fixed to handle these edge-cases.
25-
- Process instances started with DSF 1.x failed to continue on DSF 2.x ([#438](https://github.com/datasharingframework/dsf/issues/438)). Fallback code was added to correctly read the old DSF 1.x Task process variables.
26-
- A configuration error in the `DsfClient` used by v2 process plugins via the [FHIR client connections API](https://dsf.dev/operations/v2.1.0/bpe/fhir-client-connections.html) resulted in bearer tokens and basic authentication credentials not being send ([#432](https://github.com/datasharingframework/dsf/issues/432)). The feature registration order was fixed to send authentication credentials in the `DsfClient` implementation.
27-
28-
Feature Summary:
29-
- An identifier constraint rule was added to the `Task` base profile http://dsf.dev/fhir/StructureDefinition/task for resources with status `draft`. The constraint adds a rule to the base profile that was previously only enforced via the [TaskAuthorizationRule](https://github.com/datasharingframework/dsf/blob/main/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/TaskAuthorizationRule.java#L357).
30-
- The DSF FHIR server front-end was improved to display the `Binary` resource content inline. This feature is enabled for `Binary` resources with content-types: `text/html` and `text/plain`.
31-
- The performance of allow-list and other bundle executions was improved by modifying the database schema and optimizing the FHIR server code base. A new `current` column was added to resource tables together with a number of new database indexes. A "not found" cache was added for metadata resources to reduce unnecessary database calls.
32-
- Other security improvements were implemented and are detailed in the [DSF 2.1.0 hardening measures](https://dsf.dev/operations/v2.1.0/hardening-measures.html) document.
33-
- Starting with this release our docker images are cryptographically signed. Take a look at the [Verify Image Signatures](https://dsf.dev/operations/latest/image-verification.html) document for details.
34-
35-
Docker images for this release can be accessed via the GitHub Docker registry - ghcr.io:
36-
* **bpe**: [ghcr.io/datasharingframework/bpe:2.1.0](https://github.com/datasharingframework/dsf/pkgs/container/bpe/796016761?tag=2.1.0)
37-
Digest: sha256:3ee7ef0ac201fc3776273fbfc2569bdc4edf724a2bb9f1b4a889eb7e13ff4049
38-
* **bpe_proxy**: [ghcr.io/datasharingframework/bpe_proxy:2.1.0](https://github.com/datasharingframework/dsf/pkgs/container/bpe_proxy/796013677?tag=2.1.0)
39-
Digest: sha256:c67da4a1720ea75a383764db2bf25619fe70f57773b1069029f5b49588eb1ecc
40-
* **fhir**: [ghcr.io/datasharingframework/fhir:2.1.0](https://github.com/datasharingframework/dsf/pkgs/container/fhir/796016727?tag=2.1.0)
41-
Digest: sha256:71599af143f0262a7265aa2bc4ea5a9660f11de6248a053e060b5667070203fd
42-
* **fhir_proxy**: [ghcr.io/datasharingframework/fhir_proxy:2.1.0](https://github.com/datasharingframework/dsf/pkgs/container/fhir_proxy/796013880?tag=2.1.0)
43-
Digest: sha256:9f11a3580c970314532f5951808be6fe72f1de7d53348e625d2dd0c95bcf1d96
44-
45-
Process Plugin API v1 on Maven Central:
46-
```xml
47-
<dependency>
48-
<groupId>dev.dsf</groupId>
49-
<artifactId>dsf-bpe-process-api-v1</artifactId>
50-
<version>2.1.0</version>
51-
</dependency>
52-
```
53-
Process Plugin API v2 on Maven Central:
54-
```xml
55-
<dependency>
56-
<groupId>dev.dsf</groupId>
57-
<artifactId>dsf-bpe-process-api-v2</artifactId>
58-
<version>2.1.0</version>
59-
</dependency>
60-
```
61-
DSF Maven Plugin on Maven Central:
62-
```xml
63-
<plugin>
64-
<groupId>dev.dsf</groupId>
65-
<artifactId>dsf-maven-plugin</artifactId>
66-
<version>2.1.0</version>
67-
</plugin>
68-
```
69-
70-
Issues closed:
71-
- Security Improvements / Defense-in-Depth [#453](https://github.com/datasharingframework/dsf/issues/453)
72-
- Upgrade Dependencies [#448](https://github.com/datasharingframework/dsf/issues/448)
73-
- Improve Allow-List Bundle Execution Performance [#443](https://github.com/datasharingframework/dsf/issues/443)
74-
- Form.js builds invalid Task resource when submitting form [#442](https://github.com/datasharingframework/dsf/issues/442)
75-
- Add Identifier Constraint to Task Profile [#440](https://github.com/datasharingframework/dsf/issues/440)
76-
- Process Instances from DSF 1.x Fail to Continue on DSF 2.x [#438](https://github.com/datasharingframework/dsf/issues/438)
77-
- Start New Development Cycle [#435](https://github.com/datasharingframework/dsf/issues/435)
78-
- Automate Docker Image Builds and Maven Central Deploys [#434](https://github.com/datasharingframework/dsf/issues/434)
79-
- ClientConfig in DsfClientJersey overwrites Authentication Features [#432](https://github.com/datasharingframework/dsf/issues/432)
80-
13+
General remarks:
14+
15+
- This is a feature update for DSF 2.x with security and performance improvements.
16+
- To Update from an existing 2.x installation, please see the [2.x -> 2.1.0 Upgrade Guide](/operations/v2.1.0/upgrade-from-2.html).
17+
- For a fresh deployment, follow the [installation instructions](/operations/v2.1.0/install.html).
18+
19+
Security Advisories:
20+
- Missing Session Timeout for OIDC Sessions: [GHSA-gj7p-595x-qwf5](https://github.com/datasharingframework/dsf/security/advisories/GHSA-gj7p-595x-qwf5)
21+
- Inverted Time Comparison in OIDC JWKS and Token Cache: [GHSA-xmj9-7625-f634](https://github.com/datasharingframework/dsf/security/advisories/GHSA-xmj9-7625-f634)
22+
23+
Bug Fixes:
24+
- In previous versions starting processes via the FHIR server front-end failed, if `Task` resources used input parameter codes (`Task.input.type`) that were substrings of other input parameter codes ([#442](https://github.com/datasharingframework/dsf/issues/442)). The front-end code was fixed to handle these edge-cases.
25+
- Process instances started with DSF 1.x failed to continue on DSF 2.x ([#438](https://github.com/datasharingframework/dsf/issues/438)). Fallback code was added to correctly read the old DSF 1.x Task process variables.
26+
- A configuration error in the `DsfClient` used by v2 process plugins via the [FHIR client connections API](/operations/v2.1.0/bpe/fhir-client-connections.html) resulted in bearer tokens and basic authentication credentials not being send ([#432](https://github.com/datasharingframework/dsf/issues/432)). The feature registration order was fixed to send authentication credentials in the `DsfClient` implementation.
27+
28+
Feature Summary:
29+
- An identifier constraint rule was added to the `Task` base profile http://dsf.dev/fhir/StructureDefinition/task for resources with status `draft`. The constraint adds a rule to the base profile that was previously only enforced via the [TaskAuthorizationRule](https://github.com/datasharingframework/dsf/blob/main/dsf-fhir/dsf-fhir-server/src/main/java/dev/dsf/fhir/authorization/TaskAuthorizationRule.java#L357).
30+
- The DSF FHIR server front-end was improved to display the `Binary` resource content inline. This feature is enabled for `Binary` resources with content-types: `text/html` and `text/plain`.
31+
- The performance of allow-list and other bundle executions was improved by modifying the database schema and optimizing the FHIR server code base. A new `current` column was added to resource tables together with a number of new database indexes. A "not found" cache was added for metadata resources to reduce unnecessary database calls.
32+
- Other security improvements were implemented and are detailed in the [DSF 2.1.0 hardening measures](/operations/v2.1.0/hardening-measures.html) document.
33+
- Starting with this release our docker images are cryptographically signed. Take a look at the [Verify Image Signatures](/operations/latest/image-verification.html) document for details.
34+
35+
Docker images for this release can be accessed via the GitHub Docker registry - ghcr.io:
36+
* **bpe**: [ghcr.io/datasharingframework/bpe:2.1.0](https://github.com/datasharingframework/dsf/pkgs/container/bpe/796016761?tag=2.1.0)
37+
Digest: sha256:3ee7ef0ac201fc3776273fbfc2569bdc4edf724a2bb9f1b4a889eb7e13ff4049
38+
* **bpe_proxy**: [ghcr.io/datasharingframework/bpe_proxy:2.1.0](https://github.com/datasharingframework/dsf/pkgs/container/bpe_proxy/796013677?tag=2.1.0)
39+
Digest: sha256:c67da4a1720ea75a383764db2bf25619fe70f57773b1069029f5b49588eb1ecc
40+
* **fhir**: [ghcr.io/datasharingframework/fhir:2.1.0](https://github.com/datasharingframework/dsf/pkgs/container/fhir/796016727?tag=2.1.0)
41+
Digest: sha256:71599af143f0262a7265aa2bc4ea5a9660f11de6248a053e060b5667070203fd
42+
* **fhir_proxy**: [ghcr.io/datasharingframework/fhir_proxy:2.1.0](https://github.com/datasharingframework/dsf/pkgs/container/fhir_proxy/796013880?tag=2.1.0)
43+
Digest: sha256:9f11a3580c970314532f5951808be6fe72f1de7d53348e625d2dd0c95bcf1d96
44+
45+
Process Plugin API v1 on Maven Central:
46+
```xml
47+
<dependency>
48+
<groupId>dev.dsf</groupId>
49+
<artifactId>dsf-bpe-process-api-v1</artifactId>
50+
<version>2.1.0</version>
51+
</dependency>
52+
```
53+
Process Plugin API v2 on Maven Central:
54+
```xml
55+
<dependency>
56+
<groupId>dev.dsf</groupId>
57+
<artifactId>dsf-bpe-process-api-v2</artifactId>
58+
<version>2.1.0</version>
59+
</dependency>
60+
```
61+
DSF Maven Plugin on Maven Central:
62+
```xml
63+
<plugin>
64+
<groupId>dev.dsf</groupId>
65+
<artifactId>dsf-maven-plugin</artifactId>
66+
<version>2.1.0</version>
67+
</plugin>
68+
```
69+
70+
Issues closed:
71+
- Security Improvements / Defense-in-Depth [#453](https://github.com/datasharingframework/dsf/issues/453)
72+
- Upgrade Dependencies [#448](https://github.com/datasharingframework/dsf/issues/448)
73+
- Improve Allow-List Bundle Execution Performance [#443](https://github.com/datasharingframework/dsf/issues/443)
74+
- Form.js builds invalid Task resource when submitting form [#442](https://github.com/datasharingframework/dsf/issues/442)
75+
- Add Identifier Constraint to Task Profile [#440](https://github.com/datasharingframework/dsf/issues/440)
76+
- Process Instances from DSF 1.x Fail to Continue on DSF 2.x [#438](https://github.com/datasharingframework/dsf/issues/438)
77+
- Start New Development Cycle [#435](https://github.com/datasharingframework/dsf/issues/435)
78+
- Automate Docker Image Builds and Maven Central Deploys [#434](https://github.com/datasharingframework/dsf/issues/434)
79+
- ClientConfig in DsfClientJersey overwrites Authentication Features [#432](https://github.com/datasharingframework/dsf/issues/432)
80+
8181
This release contains contributions from [@EmteZogaf](https://github.com/EmteZogaf), [@hhund](https://github.com/hhund), [@jaboehri](https://github.com/jaboehri), [@schwzr](https://github.com/schwzr) and [@wetret](https://github.com/wetret).

0 commit comments

Comments
 (0)