From 3a15eaa292c88a3b1be10824f06cf4eff3a8d07c Mon Sep 17 00:00:00 2001 From: Jeff Bailey <776901+jeffabailey@users.noreply.github.com> Date: Mon, 2 Mar 2026 19:18:20 -0800 Subject: [PATCH 01/11] feat: add InnerSource and AI section --- SUMMARY.md | 5 ++++ governance/governance.md | 2 ++ innersource-and-ai/authors.md | 15 ++++++++++++ innersource-and-ai/innersource-and-ai.md | 13 +++++++++++ innersource-and-ai/risks-and-guardrails.md | 21 +++++++++++++++++ innersource-and-ai/shaping-for-ai.md | 21 +++++++++++++++++ .../why-innersource-matters-with-ai.md | 23 +++++++++++++++++++ introduction/framework.md | 4 ++++ tooling/innersource-tooling.md | 2 ++ 9 files changed, 106 insertions(+) create mode 100644 innersource-and-ai/authors.md create mode 100644 innersource-and-ai/innersource-and-ai.md create mode 100644 innersource-and-ai/risks-and-guardrails.md create mode 100644 innersource-and-ai/shaping-for-ai.md create mode 100644 innersource-and-ai/why-innersource-matters-with-ai.md diff --git a/SUMMARY.md b/SUMMARY.md index f6cc320..be7fb86 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -31,6 +31,11 @@ * [References](measuring/references.md) * [Authors and Reviewers](measuring/authors.md) * [Governance](governance/governance.md) +* [InnerSource and AI](innersource-and-ai/innersource-and-ai.md) + * [Why InnerSource Matters When Adopting AI](innersource-and-ai/why-innersource-matters-with-ai.md) + * [Shaping Repositories and Practices for AI](innersource-and-ai/shaping-for-ai.md) + * [Risks and Guardrails](innersource-and-ai/risks-and-guardrails.md) + * [Authors and Reviewers](innersource-and-ai/authors.md) * [Tooling](tooling/innersource-tooling.md) * [GitHub Strategy](tooling/github-strategy.md) * [GitHub Configuration](tooling/github-configuration.md) diff --git a/governance/governance.md b/governance/governance.md index 539a94b..95a15ca 100644 --- a/governance/governance.md +++ b/governance/governance.md @@ -250,6 +250,8 @@ organization and its context and find other goals InnerSource may contribute towards. Then communicate it and get as much air cover from your executives as you can. +For how governance and transparency support responsible use of AI in development, see [InnerSource and AI](/innersource-and-ai/innersource-and-ai.md), in particular [Risks and Guardrails](/innersource-and-ai/risks-and-guardrails.md). + [^1]: http://oss-watch.ac.uk/resources/governancemodels [^2]: https://ospo-alliance.org/ggi/ diff --git a/innersource-and-ai/authors.md b/innersource-and-ai/authors.md new file mode 100644 index 0000000..82e41b5 --- /dev/null +++ b/innersource-and-ai/authors.md @@ -0,0 +1,15 @@ +# Authors and Reviewers + +## Authors + +Chronological order: + +* InnerSource Program Office (ISPO) Working Group, [InnerSource Commons](https://innersourcecommons.org/). + +## Reviewers + +Chronological order: + +* (To be added as the section is reviewed and refined by the community.) + +This section was drafted as a discussion starter and is open for contributions. If you would like to be listed as an author or reviewer, please open a pull request or get in touch via [Slack](https://innersourcecommons.org/slack). diff --git a/innersource-and-ai/innersource-and-ai.md b/innersource-and-ai/innersource-and-ai.md new file mode 100644 index 0000000..f77ad1a --- /dev/null +++ b/innersource-and-ai/innersource-and-ai.md @@ -0,0 +1,13 @@ +# InnerSource and AI + +Organizations are increasingly adopting AI in the workplace—from generative AI assistants to agentic coding tools that can write, refactor, and review code. This shift is changing how developers work: less time on typing code, more on defining requirements, guiding AI, and making sure systems are reliable and maintainable. For InnerSource program leads, the question is whether InnerSource still matters in this new landscape. + +It does. InnerSource is potentially *more* important than ever. Shared repositories, clear boundaries, documentation, and collaborative practices help AI systems—and the people using them—work with the right context, reuse existing components, and keep quality high. This section explains why InnerSource matters when adopting AI, how to shape your repositories and practices for AI-assisted development, and what risks and guardrails to keep in mind. + +The following articles in this section go deeper: + +- [Why InnerSource Matters When Adopting AI](why-innersource-matters-with-ai.md) — Relevance of InnerSource in an AI-augmented world, reuse, and production readiness. +- [Shaping Repositories and Practices for AI](shaping-for-ai.md) — Repository design, documentation, and workflow integration so both humans and AI can contribute effectively. +- [Risks and Guardrails](risks-and-guardrails.md) — Balancing speed with safety, the role of code review, and organizational best practices for AI use. + +AI tooling and practices are evolving quickly. This section will be updated as the community learns more and as survey and research data become available. If you are new to InnerSource, we recommend starting with [Getting Started with InnerSource](http://www.oreilly.com/programming/free/getting-started-with-innersource.csp) and the [Introduction](/introduction/introduction.md) to this book. diff --git a/innersource-and-ai/risks-and-guardrails.md b/innersource-and-ai/risks-and-guardrails.md new file mode 100644 index 0000000..efc0de9 --- /dev/null +++ b/innersource-and-ai/risks-and-guardrails.md @@ -0,0 +1,21 @@ +# Risks and Guardrails + +Adopting AI in development can deliver short-term gains in speed and productivity. Without guardrails, it can also introduce long-term risks to quality, security, and maintainability. InnerSource practices help organizations balance innovation with responsibility. + +## Risks of rapid AI deployment + +Trusting AI-generated or AI-modified code without review or guidance can lead to subtle bugs, security issues, and technical debt. Mandating AI use without clear best practices or policies can create unintended problems—teams may not know when to rely on AI and when to double-check. A balanced approach is to encourage experimentation while reinforcing code review, testing, and clear ownership. InnerSource’s culture of transparency and review supports that balance. + +## The role of code review and systems thinking + +When AI generates or modifies code, human review remains essential. Code review catches errors, enforces consistency, and spreads knowledge. InnerSource’s existing review and governance practices—trusted committers, contribution guidelines, and transparent decision-making—apply directly to AI-assisted contributions. Systems thinking is also critical: understanding how a change fits into boundaries, interfaces, and dependencies helps avoid local optimizations that cause global problems. Program leads can emphasize that AI output is a draft to be reviewed, not a substitute for human judgment. + +## Transparency and stakeholder involvement + +Involving stakeholders and keeping development transparent supports responsible AI deployment. When decisions about tools, patterns, and policies are visible and discussable, teams can align on what is acceptable and what is not. This aligns with InnerSource principles of openness and collaboration and helps prevent AI from being used in ways that conflict with organizational values or compliance requirements. + +## Best practices and guidance + +Organizations need practical guidance on when and how to use AI in development. That may include policies on which tools are approved, how to attribute and review AI-assisted contributions, and how to handle sensitive or regulated code. Detailed policies and playbooks may live in your governance model or in the [InnerSource Patterns](https://patterns.innersourcecommons.org/) book. As a program lead, you can work with governance, security, and engineering leadership to develop and communicate these practices so that adoption of AI remains safe and sustainable. + +For more on governance in InnerSource, see [Governance](/governance/governance.md). diff --git a/innersource-and-ai/shaping-for-ai.md b/innersource-and-ai/shaping-for-ai.md new file mode 100644 index 0000000..bb62eb2 --- /dev/null +++ b/innersource-and-ai/shaping-for-ai.md @@ -0,0 +1,21 @@ +# Shaping Repositories and Practices for AI + +InnerSource practices that make life easier for human contributors also help AI systems and agentic tools. Clear scope, good documentation, and consistent workflows make it easier for both people and AI to discover, understand, and contribute to shared code safely. + +## Repository and boundary design + +Well-defined repositories with clear scope and interfaces make it easier for humans and AI to contribute without stepping on each other’s toes. When boundaries are explicit—what belongs in this repo, what the APIs are, what the project is *not* responsible for—AI agents and assistants can operate within a manageable context. The community is exploring a pattern sometimes called “InnerSource the AI way,” which emphasizes clear scope and boundaries; as it matures, it may be documented in the [InnerSource Patterns](https://patterns.innersourcecommons.org/) book and linked from here. + +## Documentation and discoverability + +InnerSource behaviors like solid READMEs, CONTRIBUTING guides, and architecture decision records are increasingly important when AI is in the loop. They help AI and people alike understand how to use and extend shared code correctly. Documentation that explains *why* decisions were made, not just *what* the code does, supports better AI-generated contributions and reduces misuse. Making repositories searchable and well-described also helps teams and tools find the right building blocks instead of reimplementing them. + +## Playbooks for people and agents + +Playbooks that describe how to contribute—and what to avoid—benefit both human contributors and AI-assisted workflows. The community is starting to develop playbooks that work for both. As these emerge, they will be reflected in the InnerSource Patterns book and linked from this section. The goal is to make it easy for contributors and tools to follow the same rules and expectations. + +## Skills, plugins, and workflow integration + +InnerSource can be integrated directly into coding workflows through skills, plugins, and tooling. When reuse and contribution are part of the daily environment—for example, by suggesting existing InnerSource components when starting a new feature—both developers and AI-assisted flows are more likely to reuse rather than duplicate. This is an area of active development; program leads can work with their tooling and platform teams to explore how to surface InnerSource projects and contribution paths where developers (and their tools) already work. + +For more on infrastructure and tooling in InnerSource, see [Tooling](/tooling/innersource-tooling.md) and [Infrastructure](/infrastructure/infrastructure.md). diff --git a/innersource-and-ai/why-innersource-matters-with-ai.md b/innersource-and-ai/why-innersource-matters-with-ai.md new file mode 100644 index 0000000..217dc84 --- /dev/null +++ b/innersource-and-ai/why-innersource-matters-with-ai.md @@ -0,0 +1,23 @@ +# Why InnerSource Matters When Adopting AI + +AI and agentic coding are changing how development work gets done. Developers spend more time specifying requirements and guiding AI tools than writing every line of code by hand. Yet collaboration, reuse, and clear boundaries remain critical. InnerSource helps organizations move faster with *shared* components and practices instead of scattered, duplicated solutions. + +## InnerSource is more relevant than ever + +When many teams use AI to generate or modify code, the risk of duplication and inconsistency grows. InnerSource encourages shared building blocks and a single place to contribute improvements. That reduces waste and keeps quality consistent across the organization. The demand for software architecture and orchestration skills is also rising: understanding system boundaries, interfaces, and processes is essential for building valuable, reliable AI-assisted systems. InnerSource’s emphasis on transparency, documentation, and community aligns with this need. + +## Reducing context for AI + +AI systems and coding agents work best when they have a well-scoped, well-boundaried context. InnerSource projects that are clearly scoped—with explicit interfaces and a clear purpose—give AI a manageable surface area. That improves reliability and reduces the chance of AI “hallucinating” or misusing code from outside the intended scope. Shaping your repositories for both humans and AI is a theme we explore in [Shaping Repositories and Practices for AI](shaping-for-ai.md). + +## Reuse and avoiding duplication + +Reuse at the service or component level is especially valuable when many teams use AI to generate code. Without shared standards and shared repos, each team may produce similar solutions in isolation. InnerSource fosters reuse and cost sharing across units, which in turn supports sustainability and efficiency. This is the same benefit InnerSource has always offered; in an AI-augmented world, it becomes harder to ignore. + +## Enterprise AI and production readiness + +This section focuses on large-scale enterprise adoption of AI—internal tools, pipelines, and agentic workflows—rather than consumer-facing AI products. In that context, the difference between prototype AI solutions and production-ready ones matters a lot. InnerSource practices—transparency, code review, documentation, and governance—help teams build robust, secure, and maintainable AI-assisted development. They also help leaders see what is ready for production and what still needs work. + +## Evidence and further reading + +AI tooling and organizational practices are evolving. This section will be updated with results from the [InnerSource Commons](https://innersourcecommons.org/) survey and from research partnerships (e.g. with universities, [FINOS](https://finos.org/), and other organizations) as data becomes available. If you have case studies or data to share, we encourage you to contribute or get in touch via the [InnerSource Commons Slack](https://innersourcecommons.org/slack). diff --git a/introduction/framework.md b/introduction/framework.md index a9ef3e8..757f6e2 100644 --- a/introduction/framework.md +++ b/introduction/framework.md @@ -112,3 +112,7 @@ Open measurement gives a lot of benefits for our InnerSource community: - transparency, as trust generator for third parties and fairness for our InnerSource community + +## InnerSource and AI + +Organizations adopting AI in the workplace—from generative AI assistants to agentic coding tools—can benefit from InnerSource in new ways. Shared repositories, clear boundaries, and collaborative practices help both humans and AI work with the right context and reuse. See the [InnerSource and AI](/innersource-and-ai/innersource-and-ai.md) section for why it matters, how to shape repositories and practices for AI, and what risks and guardrails to consider. diff --git a/tooling/innersource-tooling.md b/tooling/innersource-tooling.md index d704ff4..7f279ad 100644 --- a/tooling/innersource-tooling.md +++ b/tooling/innersource-tooling.md @@ -1,5 +1,7 @@ # InnerSource with GitHub +For how tooling and workflow integration support AI-assisted development and InnerSource together, see the [InnerSource and AI](/innersource-and-ai/innersource-and-ai.md) section, in particular [Shaping Repositories and Practices for AI](/innersource-and-ai/shaping-for-ai.md). + ## Effective InnerSource Strategies and Configuration for GitHub This documentation is a compilation of the essential settings and strategies necessary for implementing InnerSource inside an organization. It encompasses both overall strategic elements and specific points relating to SCM configuration. From 82ec8e0b70ba7f7f7726e730d2efea58843b1013 Mon Sep 17 00:00:00 2001 From: Jeff Bailey <776901+jeffabailey@users.noreply.github.com> Date: Mon, 16 Mar 2026 18:02:01 -0700 Subject: [PATCH 02/11] Update innersource-and-ai/authors.md --- innersource-and-ai/authors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/innersource-and-ai/authors.md b/innersource-and-ai/authors.md index 82e41b5..fb5ee02 100644 --- a/innersource-and-ai/authors.md +++ b/innersource-and-ai/authors.md @@ -10,6 +10,6 @@ Chronological order: Chronological order: -* (To be added as the section is reviewed and refined by the community.) +* Jeff Bailey This section was drafted as a discussion starter and is open for contributions. If you would like to be listed as an author or reviewer, please open a pull request or get in touch via [Slack](https://innersourcecommons.org/slack). From 71054d8d5b66df85d1a4f9d43fe50a14cfdec37d Mon Sep 17 00:00:00 2001 From: Jeff Bailey <776901+jeffabailey@users.noreply.github.com> Date: Mon, 16 Mar 2026 19:13:04 -0700 Subject: [PATCH 03/11] chore: updated per PR feedback --- innersource-and-ai/authors.md | 2 ++ innersource-and-ai/risks-and-guardrails.md | 6 ++++-- innersource-and-ai/why-innersource-matters-with-ai.md | 4 ++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/innersource-and-ai/authors.md b/innersource-and-ai/authors.md index fb5ee02..16d55c6 100644 --- a/innersource-and-ai/authors.md +++ b/innersource-and-ai/authors.md @@ -11,5 +11,7 @@ Chronological order: Chronological order: * Jeff Bailey +* Russ Rutledge +* Micaela Eller This section was drafted as a discussion starter and is open for contributions. If you would like to be listed as an author or reviewer, please open a pull request or get in touch via [Slack](https://innersourcecommons.org/slack). diff --git a/innersource-and-ai/risks-and-guardrails.md b/innersource-and-ai/risks-and-guardrails.md index efc0de9..2e7fc7a 100644 --- a/innersource-and-ai/risks-and-guardrails.md +++ b/innersource-and-ai/risks-and-guardrails.md @@ -1,6 +1,8 @@ # Risks and Guardrails -Adopting AI in development can deliver short-term gains in speed and productivity. Without guardrails, it can also introduce long-term risks to quality, security, and maintainability. InnerSource practices help organizations balance innovation with responsibility. +AI is the ultimate InnerSource contributor. Like any external contributor, AI agents generate code that must be reviewed, validated, and integrated thoughtfully into your systems. The same InnerSource practices that enable trusted external contributions—code review, clear guidelines, transparent decision-making, and systems thinking—are exactly what you need to safely and sustainably adopt AI in development. + +Adopting AI without these guardrails can deliver short-term gains in speed and productivity, but at the cost of long-term risks to quality, security, and maintainability. The good news: if your organization has built a strong InnerSource culture, you already have the foundations in place. ## Risks of rapid AI deployment @@ -8,7 +10,7 @@ Trusting AI-generated or AI-modified code without review or guidance can lead to ## The role of code review and systems thinking -When AI generates or modifies code, human review remains essential. Code review catches errors, enforces consistency, and spreads knowledge. InnerSource’s existing review and governance practices—trusted committers, contribution guidelines, and transparent decision-making—apply directly to AI-assisted contributions. Systems thinking is also critical: understanding how a change fits into boundaries, interfaces, and dependencies helps avoid local optimizations that cause global problems. Program leads can emphasize that AI output is a draft to be reviewed, not a substitute for human judgment. +When AI generates or modifies code, human review remains essential. Code review catches errors, enforces consistency, and spreads knowledge. InnerSource's existing review and governance practices—trusted committers, contribution guidelines, and transparent decision-making—apply directly to AI-assisted contributions. Systems thinking is also critical: understanding how a change fits into boundaries, interfaces, and dependencies helps avoid local optimizations that cause global problems. Resources like the [InnerSource Patterns](https://patterns.innersourcecommons.org/) and [Trusted Committer guide](https://innersourcecommons.org/learn/learning-path/trusted-committer/) provide guidance on how to frame and review contributions responsibly. ## Transparency and stakeholder involvement diff --git a/innersource-and-ai/why-innersource-matters-with-ai.md b/innersource-and-ai/why-innersource-matters-with-ai.md index 217dc84..c079bc4 100644 --- a/innersource-and-ai/why-innersource-matters-with-ai.md +++ b/innersource-and-ai/why-innersource-matters-with-ai.md @@ -14,6 +14,10 @@ AI systems and coding agents work best when they have a well-scoped, well-bounda Reuse at the service or component level is especially valuable when many teams use AI to generate code. Without shared standards and shared repos, each team may produce similar solutions in isolation. InnerSource fosters reuse and cost sharing across units, which in turn supports sustainability and efficiency. This is the same benefit InnerSource has always offered; in an AI-augmented world, it becomes harder to ignore. +## Platforms ready for InnerSource + +Platforms and tooling play a crucial role in enabling InnerSource at scale. As organizations adopt AI and agentic workflows, collaboration platforms must support discovery, visibility, and contribution across team boundaries. Platforms that make it easy to find reusable components, understand interfaces, and submit improvements reduce friction and encourage participation. Investment in platform capabilities—search, documentation, governance workflows, and integration with development tools—directly multiplies the effectiveness of InnerSource practices in an AI-augmented environment. + ## Enterprise AI and production readiness This section focuses on large-scale enterprise adoption of AI—internal tools, pipelines, and agentic workflows—rather than consumer-facing AI products. In that context, the difference between prototype AI solutions and production-ready ones matters a lot. InnerSource practices—transparency, code review, documentation, and governance—help teams build robust, secure, and maintainable AI-assisted development. They also help leaders see what is ready for production and what still needs work. From b97ca3287188da5bea07c481877bdbf8e932af7b Mon Sep 17 00:00:00 2001 From: Jeff Bailey <776901+jeffabailey@users.noreply.github.com> Date: Mon, 16 Mar 2026 19:15:15 -0700 Subject: [PATCH 04/11] chore: remove non-innersource specific guidance --- innersource-and-ai/risks-and-guardrails.md | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/innersource-and-ai/risks-and-guardrails.md b/innersource-and-ai/risks-and-guardrails.md index 2e7fc7a..ab91dad 100644 --- a/innersource-and-ai/risks-and-guardrails.md +++ b/innersource-and-ai/risks-and-guardrails.md @@ -4,20 +4,6 @@ AI is the ultimate InnerSource contributor. Like any external contributor, AI ag Adopting AI without these guardrails can deliver short-term gains in speed and productivity, but at the cost of long-term risks to quality, security, and maintainability. The good news: if your organization has built a strong InnerSource culture, you already have the foundations in place. -## Risks of rapid AI deployment - -Trusting AI-generated or AI-modified code without review or guidance can lead to subtle bugs, security issues, and technical debt. Mandating AI use without clear best practices or policies can create unintended problems—teams may not know when to rely on AI and when to double-check. A balanced approach is to encourage experimentation while reinforcing code review, testing, and clear ownership. InnerSource’s culture of transparency and review supports that balance. - -## The role of code review and systems thinking - -When AI generates or modifies code, human review remains essential. Code review catches errors, enforces consistency, and spreads knowledge. InnerSource's existing review and governance practices—trusted committers, contribution guidelines, and transparent decision-making—apply directly to AI-assisted contributions. Systems thinking is also critical: understanding how a change fits into boundaries, interfaces, and dependencies helps avoid local optimizations that cause global problems. Resources like the [InnerSource Patterns](https://patterns.innersourcecommons.org/) and [Trusted Committer guide](https://innersourcecommons.org/learn/learning-path/trusted-committer/) provide guidance on how to frame and review contributions responsibly. - ## Transparency and stakeholder involvement Involving stakeholders and keeping development transparent supports responsible AI deployment. When decisions about tools, patterns, and policies are visible and discussable, teams can align on what is acceptable and what is not. This aligns with InnerSource principles of openness and collaboration and helps prevent AI from being used in ways that conflict with organizational values or compliance requirements. - -## Best practices and guidance - -Organizations need practical guidance on when and how to use AI in development. That may include policies on which tools are approved, how to attribute and review AI-assisted contributions, and how to handle sensitive or regulated code. Detailed policies and playbooks may live in your governance model or in the [InnerSource Patterns](https://patterns.innersourcecommons.org/) book. As a program lead, you can work with governance, security, and engineering leadership to develop and communicate these practices so that adoption of AI remains safe and sustainable. - -For more on governance in InnerSource, see [Governance](/governance/governance.md). From 69f5a4fb355b1208e3ec01b7ed4e582c36ce6681 Mon Sep 17 00:00:00 2001 From: Jeff Bailey <776901+jeffabailey@users.noreply.github.com> Date: Tue, 17 Mar 2026 20:10:11 -0700 Subject: [PATCH 05/11] fix: update to latest mdbook fixing build errors --- .github/workflows/mdbook.yml | 4 ---- MDBOOK.md | 7 +------ mdbook | 4 ---- scripts/install-mdbook.sh | 10 ++++------ 4 files changed, 5 insertions(+), 20 deletions(-) delete mode 100755 mdbook diff --git a/.github/workflows/mdbook.yml b/.github/workflows/mdbook.yml index c6a2fac..5a87aff 100644 --- a/.github/workflows/mdbook.yml +++ b/.github/workflows/mdbook.yml @@ -29,8 +29,6 @@ jobs: build: runs-on: ubuntu-latest env: - MDBOOK_VERSION: 0.4.52 - MDBOOK_MERMAID_VERSION: 0.10.0 CARGO_HOME: ${{ github.workspace }}/.cargo RUSTUP_HOME: ${{ github.workspace }}/.rustup steps: @@ -39,8 +37,6 @@ jobs: run: bash scripts/install-mdbook.sh env: REPO_ROOT: ${{ github.workspace }} - MDBOOK_VERSION: ${{ env.MDBOOK_VERSION }} - MDBOOK_MERMAID_VERSION: ${{ env.MDBOOK_MERMAID_VERSION }} - name: Setup Pages id: pages uses: actions/configure-pages@v5 diff --git a/MDBOOK.md b/MDBOOK.md index 86d02b8..546e154 100644 --- a/MDBOOK.md +++ b/MDBOOK.md @@ -20,15 +20,10 @@ cargo install mdbook --version 0.4.52 Install required preprocessors: ```sh -# Install mdbook-mermaid v0.10.0 (compatible with mdbook 0.4.52) -cargo install mdbook-mermaid --version 0.10.0 - -# Install mdbook-embedify for embedding external content +cargo install mdbook-mermaid cargo install mdbook-embedify ``` -**Note:** These specific versions are required for compatibility. mdbook-embedify 0.2.18 is not compatible with mdbook 0.5.x, so we use mdbook 0.4.52 and a compatible version of mdbook-mermaid. - ## Usage To build the book, run the following command: diff --git a/mdbook b/mdbook deleted file mode 100755 index e535640..0000000 --- a/mdbook +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -# Run the project's mdBook (avoids using global mdbook, which may have incompatible embedify). -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -exec "${SCRIPT_DIR}/.cargo/bin/mdbook" "$@" diff --git a/scripts/install-mdbook.sh b/scripts/install-mdbook.sh index 41324b4..2d5f11d 100755 --- a/scripts/install-mdbook.sh +++ b/scripts/install-mdbook.sh @@ -3,8 +3,9 @@ # Usage: ./scripts/install-mdbook.sh (from repo root) set -e -MDBOOK_VERSION="${MDBOOK_VERSION:-0.4.52}" -MDBOOK_MERMAID_VERSION="${MDBOOK_MERMAID_VERSION:-0.10.0}" +MDBOOK_VERSION="${MDBOOK_VERSION:-0.5.2}" +MDBOOK_MERMAID_VERSION="${MDBOOK_MERMAID_VERSION:-0.17.0}" +MDBOOK_EMBEDIFY_VERSION="${MDBOOK_EMBEDIFY_VERSION:-0.3.2}" # Install into repo so CI and local use the same layout (avoids cross-device issues in act) REPO_ROOT="${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")}" @@ -17,12 +18,9 @@ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-mod source "${CARGO_HOME}/env" rustup update -# Install mdbook v0.4.52 (required for mdbook-embedify compatibility) cargo install --version "${MDBOOK_VERSION}" mdbook -# Install mdbook-mermaid v0.10.0 (compatible with mdbook 0.4.52) cargo install --version "${MDBOOK_MERMAID_VERSION}" mdbook-mermaid -# Install mdbook-embedify (latest version compatible with mdbook 0.4.52) -cargo install mdbook-embedify +cargo install --version "${MDBOOK_EMBEDIFY_VERSION}" mdbook-embedify echo "Done. To build the book, use the project mdbook (do not use your global 'mdbook'):" echo " ./mdbook build" From 3a2ff569f3b3fd4c571e7666ec42e36a8d9f426a Mon Sep 17 00:00:00 2001 From: Jeff Bailey <776901+jeffabailey@users.noreply.github.com> Date: Tue, 17 Mar 2026 21:12:56 -0700 Subject: [PATCH 06/11] feat: add pr preview --- .github/act/pull_request.json | 16 ++++ .github/act/push.json | 3 + .github/workflows/mdbook-pr-preview.yml | 77 +++++++++++++++++++ .github/workflows/mdbook.yml | 7 ++ .github/workflows/mdbook/cleanup-preview.sh | 20 +++++ .../workflows/mdbook/comment-preview-url.js | 43 +++++++++++ scripts/test-mdbook-deploy.sh | 43 +++++++++++ 7 files changed, 209 insertions(+) create mode 100644 .github/act/pull_request.json create mode 100644 .github/act/push.json create mode 100644 .github/workflows/mdbook-pr-preview.yml create mode 100644 .github/workflows/mdbook/cleanup-preview.sh create mode 100644 .github/workflows/mdbook/comment-preview-url.js create mode 100755 scripts/test-mdbook-deploy.sh diff --git a/.github/act/pull_request.json b/.github/act/pull_request.json new file mode 100644 index 0000000..b3b75f3 --- /dev/null +++ b/.github/act/pull_request.json @@ -0,0 +1,16 @@ +{ + "act": true, + "action": "synchronize", + "repository": { + "name": "managing-innersource-projects", + "full_name": "InnerSourceCommons/managing-innersource-projects" + }, + "pull_request": { + "number": 107, + "head": { + "repo": { + "full_name": "InnerSourceCommons/managing-innersource-projects" + } + } + } +} diff --git a/.github/act/push.json b/.github/act/push.json new file mode 100644 index 0000000..35175f5 --- /dev/null +++ b/.github/act/push.json @@ -0,0 +1,3 @@ +{ + "act": true +} \ No newline at end of file diff --git a/.github/workflows/mdbook-pr-preview.yml b/.github/workflows/mdbook-pr-preview.yml new file mode 100644 index 0000000..eeef74a --- /dev/null +++ b/.github/workflows/mdbook-pr-preview.yml @@ -0,0 +1,77 @@ +name: Deploy mdBook PR preview + +on: + pull_request: + types: [opened, synchronize, reopened, closed] + +permissions: + contents: write + pull-requests: write + +concurrency: + # One running preview job per PR number. If new commits arrive, cancel older runs. + group: pr-preview-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + deploy-preview: + if: github.event.action != 'closed' && github.event.pull_request.head.repo.full_name == github.repository + runs-on: ubuntu-latest + env: + CARGO_HOME: ${{ github.workspace }}/.cargo + RUSTUP_HOME: ${{ github.workspace }}/.rustup + PREVIEW_DIR: pr-${{ github.event.pull_request.number }} + PREVIEW_URL: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/pr-${{ github.event.pull_request.number }}/ + steps: + - uses: actions/checkout@v4 + + - name: Install mdBook + run: bash scripts/install-mdbook.sh + env: + REPO_ROOT: ${{ github.workspace }} + + - name: Build with mdBook + run: ${{ env.CARGO_HOME }}/bin/mdbook build + + - name: Deploy preview to gh-pages/pr- + # Important: we build from the PR branch, but publish static files to gh-pages. + # GitHub Pages serves from a configured publishing branch (gh-pages here), + # not from arbitrary PR branches. + uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_branch: gh-pages + publish_dir: ./book + # Keep each preview isolated under pr-/ so multiple PR previews can coexist. + destination_dir: ${{ env.PREVIEW_DIR }} + keep_files: true + + - name: Comment preview URL on PR + uses: actions/github-script@v7 + with: + # Keep workflow YAML concise: run comment logic from .github/workflows/mdbook/comment-preview-url.js. + script: | + const { commentPreviewUrl } = require('./.github/workflows/mdbook/comment-preview-url.js') + await commentPreviewUrl({ + github, + context, + previewUrl: process.env.PREVIEW_URL, + }) + + cleanup-preview: + if: github.event.action == 'closed' && github.event.pull_request.head.repo.full_name == github.repository + runs-on: ubuntu-latest + env: + PREVIEW_DIR: pr-${{ github.event.pull_request.number }} + steps: + - name: Checkout gh-pages + # Cleanup edits the published site branch directly because previews live there. + uses: actions/checkout@v4 + with: + ref: gh-pages + fetch-depth: 0 + + - name: Remove preview directory + run: | + # Keep workflow YAML concise: run cleanup logic from .github/workflows/mdbook/cleanup-preview.sh. + bash .github/workflows/mdbook/cleanup-preview.sh "${PREVIEW_DIR}" "${{ github.event.pull_request.number }}" diff --git a/.github/workflows/mdbook.yml b/.github/workflows/mdbook.yml index 5a87aff..7a544f4 100644 --- a/.github/workflows/mdbook.yml +++ b/.github/workflows/mdbook.yml @@ -38,17 +38,24 @@ jobs: env: REPO_ROOT: ${{ github.workspace }} - name: Setup Pages + if: ${{ !env.ACT }} id: pages uses: actions/configure-pages@v5 - name: Build with mdBook run: ${{ env.CARGO_HOME }}/bin/mdbook build - name: Upload artifact + if: ${{ !env.ACT }} uses: actions/upload-pages-artifact@v3 with: path: ./book + - name: Confirm local act build + if: ${{ env.ACT }} + run: | + echo "Local act run: mdBook build completed; skipping Pages upload/deploy steps." # Deployment job deploy: + if: ${{ !github.event.act }} environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} diff --git a/.github/workflows/mdbook/cleanup-preview.sh b/.github/workflows/mdbook/cleanup-preview.sh new file mode 100644 index 0000000..9e60d3c --- /dev/null +++ b/.github/workflows/mdbook/cleanup-preview.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -euo pipefail + +PREVIEW_DIR="${1:?preview directory is required}" +PR_NUMBER="${2:?pull request number is required}" + +# Delete this PR's published preview folder from gh-pages. +rm -rf "${PREVIEW_DIR}" + +if git status --porcelain | grep -q .; then + # If something changed, commit+push so GitHub Pages drops that preview URL. + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + # Stage only the working-tree changes from this cleanup step before committing. + git add -A + git commit -m "chore: remove preview for #${PR_NUMBER}" + git push +else + echo "No preview directory to remove." +fi diff --git a/.github/workflows/mdbook/comment-preview-url.js b/.github/workflows/mdbook/comment-preview-url.js new file mode 100644 index 0000000..cd86364 --- /dev/null +++ b/.github/workflows/mdbook/comment-preview-url.js @@ -0,0 +1,43 @@ +function buildCommentBody(marker, previewUrl) { + return `${marker}\n📘 mdBook preview for this PR:\n\n${previewUrl}` +} + +async function commentPreviewUrl({ github, context, previewUrl }) { + const marker = '' + const body = buildCommentBody(marker, previewUrl) + + const { owner, repo } = context.repo + const issue_number = context.issue.number + + const comments = await github.paginate(github.rest.issues.listComments, { + owner, + repo, + issue_number, + per_page: 100, + }) + + const existing = comments.find( + (comment) => comment.user?.type === 'Bot' && comment.body?.includes(marker), + ) + + if (existing) { + await github.rest.issues.updateComment({ + owner, + repo, + comment_id: existing.id, + body, + }) + return + } + + await github.rest.issues.createComment({ + owner, + repo, + issue_number, + body, + }) +} + +module.exports = { + commentPreviewUrl, +} diff --git a/scripts/test-mdbook-deploy.sh b/scripts/test-mdbook-deploy.sh new file mode 100755 index 0000000..ad8958f --- /dev/null +++ b/scripts/test-mdbook-deploy.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# Run the mdBook GitHub Actions workflows locally with act. +# Usage: ./scripts/test-mdbook-deploy.sh [act args] +set -euo pipefail + +REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" +MAIN_WORKFLOW_PATH="${REPO_ROOT}/.github/workflows/mdbook.yml" +PREVIEW_WORKFLOW_PATH="${REPO_ROOT}/.github/workflows/mdbook-pr-preview.yml" +PUSH_EVENT_PATH="${REPO_ROOT}/.github/act/push.json" +PULL_REQUEST_EVENT_PATH="${REPO_ROOT}/.github/act/pull_request.json" + +if ! command -v act >/dev/null 2>&1; then + echo "Error: 'act' is not installed or not on PATH." >&2 + exit 1 +fi + +if [[ ! -f "${MAIN_WORKFLOW_PATH}" ]]; then + echo "Error: workflow file not found at ${MAIN_WORKFLOW_PATH}" >&2 + exit 1 +fi + +if [[ ! -f "${PREVIEW_WORKFLOW_PATH}" ]]; then + echo "Error: workflow file not found at ${PREVIEW_WORKFLOW_PATH}" >&2 + exit 1 +fi + +if [[ ! -f "${PUSH_EVENT_PATH}" ]]; then + echo "Error: event payload not found at ${PUSH_EVENT_PATH}" >&2 + exit 1 +fi + +if [[ ! -f "${PULL_REQUEST_EVENT_PATH}" ]]; then + echo "Error: event payload not found at ${PULL_REQUEST_EVENT_PATH}" >&2 + exit 1 +fi + +cd "${REPO_ROOT}" + +echo "Running main Pages workflow (push): ${MAIN_WORKFLOW_PATH}" +act push -W "${MAIN_WORKFLOW_PATH}" -e "${PUSH_EVENT_PATH}" "$@" + +echo "Running PR preview workflow (pull_request): ${PREVIEW_WORKFLOW_PATH}" +act pull_request -W "${PREVIEW_WORKFLOW_PATH}" -e "${PULL_REQUEST_EVENT_PATH}" "$@" From bb7357674a5fc1365a6866e8ffa1026caa2b199b Mon Sep 17 00:00:00 2001 From: Jeff Bailey <776901+jeffabailey@users.noreply.github.com> Date: Tue, 17 Mar 2026 21:39:45 -0700 Subject: [PATCH 07/11] fix: error with embedify, add caching --- .github/workflows/mdbook-pr-preview.yml | 34 +++++++++++++++++++++++++ .github/workflows/mdbook.yml | 32 +++++++++++++++++++++++ scripts/install-mdbook.sh | 15 +++++++---- 3 files changed, 76 insertions(+), 5 deletions(-) diff --git a/.github/workflows/mdbook-pr-preview.yml b/.github/workflows/mdbook-pr-preview.yml index eeef74a..5fd94e5 100644 --- a/.github/workflows/mdbook-pr-preview.yml +++ b/.github/workflows/mdbook-pr-preview.yml @@ -25,11 +25,45 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Cache Cargo registry and git index + uses: actions/cache@v4 + with: + path: | + ${{ env.CARGO_HOME }}/registry + ${{ env.CARGO_HOME }}/git + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('scripts/install-mdbook.sh') }} + restore-keys: | + ${{ runner.os }}-cargo-registry- + + - name: Cache Rust toolchains + uses: actions/cache@v4 + with: + path: | + ${{ env.RUSTUP_HOME }}/toolchains + ${{ env.RUSTUP_HOME }}/update-hashes + key: ${{ runner.os }}-rust-toolchain-${{ hashFiles('scripts/install-mdbook.sh') }} + restore-keys: | + ${{ runner.os }}-rust-toolchain- + + - name: Cache installed mdBook binaries + id: mdbook-cache + uses: actions/cache@v4 + with: + path: | + ${{ env.CARGO_HOME }}/bin + key: ${{ runner.os }}-mdbook-bin-${{ hashFiles('scripts/install-mdbook.sh') }} + restore-keys: | + ${{ runner.os }}-mdbook-bin- + - name: Install mdBook + if: steps.mdbook-cache.outputs.cache-hit != 'true' run: bash scripts/install-mdbook.sh env: REPO_ROOT: ${{ github.workspace }} + - name: Add Cargo bin to PATH + run: echo "${CARGO_HOME}/bin" >> "$GITHUB_PATH" + - name: Build with mdBook run: ${{ env.CARGO_HOME }}/bin/mdbook build diff --git a/.github/workflows/mdbook.yml b/.github/workflows/mdbook.yml index 7a544f4..18514b7 100644 --- a/.github/workflows/mdbook.yml +++ b/.github/workflows/mdbook.yml @@ -33,10 +33,42 @@ jobs: RUSTUP_HOME: ${{ github.workspace }}/.rustup steps: - uses: actions/checkout@v4 + - name: Cache Cargo registry and git index + uses: actions/cache@v4 + with: + path: | + ${{ env.CARGO_HOME }}/registry + ${{ env.CARGO_HOME }}/git + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('scripts/install-mdbook.sh') }} + restore-keys: | + ${{ runner.os }}-cargo-registry- + + - name: Cache Rust toolchains + uses: actions/cache@v4 + with: + path: | + ${{ env.RUSTUP_HOME }}/toolchains + ${{ env.RUSTUP_HOME }}/update-hashes + key: ${{ runner.os }}-rust-toolchain-${{ hashFiles('scripts/install-mdbook.sh') }} + restore-keys: | + ${{ runner.os }}-rust-toolchain- + + - name: Cache installed mdBook binaries + id: mdbook-cache + uses: actions/cache@v4 + with: + path: | + ${{ env.CARGO_HOME }}/bin + key: ${{ runner.os }}-mdbook-bin-${{ hashFiles('scripts/install-mdbook.sh') }} + restore-keys: | + ${{ runner.os }}-mdbook-bin- - name: Install mdBook + if: steps.mdbook-cache.outputs.cache-hit != 'true' run: bash scripts/install-mdbook.sh env: REPO_ROOT: ${{ github.workspace }} + - name: Add Cargo bin to PATH + run: echo "${CARGO_HOME}/bin" >> "$GITHUB_PATH" - name: Setup Pages if: ${{ !env.ACT }} id: pages diff --git a/scripts/install-mdbook.sh b/scripts/install-mdbook.sh index 2d5f11d..06ab9f6 100755 --- a/scripts/install-mdbook.sh +++ b/scripts/install-mdbook.sh @@ -1,11 +1,12 @@ #!/usr/bin/env bash # Install mdBook and plugins (same versions as CI). Safe to run locally. # Usage: ./scripts/install-mdbook.sh (from repo root) -set -e +set -euo pipefail MDBOOK_VERSION="${MDBOOK_VERSION:-0.5.2}" MDBOOK_MERMAID_VERSION="${MDBOOK_MERMAID_VERSION:-0.17.0}" MDBOOK_EMBEDIFY_VERSION="${MDBOOK_EMBEDIFY_VERSION:-0.3.2}" +RUST_TOOLCHAIN_VERSION="${RUST_TOOLCHAIN_VERSION:-1.91.1}" # Install into repo so CI and local use the same layout (avoids cross-device issues in act) REPO_ROOT="${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")}" @@ -14,14 +15,18 @@ export CARGO_HOME="${REPO_ROOT}/.cargo" echo "Installing Rust and mdBook into ${REPO_ROOT} (RUSTUP_HOME=$RUSTUP_HOME, CARGO_HOME=$CARGO_HOME)" -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path -source "${CARGO_HOME}/env" -rustup update +if ! command -v rustup >/dev/null 2>&1; then + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path + source "${CARGO_HOME}/env" +fi + +rustup toolchain install "${RUST_TOOLCHAIN_VERSION}" --profile minimal +rustup default "${RUST_TOOLCHAIN_VERSION}" cargo install --version "${MDBOOK_VERSION}" mdbook cargo install --version "${MDBOOK_MERMAID_VERSION}" mdbook-mermaid cargo install --version "${MDBOOK_EMBEDIFY_VERSION}" mdbook-embedify echo "Done. To build the book, use the project mdbook (do not use your global 'mdbook'):" -echo " ./mdbook build" +echo " ${CARGO_HOME}/bin/mdbook build" echo "Or: source \"${CARGO_HOME}/env\" && mdbook build" From b0d6f8a8160b539df56db645f1ee0bada1422fbe Mon Sep 17 00:00:00 2001 From: Jeff Bailey <776901+jeffabailey@users.noreply.github.com> Date: Tue, 17 Mar 2026 22:00:21 -0700 Subject: [PATCH 08/11] fix: adjust approach with gh-pages --- .github/workflows/mdbook-pr-preview.yml | 5 +++ .github/workflows/mdbook.yml | 48 +++++++++---------------- book.toml | 2 ++ 3 files changed, 23 insertions(+), 32 deletions(-) diff --git a/.github/workflows/mdbook-pr-preview.yml b/.github/workflows/mdbook-pr-preview.yml index 5fd94e5..8777486 100644 --- a/.github/workflows/mdbook-pr-preview.yml +++ b/.github/workflows/mdbook-pr-preview.yml @@ -64,6 +64,11 @@ jobs: - name: Add Cargo bin to PATH run: echo "${CARGO_HOME}/bin" >> "$GITHUB_PATH" + - name: Set site-url for PR preview subpath + run: | + SITE_URL="/${{ github.event.repository.name }}/${{ env.PREVIEW_DIR }}/" + sed -i "s|^site-url = .*|site-url = \"${SITE_URL}\"|" book.toml + - name: Build with mdBook run: ${{ env.CARGO_HOME }}/bin/mdbook build diff --git a/.github/workflows/mdbook.yml b/.github/workflows/mdbook.yml index 18514b7..a4ea4e5 100644 --- a/.github/workflows/mdbook.yml +++ b/.github/workflows/mdbook.yml @@ -1,7 +1,9 @@ -# Workflow for building and deploying a mdBook site to GitHub Pages -# -# To get started with mdBook see: https://rust-lang.github.io/mdBook/index.html +# Workflow for building and deploying a mdBook site to GitHub Pages. +# Publishes to the gh-pages branch so PR previews (pr-/) from +# mdbook-pr-preview.yml are served from the same branch. Set Pages source +# to "Deploy from a branch" → gh-pages, folder / (root). # +# See: https://rust-lang.github.io/mdBook/index.html name: Deploy mdBook site to Pages on: @@ -12,21 +14,17 @@ on: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: -# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +# Push to gh-pages so PR previews (mdbook-pr-preview) are served from the same branch. +# Repository Settings → Pages → Source: Deploy from a branch → gh-pages / (root). permissions: - contents: read - pages: write - id-token: write + contents: write -# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. -# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. concurrency: group: "pages" cancel-in-progress: false jobs: - # Build job - build: + build-and-deploy: runs-on: ubuntu-latest env: CARGO_HOME: ${{ github.workspace }}/.cargo @@ -69,31 +67,17 @@ jobs: REPO_ROOT: ${{ github.workspace }} - name: Add Cargo bin to PATH run: echo "${CARGO_HOME}/bin" >> "$GITHUB_PATH" - - name: Setup Pages - if: ${{ !env.ACT }} - id: pages - uses: actions/configure-pages@v5 - name: Build with mdBook run: ${{ env.CARGO_HOME }}/bin/mdbook build - - name: Upload artifact + - name: Deploy to gh-pages (root) if: ${{ !env.ACT }} - uses: actions/upload-pages-artifact@v3 + uses: peaceiris/actions-gh-pages@v4 with: - path: ./book + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_branch: gh-pages + publish_dir: ./book + keep_files: true - name: Confirm local act build if: ${{ env.ACT }} run: | - echo "Local act run: mdBook build completed; skipping Pages upload/deploy steps." - - # Deployment job - deploy: - if: ${{ !github.event.act }} - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - runs-on: ubuntu-latest - needs: build - steps: - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 + echo "Local act run: mdBook build completed; skipping gh-pages deploy." diff --git a/book.toml b/book.toml index 679b292..59c5dde 100644 --- a/book.toml +++ b/book.toml @@ -20,4 +20,6 @@ giscus.loading = "lazy" giscus.crossorigin = "anonymous" [output.html] +# Required for correct asset and 404 paths on GitHub Pages (project site and PR preview subpaths). +site-url = "/managing-innersource-projects/" additional-js = ["mermaid.min.js", "mermaid-init.js"] From 269b4b3726a193dfad5c57b1b8c99ad30a8ce50f Mon Sep 17 00:00:00 2001 From: Jeff Bailey <776901+jeffabailey@users.noreply.github.com> Date: Tue, 17 Mar 2026 22:08:41 -0700 Subject: [PATCH 09/11] fix: adjust approach with gh-pages --- .github/workflows/mdbook.yml | 56 ++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/.github/workflows/mdbook.yml b/.github/workflows/mdbook.yml index a4ea4e5..658ca73 100644 --- a/.github/workflows/mdbook.yml +++ b/.github/workflows/mdbook.yml @@ -1,36 +1,34 @@ # Workflow for building and deploying a mdBook site to GitHub Pages. -# Publishes to the gh-pages branch so PR previews (pr-/) from -# mdbook-pr-preview.yml are served from the same branch. Set Pages source -# to "Deploy from a branch" → gh-pages, folder / (root). +# Serves the main book at / and PR previews at /pr-/ by merging +# pr-* directories from the gh-pages branch (pushed by mdbook-pr-preview.yml) +# into the deployed artifact. Works with Pages source "GitHub Actions". # # See: https://rust-lang.github.io/mdBook/index.html name: Deploy mdBook site to Pages on: - # Runs on pushes targeting the default branch push: branches: ["main"] - - # Allows you to run this workflow manually from the Actions tab workflow_dispatch: -# Push to gh-pages so PR previews (mdbook-pr-preview) are served from the same branch. -# Repository Settings → Pages → Source: Deploy from a branch → gh-pages / (root). permissions: - contents: write + contents: read + pages: write + id-token: write concurrency: group: "pages" cancel-in-progress: false jobs: - build-and-deploy: + build: runs-on: ubuntu-latest env: CARGO_HOME: ${{ github.workspace }}/.cargo RUSTUP_HOME: ${{ github.workspace }}/.rustup steps: - uses: actions/checkout@v4 + - name: Cache Cargo registry and git index uses: actions/cache@v4 with: @@ -60,24 +58,46 @@ jobs: key: ${{ runner.os }}-mdbook-bin-${{ hashFiles('scripts/install-mdbook.sh') }} restore-keys: | ${{ runner.os }}-mdbook-bin- + - name: Install mdBook if: steps.mdbook-cache.outputs.cache-hit != 'true' run: bash scripts/install-mdbook.sh env: REPO_ROOT: ${{ github.workspace }} + - name: Add Cargo bin to PATH run: echo "${CARGO_HOME}/bin" >> "$GITHUB_PATH" + - name: Build with mdBook run: ${{ env.CARGO_HOME }}/bin/mdbook build - - name: Deploy to gh-pages (root) + + - name: Merge PR previews from gh-pages into artifact + run: | + git fetch origin gh-pages 2>/dev/null || true + if git rev-parse -q origin/gh-pages >/dev/null 2>&1; then + for d in $(git ls-tree -d --name-only origin/gh-pages 2>/dev/null | grep -E '^pr-[0-9]+$'); do + git archive origin/gh-pages "$d" | tar -x -C book + done + fi + + - name: Upload artifact if: ${{ !env.ACT }} - uses: peaceiris/actions-gh-pages@v4 + uses: actions/upload-pages-artifact@v3 with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_branch: gh-pages - publish_dir: ./book - keep_files: true + path: ./book + - name: Confirm local act build if: ${{ env.ACT }} - run: | - echo "Local act run: mdBook build completed; skipping gh-pages deploy." + run: echo "Local act run: mdBook build completed; skipping upload." + + deploy: + if: ${{ !env.ACT }} + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 From 9158f7ca1a33912515964f7c6f090495675f3f92 Mon Sep 17 00:00:00 2001 From: Jeff Bailey <776901+jeffabailey@users.noreply.github.com> Date: Wed, 18 Mar 2026 05:10:13 -0700 Subject: [PATCH 10/11] chore: move to pr-preview-action --- .github/act/pull_request.json | 2 + .github/act/push.json | 8 +- .github/workflows/mdbook-pr-preview.yml | 116 ----------------- .github/workflows/mdbook.yml | 119 ++++++++++++------ .github/workflows/mdbook/cleanup-preview.sh | 20 --- .../workflows/mdbook/comment-preview-url.js | 43 ------- scripts/test-mdbook-deploy.sh | 20 ++- 7 files changed, 97 insertions(+), 231 deletions(-) delete mode 100644 .github/workflows/mdbook-pr-preview.yml delete mode 100644 .github/workflows/mdbook/cleanup-preview.sh delete mode 100644 .github/workflows/mdbook/comment-preview-url.js diff --git a/.github/act/pull_request.json b/.github/act/pull_request.json index b3b75f3..6d75c34 100644 --- a/.github/act/pull_request.json +++ b/.github/act/pull_request.json @@ -2,6 +2,8 @@ "act": true, "action": "synchronize", "repository": { + "fork": false, + "default_branch": "main", "name": "managing-innersource-projects", "full_name": "InnerSourceCommons/managing-innersource-projects" }, diff --git a/.github/act/push.json b/.github/act/push.json index 35175f5..6217789 100644 --- a/.github/act/push.json +++ b/.github/act/push.json @@ -1,3 +1,7 @@ { - "act": true -} \ No newline at end of file + "act": true, + "repository": { + "fork": false, + "default_branch": "main" + } +} diff --git a/.github/workflows/mdbook-pr-preview.yml b/.github/workflows/mdbook-pr-preview.yml deleted file mode 100644 index 8777486..0000000 --- a/.github/workflows/mdbook-pr-preview.yml +++ /dev/null @@ -1,116 +0,0 @@ -name: Deploy mdBook PR preview - -on: - pull_request: - types: [opened, synchronize, reopened, closed] - -permissions: - contents: write - pull-requests: write - -concurrency: - # One running preview job per PR number. If new commits arrive, cancel older runs. - group: pr-preview-${{ github.event.pull_request.number }} - cancel-in-progress: true - -jobs: - deploy-preview: - if: github.event.action != 'closed' && github.event.pull_request.head.repo.full_name == github.repository - runs-on: ubuntu-latest - env: - CARGO_HOME: ${{ github.workspace }}/.cargo - RUSTUP_HOME: ${{ github.workspace }}/.rustup - PREVIEW_DIR: pr-${{ github.event.pull_request.number }} - PREVIEW_URL: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/pr-${{ github.event.pull_request.number }}/ - steps: - - uses: actions/checkout@v4 - - - name: Cache Cargo registry and git index - uses: actions/cache@v4 - with: - path: | - ${{ env.CARGO_HOME }}/registry - ${{ env.CARGO_HOME }}/git - key: ${{ runner.os }}-cargo-registry-${{ hashFiles('scripts/install-mdbook.sh') }} - restore-keys: | - ${{ runner.os }}-cargo-registry- - - - name: Cache Rust toolchains - uses: actions/cache@v4 - with: - path: | - ${{ env.RUSTUP_HOME }}/toolchains - ${{ env.RUSTUP_HOME }}/update-hashes - key: ${{ runner.os }}-rust-toolchain-${{ hashFiles('scripts/install-mdbook.sh') }} - restore-keys: | - ${{ runner.os }}-rust-toolchain- - - - name: Cache installed mdBook binaries - id: mdbook-cache - uses: actions/cache@v4 - with: - path: | - ${{ env.CARGO_HOME }}/bin - key: ${{ runner.os }}-mdbook-bin-${{ hashFiles('scripts/install-mdbook.sh') }} - restore-keys: | - ${{ runner.os }}-mdbook-bin- - - - name: Install mdBook - if: steps.mdbook-cache.outputs.cache-hit != 'true' - run: bash scripts/install-mdbook.sh - env: - REPO_ROOT: ${{ github.workspace }} - - - name: Add Cargo bin to PATH - run: echo "${CARGO_HOME}/bin" >> "$GITHUB_PATH" - - - name: Set site-url for PR preview subpath - run: | - SITE_URL="/${{ github.event.repository.name }}/${{ env.PREVIEW_DIR }}/" - sed -i "s|^site-url = .*|site-url = \"${SITE_URL}\"|" book.toml - - - name: Build with mdBook - run: ${{ env.CARGO_HOME }}/bin/mdbook build - - - name: Deploy preview to gh-pages/pr- - # Important: we build from the PR branch, but publish static files to gh-pages. - # GitHub Pages serves from a configured publishing branch (gh-pages here), - # not from arbitrary PR branches. - uses: peaceiris/actions-gh-pages@v4 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_branch: gh-pages - publish_dir: ./book - # Keep each preview isolated under pr-/ so multiple PR previews can coexist. - destination_dir: ${{ env.PREVIEW_DIR }} - keep_files: true - - - name: Comment preview URL on PR - uses: actions/github-script@v7 - with: - # Keep workflow YAML concise: run comment logic from .github/workflows/mdbook/comment-preview-url.js. - script: | - const { commentPreviewUrl } = require('./.github/workflows/mdbook/comment-preview-url.js') - await commentPreviewUrl({ - github, - context, - previewUrl: process.env.PREVIEW_URL, - }) - - cleanup-preview: - if: github.event.action == 'closed' && github.event.pull_request.head.repo.full_name == github.repository - runs-on: ubuntu-latest - env: - PREVIEW_DIR: pr-${{ github.event.pull_request.number }} - steps: - - name: Checkout gh-pages - # Cleanup edits the published site branch directly because previews live there. - uses: actions/checkout@v4 - with: - ref: gh-pages - fetch-depth: 0 - - - name: Remove preview directory - run: | - # Keep workflow YAML concise: run cleanup logic from .github/workflows/mdbook/cleanup-preview.sh. - bash .github/workflows/mdbook/cleanup-preview.sh "${PREVIEW_DIR}" "${{ github.event.pull_request.number }}" diff --git a/.github/workflows/mdbook.yml b/.github/workflows/mdbook.yml index 658ca73..ebf7954 100644 --- a/.github/workflows/mdbook.yml +++ b/.github/workflows/mdbook.yml @@ -1,7 +1,11 @@ # Workflow for building and deploying a mdBook site to GitHub Pages. -# Serves the main book at / and PR previews at /pr-/ by merging -# pr-* directories from the gh-pages branch (pushed by mdbook-pr-preview.yml) -# into the deployed artifact. Works with Pages source "GitHub Actions". +# - On push to main: deploys to the root of gh-pages. +# - On pull_request: deploys a preview under pr-/ on gh-pages, +# comments the preview URL, and cleans up when the PR closes. +# +# Repo Settings required: +# Pages -> Source: "Deploy from a branch" -> gh-pages / (root) +# Actions -> General -> Workflow permissions: "Read and write permissions" # # See: https://rust-lang.github.io/mdBook/index.html name: Deploy mdBook site to Pages @@ -9,20 +13,21 @@ name: Deploy mdBook site to Pages on: push: branches: ["main"] + pull_request: + types: [opened, synchronize, reopened, closed] workflow_dispatch: permissions: - contents: read - pages: write - id-token: write - -concurrency: - group: "pages" - cancel-in-progress: false + contents: write + pull-requests: write jobs: - build: + deploy: + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest + concurrency: + group: pages + cancel-in-progress: false env: CARGO_HOME: ${{ github.workspace }}/.cargo RUSTUP_HOME: ${{ github.workspace }}/.rustup @@ -71,33 +76,73 @@ jobs: - name: Build with mdBook run: ${{ env.CARGO_HOME }}/bin/mdbook build - - name: Merge PR previews from gh-pages into artifact - run: | - git fetch origin gh-pages 2>/dev/null || true - if git rev-parse -q origin/gh-pages >/dev/null 2>&1; then - for d in $(git ls-tree -d --name-only origin/gh-pages 2>/dev/null | grep -E '^pr-[0-9]+$'); do - git archive origin/gh-pages "$d" | tar -x -C book - done - fi - - - name: Upload artifact - if: ${{ !env.ACT }} - uses: actions/upload-pages-artifact@v3 + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v4 with: - path: ./book + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./book + keep_files: true - - name: Confirm local act build - if: ${{ env.ACT }} - run: echo "Local act run: mdBook build completed; skipping upload." - - deploy: - if: ${{ !env.ACT }} - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} + preview: + if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest - needs: build + concurrency: preview-${{ github.ref }} + env: + CARGO_HOME: ${{ github.workspace }}/.cargo + RUSTUP_HOME: ${{ github.workspace }}/.rustup steps: - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 + - uses: actions/checkout@v4 + + - name: Cache Cargo registry and git index + if: github.event.action != 'closed' + uses: actions/cache@v4 + with: + path: | + ${{ env.CARGO_HOME }}/registry + ${{ env.CARGO_HOME }}/git + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('scripts/install-mdbook.sh') }} + restore-keys: | + ${{ runner.os }}-cargo-registry- + + - name: Cache Rust toolchains + if: github.event.action != 'closed' + uses: actions/cache@v4 + with: + path: | + ${{ env.RUSTUP_HOME }}/toolchains + ${{ env.RUSTUP_HOME }}/update-hashes + key: ${{ runner.os }}-rust-toolchain-${{ hashFiles('scripts/install-mdbook.sh') }} + restore-keys: | + ${{ runner.os }}-rust-toolchain- + + - name: Cache installed mdBook binaries + if: github.event.action != 'closed' + id: mdbook-cache + uses: actions/cache@v4 + with: + path: | + ${{ env.CARGO_HOME }}/bin + key: ${{ runner.os }}-mdbook-bin-${{ hashFiles('scripts/install-mdbook.sh') }} + restore-keys: | + ${{ runner.os }}-mdbook-bin- + + - name: Install mdBook + if: github.event.action != 'closed' && steps.mdbook-cache.outputs.cache-hit != 'true' + run: bash scripts/install-mdbook.sh + env: + REPO_ROOT: ${{ github.workspace }} + + - name: Add Cargo bin to PATH + if: github.event.action != 'closed' + run: echo "${CARGO_HOME}/bin" >> "$GITHUB_PATH" + + - name: Build with mdBook + if: github.event.action != 'closed' + run: ${{ env.CARGO_HOME }}/bin/mdbook build + + - name: Deploy PR preview + uses: rossjrw/pr-preview-action@v1 + with: + source-dir: ./book + preview-branch: gh-pages + umbrella-dir: pr-preview diff --git a/.github/workflows/mdbook/cleanup-preview.sh b/.github/workflows/mdbook/cleanup-preview.sh deleted file mode 100644 index 9e60d3c..0000000 --- a/.github/workflows/mdbook/cleanup-preview.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -PREVIEW_DIR="${1:?preview directory is required}" -PR_NUMBER="${2:?pull request number is required}" - -# Delete this PR's published preview folder from gh-pages. -rm -rf "${PREVIEW_DIR}" - -if git status --porcelain | grep -q .; then - # If something changed, commit+push so GitHub Pages drops that preview URL. - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - # Stage only the working-tree changes from this cleanup step before committing. - git add -A - git commit -m "chore: remove preview for #${PR_NUMBER}" - git push -else - echo "No preview directory to remove." -fi diff --git a/.github/workflows/mdbook/comment-preview-url.js b/.github/workflows/mdbook/comment-preview-url.js deleted file mode 100644 index cd86364..0000000 --- a/.github/workflows/mdbook/comment-preview-url.js +++ /dev/null @@ -1,43 +0,0 @@ -function buildCommentBody(marker, previewUrl) { - return `${marker}\n📘 mdBook preview for this PR:\n\n${previewUrl}` -} - -async function commentPreviewUrl({ github, context, previewUrl }) { - const marker = '' - const body = buildCommentBody(marker, previewUrl) - - const { owner, repo } = context.repo - const issue_number = context.issue.number - - const comments = await github.paginate(github.rest.issues.listComments, { - owner, - repo, - issue_number, - per_page: 100, - }) - - const existing = comments.find( - (comment) => comment.user?.type === 'Bot' && comment.body?.includes(marker), - ) - - if (existing) { - await github.rest.issues.updateComment({ - owner, - repo, - comment_id: existing.id, - body, - }) - return - } - - await github.rest.issues.createComment({ - owner, - repo, - issue_number, - body, - }) -} - -module.exports = { - commentPreviewUrl, -} diff --git a/scripts/test-mdbook-deploy.sh b/scripts/test-mdbook-deploy.sh index ad8958f..1cba652 100755 --- a/scripts/test-mdbook-deploy.sh +++ b/scripts/test-mdbook-deploy.sh @@ -4,8 +4,7 @@ set -euo pipefail REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" -MAIN_WORKFLOW_PATH="${REPO_ROOT}/.github/workflows/mdbook.yml" -PREVIEW_WORKFLOW_PATH="${REPO_ROOT}/.github/workflows/mdbook-pr-preview.yml" +WORKFLOW_PATH="${REPO_ROOT}/.github/workflows/mdbook.yml" PUSH_EVENT_PATH="${REPO_ROOT}/.github/act/push.json" PULL_REQUEST_EVENT_PATH="${REPO_ROOT}/.github/act/pull_request.json" @@ -14,13 +13,8 @@ if ! command -v act >/dev/null 2>&1; then exit 1 fi -if [[ ! -f "${MAIN_WORKFLOW_PATH}" ]]; then - echo "Error: workflow file not found at ${MAIN_WORKFLOW_PATH}" >&2 - exit 1 -fi - -if [[ ! -f "${PREVIEW_WORKFLOW_PATH}" ]]; then - echo "Error: workflow file not found at ${PREVIEW_WORKFLOW_PATH}" >&2 +if [[ ! -f "${WORKFLOW_PATH}" ]]; then + echo "Error: workflow file not found at ${WORKFLOW_PATH}" >&2 exit 1 fi @@ -36,8 +30,8 @@ fi cd "${REPO_ROOT}" -echo "Running main Pages workflow (push): ${MAIN_WORKFLOW_PATH}" -act push -W "${MAIN_WORKFLOW_PATH}" -e "${PUSH_EVENT_PATH}" "$@" +echo "Running deploy job (push): ${WORKFLOW_PATH}" +act push -W "${WORKFLOW_PATH}" -e "${PUSH_EVENT_PATH}" "$@" -echo "Running PR preview workflow (pull_request): ${PREVIEW_WORKFLOW_PATH}" -act pull_request -W "${PREVIEW_WORKFLOW_PATH}" -e "${PULL_REQUEST_EVENT_PATH}" "$@" +echo "Running deploy-preview job (pull_request): ${WORKFLOW_PATH}" +act pull_request -W "${WORKFLOW_PATH}" -e "${PULL_REQUEST_EVENT_PATH}" "$@" From 75da1f873d6cd0f0bfe8fa4c8b668da621b99fdb Mon Sep 17 00:00:00 2001 From: Jeff Bailey <776901+jeffabailey@users.noreply.github.com> Date: Wed, 18 Mar 2026 05:30:40 -0700 Subject: [PATCH 11/11] fix: correct pr-preview comment path Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/mdbook.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mdbook.yml b/.github/workflows/mdbook.yml index ebf7954..f247864 100644 --- a/.github/workflows/mdbook.yml +++ b/.github/workflows/mdbook.yml @@ -1,6 +1,6 @@ # Workflow for building and deploying a mdBook site to GitHub Pages. # - On push to main: deploys to the root of gh-pages. -# - On pull_request: deploys a preview under pr-/ on gh-pages, +# - On pull_request: deploys a preview under pr-preview/pr-/ on gh-pages, # comments the preview URL, and cleans up when the PR closes. # # Repo Settings required: