Skip to content

Commit aae38bf

Browse files
committed
fix: mdbook install\nfix: gqm build and links
1 parent 5c97038 commit aae38bf

9 files changed

Lines changed: 153 additions & 31 deletions

File tree

Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.PHONY: build serve
2+
3+
build:
4+
./scripts/build.sh
5+
6+
serve:
7+
./scripts/serve.sh

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,30 @@ Articles should be relatively short and self-contained so that they can be read
1515
Detailed explanation of InnerSource topics should go in the [InnerSource Patterns] book and be linked from the article here.
1616
Think of the articles in this book like either a conversational introduction/summary to a pattern or possible a journey showing how multiple patterns can be used together in an InnerSource Program.
1717

18+
## Building the Book Locally
19+
20+
The book is built with [mdBook](https://rust-lang.github.io/mdBook/).
21+
You don't need to install anything manually — the helper scripts handle everything.
22+
23+
**Build the book** (output goes to `book/`):
24+
25+
```sh
26+
make build
27+
```
28+
29+
**Live-preview with auto-reload** (opens a local web server):
30+
31+
```sh
32+
make serve
33+
```
34+
35+
On the first run, the scripts will automatically install Rust and mdBook into the
36+
repo-local `.cargo/` and `.rustup/` directories (these are git-ignored).
37+
Subsequent runs reuse the existing install and start immediately.
38+
39+
> **Windows users:** Run these scripts in **Git Bash** (included with
40+
> [Git for Windows](https://gitforwindows.org/)) or in WSL.
41+
1842
## Who can contribute?
1943

2044
This book is a work in progress where anyone is more than welcome to contribute

book.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@ giscus.crossorigin = "anonymous"
2424
site-url = "/managing-innersource-projects/"
2525
additional-js = ["mermaid.min.js", "mermaid-init.js"]
2626

27-
[output.linkcheck2]
27+
[output.linkcheck2]
28+
optional = true

measuring/use_gqm.md

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,32 +31,47 @@ graph LR;
3131
subgraph GQM[Goals, Questions, Metrics]
3232
%% begin nodes
3333
find-projects.md[Find InnerSource Projects]
34+
index.md[InnerSource Goals]
3435
reduce-duplication.md[Reduce duplication]
3536
adoption-trend.md[What is the InnerSource adoption trend?]
37+
index.md[InnerSource Questions]
3638
who-contributes.md[Who contributes to the InnerSource project?]
3739
who-uses.md[Who uses the InnerSource project?]
3840
code-contributions.md[Code contributions]
3941
contribution-distance.md[Contribution Distance]
42+
index.md[InnerSource Metrics]
4043
number-of-innersource-repositories.md[Number of InnerSource repositories]
4144
usage-count.md[Usage count]
4245
%% begin edges
4346
find-projects.md-->who-uses.md
4447
find-projects.md-->who-contributes.md
48+
index.md-->find-projects.md
49+
index.md-->reduce-duplication.md
4550
reduce-duplication.md-->who-uses.md
4651
adoption-trend.md-->number-of-innersource-repositories.md
52+
index.md-->adoption-trend.md
53+
index.md-->who-contributes.md
54+
index.md-->who-uses.md
4755
who-contributes.md-->code-contributions.md
4856
who-contributes.md-->contribution-distance.md
4957
who-uses.md-->usage-count.md
58+
index.md-->code-contributions.md
59+
index.md-->contribution-distance.md
60+
index.md-->number-of-innersource-repositories.md
61+
index.md-->usage-count.md
5062
%% begin clicks
51-
click find-projects.md "/measuring/goals/find-projects" "Find InnerSource Projects"
52-
click reduce-duplication.md "/measuring/goals/reduce-duplication" "Reduce duplication"
53-
click adoption-trend.md "/measuring/questions/adoption-trend" "What is the InnerSource adoption trend?"
54-
click who-contributes.md "/measuring/questions/who-contributes" "Who contributes to the InnerSource project?"
55-
click who-uses.md "/measuring/questions/who-uses" "Who uses the InnerSource project?"
56-
click code-contributions.md "/measuring/metrics/code-contributions" "Code contributions"
57-
click contribution-distance.md "/measuring/metrics/contribution-distance" "Contribution Distance"
58-
click number-of-innersource-repositories.md "/measuring/metrics/number-of-innersource-repositories" "Number of InnerSource repositories"
59-
click usage-count.md "/measuring/metrics/usage-count" "Usage count"
63+
click find-projects.md "goals/find-projects.html" "Find InnerSource Projects"
64+
click index.md "goals/index.html" "InnerSource Goals"
65+
click reduce-duplication.md "goals/reduce-duplication.html" "Reduce duplication"
66+
click adoption-trend.md "questions/adoption-trend.html" "What is the InnerSource adoption trend?"
67+
click index.md "questions/index.html" "InnerSource Questions"
68+
click who-contributes.md "questions/who-contributes.html" "Who contributes to the InnerSource project?"
69+
click who-uses.md "questions/who-uses.html" "Who uses the InnerSource project?"
70+
click code-contributions.md "metrics/code-contributions.html" "Code contributions"
71+
click contribution-distance.md "metrics/contribution-distance.html" "Contribution Distance"
72+
click index.md "metrics/index.html" "InnerSource Metrics"
73+
click number-of-innersource-repositories.md "metrics/number-of-innersource-repositories.html" "Number of InnerSource repositories"
74+
click usage-count.md "metrics/usage-count.html" "Usage count"
6075
end
6176
subgraph Legend
6277
direction TB
@@ -65,13 +80,13 @@ graph LR;
6580
metric[Metric]
6681
6782
classDef goals stroke:green,stroke-width:2px;
68-
class goal,find-projects.md,reduce-duplication.md goals
83+
class goal,find-projects.md,index.md,reduce-duplication.md goals
6984
7085
classDef questions stroke:orange,stroke-width:2px;
71-
class question,adoption-trend.md,who-contributes.md,who-uses.md questions
86+
class question,adoption-trend.md,index.md,who-contributes.md,who-uses.md questions
7287
7388
classDef metrics stroke:purple,stroke-width:2px;
74-
class metric,code-contributions.md,contribution-distance.md,number-of-innersource-repositories.md,usage-count.md metrics
89+
class metric,code-contributions.md,contribution-distance.md,index.md,number-of-innersource-repositories.md,usage-count.md metrics
7590
end
7691
```
7792

scripts/build.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env bash
2+
# Build the book locally.
3+
# Usage: ./scripts/build.sh
4+
#
5+
# On first run this will install Rust, mdBook, and its plugins into the
6+
# repo-local .cargo/ and .rustup/ directories (ignored by git). Subsequent
7+
# runs reuse the existing install.
8+
set -euo pipefail
9+
10+
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
11+
12+
# Point Rust/Cargo at repo-local directories (matches CI and install-mdbook.sh)
13+
export RUSTUP_HOME="${REPO_ROOT}/.rustup"
14+
export CARGO_HOME="${REPO_ROOT}/.cargo"
15+
export PATH="${CARGO_HOME}/bin:${PATH}"
16+
17+
# Install mdBook if it isn't already present
18+
if [ ! -x "${CARGO_HOME}/bin/mdbook" ]; then
19+
echo "mdBook not found — running first-time install (this may take a few minutes)…"
20+
bash "${REPO_ROOT}/scripts/install-mdbook.sh"
21+
fi
22+
23+
cd "${REPO_ROOT}"
24+
mdbook build "$@"

scripts/gqm_gen/index.test.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,17 @@ import {
77
getLinks,
88
getFileLinks,
99
generateMermaidDiagram,
10-
getGQMFileLinks
10+
getGQMFileLinks,
11+
getLinkUrl,
1112
} from "./index";
1213

14+
test("getLinkUrl targets built HTML pages", () => {
15+
assert.strictEqual(
16+
getLinkUrl(LinkType.GOAL, "find-projects.md"),
17+
"goals/find-projects.html"
18+
);
19+
});
20+
1321
test("can get links", () => {
1422
const node = new Commonmark.Node("paragraph");
1523
const links = getLinks(node);
@@ -38,3 +46,11 @@ test("can generate mermaid diagram from file", () => {
3846
const diagram = generateMermaidDiagram(graph);
3947
assert(diagram.indexOf("graph LR;") > 1);
4048
});
49+
50+
test("GQM graph excludes template markdown from link edges", () => {
51+
const graph = getGQMFileLinks("../../measuring/");
52+
const hasTemplateEdge = graph.edges.some(
53+
(e) => e.to?.endsWith("template.md") ?? false
54+
);
55+
assert.strictEqual(hasTemplateEdge, false);
56+
});

scripts/gqm_gen/index.ts

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ const outputPath = process.env.npm_config_outputPath || "../../measuring/use_gqm
1010
const graph = getGQMFileLinks(mdFilePath);
1111

1212
export function getLinkUrl(linkType: LinkType, file: string) {
13-
const measuringUrl = "/measuring";
14-
const url = `${measuringUrl}/${linkType.toLowerCase()}s/${file}`
15-
return url;
13+
const htmlFile = file.replace(/\.md$/i, ".html");
14+
return `${linkType.toLowerCase()}s/${htmlFile}`;
1615
}
1716

1817
export function getGQMFileLinks(mdFilePath: string): Graph {
@@ -82,11 +81,17 @@ export function getLinks(parsed: Commonmark.Node): Link[] {
8281
node = event.node;
8382
if (event.entering && node.type === "link") {
8483
const destination = node.destination as string;
85-
if (destination.includes('.md') && !destination.includes('use_gqm')) {
84+
const linkFileName = path.parse(destination).base;
85+
// Match getFileLinks readdir filter: skip template stubs linked from index pages.
86+
if (
87+
destination.includes('.md') &&
88+
!destination.includes('use_gqm') &&
89+
!linkFileName.endsWith('template.md')
90+
) {
8691
links.push({
8792
url: destination,
8893
text: node.firstChild?.literal as string,
89-
name: path.parse(destination).base
94+
name: linkFileName
9095
});
9196
}
9297
}
@@ -105,12 +110,8 @@ function getNodeShapeSyntax(node: Node): string {
105110
}
106111

107112
export function generateMermaidDiagram(graph: Graph): string {
108-
console.log('graph', graph);
109-
110113
const { nodes, edges } = graph;
111114

112-
const getLinkUrl = (type: LinkType, nodeId: string) => `/measuring/${type.toLowerCase()}s/${nodeId}`;
113-
114115
let mermaidSyntax = "```mermaid\ngraph LR;\n subgraph GQM[Goals, Questions, Metrics]\n";
115116

116117
// Add nodes
@@ -128,7 +129,7 @@ export function generateMermaidDiagram(graph: Graph): string {
128129
// Add click handlers
129130
mermaidSyntax += " %% begin clicks\n";
130131
nodes.forEach(node => {
131-
const url = getLinkUrl(node.type, node.id).replace('.md', '');
132+
const url = getLinkUrl(node.type, node.id);
132133
mermaidSyntax += ` click ${node.id} "${url}" "${node.label}"\n`;
133134
});
134135

@@ -157,25 +158,33 @@ export function updateGQMDiagram(): void {
157158

158159
const graph = getGQMFileLinks(mdFilePath);
159160
const mermaidContent = generateMermaidDiagram(graph);
160-
161+
162+
// Strip the markdown fences to get raw mermaid syntax
163+
const rawMermaid = mermaidContent
164+
.replace(/^```mermaid\n/, '')
165+
.replace(/\n```$/, '');
166+
167+
// Write raw mermaid to stdout so it can be piped to mmdc
168+
process.stdout.write(rawMermaid + '\n');
169+
161170
// Check if the output file exists
162171
if (!fs.existsSync(outputPath)) {
163172
console.error(`Error: Output file not found at ${outputPath}`);
164173
process.exit(1);
165174
}
166-
175+
167176
// Read the existing file
168177
const existingContent = fs.readFileSync(outputPath, 'utf-8');
169-
178+
170179
// Replace the mermaid block
171180
const updatedContent = existingContent.replace(
172181
/```mermaid[\s\S]*?```/,
173182
mermaidContent
174183
);
175-
184+
176185
// Write back to file
177186
fs.writeFileSync(outputPath, updatedContent);
178-
console.log(`Successfully updated GQM diagram at ${outputPath}`);
187+
console.error(`Successfully updated GQM diagram at ${outputPath}`);
179188
} catch (error) {
180189
console.error('Error updating GQM diagram:', error);
181190
process.exit(1);

scripts/install-mdbook.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ export CARGO_HOME="${REPO_ROOT}/.cargo"
1616

1717
echo "Installing Rust and mdBook into ${REPO_ROOT} (RUSTUP_HOME=$RUSTUP_HOME, CARGO_HOME=$CARGO_HOME)"
1818

19-
if ! command -v rustup >/dev/null 2>&1; then
19+
# Install Rust into repo-local RUSTUP_HOME/CARGO_HOME if not already there
20+
if [ ! -x "${CARGO_HOME}/bin/rustup" ]; then
2021
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path
21-
source "${CARGO_HOME}/env"
2222
fi
23+
source "${CARGO_HOME}/env"
2324

2425
rustup toolchain install "${RUST_TOOLCHAIN_VERSION}" --profile minimal
2526
rustup default "${RUST_TOOLCHAIN_VERSION}"

scripts/serve.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env bash
2+
# Build and serve the book locally with live-reload.
3+
# Usage: ./scripts/serve.sh
4+
# ./scripts/serve.sh --open # also opens a browser tab
5+
#
6+
# On first run this will install Rust, mdBook, and its plugins into the
7+
# repo-local .cargo/ and .rustup/ directories (ignored by git). Subsequent
8+
# runs reuse the existing install.
9+
set -euo pipefail
10+
11+
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
12+
13+
# Point Rust/Cargo at repo-local directories (matches CI and install-mdbook.sh)
14+
export RUSTUP_HOME="${REPO_ROOT}/.rustup"
15+
export CARGO_HOME="${REPO_ROOT}/.cargo"
16+
export PATH="${CARGO_HOME}/bin:${PATH}"
17+
18+
# Install mdBook if it isn't already present
19+
if [ ! -x "${CARGO_HOME}/bin/mdbook" ]; then
20+
echo "mdBook not found — running first-time install (this may take a few minutes)…"
21+
bash "${REPO_ROOT}/scripts/install-mdbook.sh"
22+
fi
23+
24+
cd "${REPO_ROOT}"
25+
mdbook serve "$@"

0 commit comments

Comments
 (0)