Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
026280c
openRepoShape: `--install` records the ref it runs at in `openRepoSha…
Oct 14, 2026
d0cdbf4
install.sh: one line, `curl -fsSL https://github.com/opensoft/openRep…
Oct 14, 2026
319b005
openRepoShape and install.sh, the fix round on #577: `--install` reco…
Oct 15, 2026
322a305
README.md, docs/handbook.html, AGENTS.md and the v1.0.1 release notes…
Oct 15, 2026
868c9bf
docs/release-notes/v1.0.1.md: the "Before tagging" steps are safe to …
Oct 15, 2026
892a041
Merge remote-tracking branch 'origin/l3-564-one-line-install' into l3…
Oct 15, 2026
b2f0be3
tests/readme-cap.d/564.txt: README.md's cap is 1449, raised by 22 for…
Oct 15, 2026
68b999f
docs/handbook.html: the consent rules say every action the tool OFFER…
Oct 15, 2026
53416db
Merge remote-tracking branch 'origin/main' into l3-564-carry-to-main
Oct 15, 2026
a155945
Merge remote-tracking branch 'origin/main' into l3-564-carry-to-main
Oct 15, 2026
c1e6b82
README.md: the NOTE says the preflight installs nothing without the t…
Oct 15, 2026
5191f0e
docs/handbook.html: the consent rules say install.sh asks nothing bef…
Oct 15, 2026
649b089
tests/test_openreposhape_command.py and tests/test_install_sh.py run …
Oct 15, 2026
25b2aee
Merge branch 'main' into l3-564-carry-to-main
brettheap Oct 15, 2026
01e8c2c
README.md and docs/handbook.html: Git Bash runs the one-line install …
Oct 15, 2026
3095a9c
tests/test_openreposhape_command.py: the fetched-setup.sh test assert…
Oct 15, 2026
b23b245
Merge remote-tracking branch 'origin/main' into l3-564-carry-to-main
Oct 15, 2026
f655286
Merge l3-564-carry-to-main b23b2456 (main 654c476c, #597's Linux-only…
Oct 15, 2026
5f001de
.github/workflows/tests.yml, README.md and docs/handbook.html: a smal…
Oct 15, 2026
d5011b1
Merge branch 'main' into l3-564-carry-to-main
brettheap Oct 15, 2026
fe58d66
.github/workflows/tests.yml: the header says the FULL suite runs on L…
Oct 15, 2026
f9b07c9
Merge remote-tracking branch 'origin/main' into l3-564-carry-to-main
Oct 15, 2026
3d8fa05
Merge branch 'main' into l3-564-carry-to-main
brettheap Oct 15, 2026
3080ac0
Merge l3-564-carry-to-main 3d8fa05e (#587's final head, squash-landed…
Oct 15, 2026
4c3b72a
Merge main 77bb5f0f (22eaceed, #587's squash, and #615's bootstrap.py…
Oct 15, 2026
52524fe
Merge main 396c0ff4 (#598's install.sh, 3fb21d9e, and four more) into…
Oct 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 96 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ name: tests
# clones them over the filesystem. It never calls `gh`, never touches the
# network, and must never create a real repository.
#
# The suite runs on LINUX ONLY, on every trigger: a push to `main`, a pull
# The FULL suite runs on LINUX ONLY, on every trigger: a push to `main`, a pull
# request and a manual run all use the one ubuntu job below. Brett Heap decided
# on 2026-10-15, for the whole estate, to drop the macOS and Windows test jobs.
# One exception, on Brett Heap's word at 2026-10-15T18:20:35Z,
# "Option 1: keep a small Git Bash job for #596": the `tests-git-bash` job
# below runs the launcher's and the installer's suites, and nothing else, on
# Windows under Git Bash.

on:
push:
Expand Down Expand Up @@ -123,3 +127,94 @@ jobs:
.github/workflows/tests.yml
templates/assembly-root/.github/workflows/validate.yml
templates/family-root/.github/workflows/validate.yml

# THE LAUNCHER'S AND THE INSTALLER'S SUITES ON WINDOWS, UNDER GIT BASH
# (#585). README says Git Bash runs the `openRepoShape` command and the
# one-line install, "tested in CI but for a typed `yes`", and this job is
# what makes that true: `tests/test_openreposhape_command.py` and
# `tests/test_install_sh.py`, run here as Git Bash runs them.
#
# TWO SUITES, NOT THE WHOLE SUITE. #597 dropped the Windows job for the
# whole estate, and this job is the one exception made to it (see the
# header), so it runs what README's sentence claims and nothing more:
# about a minute and a half (86 s on the first run, 50 s of it pytest),
# beside the ubuntu job and not after it. No git-filter-repo, because
# these suites never reach a real one (the install suite fakes it and
# pipx, and the launcher's machine report gets a fake on the PATH it
# builds), and no actionlint, which the ubuntu job runs on this file.
#
# THE BASH IS GIT'S OWN `usr\bin\bash.exe`, which `tests/conftest.py`
# (`BASH`) finds from `git --exec-path` and never by name: a bare `bash`
# runs System32's WSL launcher, which CreateProcess searches before PATH,
# and `Git\bin\bash.exe`, the `bash` PATH names first on this image, puts
# Git's real `curl` ahead of the suites' fake. conftest's comment there
# has the rest.
#
# ON EVERY TRIGGER, a push to `main` included: a squash lands a tree no
# pull-request run tested (#122), and these two suites are the only run
# of the one-line install on Windows.
tests-git-bash:
runs-on: windows-latest
timeout-minutes: 15
env:
# The old Windows job's settings, which every Windows run of these
# two suites has had, #585's probes included. Per-invocation git
# config, never `git config --global`.
#
# PYTHONUTF8=1 (PEP 540): the suites read bash's output with
# `text=True`, which decodes in the locale's code page (cp1252 here)
# outside UTF-8 mode, and the launcher's `--help` is full of em dashes.
#
# core.autocrlf=false: Git for Windows' own default is `true`, and the
# suites commit, clone and check out repositories of their own; no test
# here asks for line-ending translation.
#
# core.longpaths=true: MAX_PATH is 260 characters, and the suites'
# clones nest under pytest's temp root.
PYTHONUTF8: '1'
GIT_CONFIG_COUNT: '2'
GIT_CONFIG_KEY_0: core.autocrlf
GIT_CONFIG_VALUE_0: 'false'
GIT_CONFIG_KEY_1: core.longpaths
GIT_CONFIG_VALUE_1: 'true'
steps:
# The SAME two commits the ubuntu job pins. `fetch-depth: 0` because
# the launcher's suite clones this checkout itself
# (`OPENREPOSHAPE_REPO` in `test_a_ref_the_doctor_would_check_out_is_
# validated`), and every Windows run of it has cloned a full one.
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
fetch-depth: 0
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: '3.x'

# `python`, not `python3`: a Windows install has no `python3`.
- name: install the test runner
run: python -m pip install --disable-pip-version-check pytest==8.3.4

# Per-invocation identity, never `git config --global`. PowerShell is
# the default shell on this runner, so the append is
# `>> $env:GITHUB_ENV` rather than the ubuntu job's
# `{ echo ... } >> "$GITHUB_ENV"` block.
- name: git identity for the test repositories (env, not global config)
run: |
"GIT_AUTHOR_NAME=openRepoShape CI" >> $env:GITHUB_ENV
"GIT_AUTHOR_EMAIL=ci@openreposhape.invalid" >> $env:GITHUB_ENV
"GIT_COMMITTER_NAME=openRepoShape CI" >> $env:GITHUB_ENV
"GIT_COMMITTER_EMAIL=ci@openreposhape.invalid" >> $env:GITHUB_ENV

# GIT BASH, OR THIS JOB FAILS HERE. Where conftest finds no Git Bash,
# both suites SKIP, and a job of skips would leave README's sentence a
# claim again, so this step refuses first and prints the bash the
# suites will run.
- name: Git Bash is the bash the launcher and installer suites run
run: python -c "import sys; sys.path.insert(0, 'tests'); from conftest import BASH; print(BASH); sys.exit(BASH is None)"

# `-rA` names every test and its result in the log. `--basetemp` puts
# pytest's temp root as near the drive root as a path the runner
# guarantees allows: `runner.temp` is `D:\a\_temp` or `C:\a\_temp`,
# and the default profile path is ~50 of MAX_PATH's 260 characters
# before the suites' own nesting starts.
- name: the launcher's and the installer's suites, under Git Bash
run: python -m pytest -q -rA tests/test_openreposhape_command.py tests/test_install_sh.py --basetemp=${{ runner.temp }}\t
36 changes: 18 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ puts it there — run that line, or the next shell cannot find `brew`. Then `bre
install gh`, and `brew install git-filter-repo` only if you are ADOPTING an
existing repository rather than scaffolding a new one. The stock `/bin/bash` is
3.2 and is enough: `setup.sh`, `install.sh` and the `openRepoShape` command are
written to use no syntax newer than that, though CI runs on Linux only and no
run of it checks them against bash 3.2. That the login shell is zsh changes
nothing — all three entry points are run under `bash` explicitly.
written to use no syntax newer than that, though no CI run, on Linux or in Git
Bash on Windows, checks them against bash 3.2. That the login shell is zsh
changes nothing — all three entry points are run under `bash` explicitly.

</details>

Expand Down Expand Up @@ -150,19 +150,19 @@ and refuses. Downloading the file first leaves stdin on your terminal.
preflight, the same naming check, the same plan, the same one `yes`, the same
self-bootstrap outside a checkout. It never needs `make` and never looks for a
`python3` — it runs the interpreter that started it. That two-liner IS the
Windows way in; the `openRepoShape` command in step 3 below is a macOS, Linux
and WSL2 convenience with no Windows twin, because on Windows there is nothing
to install. Printed commands are quoted for a POSIX shell, so paste them into
Git Bash. Only `shape-doctor.py`'s lines, `setup-project.py`'s family lines
and `family.py`'s `NEXT`, `switch -c`, `add` and `git rm -r --cached` lines
are quoted for PowerShell, on Windows.
Windows way in from PowerShell, which has no twin of step 3's `openRepoShape`
command. Git Bash runs that command and step 3's one line, tested in CI but for
a typed `yes`, which its preflight cannot take there. Printed commands are
quoted for a POSIX shell, so paste them into Git Bash. Only `shape-doctor.py`'s
lines, `setup-project.py`'s family lines and `family.py`'s `NEXT`, `switch -c`,
`add` and `git rm -r --cached` lines are quoted for PowerShell, on Windows.

</details>

<details>
<summary><b>Windows via WSL2</b></summary>

**Windows via WSL2** is still how you run the bash entry points: `wsl
**Windows via WSL2** runs every bash entry point in Linux itself: `wsl
--install` from an administrator PowerShell, reboot, open the Ubuntu app, and
run the four steps below INSIDE the WSL shell.

Expand Down Expand Up @@ -231,14 +231,14 @@ three repositories are created and the push fails.
curl -fsSL https://github.com/opensoft/openRepoShape/releases/latest/download/install.sh | bash
```

`install.sh` is attached to every release and installs the newest, with no `gh`
and no login. Its command is PINNED to the release tag, recorded in
`openRepoShape.ref` beside it: `setup.sh` and the standard are fetched at that
tag, not at main. It installs `git-filter-repo` with `pipx`, or `uv`, where it
can, or prints the command, runs `openRepoShape --preflight`, and says last if
the machine is ready to adopt or only to scaffold. `install.sh` never runs
`sudo`; the preflight offers what is missing, each behind a typed `yes` at your
terminal. `| bash -s -- v1.0.1` names a release; the same line again upgrades.
`install.sh`, attached to every release, installs the newest with no `gh` and no
login. Its command is PINNED to the release tag, recorded in `openRepoShape.ref`
beside it: `setup.sh` and the standard are fetched at that tag, not at main. It
installs `git-filter-repo` with `pipx`, or `uv`, where it can, or prints the
command, runs `openRepoShape --preflight`, and says last if the machine is ready
to adopt or only to scaffold. It never runs `sudo` itself; the preflight offers
what is missing, each behind a typed `yes` at your terminal; in Git Bash it can
take none. `| bash -s -- v1.0.1` names a release; the same line again upgrades.

By hand, the same command at main, which records no ref and follows main:

Expand Down
37 changes: 20 additions & 17 deletions docs/handbook.html
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@

<!-- reads README.md § preamble: blob ddadd23a162129f7e64fefce899105661440c05c -->

<!-- reads README.md § Starting a project in a new organisation: blob d1666fa6ce9176f71a0541d3c3b55d4bf6508d6a -->
<!-- reads README.md § Starting a project in a new organisation: blob badbb6b273215042ba0e8ae167fd760dc25430ee -->

<!-- reads README.md § The three legs: blob 39ec2c2372920177b6f7dcfb821b917eadc34314 -->

Expand All @@ -493,7 +493,7 @@ <h1>openRepoShape</h1>
several of them is held together by convention or by nothing. This repository is the
convention, as data and as running code.</p>

<h4>The fastest path &mdash; macOS, Linux, WSL2</h4>
<h4>The fastest path &mdash; macOS, Linux, WSL2, Git Bash</h4>
<div class="code" data-lang="sh"><pre><code>curl -fsSL https://github.com/opensoft/openRepoShape/releases/latest/download/install.sh | bash
openRepoShape &lt;Project&gt; --org &lt;your-org&gt;</code></pre></div>
<p class="sub">That first line installs ONE command into <code>~/.local/bin</code>: the
Expand All @@ -504,8 +504,8 @@ <h4>The fastest path &mdash; macOS, Linux, WSL2</h4>
in-flight work</a> to another workstation, are
<a href="https://github.com/opensoft/openRepoTools">opensoft/openRepoTools</a>&rsquo; and have a one-liner of
their own.</p>
<p class="sub">On Windows without WSL2 the way in is two PowerShell commands instead,
because on Windows there is nothing to install &mdash; see <a href="#start">Start
<p class="sub">In PowerShell, without WSL2 or Git Bash, the way in is two commands
instead, because there is nothing to install &mdash; see <a href="#start">Start
here</a>.</p>
</div>

Expand Down Expand Up @@ -610,7 +610,7 @@ <h4>The one thing to read before electing it</h4>

<section id="start">

<!-- reads README.md § Starting a project in a new organisation: blob d1666fa6ce9176f71a0541d3c3b55d4bf6508d6a -->
<!-- reads README.md § Starting a project in a new organisation: blob badbb6b273215042ba0e8ae167fd760dc25430ee -->

<p class="eyebrow">Setup</p>
<h2>Start here</h2>
Expand Down Expand Up @@ -690,8 +690,8 @@ <h4>What this machine needs</h4>
repository rather than scaffolding a new one.</p>
<p>The stock <code>/bin/bash</code> is 3.2 and is enough: <code>setup.sh</code>,
<code>install.sh</code> and the <code>openRepoShape</code> command are written to use no
syntax newer than that, though CI runs on Linux only and no run of it checks them against
bash 3.2. That the login shell is zsh changes nothing &mdash; all three entry points are
syntax newer than that, though no CI run, on Linux or in Git Bash on Windows, checks them
against bash 3.2. That the login shell is zsh changes nothing &mdash; all three entry points are
run under <code>bash</code> explicitly.</p>
<h4>The tool offers the rest</h4>
<p>The preflight names what is missing and, for <code>gh</code>, its login and its
Expand Down Expand Up @@ -721,9 +721,11 @@ <h4>The tool offers the rest</h4>
<code>winget install --id GitHub.cli -e</code> for <code>gh</code> and, only under
<code>py setup-project.py --preflight</code>, <code>winget install --id Git.Git -e</code>
for <code>git</code>: a run refuses a missing <code>git</code> before its preflight starts.
There is no <code>openRepoShape</code> command to install here: that two-liner IS the
Windows way in, and the <code>openRepoShape</code> command is a macOS, Linux and WSL2
convenience with no Windows twin, because on Windows there is nothing to install.
There is no <code>openRepoShape</code> command to install in PowerShell: that two-liner
IS the Windows way in there. Git Bash, the bash that Git for Windows installs, runs the
<code>openRepoShape</code> command and the one-line install, and CI tests both there, but
for a typed <code>yes</code>: CI has no terminal, and in Git Bash the preflight that the
one-line install ends with cannot take one, so none of its offers can be accepted there.
Printed commands are quoted for a POSIX shell, so paste them into Git Bash. Only
<code>shape-doctor.py</code>&rsquo;s lines, <code>setup-project.py</code>&rsquo;s family
lines and <code>family.py</code>&rsquo;s <code>NEXT</code>, <code>switch -c</code>,
Expand All @@ -737,7 +739,7 @@ <h4>The tool offers the rest</h4>
<div class="panel" role="tabpanel" id="panel-wsl" aria-labelledby="tab-wsl" tabindex="0">
<div class="stack">
<h4>What this machine needs</h4>
<p>WSL2 is still how you run the bash entry points: <code>wsl --install</code> from an
<p>WSL2 runs every bash entry point in Linux itself: <code>wsl --install</code> from an
administrator PowerShell, reboot, open the Ubuntu app, and run the steps INSIDE the WSL
shell.</p>
<div class="code" data-lang="powershell"><pre><code>wsl --install</code></pre></div>
Expand Down Expand Up @@ -973,7 +975,8 @@ <h4>Consent rules, on every platform</h4>
asks nothing before its own two acts, because running it is your act: it places the
command and installs <code>git-filter-repo</code> with <code>pipx</code> or <code>uv</code>
where one is there, and itself never runs <code>sudo</code> or installs either of them. The
preflight it ends with asks before each offer, as above.</li>
preflight it ends with asks before each offer, as above; in Git Bash it can take no
<code>yes</code>, so it installs nothing.</li>
<li><code>--yes</code> skips the scaffold question only. It does not answer an install
offer, <code>gh auth login</code> or <code>gh auth setup-git</code>.</li>
<li>With no terminal attached there is no offer at all.</li>
Expand Down Expand Up @@ -1045,7 +1048,7 @@ <h4>What you have afterwards &mdash; the same on every platform</h4>

<section id="partway">

<!-- reads README.md § Starting a project in a new organisation: blob d1666fa6ce9176f71a0541d3c3b55d4bf6508d6a -->
<!-- reads README.md § Starting a project in a new organisation: blob badbb6b273215042ba0e8ae167fd760dc25430ee -->

<p class="eyebrow">Setup</p>
<h2>If it fails part-way</h2>
Expand Down Expand Up @@ -1080,7 +1083,7 @@ <h2>If it fails part-way</h2>

<section id="ci">

<!-- reads README.md § Starting a project in a new organisation: blob d1666fa6ce9176f71a0541d3c3b55d4bf6508d6a -->
<!-- reads README.md § Starting a project in a new organisation: blob badbb6b273215042ba0e8ae167fd760dc25430ee -->

<!-- reads README.md § The three legs: blob 39ec2c2372920177b6f7dcfb821b917eadc34314 -->

Expand Down Expand Up @@ -1138,7 +1141,7 @@ <h2>Reading private legs in CI</h2>

<section id="legs">

<!-- reads README.md § Starting a project in a new organisation: blob d1666fa6ce9176f71a0541d3c3b55d4bf6508d6a -->
<!-- reads README.md § Starting a project in a new organisation: blob badbb6b273215042ba0e8ae167fd760dc25430ee -->

<!-- reads README.md § The three legs: blob 39ec2c2372920177b6f7dcfb821b917eadc34314 -->

Expand Down Expand Up @@ -1374,7 +1377,7 @@ <h3>The InkRouter example</h3>

<section id="doublepin">

<!-- reads README.md § Starting a project in a new organisation: blob d1666fa6ce9176f71a0541d3c3b55d4bf6508d6a -->
<!-- reads README.md § Starting a project in a new organisation: blob badbb6b273215042ba0e8ae167fd760dc25430ee -->

<!-- reads README.md § The double pin, and the lockstep invariant: blob 57fffa08ffad5476f8eae73dd3e8494a02e050c9 -->

Expand Down Expand Up @@ -1671,7 +1674,7 @@ <h2>Is this repository compliant? <code>openRepoShape --doctor</code></h2>

<section id="park">

<!-- reads README.md § Starting a project in a new organisation: blob d1666fa6ce9176f71a0541d3c3b55d4bf6508d6a -->
<!-- reads README.md § Starting a project in a new organisation: blob badbb6b273215042ba0e8ae167fd760dc25430ee -->

<!-- reads README.md § Carrying in-flight work to another workstation: blob b84512ad39c09085dfe6bf7ea694017f5e28c1dd -->

Expand Down
Loading
Loading