diff --git a/README.md b/README.md index d629516..44334f9 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ RepoFoundry (`src/create-project.sh`) sets up a new project in one run: - a **Gitea** repository (the source of truth), - optionally an empty **GitHub** repository that receives everything through a **push mirror from Gitea to GitHub**, -- and a **local project** with credential-free remotes and the +- and a **local project** with one credential-free remote, `origin` (Gitea), and the [SQA-QC-Framework](https://git.tirsystem.com/TirSystem/SQA-QC-Framework) added as a git submodule, with its skills, git hooks (and optionally the plan gate) and templates installed. @@ -266,9 +266,9 @@ Without `--apply` that is all that happens. With `--apply` the script asks 1. the GitHub repository (empty), if chosen; 2. the Gitea repository (with the license that applies: `PROJECT_LICENSE`, or AGPL-3.0 for a public project with GitHub); 3. the push mirror Gitea -> GitHub, and a request for its first sync; -4. the local directory, `git init` on `main`, the `origin` remote (and `github` - if chosen), and, if the Gitea repository holds the license commit, that - history; +4. the local directory, `git init` on `main`, the `origin` remote (the only + remote: a push to it reaches GitHub through the mirror) and, if the Gitea + repository holds the license commit, that history; 5. the framework as the submodule `framework`; 6. the framework's skills and git hooks, and the plan gate if chosen; 7. `AGENTS.md` and `docs/artifact-registry.md` from the framework's templates. @@ -379,8 +379,10 @@ script stops before it creates anything when a preflight check is refused. - **No destructive commands.** The script never deletes a repository or a file and never uses a recursive delete; temporary files are removed one by one. -- **Credential-free remotes.** `origin` is `ssh://git@host:port/owner/name.git` - (or plain HTTPS when SSH is not used) and `github` is a plain HTTPS address. +- **Credential-free remote.** `origin` is `ssh://git@host:port/owner/name.git` + (or plain HTTPS when SSH is not used). There is no `github` remote: push to + `origin` and the mirror carries it to GitHub. A `github` remote made by an + earlier version is left alone; remove it with `git remote remove github`. - **Redirects are not followed,** so a token is only ever sent to the host in the URL it was meant for. Unknown SSH host keys are refused. - **Framework scripts run on the new project only.** They are run with diff --git a/docs/artifact-registry.md b/docs/artifact-registry.md index 5de84ba..c9abca8 100644 --- a/docs/artifact-registry.md +++ b/docs/artifact-registry.md @@ -14,7 +14,7 @@ document of a type. `Primary File` may contain a glob (e.g. | BC | Business Case | docs/business-case.md | 002 | | SA | Stakeholder Analysis | docs/stakeholder-analysis.md | 002 | | PP | Project Plan | docs/project-plan.md | 002 | -| MIL | Milestone / Gateway | docs/milestones/*.md | 008 | +| MIL | Milestone / Gateway | docs/milestones/*.md | 009 | | US | User Story | docs/user-stories.md | 002 | | UC | Use Case | docs/uc-*/uc.md | 003 | | SSD | System Sequence Diagram | docs/uc-*/ssd.md | 003 | @@ -24,7 +24,7 @@ document of a type. `Primary File` may contain a glob (e.g. | DCD | Design Class Diagram | docs/dcd.md | 004 | | DICT | Domain Dictionary (PO and IT terms) | docs/dictionary.md | 002 | | UCD | Use Case Diagram | docs/use-case-diagram.md | 002 | -| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 031 | +| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 032 | | TM | Traceability Matrix | docs/sqa/traceability-matrix.md | 002 | ## Languages diff --git a/docs/business-case.md b/docs/business-case.md index fdb9336..c292d49 100644 --- a/docs/business-case.md +++ b/docs/business-case.md @@ -9,8 +9,8 @@ ## Version History | Date | Status | Author | Reviewer | Change | Commit | | --- | --- | --- | --- | --- | --- | -| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Added objective 11 (global command, project created in the current folder), a scope item and success criterion 11 | [1cd27f7] | -| 2026-10-07 | Accepted | Jens Tirsvad Nielsen | S02 | Objective 11, scope item and criterion 11: the configuration files default to the working folder's, then the checkout's | [0ab5006] | +| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Objective 11, scope item and criterion 11: the configuration files default to the working folder's, then the checkout's | [0ab5006] | +| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Objective 4: the local project has one remote, origin; no github remote, because a push to origin reaches GitHub through the mirror (MIL-008) | [039a28c] | --- @@ -37,7 +37,7 @@ One repeatable, reviewed procedure gives every new project the same secure basel 1. Optionally create an empty GitHub repository under a chosen user or organization. 2. Create a Gitea repository under a chosen user or organization, empty, or with a license: the one set in `config.env` (`PROJECT_LICENSE`), or AGPL-3.0 when GitHub is chosen, the project is public and none is set. 3. When GitHub was chosen, configure the Gitea repository as a push mirror to GitHub (direction Gitea to GitHub). -4. Create the local project directory with an `origin` (Gitea) remote and, when GitHub was chosen, a `github` remote, neither containing credentials. +4. Create the local project directory with one remote, `origin` (Gitea), containing no credential. There is no `github` remote: a push to `origin` reaches GitHub through the push mirror. 5. Add the SQA-QC-Framework as the `framework` submodule with its own submodules (the `qc` checklists) fetched, install its skills and git hooks, and copy its templates, optionally enabling the plan gate. 6. Never print a token or put one in a URL, a remote or a log, write one to disk only in the new project's own `.env` and only after the Maintainer agrees, and never overwrite existing files or directories without consent. 7. Document installation, configuration, usage, security decisions and error handling in clear English for GitHub readers. @@ -153,5 +153,5 @@ Proceed — the procedure is small, well bounded and removes a repeated, securit [SA-001]: ./stakeholder-analysis.md [UCD-001]: ./use-case-diagram.md -[1cd27f7]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/1cd27f77ed844773a969210a11de0d8bb98ac98f [0ab5006]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/0ab50068bf9e5be82a801af9dbe5b763eeaf7f31 +[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03 diff --git a/docs/dcd.md b/docs/dcd.md index f3b9d98..7ee2c73 100644 --- a/docs/dcd.md +++ b/docs/dcd.md @@ -9,8 +9,8 @@ ## Version History | Date | Status | Author | Reviewer | Change | Commit | | --- | --- | --- | --- | --- | --- | -| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Default configuration files: --config and --env, else ./config.env and ./.env in the working folder, else the checkout's | [0ab5006] | -| 2026-10-07 | Accepted | Jens Tirsvad Nielsen | S02 | .env is optional (as in UC-001 extension 2b): only config.env is required; a .env found nowhere means the token is asked | [24f1507] | +| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | .env is optional (as in UC-001 extension 2b): only config.env is required; a .env found nowhere means the token is asked | [24f1507] | +| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | LocalProjectBuilder.build() no longer takes the GitHub repository; a Local Project has one Remote, origin (MIL-008) | [039a28c] | --- @@ -71,7 +71,7 @@ class GitHubClient <> { +createEmptyRepository(request : ProjectRequest) : GitHubRepository } class LocalProjectBuilder { - +build(directory : Path, source : GiteaRepository, target : GitHubRepository [0..1], sshPassed : Boolean) : LocalProject + +build(directory : Path, source : GiteaRepository, sshPassed : Boolean) : LocalProject } class FrameworkInstaller { +install(project : LocalProject, enablePlanGate : Boolean) : InstallResult @@ -238,7 +238,7 @@ PushMirror "0..*" --> "1" GiteaRepository : source PushMirror "0..*" --> "1" GitHubRepository : target PushMirror "0..*" --> "1" Credential : authorised by -LocalProject "1" *-- "1..2" Remote +LocalProject "1" *-- "1" Remote Remote "0..*" --> "1" Repository : points to LocalProject "1" *-- "1" Submodule LocalProject "1" *-- "1" HookSetup @@ -288,7 +288,7 @@ Repository "0..*" --> "1" Visibility | `LicenseFile` | License | The license file in the Gitea repository when a license applies. | `key` | none | | `PushMirror` | Mirror | The Gitea to GitHub push mirror. | `interval`, `syncOnCommit` | none | | `LocalProject` | Local Project | The project directory on the Maintainer's machine. | `directory` | none | -| `Remote` | Remote | A named link to a repository (`origin`, `github`), without a credential. | `name`, `address` | none | +| `Remote` | Remote | A named link to a repository (`origin`), without a credential. | `name`, `address` | none | | `Submodule` | Framework | The framework added to the local project. | `name`, `address` | none | | `HookSetup` | Framework Setup | Records the skills and hooks installed and the plan gate state. | `areSkillsInstalled`, `areHooksInstalled`, `isPlanGateEnabled` | none | | `EnvFile` | Credentials File | The `.env` of the project: a copy of the credentials it needs. | `address`, `keys` | none | @@ -321,7 +321,7 @@ Repository "0..*" --> "1" Visibility | `GiteaClient.requestSync(mirror) : void` | [SD-001] `requestSync(pushMirror)`; P6 | | `GitHubClient(configuration)` | [SD-001] `new(configuration)` to `GitHubClient` | | `GitHubClient.createEmptyRepository(request) : GitHubRepository` | [SD-001] `createEmptyRepository(request)`; P5 | -| `LocalProjectBuilder.build(directory, source, target, sshPassed) : LocalProject` | [SD-001] `build(directory, giteaRepository, gitHubRepository, sshPassed)`; P7, P8, P9 | +| `LocalProjectBuilder.build(directory, source, sshPassed) : LocalProject` | [SD-001] `build(directory, giteaRepository, sshPassed)`; P7, P8, P9 | | `FrameworkInstaller.install(project, enablePlanGate) : InstallResult` | [SD-001] `install(localProject, enablePlanGate)`; P10, P11, P12 | | `SummaryReport.compose(request) : Summary` | [SD-001] `compose(projectRequest)`; P13 | @@ -373,5 +373,5 @@ SOLID check: no class has more than one reason to change (one host API, one kind [SD-001]: ./uc-001/sd.md [MIL-005]: ./milestones/mil-005-credentials.md [DICT-001]: ./dictionary.md -[0ab5006]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/0ab50068bf9e5be82a801af9dbe5b763eeaf7f31 [24f1507]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/24f15070fc73fb06e61865141fe0b825ea9e821e +[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03 diff --git a/docs/domain-model.md b/docs/domain-model.md index f687567..08c12d8 100644 --- a/docs/domain-model.md +++ b/docs/domain-model.md @@ -9,8 +9,8 @@ ## Version History | Date | Status | Author | Reviewer | Change | Commit | | --- | --- | --- | --- | --- | --- | -| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Added Command Link, Checkout and Working Folder (from DM-003, UC-002) | [1cd27f7] | -| 2026-10-07 | Accepted | Jens Tirsvad Nielsen | S02 | Default configuration files: --config and --env, else ./config.env and ./.env in the working folder, else the checkout's | [0ab5006] | +| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Default configuration files: --config and --env, else ./config.env and ./.env in the working folder, else the checkout's | [0ab5006] | +| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | A Local Project has one Remote, origin, no longer one or two (MIL-008) | [039a28c] | --- @@ -114,7 +114,7 @@ Mirror "1" --> "1" GiteaRepository : copies from Mirror "1" --> "1" GitHubRepository : copies to Mirror "0..*" --> "1" AccessToken : is authorised by LocalProject "1" --> "1" Project : is the working copy of -LocalProject "1" --> "1..2" Remote : has +LocalProject "1" --> "1" Remote : has Remote "0..*" --> "1" Repository : points to LocalProject "1" --> "1" Framework : includes LocalProject "1" --> "1" FrameworkSetup : has @@ -149,7 +149,7 @@ WorkingFolder "1" --> "0..*" LocalProject : is the base of | License | The legal terms file added to a Gitea Repository when a license applies: the one set in the Configuration, or AGPL-3.0 when GitHub is chosen, the project is public and none is set | name | [UC-001] step 6 "license" | | Mirror | The push mirror that copies a Gitea Repository to a GitHub Repository | interval, sync on commit | [UC-001] step 7 "push mirror" | | Local Project | The project directory on the Maintainer's machine | directory | [UC-001] step 8 "local project" | -| Remote | A named link from a Local Project to a Repository (`origin`, `github`) | name, address | [UC-001] step 8 "remote" | +| Remote | A named link from a Local Project to a Repository (`origin`) | name, address | [UC-001] step 8 "remote" | | Framework | The SQA-QC-Framework added to a Local Project | name, address | [UC-001] step 9 "framework submodule" | | Framework Setup | The skills and git hooks installed from the Framework, with the plan gate on or off | plan gate enabled | [UC-001] step 9 "skills and hooks", "plan gate" | | Template | A file the Framework provides to copy into a project (`AGENTS.md`, artifact registry) | name | [UC-001] step 9 "templates" | @@ -176,7 +176,7 @@ WorkingFolder "1" --> "0..*" LocalProject : is the base of | Mirror | copies to | GitHub Repository | 1 to 1 | | Mirror | is authorised by | Access Token | 0..* to 1 | | Local Project | is the working copy of | Project | 1 to 1 | -| Local Project | has | Remote | 1 to 1..2 | +| Local Project | has | Remote | 1 to 1 | | Remote | points to | Repository | 0..* to 1 | | Local Project | includes | Framework | 1 to 1 | | Local Project | has | Framework Setup | 1 to 1 | @@ -207,5 +207,5 @@ WorkingFolder "1" --> "0..*" LocalProject : is the base of [SSD-001]: ./uc-001/ssd.md [DICT-001]: ./dictionary.md [DM-001]: ./uc-001/dm.md -[1cd27f7]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/1cd27f77ed844773a969210a11de0d8bb98ac98f [0ab5006]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/0ab50068bf9e5be82a801af9dbe5b763eeaf7f31 +[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03 diff --git a/docs/milestones/mil-003-scaffold-and-release.md b/docs/milestones/mil-003-scaffold-and-release.md index 964b254..df678cd 100644 --- a/docs/milestones/mil-003-scaffold-and-release.md +++ b/docs/milestones/mil-003-scaffold-and-release.md @@ -9,8 +9,8 @@ ## Version History | Date | Status | Author | Reviewer | Change | Commit | | --- | --- | --- | --- | --- | --- | -| 2026-10-05 | Deprecated | Jens Tirsvad Nielsen | S02 | Initial version | [424f14f] | -| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Optional GitHub; choosing GitHub applies the AGPL license to the Gitea repository
Cited US-001.03
Traces to objective 7
Criterion 2 names the framework URL
Target date accepted | [02875ae] | +| 2026-10-05 | Deprecated | Jens Tirsvad Nielsen | S02 | Optional GitHub; choosing GitHub applies the AGPL license to the Gitea repository
Cited US-001.03
Traces to objective 7
Criterion 2 names the framework URL
Target date accepted | [02875ae] | +| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Criterion 1 and task 1: origin is the only remote (MIL-008) | [039a28c] | --- @@ -26,7 +26,7 @@ Complete `create-project.sh` (local directory, credential-free remotes, framewor | # | Criterion (objectively checkable) | Go | No-Go | | --- | --- | --- | --- | -| 1 | `git remote -v` shows `origin` (Gitea) and, when GitHub was chosen, `github`, with no credentials in any URL; with GitHub chosen the local history contains the license commit | Verified | Any credential, or a missing license commit | +| 1 | `git remote -v` shows `origin` (Gitea) only, with or without GitHub, with no credentials in any URL; with GitHub chosen the local history contains the license commit | Verified | Any credential, or a missing license commit | | 2 | `framework` is a submodule of `ssh://git@git.tirsystem.com:10022/TirSystem/SQA-QC-Framework.git` and the install scripts have run once, in the documented order | Verified | Missing or repeated | | 3 | An existing directory, `AGENTS.md` or `docs/artifact-registry.md` is never overwritten without a yes | Verified by a second run | Overwritten | | 4 | With the plan gate enabled, a commit touching `src/` or `tests/` without a `Task: MIL-NNN#N` trailer is refused | Verified | Accepted | @@ -64,7 +64,7 @@ Complete `create-project.sh` (local directory, credential-free remotes, framewor | # | Task | Summary | Needs its own Use Case/User Story? | Reference | | --- | --- | --- | --- | --- | -| 1 | Create the local project directory and credential-free remotes | After consent, create the directory (refuse to reuse an existing one without a yes), run `git init` on `main`, and add `origin` (Gitea) and, only if GitHub was chosen, `github` using URLs derived from the configured base URLs and the selected owners, with no token in any URL. `origin` uses HTTPS derived from `GITEA_URL`, unless the SSH test from the preflight passed, in which case it uses SSH on port 10022. When the Gitea repository is not empty (GitHub chosen, AGPL license), fetch it and check out its default branch so the local history starts from the license commit. Do not make a commit. | Yes | [UC-001] | +| 1 | Create the local project directory and credential-free remotes | After consent, create the directory (refuse to reuse an existing one without a yes), run `git init` on `main`, and add `origin` (Gitea) using a URL derived from the configured base URL and the selected owner, with no token in any URL; there is no `github` remote, because a push to `origin` reaches GitHub through the mirror ([MIL-008]). `origin` uses HTTPS derived from `GITEA_URL`, unless the SSH test from the preflight passed, in which case it uses SSH on port 10022. When the Gitea repository is not empty (GitHub chosen, AGPL license), fetch it and check out its default branch so the local history starts from the license commit. Do not make a commit. | Yes | [UC-001] | | 2 | Add the framework submodule | From the project directory run `git submodule add ssh://git@git.tirsystem.com:10022/TirSystem/SQA-QC-Framework.git framework`. Check beforehand that SSH on port 10022 works and stop with an actionable message if not. Document that this SSH access must be configured. | Yes | [UC-001] | | 3 | Install skills and git hooks, with optional plan gate | Run `framework/scripts/install-skills.sh` and `install-git-hooks.sh`. The hook installer only sets `core.hooksPath` to `framework/githooks` and is safe to rerun, but it would replace a different existing value, so read the current value first and ask. Offer `--enable-plan-gate` as an optional choice, which requires a `Task: MIL-NNN#N` trailer on commits changing `src/` or `tests/`. | Yes | [UC-001] | | 4 | Copy the framework templates without overwriting | Copy `AGENTS-template.md` to `AGENTS.md` and `artifact-registry-template.md` to `docs/artifact-registry.md` after `mkdir -p docs`, asking before replacing an existing file. | Yes | [UC-001] | @@ -77,5 +77,6 @@ Complete `create-project.sh` (local directory, credential-free remotes, framewor [US-001]: ../user-stories.md [UC-001]: ../uc-001/uc.md [MIL-002]: ./mil-002-repositories-and-mirror.md -[424f14f]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/424f14f4f5577bb47fea41c8f3a655dca953e6d8 +[MIL-008]: ./mil-008-gitea-only-remote.md [02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a +[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03 diff --git a/docs/milestones/mil-008-gitea-only-remote.md b/docs/milestones/mil-008-gitea-only-remote.md new file mode 100644 index 0000000..ffdddd8 --- /dev/null +++ b/docs/milestones/mil-008-gitea-only-remote.md @@ -0,0 +1,85 @@ +# MIL-008 Gitea Is the Only Remote + +## Metadata +| Key | Value | +| --- | --- | +| ID | MIL-008 | +| CrossReference | [BC-001], [US-001], [UC-001], [OC-001], [DCD-002] | + +## Version History +| Date | Status | Author | Reviewer | Change | Commit | +| --- | --- | --- | --- | --- | --- | +| 2026-10-08 | Deprecated | Jens Tirsvad Nielsen | S02 | Initial version | [039a28c] | +| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Task 4 and criterion 7: the version is raised to 0.3.1 and release v0.3.1 is tagged after the merge | [1056639] | + +--- + +## Purpose + +Decide whether the local project can keep a single remote, `origin` (Gitea), with or without GitHub. Gitea pushes to GitHub through the push mirror, so a push to `origin` already reaches GitHub; a second `github` remote adds nothing and invites a push that goes around the mirror, with a token typed by hand. The first version of the documents and of the script added that remote when GitHub was chosen; this phase removes it. + +## Deliverable + +`create-project.sh` that adds only the `origin` remote to the local project, whether or not GitHub was chosen, and no longer builds a GitHub remote address. The documents agree with it: Business Case objective 4, US-001.03, UC-001 (postcondition and step 8), OC-001 P9, SD-001, DCD-001 and DCD-002, DM-001 and DM-002. `README.md` describes the one remote and says that a push to `origin` reaches GitHub through the mirror. The tests cover both cases. The version is raised to 0.3.1, and release `v0.3.1` is tagged on Gitea after the pull request is merged. + +A project that already has a `github` remote, such as one created by an earlier version of the script, keeps it: the script never removes or replaces a remote (it still refuses an `origin` that points elsewhere). + +## Go / No-Go Criteria + +| # | Criterion (objectively checkable) | Go | No-Go | +| --- | --- | --- | --- | +| 1 | With GitHub chosen, `git remote` in the new project lists exactly `origin`; without GitHub it lists exactly `origin` as well | Tests pass | Any other remote | +| 2 | No `remote.github.*` key and no GitHub address is in the new project's `.git/config`, and `origin` keeps its address (SSH if the test passed, else HTTPS) with no credential | Tests pass | A `github` key, a GitHub address or a credential | +| 3 | A project directory that already has a `github` remote keeps it unchanged and the run does not fail because of it; a different `origin` is still refused | Tests pass | The remote removed, replaced or the run stopped | +| 4 | With GitHub chosen the mirror, the license history and the other steps are unchanged | Tests pass | Any other step changed | +| 5 | The README, UC-001, OC-001, SD-001, DCD-001, DCD-002, DM-001 and DM-002 all describe one remote and agree with the code | Reviewed by S02 in [RC-031] | A document still naming a `github` remote | +| 6 | All acceptance criteria of US-001.03 in [US-001] are met | Verified | Any unmet | +| 7 | `create-project.sh --version` prints `RepoFoundry 0.3.1` | Tests pass | Another version | + +## Dependencies + +| Depends on | Reason | +| --- | --- | +| [MIL-002] | The push mirror is what makes a second remote unnecessary | +| [MIL-003] | The step that creates the local project and its remotes is the one that changes | + +## Traceability + +| Business Case objective / KPI / user story | Reference | +| --- | --- | +| User story US-001.03 | [US-001] | +| Objective 4 (the local project with its remotes) | [BC-001] | +| Success criteria 1 (credential exposure: fewer places a token can be typed into an address) and 3 (mirror direction: a push to `origin` appears on GitHub) | [BC-001] | + +## Ownership + +| Role | Stakeholder ID (SA) | +| --- | --- | +| Owner | S01 | +| Approving reviewer | S02 | + +## Target Date + +2026-12-18 — proposed; the Business Case sets no deadline. + +## Tasks + +| # | Task | Summary | Needs its own Use Case/User Story? | Reference | +| --- | --- | --- | --- | --- | +| 1 | Add only the origin remote | In `create_local_project` (`src/lib/localproject.sh`) stop adding the `github` remote, with or without GitHub, and delete `github_remote_url` (`src/lib/hosts.sh`), which nothing else uses. `origin` is unchanged (SSH on the configured port when the SSH test passed, else HTTPS, no credential). An existing `github` remote is left alone; a different `origin` is still refused. Step 8 of [UC-001] and P9 of [OC-001]. | Yes | [UC-001] | +| 2 | Describe the one remote in the README | Update the overview, the run steps and the "Credential-free remotes" security point: the project has one remote, `origin`, and a push to it reaches GitHub through the Gitea push mirror. Mention that a `github` remote from an earlier version can be removed with `git remote remove github`. | No | | +| 3 | Test the single remote | Replace the `github` remote assertion of `test_local_project_gets_credential_free_remotes_and_the_license_history` with "only `origin`, no GitHub address in `.git/config`", keep the Gitea-only case, add a rerun on a directory that already has a `github` remote (kept, no failure), and drop the `github_remote_url` check from `test_remote_addresses_are_built_from_the_configuration`. | No | | +| 4 | Bump the version to 0.3.1 | Set `VERSION` in `src/lib/constants.sh` to 0.3.1 and the `--version` check in `tests/test-security.sh` to match. Release `v0.3.1` is tagged on Gitea from the merge commit once the pull request is merged. | No | | + +--- + +[BC-001]: ../business-case.md +[US-001]: ../user-stories.md +[UC-001]: ../uc-001/uc.md +[OC-001]: ../uc-001/oc.md +[DCD-002]: ../dcd.md +[MIL-002]: ./mil-002-repositories-and-mirror.md +[MIL-003]: ./mil-003-scaffold-and-release.md +[RC-031]: ../sqa/reviews/rc-031-gitea-only-remote.md +[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03 +[1056639]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/commit/1056639d5b0f84ce8b591e33e8f5a1e03e99de37 diff --git a/docs/project-plan.md b/docs/project-plan.md index 80c8147..f3bcbc8 100644 --- a/docs/project-plan.md +++ b/docs/project-plan.md @@ -4,23 +4,23 @@ | Key | Value | | --- | --- | | ID | PP-001 | -| CrossReference | [BC-001], [SA-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [US-001] | +| CrossReference | [BC-001], [SA-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [MIL-008], [US-001] | ## Version History | Date | Status | Author | Reviewer | Change | Commit | | --- | --- | --- | --- | --- | --- | -| 2026-10-06 | Deprecated | Jens Tirsvad Nielsen | S02 | Added phase MIL-006 (proposed dates 2026-11-30 to 2026-12-04) | [d773fa9] | -| 2026-10-07 | Accepted | Jens Tirsvad Nielsen | S02 | Added phase MIL-007 (proposed dates 2026-12-07 to 2026-12-11); MIL-006 deliverable names the public-only AGPL-3.0 default | [1cd27f7] | +| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Added phase MIL-007 (proposed dates 2026-12-07 to 2026-12-11); MIL-006 deliverable names the public-only AGPL-3.0 default | [1cd27f7] | +| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Added phase MIL-008 (proposed dates 2026-12-14 to 2026-12-18): the local project has origin as its only remote | [039a28c] | --- ## Purpose -Schedule the seven phases that deliver RepoFoundry (`create-project.sh` and its documentation) in dependency order. The Business Case sets no deadline, so the dates below are proposals for S01 to confirm. +Schedule the eight phases that deliver RepoFoundry (`create-project.sh` and its documentation) in dependency order. The Business Case sets no deadline, so the dates below are proposals for S01 to confirm. ## Planning Assumptions -- Week 1 starts 2026-10-05; the plan ends by 2026-12-11 (the last two phases are proposed). +- Week 1 starts 2026-10-05; the plan ends by 2026-12-18 (the last three phases are proposed). - Phase length: two weeks. - S01 and S02 review each phase through a pull request, as described in [SA-001]. For now one person holds both roles. - The PO language is English, so no translated copies are kept. @@ -36,6 +36,7 @@ Schedule the seven phases that deliver RepoFoundry (`create-project.sh` and its | Credentials | [MIL-005] | 2026-11-23 to 2026-11-27 | 2026-11-27 | S01 | US-001.05 | Missing credentials asked; project .env | | | Project License | [MIL-006] | 2026-11-30 to 2026-12-04 | 2026-12-04 | S01 | US-001.06 | PROJECT_LICENSE in config.env; AGPL-3.0 default only for a public GitHub project | | | Framework Checklists and Usage | [MIL-007] | 2026-12-07 to 2026-12-11 | 2026-12-11 | S01 | US-001.07 | qc fetched with the framework; global command; README usage | | +| Gitea Is the Only Remote | [MIL-008] | 2026-12-14 to 2026-12-18 | 2026-12-18 | S01 | US-001.03 | The local project has `origin` only; GitHub is reached through the mirror | | ```plantuml @startgantt @@ -54,6 +55,8 @@ Project starts 2026-10-05 [Project License Go/No-Go] happens 2026-12-04 [Framework Checklists and Usage] starts 2026-12-07 and ends 2026-12-11 [Framework Checklists and Usage Go/No-Go] happens 2026-12-11 +[Gitea Is the Only Remote] starts 2026-12-14 and ends 2026-12-18 +[Gitea Is the Only Remote Go/No-Go] happens 2026-12-18 @endgantt ``` @@ -72,11 +75,12 @@ Project starts 2026-10-05 | Project license set in `config.env` | [MIL-006] | | Framework's own submodules fetched | [MIL-007] | | README usage from the target folder and as a global command | [MIL-007] | +| The local project has `origin` as its only remote | [MIL-008] | ## Dependencies ``` -MIL-001 → MIL-002 → MIL-003 → MIL-004 → MIL-005 → MIL-006 → MIL-007 +MIL-001 → MIL-002 → MIL-003 → MIL-004 → MIL-005 → MIL-006 → MIL-007 → MIL-008 ``` A No-Go moves every later date by the time needed to rework the failed criteria. @@ -107,11 +111,12 @@ A No-Go moves every later date by the time needed to rework the failed criteria. [MIL-005]: ./milestones/mil-005-credentials.md [MIL-006]: ./milestones/mil-006-project-license.md [MIL-007]: ./milestones/mil-007-framework-checklists.md +[MIL-008]: ./milestones/mil-008-gitea-only-remote.md [US-001]: ./user-stories.md [UC-001]: ./uc-001/uc.md [SSD-001]: ./uc-001/ssd.md [Milestone 43]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/milestone/43 [Milestone 44]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/milestone/44 [Milestone 45]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/milestone/45 -[d773fa9]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/d773fa91df5a54090254e12e074880fb6526a9ff [1cd27f7]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/1cd27f77ed844773a969210a11de0d8bb98ac98f +[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03 diff --git a/docs/sqa/reviews/rc-031-gitea-only-remote.md b/docs/sqa/reviews/rc-031-gitea-only-remote.md new file mode 100644 index 0000000..69f9016 --- /dev/null +++ b/docs/sqa/reviews/rc-031-gitea-only-remote.md @@ -0,0 +1,80 @@ +# SQA Review Record: Gitea is the only remote + +## Metadata +| Key | Value | +| --- | --- | +| ID | RC-031 | +| CrossReference | [MIL-008], [QC-MIL-001], [MIL-003], [BC-001], [US-001], [UC-001], [OC-001], [SD-001], [DCD-001], [DCD-002], [DM-001], [DM-002], [PP-001] | + +## Version History +| Date | Status | Author | Reviewer | Change | Commit | +| --- | --- | --- | --- | --- | --- | +| 2026-10-08 | Deprecated | Jens Tirsvad Nielsen | S02 | Initial version | [039a28c] | +| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Criterion count of MIL-008 is seven (the version criterion) | [1056639] | + +--- + +## Artifact Under Review + +- Instance reviewed: [MIL-008], and the changes it causes in [MIL-003], [BC-001], [US-001], [UC-001], [OC-001], [SD-001], [DCD-001], [DCD-002], [DM-001], [DM-002], [PP-001] and [TM-001]. +- Why: a project created by the script had two remotes, `origin` (Gitea) and `github`. The documents required the second one when GitHub was chosen (objective 4, US-001.03, step 8 of [UC-001], P9 of [OC-001]). Gitea already pushes to GitHub through the push mirror, so the second remote is not needed and invites a push that goes around the mirror. The Business Case already expects "a push to `origin` appears on GitHub" (success criterion 3 of [BC-001]). +- Checklist used: [QC-MIL-001] for [MIL-008]. The other artifacts were changed, not created; their change is checked below. +- Review date: 2026-10-08 + +## Checklist Results (QC-MIL-001) + +| # | Criterion | Status | Evidence/Notes | +| --- | --- | --- | --- | +| 1 | A concrete deliverable is defined for every gate | Pass | The script that adds `origin` only, the documents that agree with it, the README and the tests. | +| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Seven criteria, each with an objective Go and No-Go: the remote list with and without GitHub, the contents of `.git/config`, an existing `github` remote kept, the other steps unchanged, the documents in agreement, the acceptance criteria of US-001.03, and the version printed by `--version`. | +| 3 | Dependencies on other milestones are explicitly mapped | Pass | [MIL-002] (the mirror makes the second remote unnecessary) and [MIL-003] (the step that changes), each with its reason. | +| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Objective 4 and success criteria 1 and 3 of [BC-001], and US-001.03. | +| 5 | Milestone owner and approving reviewer are identified | Pass | Owner S01, approving reviewer S02. | +| 6 | Milestone has a defined target date consistent with project constraints | Pass | 2026-12-18, proposed in [PP-001]; the Business Case sets no deadline. | + +## Change checks on the other artifacts + +| Artifact | Change | Status | Evidence/Notes | +| --- | --- | --- | --- | +| [BC-001] | Objective 4 names `origin` as the only remote | Pass | Success criterion 3 already says a push to `origin` appears on GitHub. | +| [US-001] | US-001.03 acceptance criterion; [MIL-008] added to the CrossReference | Pass | One given/when/then; it says there is no `github` remote and why. | +| [UC-001] | Postcondition, step 8 and the rule for step 8; the rule for steps 3, 5 and 7 no longer names the remote | Pass | The rule says an existing remote of another name is never removed or replaced. | +| [OC-001] | P9 | Pass | Numbering is kept: P9 now says no other remote was associated, so the references to P10 to P14 in [SD-001] and [DCD-002] still hold. | +| [SD-001] | `build(directory, giteaRepository, sshPassed)`, the returned `localProject (remote origin)` and the P9 row | Pass | The GitHub repository is no longer passed to `LocalProjectBuilder`. | +| [DCD-001], [DCD-002] | `build` loses its `target` parameter; `Remote` lists `origin` only; a Local Project has 1 Remote; the `build` mapping row | Pass | Names match [SD-001]; the class table and the mapping table agree with the diagram. | +| [DM-001], [DM-002] | A Local Project has 1 Remote (was 1..2); the Remote description | Pass | Names unchanged. The dictionary needs no change: the term Remote and its definition do not name `github`. | +| [MIL-003] | Criterion 1 and task 1 | Pass | They now say `origin` only and point to [MIL-008]. | +| [PP-001] | Phase [MIL-008], its window, the Gantt, the scope coverage and the dependency chain | Pass | Proposed dates 2026-12-14 to 2026-12-18. | +| [TM-001] | Rows for [MIL-008] and this record; Last Reviewed updated | Pass | See the matrix. | + +The code, the README and the tests (the three tasks of [MIL-008]) were changed after S01 waived the plan in chat for this request, so the milestone was not synced as issues first. `create_local_project` adds `origin` only, `github_remote_url` is gone, the README describes the one remote, and `tests/test-local.sh` checks the remote list with and without GitHub, no GitHub address in `.git/config`, and a `github` remote from an earlier version kept. The full suite passed with 1141 checks and no failed static check. Criterion 5 of [MIL-008] is still for S02 to check against the documents. + +## Overall Verdict + +Go — the documents, the code, the README and the tests agree with each other, and every criterion of the checklist passes. Drafted by Claude Code for S02; the author and reviewer are the same person for now. S02 gave the Go in chat on 2026-10-08 for [MIL-008] and the changes it causes, and the Version History rows of the changed documents were set to `Accepted` and the rows before them to `Deprecated`. + +## Action Items + +| Action | Owner | Due | +| --- | --- | --- | +| None | - | - | + +--- + +[MIL-008]: ../../milestones/mil-008-gitea-only-remote.md +[MIL-002]: ../../milestones/mil-002-repositories-and-mirror.md +[MIL-003]: ../../milestones/mil-003-scaffold-and-release.md +[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md +[BC-001]: ../../business-case.md +[US-001]: ../../user-stories.md +[UC-001]: ../../uc-001/uc.md +[OC-001]: ../../uc-001/oc.md +[SD-001]: ../../uc-001/sd.md +[DCD-001]: ../../uc-001/dcd.md +[DCD-002]: ../../dcd.md +[DM-001]: ../../uc-001/dm.md +[DM-002]: ../../domain-model.md +[PP-001]: ../../project-plan.md +[TM-001]: ../traceability-matrix.md +[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03 +[1056639]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/commit/1056639d5b0f84ce8b591e33e8f5a1e03e99de37 diff --git a/docs/sqa/traceability-matrix.md b/docs/sqa/traceability-matrix.md index fa91e49..18d32fd 100644 --- a/docs/sqa/traceability-matrix.md +++ b/docs/sqa/traceability-matrix.md @@ -9,8 +9,8 @@ ## Version History | Date | Status | Author | Reviewer | Change | Commit | | --- | --- | --- | --- | --- | --- | -| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Added MIL-007, UC-002, SSD-002, DM-003, OC-002, SD-002 and DCD-003 with their reviews RC-022 to RC-028 | [1cd27f7] | -| 2026-10-07 | Accepted | Jens Tirsvad Nielsen | S02 | Added review RC-030 (.env optional) | [24f1507] | +| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Added review RC-030 (.env optional) | [24f1507] | +| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Added MIL-008 with its review RC-031 (Gitea is the only remote) | [039a28c] | --- @@ -24,19 +24,20 @@ updated whenever an artifact instance is created or reviewed. | Artifact Instance | Type | Upstream (Backward Link) | Downstream (Forward Link) | Last Reviewed (RC-ID) | | --- | --- | --- | --- | --- | -| [BC-001] | BC | - | [SA-001], [PP-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [US-001], [UCD-001] | [RC-010], [RC-018], [RC-020], [RC-022], [RC-029] | +| [BC-001] | BC | - | [SA-001], [PP-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [MIL-008], [US-001], [UCD-001] | [RC-010], [RC-018], [RC-020], [RC-022], [RC-029], [RC-031] | | [SA-001] | SA | [BC-001] | [UCD-001], [UC-001], [DICT-001] | [RC-013] | -| [PP-001] | PP | [BC-001], [SA-001] | [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007] | [RC-012], [RC-018], [RC-020], [RC-022] | +| [PP-001] | PP | [BC-001], [SA-001] | [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [MIL-008] | [RC-012], [RC-018], [RC-020], [RC-022], [RC-031] | | [MIL-001] | MIL | [BC-001], [PP-001] | [US-001] | [RC-011], [RC-016] | | [MIL-002] | MIL | [BC-001], [PP-001] | [US-001] | [RC-014], [RC-017] | -| [MIL-003] | MIL | [BC-001], [PP-001] | [US-001] | [RC-015], [RC-017] | +| [MIL-003] | MIL | [BC-001], [PP-001] | [US-001] | [RC-015], [RC-017], [RC-031] | | [MIL-004] | MIL | [BC-001], [PP-001] | [US-001] | [RC-018], [RC-019] | | [MIL-005] | MIL | [BC-001], [PP-001] | [US-001] | [RC-020] | | [MIL-006] | MIL | [BC-001], [PP-001] | [US-001] | [RC-022] | | [MIL-007] | MIL | [BC-001], [PP-001] | [US-001], [UC-002] | [RC-022], [RC-029], [RC-030] | +| [MIL-008] | MIL | [BC-001], [PP-001] | [US-001] | [RC-031] | | [UCD-001] | UCD | [BC-001], [SA-001] | [US-001], [UC-001], [UC-002] | [RC-009], [RC-023] | -| [US-001] | US | [BC-001], [UCD-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007] | [UC-001] | [RC-001], [RC-020], [RC-022], [RC-029], [RC-030] | -| [UC-001] | UC | [UCD-001], [US-001], [SA-001] | [SSD-001], [DM-001] | [RC-002], [RC-020], [RC-023] | +| [US-001] | US | [BC-001], [UCD-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [MIL-008] | [UC-001] | [RC-001], [RC-020], [RC-022], [RC-029], [RC-030], [RC-031] | +| [UC-001] | UC | [UCD-001], [US-001], [SA-001] | [SSD-001], [DM-001] | [RC-002], [RC-020], [RC-023], [RC-031] | | [UC-002] | UC | [UCD-001], [US-001], [SA-001], [BC-001] | [SSD-002], [DM-003] | [RC-023], [RC-029], [RC-030] | | [SSD-002] | SSD | [UC-002], [DM-003] | [OC-002] | [RC-024], [RC-029] | | [DM-003] | DM | [UC-002], [UCD-001], [SSD-002], [DICT-001], [DM-001] | [OC-002], [DCD-003] | [RC-025], [RC-029] | @@ -44,13 +45,13 @@ updated whenever an artifact instance is created or reviewed. | [SD-002] | SD | [OC-002], [DCD-003] | [DCD-003] | [RC-027], [RC-029] | | [DCD-003] | DCD | [DM-003], [SD-002], [DICT-001], [UC-002], [DCD-001] | [DCD-002] | [RC-028], [RC-029], [RC-030] | | [SSD-001] | SSD | [UC-001] | [OC-001] | [RC-003], [RC-020] | -| [DM-001] | DM | [UC-001], [SSD-001] | [DM-002], [DICT-001], [OC-001], [DCD-001] | [RC-004], [RC-020] | -| [DM-002] | DM | [DM-001] | [DICT-001], [DCD-001], [DCD-002] | [RC-005], [RC-020], [RC-025], [RC-029] | +| [DM-001] | DM | [UC-001], [SSD-001] | [DM-002], [DICT-001], [OC-001], [DCD-001] | [RC-004], [RC-020], [RC-031] | +| [DM-002] | DM | [DM-001] | [DICT-001], [DCD-001], [DCD-002] | [RC-005], [RC-020], [RC-025], [RC-029], [RC-031] | | [DICT-001] | DICT | [BC-001], [SA-001], [DM-001], [DM-002] | [OC-001], [SD-001] | [RC-008], [RC-020], [RC-025], [RC-029] | -| [OC-001] | OC | [SSD-001], [DM-001] | [SD-001] | [RC-006], [RC-020], [RC-026] | -| [SD-001] | SD | [OC-001] | [DCD-001] | [RC-007], [RC-020], [RC-021] | -| [DCD-001] | DCD | [UC-001], [DM-001], [DM-002], [OC-001], [SD-001], [DICT-001] | [DCD-002] | [RC-021] | -| [DCD-002] | DCD | [DCD-001], [DCD-003], [DM-002], [DICT-001] | - | [RC-021], [RC-028], [RC-029], [RC-030] | +| [OC-001] | OC | [SSD-001], [DM-001] | [SD-001] | [RC-006], [RC-020], [RC-026], [RC-031] | +| [SD-001] | SD | [OC-001] | [DCD-001] | [RC-007], [RC-020], [RC-021], [RC-031] | +| [DCD-001] | DCD | [UC-001], [DM-001], [DM-002], [OC-001], [SD-001], [DICT-001] | [DCD-002] | [RC-021], [RC-031] | +| [DCD-002] | DCD | [DCD-001], [DCD-003], [DM-002], [DICT-001] | - | [RC-021], [RC-028], [RC-029], [RC-030], [RC-031] | ## Coverage Notes @@ -69,6 +70,7 @@ updated whenever an artifact instance is created or reviewed. [MIL-005]: ../milestones/mil-005-credentials.md [MIL-006]: ../milestones/mil-006-project-license.md [MIL-007]: ../milestones/mil-007-framework-checklists.md +[MIL-008]: ../milestones/mil-008-gitea-only-remote.md [RC-018]: ./reviews/rc-018-mil-004.md [RC-019]: ./reviews/rc-019-mil-004-code.md [RC-020]: ./reviews/rc-020-mil-005.md @@ -82,6 +84,7 @@ updated whenever an artifact instance is created or reviewed. [RC-028]: ./reviews/rc-028-dcd-003.md [RC-029]: ./reviews/rc-029-default-config-files.md [RC-030]: ./reviews/rc-030-env-optional.md +[RC-031]: ./reviews/rc-031-gitea-only-remote.md [DCD-001]: ../uc-001/dcd.md [DCD-002]: ../dcd.md [UCD-001]: ../use-case-diagram.md @@ -116,5 +119,5 @@ updated whenever an artifact instance is created or reviewed. [RC-015]: ./reviews/rc-015-mil-003.md [RC-016]: ./reviews/rc-016-create-project-sh.md [RC-017]: ./reviews/rc-017-e2e-security-review.md -[1cd27f7]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/1cd27f77ed844773a969210a11de0d8bb98ac98f [24f1507]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/24f15070fc73fb06e61865141fe0b825ea9e821e +[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03 diff --git a/docs/uc-001/dcd.md b/docs/uc-001/dcd.md index e78deee..809adee 100644 --- a/docs/uc-001/dcd.md +++ b/docs/uc-001/dcd.md @@ -9,8 +9,8 @@ ## Version History | Date | Status | Author | Reviewer | Change | Commit | | --- | --- | --- | --- | --- | --- | -| 2026-10-06 | Deprecated | Jens Tirsvad Nielsen | S02 | ProjectRequest carries the license that applies | [d773fa9] | -| 2026-10-07 | Accepted | Jens Tirsvad Nielsen | S02 | Note that DCD-003 and DCD-002 supersede the signature of startProjectCreation | [0b0a3b4] | +| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Note that DCD-003 and DCD-002 supersede the signature of startProjectCreation | [0b0a3b4] | +| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | LocalProjectBuilder.build() no longer takes the GitHub repository; a Local Project has one Remote, origin (MIL-008) | [039a28c] | --- @@ -75,7 +75,7 @@ class GitHubClient <> { +createEmptyRepository(request : ProjectRequest) : GitHubRepository } class LocalProjectBuilder { - +build(directory : Path, source : GiteaRepository, target : GitHubRepository [0..1], sshPassed : Boolean) : LocalProject + +build(directory : Path, source : GiteaRepository, sshPassed : Boolean) : LocalProject } class FrameworkInstaller { +install(project : LocalProject, enablePlanGate : Boolean) : InstallResult @@ -215,7 +215,7 @@ PushMirror "0..*" --> "1" GiteaRepository : source PushMirror "0..*" --> "1" GitHubRepository : target PushMirror "0..*" --> "1" Credential : authorised by -LocalProject "1" *-- "1..2" Remote +LocalProject "1" *-- "1" Remote Remote "0..*" --> "1" Repository : points to LocalProject "1" *-- "1" Submodule LocalProject "1" *-- "1" HookSetup @@ -261,7 +261,7 @@ Repository "0..*" --> "1" Visibility | `LicenseFile` | License | The license file in the Gitea repository when a license applies. | `key` | none | | `PushMirror` | Mirror | The Gitea to GitHub push mirror. | `interval`, `syncOnCommit` | none | | `LocalProject` | Local Project | The project directory on the Maintainer's machine. | `directory` | none | -| `Remote` | Remote | A named link to a repository (`origin`, `github`), without a credential. | `name`, `address` | none | +| `Remote` | Remote | A named link to a repository (`origin`), without a credential. | `name`, `address` | none | | `Submodule` | Framework | The framework added to the local project. | `name`, `address` | none | | `HookSetup` | Framework Setup | Records the skills and hooks installed and the plan gate state. | `areSkillsInstalled`, `areHooksInstalled`, `isPlanGateEnabled` | none | | `EnvFile` | Credentials File | The `.env` of the project: a copy of the credentials it needs. | `address`, `keys` | none | @@ -291,7 +291,7 @@ Repository "0..*" --> "1" Visibility | `GiteaClient.requestSync(mirror) : void` | [SD-001] `requestSync(pushMirror)`; P6 | | `GitHubClient(configuration)` | [SD-001] `new(configuration)` to `GitHubClient` | | `GitHubClient.createEmptyRepository(request) : GitHubRepository` | [SD-001] `createEmptyRepository(request)`; P5 | -| `LocalProjectBuilder.build(directory, source, target, sshPassed) : LocalProject` | [SD-001] `build(directory, giteaRepository, gitHubRepository, sshPassed)`; P7, P8, P9 | +| `LocalProjectBuilder.build(directory, source, sshPassed) : LocalProject` | [SD-001] `build(directory, giteaRepository, sshPassed)`; P7, P8, P9 | | `FrameworkInstaller.install(project, enablePlanGate) : InstallResult` | [SD-001] `install(localProject, enablePlanGate)`; P10, P11, P12 | | `SummaryReport.compose(request) : Summary` | [SD-001] `compose(projectRequest)`; P13 | @@ -339,7 +339,7 @@ SOLID check: no class has more than one reason to change (one host API, one kind [MIL-005]: ../milestones/mil-005-credentials.md [DICT-001]: ../dictionary.md [DCD-002]: ../dcd.md -[d773fa9]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/d773fa91df5a54090254e12e074880fb6526a9ff [DCD-003]: ../uc-002/dcd.md [UC-002]: ../uc-002/uc.md [0b0a3b4]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/0b0a3b419a1157b23bddd2f8957a08adaf6974a6 +[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03 diff --git a/docs/uc-001/dm.md b/docs/uc-001/dm.md index 744d7c1..e092d48 100644 --- a/docs/uc-001/dm.md +++ b/docs/uc-001/dm.md @@ -9,8 +9,8 @@ ## Version History | Date | Status | Author | Reviewer | Change | Commit | | --- | --- | --- | --- | --- | --- | -| 2026-10-06 | Proposed | Jens Tirsvad Nielsen | S02 | License applies when configured, not only when GitHub is chosen | [d773fa9] | -| 2026-10-07 | Proposed | Jens Tirsvad Nielsen | S02 | License: the AGPL-3.0 default needs GitHub and a public project | [1cd27f7] | +| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | License: the AGPL-3.0 default needs GitHub and a public project | [1cd27f7] | +| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | A Local Project has one Remote, origin, no longer one or two (MIL-008) | [039a28c] | --- @@ -104,7 +104,7 @@ Mirror "1" --> "1" GiteaRepository : copies from Mirror "1" --> "1" GitHubRepository : copies to Mirror "0..*" --> "1" AccessToken : is authorised by LocalProject "1" --> "1" Project : is the working copy of -LocalProject "1" --> "1..2" Remote : has +LocalProject "1" --> "1" Remote : has Remote "0..*" --> "1" Repository : points to LocalProject "1" --> "1" Framework : includes LocalProject "1" --> "1" FrameworkSetup : has @@ -133,7 +133,7 @@ Summary "1" --> "1" Project : reports on | License | The legal terms file added to a Gitea Repository when a license applies: the one set in the Configuration, or AGPL-3.0 when GitHub is chosen, the project is public and none is set | name | [UC-001] step 6 "license" | | Mirror | The push mirror that copies a Gitea Repository to a GitHub Repository | interval, sync on commit | [UC-001] step 7 "push mirror" | | Local Project | The project directory on the Maintainer's machine | directory | [UC-001] step 8 "local project" | -| Remote | A named link from a Local Project to a Repository (`origin`, `github`) | name, address | [UC-001] step 8 "remote" | +| Remote | A named link from a Local Project to a Repository (`origin`) | name, address | [UC-001] step 8 "remote" | | Framework | The SQA-QC-Framework added to a Local Project | name, address | [UC-001] step 9 "framework submodule" | | Framework Setup | The skills and git hooks installed from the Framework, with the plan gate on or off | plan gate enabled | [UC-001] step 9 "skills and hooks", "plan gate" | | Template | A file the Framework provides to copy into a project (`AGENTS.md`, artifact registry) | name | [UC-001] step 9 "templates" | @@ -157,7 +157,7 @@ Summary "1" --> "1" Project : reports on | Mirror | copies to | GitHub Repository | 1 to 1 | | Mirror | is authorised by | Access Token | 0..* to 1 | | Local Project | is the working copy of | Project | 1 to 1 | -| Local Project | has | Remote | 1 to 1..2 | +| Local Project | has | Remote | 1 to 1 | | Remote | points to | Repository | 0..* to 1 | | Local Project | includes | Framework | 1 to 1 | | Local Project | has | Framework Setup | 1 to 1 | @@ -180,5 +180,5 @@ Summary "1" --> "1" Project : reports on [SSD-001]: ./ssd.md [DICT-001]: ../dictionary.md [DM-002]: ../domain-model.md -[d773fa9]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/d773fa91df5a54090254e12e074880fb6526a9ff [1cd27f7]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/1cd27f77ed844773a969210a11de0d8bb98ac98f +[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03 diff --git a/docs/uc-001/oc.md b/docs/uc-001/oc.md index c58bd36..19cc2e9 100644 --- a/docs/uc-001/oc.md +++ b/docs/uc-001/oc.md @@ -9,8 +9,8 @@ ## Version History | Date | Status | Author | Reviewer | Change | Commit | | --- | --- | --- | --- | --- | --- | -| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | P4: the AGPL-3.0 default needs githubOwner and a public visibility; P10: the framework's own submodules were initialised, with an exception for a failed fetch | [1cd27f7] | -| 2026-10-07 | Accepted | Jens Tirsvad Nielsen | S02 | Note that OC-002 and DCD-002 supersede the signature of startProjectCreation | [0b0a3b4] | +| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Note that OC-002 and DCD-002 supersede the signature of startProjectCreation | [0b0a3b4] | +| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | P9: no other remote is associated with the local project (MIL-008) | [039a28c] | --- @@ -71,7 +71,7 @@ Concepts below use the IT terms of [DICT-001] for the PO concepts of [DM-001]. ` - P6. If `githubOwner` is present, a `PushMirror` instance was created, associated with the `GiteaRepository` as source and the `GitHubRepository` as target, with its effective sync setting recorded, and a first sync was requested. - P7. A `LocalProject` instance was created at `directory`, associated with the `ProjectRequest`. If the `GiteaRepository` is not empty, the `LocalProject` holds its history, including the `LicenseFile` commit. - P8. A `Remote` named `origin` was associated with the `LocalProject`, pointing at the `GiteaRepository` over SSH if the SSH test passed, otherwise over HTTPS, with no credential in its URL. -- P9. If `githubOwner` is present, a `Remote` named `github` was associated with the `LocalProject`, pointing at the `GitHubRepository`, with no credential in its URL. +- P9. No other `Remote` was associated with the `LocalProject`, whether or not `githubOwner` is present: the `GitHubRepository`, when there is one, is reached through the `PushMirror` of P6, not through a remote. - P10. A `Submodule` named `framework` was associated with the `LocalProject`, and the submodules the framework itself holds (`qc`) were initialised. - P11. A `HookSetup` instance was associated with the `LocalProject`, recording that skills and git hooks were installed once and, if `enablePlanGate`, that the plan gate was enabled. - P12. `AGENTS.md` and `docs/artifact-registry.md` exist in the `LocalProject`, each either newly copied from the framework templates or left as it was because the Maintainer declined to replace it. @@ -98,8 +98,8 @@ Concepts below use the IT terms of [DICT-001] for the PO concepts of [DM-001]. ` [DM-001]: ./dm.md [DICT-001]: ../dictionary.md [SD-001]: ./sd.md -[1cd27f7]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/1cd27f77ed844773a969210a11de0d8bb98ac98f [OC-002]: ../uc-002/oc.md [DCD-002]: ../dcd.md [UC-002]: ../uc-002/uc.md [0b0a3b4]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/0b0a3b419a1157b23bddd2f8957a08adaf6974a6 +[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03 diff --git a/docs/uc-001/sd.md b/docs/uc-001/sd.md index d4f5e30..ce99472 100644 --- a/docs/uc-001/sd.md +++ b/docs/uc-001/sd.md @@ -9,8 +9,8 @@ ## Version History | Date | Status | Author | Reviewer | Change | Commit | | --- | --- | --- | --- | --- | --- | -| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | P4: the license passed is AGPL-3.0 only for GitHub with a public project | [1cd27f7] | -| 2026-10-07 | Accepted | Jens Tirsvad Nielsen | S02 | Note that SD-002 and DCD-002 supersede the signature of startProjectCreation | [0b0a3b4] | +| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | Note that SD-002 and DCD-002 supersede the signature of startProjectCreation | [0b0a3b4] | +| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | build() no longer receives the GitHub repository and returns a local project with the remote origin; P9 (MIL-008) | [039a28c] | --- @@ -146,9 +146,9 @@ opt githubOwner present end create LB -PC -> LB : build(directory, giteaRepository, gitHubRepository, sshPassed) +PC -> LB : build(directory, giteaRepository, sshPassed) activate LB -LB --> PC : localProject (remotes origin, github) +LB --> PC : localProject (remote origin) deactivate LB create FI @@ -203,7 +203,7 @@ destroy SR | P6 PushMirror and first sync | `addPushMirror(...)` and `requestSync(pushMirror)` | | P7 LocalProject created, history from Gitea when not empty | `build(directory, ...)` | | P8 origin remote (SSH if the test passed, else HTTPS) | `build(..., sshPassed)` | -| P9 github remote when chosen | `build(...)` | +| P9 no other remote (GitHub is reached through the mirror) | `build(...)` adds `origin` only | | P10 framework Submodule | `install(localProject, ...)` | | P11 HookSetup, plan gate if chosen | `install(localProject, enablePlanGate)` | | P12 AGENTS.md and registry copied or kept | `install(...)` returning `templates` | @@ -218,8 +218,8 @@ destroy SR [OC-001]: ./oc.md [DCD-001]: ./dcd.md -[1cd27f7]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/1cd27f77ed844773a969210a11de0d8bb98ac98f [SD-002]: ../uc-002/sd.md [DCD-002]: ../dcd.md [UC-002]: ../uc-002/uc.md [0b0a3b4]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/0b0a3b419a1157b23bddd2f8957a08adaf6974a6 +[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03 diff --git a/docs/uc-001/uc.md b/docs/uc-001/uc.md index ce6d7de..3584ca7 100644 --- a/docs/uc-001/uc.md +++ b/docs/uc-001/uc.md @@ -9,8 +9,8 @@ ## Version History | Date | Status | Author | Reviewer | Change | Commit | | --- | --- | --- | --- | --- | --- | -| 2026-10-06 | Deprecated | Jens Tirsvad Nielsen | S02 | The license comes from PROJECT_LICENSE (step 6, extension 4c); AGPL-3.0 is only the default when GitHub is chosen | [d773fa9] | -| 2026-10-07 | Accepted | Jens Tirsvad Nielsen | S02 | License rule: the AGPL-3.0 default needs GitHub and a public project (step 6, rule 6); step 9 and extension 9e fetch the framework's own submodules | [1cd27f7] | +| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | License rule: the AGPL-3.0 default needs GitHub and a public project (step 6, rule 6); step 9 and extension 9e fetch the framework's own submodules | [1cd27f7] | +| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | Postcondition, step 8 and its rule: origin is the only remote; no github remote (MIL-008) | [039a28c] | --- @@ -33,7 +33,7 @@ - **Postconditions (success guarantee):** - A repository exists on Gitea under the chosen owner. It is empty, or it holds the license file that applies: the license set in `config.env`, or AGPL-3.0 when the Maintainer chose GitHub, the project is public and no license is set. - When the Maintainer chose to create a GitHub repository, an empty repository exists on GitHub under the chosen owner, the Gitea repository is a push mirror to it, and the license file, if any, reaches GitHub through the mirror. - - A local project directory exists with credential-free remotes `origin` (Gitea) and, when GitHub was chosen, `github`, the `framework` submodule, installed skills and hooks, and the copied templates. + - A local project directory exists with one credential-free remote, `origin` (Gitea), the `framework` submodule, installed skills and hooks, and the copied templates. - When the Maintainer agreed, the local project has a `.env` that holds only the credentials the project needs, is readable by its owner only and is ignored by git. - The Maintainer has a summary of what was created. @@ -46,7 +46,7 @@ 5. Optional: if the Maintainer chose GitHub, the system creates the empty GitHub repository. 6. The system creates the Gitea repository. If a license applies, the repository is created with its license file and so is not empty; otherwise it is empty. The license that applies is the one set in `config.env` (`PROJECT_LICENSE`; `none` means no license); when none is set it is AGPL-3.0 if the Maintainer chose GitHub and the project is public, and none otherwise. The license is never asked. 7. Optional: if GitHub was chosen, the system configures the Gitea repository as a push mirror to GitHub and verifies it. A license file in the Gitea repository is pushed to GitHub by the mirror. -8. The system creates the local project with the `origin` remote and, if GitHub was chosen, the `github` remote. +8. The system creates the local project with the `origin` remote. It adds no `github` remote: a push to `origin` reaches GitHub through the mirror of step 7. 9. The system adds the framework submodule and fetches its own submodules (the `qc` checklists), installs its skills and hooks (and the plan gate if chosen) and copies the templates. If the Maintainer agrees, it also creates the project's own `.env` with the credentials the project needs. 10. The system reports a summary of what was created. @@ -88,10 +88,10 @@ | 9 | The project's `.env` is the only place a token is written. It is created only after a yes (default no), holds only the keys the project needs (`GITEA_TOKEN`; `GITHUB_PAT` and `GITHUB_USER` when GitHub was chosen), is readable by its owner only, is excluded from git without changing a tracked file, and is never replaced without a yes | | 3 | The GitHub owner and the Gitea owner are chosen separately; `GITHUB_USER` is only the authenticating account | | 3 | A project detail set in `config.env` (the key is present, even if empty where an empty value is allowed) is not asked; only the confirmations stay interactive | -| 3, 5, 7 | GitHub is optional; without it no GitHub repository, mirror or `github` remote is created and the GitHub credentials are not required | +| 3, 5, 7 | GitHub is optional; without it no GitHub repository or mirror is created and the GitHub credentials are not required | | 6 | The license that applies is added to the Gitea repository when it is created, so that repository is not empty: `PROJECT_LICENSE` if set (a Gitea license key such as `MIT`, or `none`), otherwise AGPL-3.0 when GitHub is chosen and the project is public, otherwise none. It is independent of the GitHub choice when set, and it is never asked | | 7 | The mirror direction is Gitea to GitHub; the GitHub repository stays empty and receives its content from the mirror | -| 8 | `origin` uses HTTPS derived from `GITEA_URL`, or SSH when the SSH test in step 4 passed; when the Gitea repository is not empty (GitHub chosen) the local project is created by fetching it, not by an unrelated `git init` history | +| 8 | `origin` is the only remote, with or without GitHub, and a remote already in the directory, such as a `github` remote made by an earlier version, is never removed or replaced. `origin` uses HTTPS derived from `GITEA_URL`, or SSH when the SSH test in step 4 passed; when the Gitea repository is not empty (GitHub chosen) the local project is created by fetching it, not by an unrelated `git init` history | | 8, 9 | Nothing is overwritten or deleted without consent, and no commit is made | ### Open Issues @@ -104,5 +104,5 @@ [US-001]: ../user-stories.md [SA-001]: ../stakeholder-analysis.md [DM-001]: ./dm.md -[d773fa9]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/d773fa91df5a54090254e12e074880fb6526a9ff [1cd27f7]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/1cd27f77ed844773a969210a11de0d8bb98ac98f +[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03 diff --git a/docs/user-stories.md b/docs/user-stories.md index 96d0123..cdaf659 100644 --- a/docs/user-stories.md +++ b/docs/user-stories.md @@ -4,13 +4,13 @@ | Key | Value | | --- | --- | | ID | US-001 | -| CrossReference | [BC-001], [UCD-001], [UC-002], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007] | +| CrossReference | [BC-001], [UCD-001], [UC-002], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [MIL-007], [MIL-008] | ## Version History | Date | Status | Author | Reviewer | Change | Commit | | --- | --- | --- | --- | --- | --- | -| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | US-002: the default configuration files are the working folder's, then the checkout's; confirmed and named | [0ab5006] | -| 2026-10-07 | Accepted | Jens Tirsvad Nielsen | S02 | US-002: only config.env is required; a .env found nowhere means the token is asked | [24f1507] | +| 2026-10-07 | Deprecated | Jens Tirsvad Nielsen | S02 | US-002: only config.env is required; a .env found nowhere means the token is asked | [24f1507] | +| 2026-10-08 | Accepted | Jens Tirsvad Nielsen | S02 | US-001.03: one remote, origin; no github remote (MIL-008) | [039a28c] | --- @@ -56,7 +56,7 @@ The epic is split into seven stories, one per milestone (US-001.01 to US-001.07) **Acceptance Criteria** -- Given the repositories exist, when the script finishes, then the project directory has an `origin` remote and, if GitHub was chosen, a `github` remote, neither containing a credential. +- Given the repositories exist, when the script finishes, then the project directory has one remote, `origin` (Gitea), with or without GitHub, containing no credential; there is no `github` remote, because a push to `origin` reaches GitHub through the mirror. - Given the project directory, when the script finishes, then the framework, its skills and git hooks (and the plan gate if chosen) and the copied templates are in place. - Given a directory or file already exists, when the script would replace it, then it asks first. @@ -165,6 +165,7 @@ Valuable, Negotiable, Estimable, Small and Testable hold for each story. Indepen [MIL-005]: ./milestones/mil-005-credentials.md [MIL-006]: ./milestones/mil-006-project-license.md [MIL-007]: ./milestones/mil-007-framework-checklists.md +[MIL-008]: ./milestones/mil-008-gitea-only-remote.md [PP-001]: ./project-plan.md -[0ab5006]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/0ab50068bf9e5be82a801af9dbe5b763eeaf7f31 [24f1507]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/24f15070fc73fb06e61865141fe0b825ea9e821e +[039a28c]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/039a28c01b56f8cf0af73f55d1a604b43d67ba03 diff --git a/src/lib/constants.sh b/src/lib/constants.sh index 534c175..d5775dd 100644 --- a/src/lib/constants.sh +++ b/src/lib/constants.sh @@ -8,7 +8,7 @@ # shellcheck disable=SC2034 # read and written by the other library files readonly PROJECT_NAME="${REPOFOUNDRY_NAME:-RepoFoundry}" -readonly VERSION="0.3.0" +readonly VERSION="0.3.1" readonly EXIT_FAILURE=1 readonly EXIT_USAGE=2 readonly MAX_VALUE_LENGTH=2048 diff --git a/src/lib/hosts.sh b/src/lib/hosts.sh index 7fcae2d..6ccc177 100644 --- a/src/lib/hosts.sh +++ b/src/lib/hosts.sh @@ -4,7 +4,7 @@ # # Part of create-project.sh: sourced by it, never run on its own. # -# Provides: is_reused, repo_owner, repo_url, gitea_host, origin_protocol, origin_url, github_remote_url, framework_url +# Provides: is_reused, repo_owner, repo_url, gitea_host, origin_protocol, origin_url, framework_url # is_reused HOST: succeed if the existing repository on HOST will be reused. is_reused() { @@ -54,10 +54,6 @@ origin_url() { fi } -github_remote_url() { - printf '%s/%s/%s.git' "${CONFIG[GITHUB_WEB_URL]}" "${PROJECT[github_owner]}" "${PROJECT[name]}" -} - # framework_url: where the framework submodule comes from (always SSH). framework_url() { printf 'ssh://git@%s:%s/%s.git' "$(gitea_host)" "${CONFIG[GITEA_SSH_PORT]}" \ diff --git a/src/lib/localproject.sh b/src/lib/localproject.sh index cb51dc6..96cd267 100644 --- a/src/lib/localproject.sh +++ b/src/lib/localproject.sh @@ -71,8 +71,10 @@ checkout_gitea_history() { fi } -# create_local_project: the directory, the git repository on main, the -# remotes and, when a license applies, the license history. No commit is made. +# create_local_project: the directory, the git repository on main, the origin +# remote and, when a license applies, the license history. No commit is made. +# Gitea is the only remote: a push to it reaches GitHub through the push +# mirror, so no github remote is added (and none that exists is removed). create_local_project() { local label="Local project" dir="${PROJECT[directory]}" begin_step "$label" @@ -82,9 +84,6 @@ create_local_project() { git_project "$dir" symbolic-ref HEAD "refs/heads/$DEFAULT_BRANCH" fi ensure_remote "$dir" origin "$(origin_url)" - if ((PROJECT[has_github])); then - ensure_remote "$dir" github "$(github_remote_url)" - fi if [[ -n ${PROJECT[license]} ]]; then checkout_gitea_history "$dir" fi diff --git a/tests/test-local.sh b/tests/test-local.sh index 8fe1f5d..48e77d4 100644 --- a/tests/test-local.sh +++ b/tests/test-local.sh @@ -35,7 +35,7 @@ readonly SSH_FRAMEWORK_URL="ssh://git@git.example.test:10022/TirSystem/SQA-QC-Fr # ----------------------------------------------------- directory and remotes -test_local_project_gets_credential_free_remotes_and_the_license_history() { +test_local_project_gets_the_origin_remote_only_and_the_license_history() { setup_hosts local dir="$WORK/project" local_answers "$dir" y n @@ -44,7 +44,9 @@ test_local_project_gets_credential_free_remotes_and_the_license_history() { assert_file_exists "directory created" "$dir/.git" assert_eq "branch is main" "main" "$(project_git "$dir" symbolic-ref --short HEAD)" assert_eq "origin over SSH, no credential" "ssh://git@git.example.test:10022/TirSystem/my-app.git" "$(project_git "$dir" config --get remote.origin.url)" - assert_eq "github remote over HTTPS, no credential" "https://github.com/acme-org/my-app.git" "$(project_git "$dir" config --get remote.github.url)" + assert_eq "origin is the only remote, also with GitHub" "origin" "$(project_git "$dir" remote)" + assert_eq "no github remote" "" "$(project_git "$dir" config --get remote.github.url || true)" + assert_not_contains "no GitHub address in the git config" "$(cat "$dir/.git/config")" "github.com" assert_eq "the license commit is the whole history" "1" "$(project_git "$dir" rev-list --count HEAD)" assert_eq "it is the Gitea commit" "Initial commit" "$(project_git "$dir" log -1 --format=%s)" assert_file_exists "LICENSE from Gitea" "$dir/LICENSE" @@ -53,7 +55,7 @@ test_local_project_gets_credential_free_remotes_and_the_license_history() { assert_contains "reported" "$OUT" "Local project : created $dir (origin over SSH)" } -test_gitea_only_project_has_no_github_remote_and_no_commit() { +test_gitea_only_project_has_the_origin_remote_only_and_no_commit() { setup_hosts printf 'GITEA_TOKEN=%s\n' "$FAKE_GITEA_TOKEN" >"$WORK/.env" local dir="$WORK/project" @@ -61,7 +63,7 @@ test_gitea_only_project_has_no_github_remote_and_no_commit() { run_apply "$LOCAL_ANSWERS"$'y\n' assert_status "apply" 0 "$STATUS" assert_eq "origin" "ssh://git@git.example.test:10022/TirSystem/my-app.git" "$(project_git "$dir" config --get remote.origin.url)" - assert_eq "no github remote" "" "$(project_git "$dir" config --get remote.github.url || true)" + assert_eq "origin is the only remote" "origin" "$(project_git "$dir" remote)" assert_file_missing "no license file" "$dir/LICENSE" assert_eq "no commit was made" "0" "$(project_git "$dir" rev-list --all --count)" assert_eq "no token in any file" "" "$(files_with_secret "$dir")" @@ -109,6 +111,20 @@ test_a_file_that_would_be_overwritten_by_the_license_history_is_kept() { assert_contains "later steps not attempted" "$OUT" "Framework : not attempted" } +test_a_github_remote_from_an_earlier_version_is_left_alone() { + setup_hosts + local dir="$WORK/project" + mkdir -p "$dir" + project_git "$dir" init -q + project_git "$dir" remote add github https://github.com/acme-org/my-app.git + local_answers "$dir" y n + run_apply "$LOCAL_ANSWERS"$'y\ny\n' + assert_status "apply" 0 "$STATUS" + assert_eq "the github remote is kept as it was" "https://github.com/acme-org/my-app.git" "$(project_git "$dir" config --get remote.github.url)" + assert_eq "origin was added beside it" "ssh://git@git.example.test:10022/TirSystem/my-app.git" "$(project_git "$dir" config --get remote.origin.url)" + assert_eq "no other remote" $'github\norigin' "$(project_git "$dir" remote | sort)" +} + test_a_remote_with_another_address_is_never_replaced() { setup_hosts local dir="$WORK/project" @@ -379,16 +395,15 @@ test_a_project_path_that_is_a_file_is_refused_in_the_preflight() { test_remote_addresses_are_built_from_the_configuration() { run_lib "" 'CONFIG[GITEA_URL]=https://git.example.test/sub -CONFIG[GITEA_SSH_PORT]=2222 CONFIG[FRAMEWORK_REPO]=Org/Fw CONFIG[GITHUB_WEB_URL]=https://github.com -PROJECT[gitea_owner]=TirSystem PROJECT[github_owner]=acme PROJECT[name]=my-app +CONFIG[GITEA_SSH_PORT]=2222 CONFIG[FRAMEWORK_REPO]=Org/Fw +PROJECT[gitea_owner]=TirSystem PROJECT[name]=my-app STATE[is_ssh_ok]=1 origin_url; echo STATE[is_ssh_ok]=0 origin_url; echo -github_remote_url; echo framework_url; echo gitea_host; echo' - assert_eq "addresses" $'ssh://git@git.example.test:2222/TirSystem/my-app.git\nhttps://git.example.test/sub/TirSystem/my-app.git\nhttps://github.com/acme/my-app.git\nssh://git@git.example.test:2222/Org/Fw.git\ngit.example.test' "$OUT" + assert_eq "addresses" $'ssh://git@git.example.test:2222/TirSystem/my-app.git\nhttps://git.example.test/sub/TirSystem/my-app.git\nssh://git@git.example.test:2222/Org/Fw.git\ngit.example.test' "$OUT" } test_the_https_fetch_hands_the_token_over_through_the_environment_only() { diff --git a/tests/test-security.sh b/tests/test-security.sh index 1f7e86d..f87723f 100644 --- a/tests/test-security.sh +++ b/tests/test-security.sh @@ -103,7 +103,7 @@ test_usage_errors() { assert_contains "help shows exit codes" "$OUT" "Exit codes" run_cli "" --version assert_status "version" 0 "$STATUS" - assert_contains "version output" "$OUT" "RepoFoundry 0.3.0" + assert_contains "version output" "$OUT" "RepoFoundry 0.3.1" } test_warns_when_env_is_not_ignored_by_git() {