Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
905a5e745a | ||
|
|
de78fb195f | ||
|
|
2a6bb8e8af | ||
|
|
f34affa071 | ||
|
|
613a288dea |
@@ -15,8 +15,12 @@ and owner (a user or an organization, separately on each host), shows a plan,
|
|||||||
and only creates anything after you pass `--apply` and answer yes.
|
and only creates anything after you pass `--apply` and answer yes.
|
||||||
|
|
||||||
> **Status.** The script is tested with stubbed host APIs and real git against
|
> **Status.** The script is tested with stubbed host APIs and real git against
|
||||||
> local repositories (see [Development](#development)). A first run against
|
> local repositories (see [Development](#development)). A first end-to-end run
|
||||||
> real GitHub and Gitea repositories is still to be recorded.
|
> on real GitHub and Gitea repositories, with organization owners on both, has
|
||||||
|
> passed (2026-10-05, review record RC-017). Creating a repository under your
|
||||||
|
> own Gitea account needs the `write:user` token scope (see
|
||||||
|
> [Token permissions](#token-permissions)); that path has not been completed
|
||||||
|
> yet.
|
||||||
|
|
||||||
## Contents
|
## Contents
|
||||||
|
|
||||||
@@ -63,7 +67,7 @@ are accepted, and anything else stops the run with a message that names the key
|
|||||||
and the line, never the value.
|
and the line, never the value.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cp config.env.example config.env # service addresses, not secret
|
cp config.env.example config.env # service addresses, not secret: set GITEA_URL (and GITEA_API_URL)
|
||||||
cp .env.example .env # credentials: keep private
|
cp .env.example .env # credentials: keep private
|
||||||
chmod 600 .env # Linux and macOS
|
chmod 600 .env # Linux and macOS
|
||||||
```
|
```
|
||||||
@@ -195,7 +199,7 @@ repositories for the chosen owner and to push to the new one.
|
|||||||
| Create a private repository | classic token with the `repo` scope | GitHub REST documentation, "Create a repository" |
|
| Create a private repository | classic token with the `repo` scope | GitHub REST documentation, "Create a repository" |
|
||||||
| Create a public repository only | classic token with `public_repo` is enough | same |
|
| Create a public repository only | classic token with `public_repo` is enough | same |
|
||||||
| Push from the Gitea mirror | covered by `repo` | |
|
| Push from the Gitea mirror | covered by `repo` | |
|
||||||
| Check that you belong to the organization owner | probably `read:org` | **Not confirmed**: the GitHub documentation names no scope for this call. If the script says you do not belong to an organization that you do belong to, add `read:org`. |
|
| Check that you belong to the organization owner | worked with a classic token that has `repo` and `admin:org` | `read:org` alone was **not tested**: the GitHub documentation names no scope for this call. If the script says you do not belong to an organization that you do belong to, add `read:org`. |
|
||||||
|
|
||||||
- **Organization owners:** you must be an active member who is allowed to
|
- **Organization owners:** you must be an active member who is allowed to
|
||||||
create repositories in the organization. Organizations that require SSO or
|
create repositories in the organization. Organizations that require SSO or
|
||||||
@@ -211,9 +215,9 @@ repositories for the chosen owner and to push to the new one.
|
|||||||
| Need | Scope | Source |
|
| Need | Scope | Source |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| Read the account the token belongs to | `read:user` | Gitea documentation |
|
| Read the account the token belongs to | `read:user` | Gitea documentation |
|
||||||
| Create repositories, manage the push mirror | `write:repository` | Gitea documentation |
|
| Create a repository **under your own account** | `write:user` | **Confirmed by a real server**: without it Gitea answers `required=[write:user]` |
|
||||||
| Look up an organization and your permissions in it | `read:organization` | Gitea documentation |
|
| Create a repository in an organization, manage its push mirror | `write:organization` and `write:repository` | worked with a token that has both, plus `read:user`; the minimum was not narrowed down |
|
||||||
| Create a repository in an organization | probably `write:organization` as well | **Not confirmed**: expected from how the Gitea API groups organization calls; to be confirmed in the first end-to-end run. |
|
| Look up an organization and your permissions in it | covered by the scopes above | worked in the end-to-end run |
|
||||||
|
|
||||||
A missing scope shows up as an HTTP 403 with the server's own message. The
|
A missing scope shows up as an HTTP 403 with the server's own message. The
|
||||||
script stops before it creates anything when a preflight check is refused.
|
script stops before it creates anything when a preflight check is refused.
|
||||||
@@ -256,7 +260,7 @@ step, `2` a usage error.
|
|||||||
| A tool, a config key or a token is missing or invalid | stops before any request | fix it and run again |
|
| A tool, a config key or a token is missing or invalid | stops before any request | fix it and run again |
|
||||||
| A token is refused, an owner is unknown, a name is taken, the license is missing | stops in the preflight; nothing was created | fix the cause |
|
| A token is refused, an owner is unknown, a name is taken, the license is missing | stops in the preflight; nothing was created | fix the cause |
|
||||||
| The host cannot be reached | stops with the host name | try again |
|
| The host cannot be reached | stops with the host name | try again |
|
||||||
| A repository already exists and is empty (Gitea: or holds only the license) | offers to reuse it (default no) | answer, or choose another name |
|
| A repository already exists and is empty (Gitea: or holds only the license and the README Gitea adds) | offers to reuse it (default no) | answer, or choose another name |
|
||||||
| A repository already has content | stops | choose another name or remove it |
|
| A repository already has content | stops | choose another name or remove it |
|
||||||
| A step fails after another succeeded | stops and prints what exists, what failed and how to continue | fix the cause and run the **same command again with `--apply`**: what was created is offered for reuse |
|
| A step fails after another succeeded | stops and prints what exists, what failed and how to continue | fix the cause and run the **same command again with `--apply`**: what was created is offered for reuse |
|
||||||
| The mirror is refused (disabled, interval too short) | keeps the repositories and reports it | change `MIRROR_INTERVAL` or ask the Gitea administrator, then run again |
|
| The mirror is refused (disabled, interval too short) | keeps the repositories and reports it | change `MIRROR_INTERVAL` or ask the Gitea administrator, then run again |
|
||||||
@@ -285,17 +289,20 @@ web interface and the project directory by hand.
|
|||||||
this, and revoke it if the Gitea server is ever in doubt.
|
this, and revoke it if the Gitea server is ever in doubt.
|
||||||
- **`sync_on_commit` may be ignored.** When a push mirror is created through
|
- **`sync_on_commit` may be ignored.** When a push mirror is created through
|
||||||
the API, some Gitea versions ignore `sync_on_commit` (upstream issue
|
the API, some Gitea versions ignore `sync_on_commit` (upstream issue
|
||||||
go-gitea/gitea#22990). The script reads the mirror back and warns if the
|
go-gitea/gitea#22990). On Gitea 1.27.3 it was applied: a branch pushed to
|
||||||
setting was not applied; the mirror then syncs on its interval
|
Gitea reached GitHub within seconds. The script reads the mirror back and
|
||||||
|
warns if the setting was not applied; the mirror then syncs on its interval
|
||||||
(`MIRROR_INTERVAL`, default 10 minutes). The first sync is requested right
|
(`MIRROR_INTERVAL`, default 10 minutes). The first sync is requested right
|
||||||
after the mirror is created.
|
after the mirror is created.
|
||||||
- **The server decides the shortest interval** and whether push mirrors are
|
- **The server decides the shortest interval** and whether push mirrors are
|
||||||
allowed at all. A refused mirror stops the run with the server's message;
|
allowed at all. A refused mirror stops the run with the server's message;
|
||||||
the repositories created so far are kept.
|
the repositories created so far are kept.
|
||||||
- **The license commit.** Gitea adds the license file when the repository is
|
- **The license commit.** Gitea adds the license file when the repository is
|
||||||
created with `auto_init`. The script sends no README, so the repository
|
created with `auto_init`, and on the real server it also adds a generated
|
||||||
should hold only `LICENSE`; this is still to be confirmed against a real
|
`README.md`. Both are mirrored to GitHub and become the first commit of the
|
||||||
server.
|
local project. A Gitea repository that holds only these files counts as
|
||||||
|
content this script created and is offered for reuse; a repository with
|
||||||
|
anything else counts as having content and is refused.
|
||||||
- **No rollback.** See [Error handling and recovery](#error-handling-and-recovery).
|
- **No rollback.** See [Error handling and recovery](#error-handling-and-recovery).
|
||||||
- **Mirror direction is Gitea to GitHub only.** Push to Gitea; GitHub is a
|
- **Mirror direction is Gitea to GitHub only.** Push to Gitea; GitHub is a
|
||||||
copy.
|
copy.
|
||||||
|
|||||||
+2
-2
@@ -17,10 +17,10 @@ GITHUB_API_URL=https://api.github.com
|
|||||||
GITHUB_WEB_URL=https://github.com
|
GITHUB_WEB_URL=https://github.com
|
||||||
|
|
||||||
# Gitea instance base URL. Repository links are derived from it.
|
# Gitea instance base URL. Repository links are derived from it.
|
||||||
GITEA_URL=https://git.tirsystem.com/
|
GITEA_URL=https://<your gitea instance>/
|
||||||
|
|
||||||
# Gitea REST API base URL. If you leave this out it is GITEA_URL + /api/v1.
|
# Gitea REST API base URL. If you leave this out it is GITEA_URL + /api/v1.
|
||||||
GITEA_API_URL=https://git.tirsystem.com/api/v1
|
GITEA_API_URL=https://<your gitea instance>/api/v1
|
||||||
|
|
||||||
# Optional. SSH port of the Gitea server, used for the SSH check and later
|
# Optional. SSH port of the Gitea server, used for the SSH check and later
|
||||||
# for the framework submodule. Default: 10022.
|
# for the framework submodule. Default: 10022.
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ document of a type. `Primary File` may contain a glob (e.g.
|
|||||||
| BC | Business Case | docs/business-case.md | 002 |
|
| BC | Business Case | docs/business-case.md | 002 |
|
||||||
| SA | Stakeholder Analysis | docs/stakeholder-analysis.md | 002 |
|
| SA | Stakeholder Analysis | docs/stakeholder-analysis.md | 002 |
|
||||||
| PP | Project Plan | docs/project-plan.md | 002 |
|
| PP | Project Plan | docs/project-plan.md | 002 |
|
||||||
| MIL | Milestone / Gateway | docs/milestones/*.md | 004 |
|
| MIL | Milestone / Gateway | docs/milestones/*.md | 005 |
|
||||||
| US | User Story | docs/user-stories.md | 002 |
|
| US | User Story | docs/user-stories.md | 002 |
|
||||||
| UC | Use Case | docs/uc-*/uc.md | 002 |
|
| UC | Use Case | docs/uc-*/uc.md | 002 |
|
||||||
| SSD | System Sequence Diagram | docs/uc-*/ssd.md | 002 |
|
| SSD | System Sequence Diagram | docs/uc-*/ssd.md | 002 |
|
||||||
@@ -23,7 +23,7 @@ document of a type. `Primary File` may contain a glob (e.g.
|
|||||||
| DM | Domain Model | docs/domain-model.md | 003 |
|
| DM | Domain Model | docs/domain-model.md | 003 |
|
||||||
| DICT | Domain Dictionary (PO and IT terms) | docs/dictionary.md | 002 |
|
| DICT | Domain Dictionary (PO and IT terms) | docs/dictionary.md | 002 |
|
||||||
| UCD | Use Case Diagram | docs/use-case-diagram.md | 002 |
|
| UCD | Use Case Diagram | docs/use-case-diagram.md | 002 |
|
||||||
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 017 |
|
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 019 |
|
||||||
| TM | Traceability Matrix | docs/sqa/traceability-matrix.md | 002 |
|
| TM | Traceability Matrix | docs/sqa/traceability-matrix.md | 002 |
|
||||||
|
|
||||||
## Languages
|
## Languages
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| 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<br>Cited UCD-001<br>Justified the qualitative cost-benefit; stakeholder roles replaced by interests; success criteria 2 and 3 reworded for optional GitHub<br>Added objective 7 (documentation) and its success criterion | [02875ae] |
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Optional GitHub; choosing GitHub applies the AGPL license to the Gitea repository<br>Cited UCD-001<br>Justified the qualitative cost-benefit; stakeholder roles replaced by interests; success criteria 2 and 3 reworded for optional GitHub<br>Added objective 7 (documentation) and its success criterion | [02875ae] |
|
||||||
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Added objective 8 (project details preset in config.env), the matching scope item and success criterion 8 | [2a6bb8e] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -41,6 +41,7 @@ One repeatable, reviewed procedure gives every new project the same secure basel
|
|||||||
5. Add the SQA-QC-Framework as the `framework` submodule, install its skills and git hooks, and copy its templates, optionally enabling the plan gate.
|
5. Add the SQA-QC-Framework as the `framework` submodule, install its skills and git hooks, and copy its templates, optionally enabling the plan gate.
|
||||||
6. Never print or persist a token, and never overwrite existing files or directories without consent.
|
6. Never print or persist a token, 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.
|
7. Document installation, configuration, usage, security decisions and error handling in clear English for GitHub readers.
|
||||||
|
8. Let the Maintainer preset the project details in `config.env`, so that a detail that is set there is not asked again.
|
||||||
|
|
||||||
## Scope
|
## Scope
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ One repeatable, reviewed procedure gives every new project the same secure basel
|
|||||||
|
|
||||||
- `create-project.sh`, `config.env.example`, `.env.example`, `.gitignore` and `README.md`.
|
- `create-project.sh`, `config.env.example`, `.env.example`, `.gitignore` and `README.md`.
|
||||||
- Safe parsing and validation of `config.env` and `.env` (never `source`d).
|
- Safe parsing and validation of `config.env` and `.env` (never `source`d).
|
||||||
- Prompts for name, description, visibility and owner on each chosen host, and whether to use GitHub (which also applies the AGPL license).
|
- Prompts for name, description, visibility and owner on each chosen host, and whether to use GitHub (which also applies the AGPL license). Each of these details may be set in `config.env` instead and is then not asked.
|
||||||
- Checks for required tools (`git`, `curl`, optional `jq`) before any change.
|
- Checks for required tools (`git`, `curl`, optional `jq`) before any change.
|
||||||
- A check that the project name is not already taken on GitHub.
|
- A check that the project name is not already taken on GitHub.
|
||||||
- Partial-failure reporting with a documented way to continue.
|
- Partial-failure reporting with a documented way to continue.
|
||||||
@@ -89,6 +90,7 @@ Supports developing on self-hosted Gitea while publishing to GitHub, and adoptin
|
|||||||
| 5 | No overwrite | An existing directory or file is never replaced without a yes | Run twice in the same location |
|
| 5 | No overwrite | An existing directory or file is never replaced without a yes | Run twice in the same location |
|
||||||
| 6 | Lint | `shellcheck` reports no errors on `create-project.sh` | `shellcheck create-project.sh` |
|
| 6 | Lint | `shellcheck` reports no errors on `create-project.sh` | `shellcheck create-project.sh` |
|
||||||
| 7 | Documentation | `README.md` covers installation, configuration, usage, security decisions, error handling and stakeholders | Review by S02 against MIL-003 Go/No-Go criterion 6 |
|
| 7 | Documentation | `README.md` covers installation, configuration, usage, security decisions, error handling and stakeholders | Review by S02 against MIL-003 Go/No-Go criterion 6 |
|
||||||
|
| 8 | Preset details | A project detail set in `config.env` is never asked; an invalid one stops the run before any request and names the key | Tests with each key set, absent, empty and invalid |
|
||||||
|
|
||||||
## Risks
|
## Risks
|
||||||
|
|
||||||
@@ -138,5 +140,5 @@ Proceed — the procedure is small, well bounded and removes a repeated, securit
|
|||||||
|
|
||||||
[SA-001]: ./stakeholder-analysis.md
|
[SA-001]: ./stakeholder-analysis.md
|
||||||
[UCD-001]: ./use-case-diagram.md
|
[UCD-001]: ./use-case-diagram.md
|
||||||
[424f14f]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/424f14f4f5577bb47fea41c8f3a655dca953e6d8
|
|
||||||
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
||||||
|
[2a6bb8e]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/2a6bb8e8afadfe6ca4a621da30e44a372898ca62
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Initial version, created from [DM-001] (UC-001) | [02875ae] |
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Initial version, created from [DM-001] (UC-001) | [02875ae] |
|
||||||
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Configuration may hold preset project details (from DM-001, UC-001 step 3) | [2a6bb8e] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -31,7 +32,9 @@ class Project {
|
|||||||
description
|
description
|
||||||
visibility
|
visibility
|
||||||
}
|
}
|
||||||
class Configuration
|
class Configuration {
|
||||||
|
preset project details
|
||||||
|
}
|
||||||
class "Git Host" as GitHost {
|
class "Git Host" as GitHost {
|
||||||
name
|
name
|
||||||
web address
|
web address
|
||||||
@@ -115,7 +118,7 @@ Summary "1" --> "1" Project : reports on
|
|||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| Maintainer | The person who creates a new project (S01 or S02) | name | [UC-001] primary actor |
|
| Maintainer | The person who creates a new project (S01 or S02) | name | [UC-001] primary actor |
|
||||||
| Project | The new software project being set up | name, description, visibility | [UC-001] "new project", step 3 |
|
| Project | The new software project being set up | name, description, visibility | [UC-001] "new project", step 3 |
|
||||||
| Configuration | The service addresses and access tokens the Maintainer has set up before starting | none | [UC-001] precondition, step 2 "configuration and credentials" |
|
| Configuration | The service addresses and access tokens the Maintainer has set up before starting, and any project details preset in it | preset project details (optional) | [UC-001] precondition, steps 2 and 3 |
|
||||||
| Git Host | A service that holds repositories: Gitea or GitHub | name, web address, API address | [UC-001] steps 5 to 7 "GitHub", "Gitea" |
|
| Git Host | A service that holds repositories: Gitea or GitHub | name, web address, API address | [UC-001] steps 5 to 7 "GitHub", "Gitea" |
|
||||||
| Access Token | A secret that lets the Maintainer act on a Git Host; it is never part of an address | kind | [UC-001] precondition "Gitea token", "GitHub PAT" |
|
| Access Token | A secret that lets the Maintainer act on a Git Host; it is never part of an address | kind | [UC-001] precondition "Gitea token", "GitHub PAT" |
|
||||||
| Owner | The user or organization on a Git Host that owns repositories | name, kind (user or organization) | [UC-001] step 3 "owner" |
|
| Owner | The user or organization on a Git Host that owns repositories | name, kind (user or organization) | [UC-001] step 3 "owner" |
|
||||||
@@ -170,3 +173,4 @@ Summary "1" --> "1" Project : reports on
|
|||||||
[DICT-001]: ./dictionary.md
|
[DICT-001]: ./dictionary.md
|
||||||
[DM-001]: ./uc-001/dm.md
|
[DM-001]: ./uc-001/dm.md
|
||||||
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
||||||
|
[2a6bb8e]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/2a6bb8e8afadfe6ca4a621da30e44a372898ca62
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| 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<br>Cited US-001.02<br>Purpose and criterion 1 reworded for optional GitHub<br>Target date accepted | [02875ae] |
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Optional GitHub; choosing GitHub applies the AGPL license to the Gitea repository<br>Cited US-001.02<br>Purpose and criterion 1 reworded for optional GitHub<br>Target date accepted | [02875ae] |
|
||||||
|
| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Criterion 2 corrected after the live run: Gitea also adds a README.md with the license | [613a288] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ Decide whether the script creates the Gitea repository and, if GitHub is chosen,
|
|||||||
| # | Criterion (objectively checkable) | Go | No-Go |
|
| # | Criterion (objectively checkable) | Go | No-Go |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| 1 | Repositories are created under the owner chosen at the prompt, for a user owner and for an organization owner, on each host used | Both verified | Any under the wrong owner |
|
| 1 | Repositories are created under the owner chosen at the prompt, for a user owner and for an organization owner, on each host used | Both verified | Any under the wrong owner |
|
||||||
| 2 | The GitHub repository is created empty. The Gitea repository holds only the AGPL license file when GitHub is chosen, otherwise it is empty. Neither has a generated README or `.gitignore` | Verified | Any other commit present |
|
| 2 | The GitHub repository is created empty. The Gitea repository holds only the AGPL license file and the `README.md` that Gitea generates for it when GitHub is chosen, otherwise it is empty. Neither has a `.gitignore` | Verified | Any other file present |
|
||||||
| 3 | When GitHub is chosen, a commit pushed to Gitea (including the license file) appears on GitHub; nothing flows the other way. When GitHub is not chosen, no GitHub call is made | Verified | Wrong direction, no sync, or a GitHub call without the choice |
|
| 3 | When GitHub is chosen, a commit pushed to Gitea (including the license file) appears on GitHub; nothing flows the other way. When GitHub is not chosen, no GitHub call is made | Verified | Wrong direction, no sync, or a GitHub call without the choice |
|
||||||
| 4 | Mirror credentials are never part of a remote URL, log or output | None found | Any found |
|
| 4 | Mirror credentials are never part of a remote URL, log or output | None found | Any found |
|
||||||
| 5 | With an invalid token on one host, the script stops before creating anything or reports exactly what was created and how to continue | Verified | Silent or misleading |
|
| 5 | With an invalid token on one host, the script stops before creating anything or reports exactly what was created and how to continue | Verified | Silent or misleading |
|
||||||
@@ -76,5 +76,5 @@ Decide whether the script creates the Gitea repository and, if GitHub is chosen,
|
|||||||
[US-001]: ../user-stories.md
|
[US-001]: ../user-stories.md
|
||||||
[UC-001]: ../uc-001/uc.md
|
[UC-001]: ../uc-001/uc.md
|
||||||
[MIL-001]: ./mil-001-foundation.md
|
[MIL-001]: ./mil-001-foundation.md
|
||||||
[424f14f]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/424f14f4f5577bb47fea41c8f3a655dca953e6d8
|
|
||||||
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
||||||
|
[613a288]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/613a288dead4c19c00dee6fbb60d46bc3edf8889
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
# MIL-004 Configurable Details
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | MIL-004 |
|
||||||
|
| CrossReference | [BC-001], [US-001], [UC-001] |
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Initial version | [2a6bb8e] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Decide whether the project details can be preset in `config.env` without weakening the safety questions: a detail that is set there is not asked, an invalid one stops the run, and the confirmations stay interactive.
|
||||||
|
|
||||||
|
## Deliverable
|
||||||
|
|
||||||
|
`create-project.sh` that reads eight optional keys from `config.env`, checks them with the same rules as the prompts, skips the prompt for each key that is set and marks that value as coming from the configuration in the summary. `config.env.example` and the README document the keys. The tests cover every key.
|
||||||
|
|
||||||
|
The keys (a key that is present counts as set, even when empty, but only the description may be empty):
|
||||||
|
|
||||||
|
| Key | Detail | Accepted value |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `PROJECT_NAME` | repository name | the repository name rules of the prompt |
|
||||||
|
| `PROJECT_DESCRIPTION` | description | up to 350 characters, no control characters; may be empty |
|
||||||
|
| `PROJECT_VISIBILITY` | visibility | `private` or `public` |
|
||||||
|
| `GITEA_OWNER` | Gitea owner (user or organization) | the Gitea owner rules of the prompt |
|
||||||
|
| `USE_GITHUB` | also create a GitHub repository | `yes` or `no` |
|
||||||
|
| `GITHUB_OWNER` | GitHub owner (user or organization) | the GitHub owner rules; used only when GitHub is used |
|
||||||
|
| `PROJECT_DIRECTORY` | local directory | the directory rules of the prompt |
|
||||||
|
| `ENABLE_PLAN_GATE` | enable the plan gate | `yes` or `no` |
|
||||||
|
|
||||||
|
## Go / No-Go Criteria
|
||||||
|
|
||||||
|
| # | Criterion (objectively checkable) | Go | No-Go |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 1 | For each of the eight keys: when it is present its prompt is not shown and its value is used and shown in the summary as coming from `config.env` | Tests pass | Any prompt shown or value ignored |
|
||||||
|
| 2 | A key that is absent is asked as before; asked and preset details can be mixed | Tests pass | Any asked wrongly |
|
||||||
|
| 3 | A present but empty value is accepted for `PROJECT_DESCRIPTION` and refused, naming the key, for the other seven | Tests pass | Any other result |
|
||||||
|
| 4 | An invalid value stops the run before any request to a host, names the key, and never falls back to asking | Tests pass | A request made or a prompt shown |
|
||||||
|
| 5 | `USE_GITHUB=no` skips the GitHub owner and the GitHub steps; a `GITHUB_OWNER` set while GitHub is not used is ignored with a warning | Tests pass | Any GitHub call or owner prompt |
|
||||||
|
| 6 | With all eight keys set, the only questions left are the confirmations: create now, reuse of an existing repository, directory, hooks path or file, each still defaulting to no | Tests pass | A confirmation skipped |
|
||||||
|
| 7 | The new keys are rejected in `.env`, and credentials are still rejected in `config.env` | Tests pass | Any accepted |
|
||||||
|
| 8 | All acceptance criteria of US-001.04 in [US-001] are met | Verified | Any unmet |
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
| Depends on | Reason |
|
||||||
|
| --- | --- |
|
||||||
|
| [MIL-003] | Needs the complete prompt and apply flow to change |
|
||||||
|
|
||||||
|
## Traceability
|
||||||
|
|
||||||
|
| Business Case objective / KPI / user story | Reference |
|
||||||
|
| --- | --- |
|
||||||
|
| User story US-001.04 | [US-001] |
|
||||||
|
| Objective 8 (details preset in `config.env`) | [BC-001] |
|
||||||
|
| Success criterion 8 | [BC-001] |
|
||||||
|
|
||||||
|
## Ownership
|
||||||
|
|
||||||
|
| Role | Stakeholder ID (SA) |
|
||||||
|
| --- | --- |
|
||||||
|
| Owner | S01 |
|
||||||
|
| Approving reviewer | S02 |
|
||||||
|
|
||||||
|
## Target Date
|
||||||
|
|
||||||
|
2026-11-20 — proposed; the Business Case sets no deadline.
|
||||||
|
|
||||||
|
## Tasks
|
||||||
|
|
||||||
|
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| 1 | Read and validate the eight optional config keys | Add `PROJECT_NAME`, `PROJECT_DESCRIPTION`, `PROJECT_VISIBILITY`, `GITEA_OWNER`, `USE_GITHUB`, `GITHUB_OWNER`, `PROJECT_DIRECTORY` and `ENABLE_PLAN_GATE` to the `config.env` parser, checked with the validators the prompts use. A present key counts as set; only the description may be empty. Errors name the key. The new keys are rejected in `.env`; credentials stay rejected in `config.env`. | Yes | [UC-001] |
|
||||||
|
| 2 | Use configured details instead of asking, and show their source | In the step that collects the details, take each configured value instead of asking and mark it `(from config.env)` in the summary. `USE_GITHUB=no` skips the GitHub owner; a `GITHUB_OWNER` set while GitHub is not used is ignored with a warning. Extension 3a of UC-001. | Yes | [UC-001] |
|
||||||
|
| 3 | Keep the confirmations interactive | Create now, reuse of an existing repository, directory, hooks path and template files stay questions that default to no, even when every detail is configured. Add tests that prove no run creates or replaces anything without them, because this is where a configurable run could weaken the rule never to overwrite without a yes. | No | |
|
||||||
|
| 4 | Document the keys | Add commented examples to `config.env.example` and a table of the keys to the README, with an example of a run in which only the confirmations are asked, and a note that a key that is present but empty counts as set. | No | |
|
||||||
|
| 5 | Test every key and case | Each key set, absent, empty and invalid; mixed asked and preset details; the `USE_GITHUB` interplay; the source marking in the summary; no prompt text shown for a preset detail; the existing tests unchanged. | No | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[BC-001]: ../business-case.md
|
||||||
|
[US-001]: ../user-stories.md
|
||||||
|
[UC-001]: ../uc-001/uc.md
|
||||||
|
[MIL-003]: ./mil-003-scaffold-and-release.md
|
||||||
|
[2a6bb8e]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/2a6bb8e8afadfe6ca4a621da30e44a372898ca62
|
||||||
+11
-6
@@ -4,23 +4,23 @@
|
|||||||
| Key | Value |
|
| Key | Value |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| ID | PP-001 |
|
| ID | PP-001 |
|
||||||
| CrossReference | [BC-001], [SA-001], [MIL-001], [MIL-002], [MIL-003], [US-001] |
|
| CrossReference | [BC-001], [SA-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [US-001] |
|
||||||
|
|
||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| 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 | Stories per phase: US-001.01 to US-001.03<br>Dates accepted | [02875ae] |
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Stories per phase: US-001.01 to US-001.03<br>Dates accepted | [02875ae] |
|
||||||
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Added phase MIL-004 (proposed dates 2026-11-16 to 2026-11-20) | [2a6bb8e] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|
||||||
Schedule the three 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 four 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
|
## Planning Assumptions
|
||||||
|
|
||||||
- Week 1 starts 2026-10-05; the plan ends by 2026-11-13.
|
- Week 1 starts 2026-10-05; the plan ends by 2026-11-20 (the last phase is proposed).
|
||||||
- Phase length: two weeks.
|
- 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.
|
- 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.
|
- The PO language is English, so no translated copies are kept.
|
||||||
@@ -32,6 +32,7 @@ Schedule the three phases that deliver RepoFoundry (`create-project.sh` and its
|
|||||||
| Foundation | [MIL-001] | 2026-10-05 to 2026-10-16 | 2026-10-16 | S01 | US-001.01 | Safe skeleton, config parsing, prompts, tests | [Milestone 43] |
|
| Foundation | [MIL-001] | 2026-10-05 to 2026-10-16 | 2026-10-16 | S01 | US-001.01 | Safe skeleton, config parsing, prompts, tests | [Milestone 43] |
|
||||||
| Repositories and Mirror | [MIL-002] | 2026-10-19 to 2026-10-30 | 2026-10-30 | S02 | US-001.02 | GitHub and Gitea repositories and the push mirror | [Milestone 44] |
|
| Repositories and Mirror | [MIL-002] | 2026-10-19 to 2026-10-30 | 2026-10-30 | S02 | US-001.02 | GitHub and Gitea repositories and the push mirror | [Milestone 44] |
|
||||||
| Scaffold and Release | [MIL-003] | 2026-11-02 to 2026-11-13 | 2026-11-13 | S01 | US-001.03 | Local project, framework, README, final review | [Milestone 45] |
|
| Scaffold and Release | [MIL-003] | 2026-11-02 to 2026-11-13 | 2026-11-13 | S01 | US-001.03 | Local project, framework, README, final review | [Milestone 45] |
|
||||||
|
| Configurable Details | [MIL-004] | 2026-11-16 to 2026-11-20 | 2026-11-20 | S01 | US-001.04 | Project details preset in config.env | |
|
||||||
|
|
||||||
```plantuml
|
```plantuml
|
||||||
@startgantt
|
@startgantt
|
||||||
@@ -42,6 +43,8 @@ Project starts 2026-10-05
|
|||||||
[Repositories and Mirror Go/No-Go] happens 2026-10-30
|
[Repositories and Mirror Go/No-Go] happens 2026-10-30
|
||||||
[Scaffold and Release] starts 2026-11-02 and ends 2026-11-13
|
[Scaffold and Release] starts 2026-11-02 and ends 2026-11-13
|
||||||
[Scaffold and Release Go/No-Go] happens 2026-11-13
|
[Scaffold and Release Go/No-Go] happens 2026-11-13
|
||||||
|
[Configurable Details] starts 2026-11-16 and ends 2026-11-20
|
||||||
|
[Configurable Details Go/No-Go] happens 2026-11-20
|
||||||
@endgantt
|
@endgantt
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -55,11 +58,12 @@ Project starts 2026-10-05
|
|||||||
| Partial-failure reporting | [MIL-002] |
|
| Partial-failure reporting | [MIL-002] |
|
||||||
| Local directory, remotes, framework submodule, skills, hooks, templates, plan gate | [MIL-003] |
|
| Local directory, remotes, framework submodule, skills, hooks, templates, plan gate | [MIL-003] |
|
||||||
| README and SSH prerequisite documentation | [MIL-003] |
|
| README and SSH prerequisite documentation | [MIL-003] |
|
||||||
|
| Project details set in `config.env` instead of asked | [MIL-004] |
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
```
|
```
|
||||||
MIL-001 → MIL-002 → MIL-003
|
MIL-001 → MIL-002 → MIL-003 → MIL-004
|
||||||
```
|
```
|
||||||
|
|
||||||
A No-Go moves every later date by the time needed to rework the failed criteria.
|
A No-Go moves every later date by the time needed to rework the failed criteria.
|
||||||
@@ -86,11 +90,12 @@ A No-Go moves every later date by the time needed to rework the failed criteria.
|
|||||||
[MIL-001]: ./milestones/mil-001-foundation.md
|
[MIL-001]: ./milestones/mil-001-foundation.md
|
||||||
[MIL-002]: ./milestones/mil-002-repositories-and-mirror.md
|
[MIL-002]: ./milestones/mil-002-repositories-and-mirror.md
|
||||||
[MIL-003]: ./milestones/mil-003-scaffold-and-release.md
|
[MIL-003]: ./milestones/mil-003-scaffold-and-release.md
|
||||||
|
[MIL-004]: ./milestones/mil-004-configurable-details.md
|
||||||
[US-001]: ./user-stories.md
|
[US-001]: ./user-stories.md
|
||||||
[UC-001]: ./uc-001/uc.md
|
[UC-001]: ./uc-001/uc.md
|
||||||
[SSD-001]: ./uc-001/ssd.md
|
[SSD-001]: ./uc-001/ssd.md
|
||||||
[424f14f]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/424f14f4f5577bb47fea41c8f3a655dca953e6d8
|
|
||||||
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
||||||
[Milestone 43]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/milestone/43
|
[Milestone 43]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/milestone/43
|
||||||
[Milestone 44]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/milestone/44
|
[Milestone 44]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/milestone/44
|
||||||
[Milestone 45]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/milestone/45
|
[Milestone 45]: https://git.tirsystem.com/TirSystem-BashScript/RepoFoundry/milestone/45
|
||||||
|
[2a6bb8e]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/2a6bb8e8afadfe6ca4a621da30e44a372898ca62
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
# SQA Review Record: End-to-end test and final security review (MIL-003)
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | RC-017 |
|
||||||
|
| CrossReference | [MIL-003], [MIL-002], [RC-016] |
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | [613a288] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Artifact Under Review
|
||||||
|
|
||||||
|
- Instance reviewed: the whole flow of `src/create-project.sh` (branch `mil-003-scaffold-and-release` plus the fixes below), run against real GitHub and Gitea repositories; this is task 6 (issue #20) of [MIL-003] and the live evidence for [MIL-002].
|
||||||
|
- Checklist used: the Go/No-Go criteria of [MIL-003] and the credential, ownership, mirror, submodule and API items named in its task 6. No QC checklist covers an end-to-end run; the code itself was reviewed in [RC-016].
|
||||||
|
- Review date: 2026-10-05
|
||||||
|
- Hosts: Gitea 1.27.3 at `git.tirsystem.com` (SSH on port 10022) and GitHub; real tokens from `.env` (a classic GitHub token with `repo` and `admin:org`; a Gitea token with `write:repository`, `write:organization`, `read:user` and other scopes, but not `write:user`).
|
||||||
|
|
||||||
|
## End-to-end runs
|
||||||
|
|
||||||
|
| Run | Owners | Result |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Dry run | `Tirsvad` on both hosts | All preflight checks passed; nothing created. |
|
||||||
|
| First `--apply` | `Tirsvad` on both hosts | Stopped before creating anything: **a defect** (see finding F1). |
|
||||||
|
| A, after the fix | user `Tirsvad` on both hosts | GitHub repository created. Gitea refused: `required=[write:user]`, which the token lacks. The script stopped, reported what existed (GitHub created, Gitea FAILED, the rest not attempted) and how to continue, and deleted nothing. |
|
||||||
|
| B | organization `TirSystem-BashScript` on both hosts, plan gate on | Everything created: both repositories, the mirror, the local project, the framework, skills, hooks, plan gate and templates. No warning. |
|
||||||
|
|
||||||
|
After run B the following was checked independently of the script's own report:
|
||||||
|
|
||||||
|
- **Gitea:** private, owner the organization, default branch `main`, contents `LICENSE` and `README.md`; push mirror to `https://github.com/TirSystem-BashScript/repofoundry-e2e-org.git`, interval `10m0s`, `sync_on_commit` true, `last_error` empty.
|
||||||
|
- **GitHub:** private, owner the organization, contents `LICENSE` and `README.md`, one commit `Initial commit` (arrived through the mirror).
|
||||||
|
- **Local project:** on `main` with that one commit as its whole history, tracking `origin`; `origin` is `ssh://git@git.tirsystem.com:10022/TirSystem-BashScript/repofoundry-e2e-org.git` and `github` is `https://github.com/TirSystem-BashScript/repofoundry-e2e-org.git`; the submodule `framework` comes from `ssh://git@git.tirsystem.com:10022/TirSystem/SQA-QC-Framework.git`; `core.hooksPath` is `framework/githooks` and `planGate.enabled` is true; skills are installed for both harnesses; `AGENTS.md` equals the framework template; no commit was made by the script.
|
||||||
|
- **Hooks and gate, for real:** a commit on `main` was refused ("refusing to commit directly on 'main'"); a `src/` change without a `Task:` trailer on a branch was refused ("plan-first gate"); a documentation-only commit on a branch was accepted.
|
||||||
|
- **Mirror direction, for real:** that commit was pushed to Gitea over SSH and the branch `work` appeared on GitHub within seconds, without a manual sync.
|
||||||
|
|
||||||
|
## Checklist Results (MIL-003 Go/No-Go)
|
||||||
|
|
||||||
|
| # | Criterion | Status | Evidence/Notes |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 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 | Pass | Run B: configured addresses above, credential-free; history is the Gitea 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 | Pass | Run B: `.gitmodules` holds that address; skills, then hooks, then templates; each once. |
|
||||||
|
| 3 | An existing directory, `AGENTS.md` or `docs/artifact-registry.md` is never overwritten without a yes | Pass | Verified by the automated tests with real git (existing directory, conflicting `LICENSE`, existing templates); not repeated on the real hosts. |
|
||||||
|
| 4 | With the plan gate enabled, a commit touching `src/` or `tests/` without a `Task: MIL-NNN#N` trailer is refused | Pass | Run B, for real. |
|
||||||
|
| 5 | An existing `core.hooksPath` is reported and not replaced without consent | Pass | Verified by the automated tests with real git (local and global setting); not repeated on the real hosts. |
|
||||||
|
| 6 | README covers installation, configuration, usage examples, security decisions, error handling and stakeholders, in clear English | N-A | The sections are written; the review by S02 has not happened yet (action item). |
|
||||||
|
| 7 | End-to-end run on disposable repositories passes and the final review records no open security finding | Fail | No open security finding, and the organization-owner run passes on both hosts. The user-owner run could not be completed on Gitea (token scope). |
|
||||||
|
| 8 | All acceptance criteria of US-001.03 in [US-001] are met | Pass | Run B: remotes without credentials, framework, skills, hooks, plan gate and templates in place; the "asks first" criterion by the automated tests. |
|
||||||
|
|
||||||
|
## Final security review
|
||||||
|
|
||||||
|
| Item | Result | Evidence |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Credential handling | No finding | Both tokens were searched for in every file of the new project, including the whole `.git` folder, and in all output of all runs: zero hits. Remote addresses and `.gitmodules` carry no credential. Tokens went to `curl` through a private configuration file and, for an HTTPS fetch, to git through `GIT_ASKPASS` and the environment (covered by tests; the live runs used SSH). |
|
||||||
|
| Repository ownership | No finding | Created under the owner chosen at the prompt on both hosts (organization in run B; GitHub user in run A). `GITHUB_USER` was only a default. |
|
||||||
|
| Mirror direction | No finding | Gitea is the source: a branch pushed to Gitea reached GitHub on its own. Nothing was pushed from GitHub; that direction was not tested. |
|
||||||
|
| Submodule setup | No finding | Added over SSH on port 10022 from the configured framework repository; the SSH test and the host key check passed. |
|
||||||
|
| API limitations | Findings F2 to F4 | `sync_on_commit` was applied on Gitea 1.27.3 (the upstream bug did not occur). Token scopes and the README Gitea adds are covered below. |
|
||||||
|
| Residual risks | Accepted, documented | The mirror password (the GitHub token) is stored by the Gitea server. The tokens used here are broad (for example `admin:org` on GitHub); tokens limited to what the script needs would reduce the damage of a leak. |
|
||||||
|
|
||||||
|
## Findings
|
||||||
|
|
||||||
|
| # | Finding | Severity | Status |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| F1 | The real `ssh` used for the SSH test reads standard input and swallowed the answers meant for later prompts, so a run that was piped or pasted stopped before creating anything. The test stub did not read stdin, so no test could see it. | Defect (no data lost) | Fixed: stdin is closed for `ssh`, `git`, `curl` and the framework scripts; the test stub now reads stdin like the real tool; a regression test fails without the fix. |
|
||||||
|
| F2 | Gitea adds a generated `README.md` next to the `LICENSE`. The script, the README and MIL-002 criterion 2 assumed only the license. A repository this script created was therefore counted as "has content" and could not be reused after a partial failure. | Defect | Fixed: `LICENSE` and `LICENSE` + `README.md` count as content created by the script; any other file still counts as content; tests added; README corrected. MIL-002 criterion 2 corrected (new `Proposed` version row, to be accepted). |
|
||||||
|
| F3 | Creating a repository under one's own Gitea account needs the `write:user` scope, not `write:repository`. | Documentation | Fixed in the README, marked as confirmed by the server. |
|
||||||
|
| F4 | Documentation had marked two scopes "not confirmed". Result: `write:user` is needed for user-owned Gitea repositories (F3); organization-owned repositories worked with `write:organization`, `write:repository` and `read:user`, and the minimum was not narrowed down; the GitHub membership check worked with `repo` and `admin:org`, `read:org` alone was not tested. | Documentation | README updated with what was observed. |
|
||||||
|
|
||||||
|
## Files created and external prerequisites
|
||||||
|
|
||||||
|
The script creates, in the new project: `.git`, `.gitmodules`, `framework/` (submodule), `.agents/skills/` and `.claude/skills/`, `AGENTS.md`, `docs/artifact-registry.md`, and (through the Gitea history) `LICENSE` and `README.md`. It never deletes anything.
|
||||||
|
|
||||||
|
External prerequisites: bash 4.4 or later, `git`, `curl`, `mktemp`; optional `jq` and `ssh`. An SSH key in the Gitea account and a known host key for `git.tirsystem.com` port 10022 (the script refuses unknown host keys). A GitHub token that can create repositories and push (classic `repo`), only when GitHub is chosen. A Gitea token with `write:repository`, `write:organization` and `read:user`, plus `write:user` for a repository under one's own account. Push mirrors must be enabled on the Gitea server.
|
||||||
|
|
||||||
|
## Disposable resources left in place (nothing was deleted)
|
||||||
|
|
||||||
|
- Gitea: `TirSystem-BashScript/repofoundry-e2e-org` (private; branches `main` and `work`).
|
||||||
|
- GitHub: `TirSystem-BashScript/repofoundry-e2e-org` (private; branches `main` and `work`).
|
||||||
|
- GitHub: `Tirsvad/repofoundry-e2e-user` (private, empty; created by run A).
|
||||||
|
- A local temporary directory with the run output and the new project.
|
||||||
|
|
||||||
|
## Overall Verdict
|
||||||
|
|
||||||
|
Go-with-conditions — No open security finding, the organization-owner flow works end to end on both hosts, and the two defects the live run found are fixed with regression tests. Criterion 6 awaits the README review, and criterion 7 is not complete because the user-owner run could not finish on Gitea without `write:user`. Author and reviewer are the same person for now (S01 and S02 are both held by the Maintainer), so the framework independence rule is not met; re-review when a second person takes S02.
|
||||||
|
|
||||||
|
## Action Items
|
||||||
|
|
||||||
|
| Action | Owner | Due |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Create a Gitea token that also has `write:user` and repeat run A (the empty GitHub repository `Tirsvad/repofoundry-e2e-user` is offered for reuse) to complete criterion 7 | S01 | 2026-10-16 |
|
||||||
|
| Review the README against criterion 6 | S02 | 2026-10-12 |
|
||||||
|
| Accept the corrected criterion 2 of [MIL-002] (version row `Proposed`) | S02 | 2026-10-12 |
|
||||||
|
| Delete the disposable repositories listed above in the web interfaces | S01 | 2026-10-12 |
|
||||||
|
| Run `tests/run-tests.sh` on Linux and macOS (carried over from [RC-016]) | S02 | 2026-10-30 |
|
||||||
|
| Consider tokens limited to what the script needs, for the Gitea and GitHub accounts used with it | S02 | 2026-10-30 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[MIL-003]: ../../milestones/mil-003-scaffold-and-release.md
|
||||||
|
[MIL-002]: ../../milestones/mil-002-repositories-and-mirror.md
|
||||||
|
[RC-016]: ./rc-016-create-project-sh.md
|
||||||
|
[US-001]: ../../user-stories.md
|
||||||
|
[613a288]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/613a288dead4c19c00dee6fbb60d46bc3edf8889
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
# SQA Review Record: MIL-004 and the planning change it causes
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | RC-018 |
|
||||||
|
| CrossReference | [MIL-004], [QC-MIL-001], [US-001], [UC-001] |
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | [2a6bb8e] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Artifact Under Review
|
||||||
|
|
||||||
|
- Instance reviewed: [MIL-004], and the changes it causes in [BC-001], [US-001], [UC-001], [SSD-001], [OC-001], [SD-001], [DM-001], [DM-002] and [PP-001].
|
||||||
|
- Checklist used: [QC-MIL-001] for [MIL-004]. The other artifacts were changed, not created; their change is checked below for consistency with the checklists of their types (user story, use case, SSD, operation contract, sequence diagram, domain model) and with the PP reference.
|
||||||
|
- Review date: 2026-10-05
|
||||||
|
|
||||||
|
## Checklist Results ([MIL-004], QC-MIL-001)
|
||||||
|
|
||||||
|
| # | Criterion | Status | Evidence/Notes |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 1 | A concrete deliverable is defined for every gate | Pass | The script reads eight optional keys, skips their prompts and marks the source; the example config and the README document the keys; tests cover each key. |
|
||||||
|
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Eight criteria, each with an objective Go and No-Go, including all acceptance criteria of US-001.04. |
|
||||||
|
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Depends on [MIL-003], with the reason. |
|
||||||
|
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Maps to objective 8 and success criterion 8 of [BC-001], and to US-001.04. |
|
||||||
|
| 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-11-20 matches [PP-001]; the Business Case sets no duration, so nothing conflicts. The date is a proposal and is accepted here. |
|
||||||
|
|
||||||
|
## Change checks on the other artifacts
|
||||||
|
|
||||||
|
| Artifact | Change | Status | Evidence/Notes |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| [BC-001] | Objective 8, scope item, success criterion 8 | Pass | The criterion is measurable (tests with each key set, absent, empty and invalid). |
|
||||||
|
| [US-001] | US-001.04 with four acceptance criteria | Pass | Given/when/then; traces to [UC-001] step 3 and [MIL-004]; size and INVEST exception recorded. |
|
||||||
|
| [UC-001] | Precondition, step 3 note, extensions 3a and 3b, business rule | Pass | Extensions name the failure (invalid key) and the outcome (stop before any request, no fallback to asking). |
|
||||||
|
| [SSD-001] | Parameters of `provideProjectDetails` may come from `config.env` | Pass | The message itself is unchanged, so the diagram is unchanged. |
|
||||||
|
| [OC-001] | Preset details are part of the Configuration | Pass | Postcondition and rule added; no new operation. |
|
||||||
|
| [SD-001] | Note that `ConfigLoader` reads and validates the preset details | Pass | The second sequence is unchanged because the arguments are the same whether asked or preset. |
|
||||||
|
| [DM-001], [DM-002] | `Configuration` may hold preset project details | Pass | Both models changed in the same way and the project model stays consistent with the use-case model, as the project rule requires. Dictionary unchanged: no new term. |
|
||||||
|
| [PP-001] | Phase [MIL-004], dependency chain and timeline | Pass | Dates agree with [MIL-004]; scope table and Gantt updated. |
|
||||||
|
|
||||||
|
## Overall Verdict
|
||||||
|
|
||||||
|
Go — [MIL-004] passes every mandatory criterion and the changes to the other artifacts are consistent with each other and with the Business Case. Author and reviewer are the same person for now (S01 and S02 are both held by the Maintainer), so the framework independence rule is not met; re-review when a second person takes S02.
|
||||||
|
|
||||||
|
## Action Items
|
||||||
|
|
||||||
|
| Action | Owner | Due |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| None | - | - |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[MIL-004]: ../../milestones/mil-004-configurable-details.md
|
||||||
|
[BC-001]: ../../business-case.md
|
||||||
|
[US-001]: ../../user-stories.md
|
||||||
|
[UC-001]: ../../uc-001/uc.md
|
||||||
|
[SSD-001]: ../../uc-001/ssd.md
|
||||||
|
[OC-001]: ../../uc-001/oc.md
|
||||||
|
[SD-001]: ../../uc-001/sd.md
|
||||||
|
[DM-001]: ../../uc-001/dm.md
|
||||||
|
[DM-002]: ../../domain-model.md
|
||||||
|
[PP-001]: ../../project-plan.md
|
||||||
|
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||||
|
[2a6bb8e]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/2a6bb8e8afadfe6ca4a621da30e44a372898ca62
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version, UC-001 artifacts and baseline | [02875ae] |
|
| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version, UC-001 artifacts and baseline | [02875ae] |
|
||||||
|
| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Added MIL-004 and RC-018 | [2a6bb8e] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -23,14 +24,15 @@ updated whenever an artifact instance is created or reviewed.
|
|||||||
|
|
||||||
| Artifact Instance | Type | Upstream (Backward Link) | Downstream (Forward Link) | Last Reviewed (RC-ID) |
|
| 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], [US-001], [UCD-001] | [RC-010] |
|
| [BC-001] | BC | - | [SA-001], [PP-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [US-001], [UCD-001] | [RC-010], [RC-018] |
|
||||||
| [SA-001] | SA | [BC-001] | [UCD-001], [UC-001], [DICT-001] | [RC-013] |
|
| [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] | [RC-012] |
|
| [PP-001] | PP | [BC-001], [SA-001] | [MIL-001], [MIL-002], [MIL-003], [MIL-004] | [RC-012], [RC-018] |
|
||||||
| [MIL-001] | MIL | [BC-001], [PP-001] | [US-001] | [RC-011], [RC-016] |
|
| [MIL-001] | MIL | [BC-001], [PP-001] | [US-001] | [RC-011], [RC-016] |
|
||||||
| [MIL-002] | MIL | [BC-001], [PP-001] | [US-001] | [RC-014] |
|
| [MIL-002] | MIL | [BC-001], [PP-001] | [US-001] | [RC-014], [RC-017] |
|
||||||
| [MIL-003] | MIL | [BC-001], [PP-001] | [US-001] | [RC-015] |
|
| [MIL-003] | MIL | [BC-001], [PP-001] | [US-001] | [RC-015], [RC-017] |
|
||||||
|
| [MIL-004] | MIL | [BC-001], [PP-001] | [US-001] | [RC-018] |
|
||||||
| [UCD-001] | UCD | [BC-001], [SA-001] | [US-001], [UC-001] | [RC-009] |
|
| [UCD-001] | UCD | [BC-001], [SA-001] | [US-001], [UC-001] | [RC-009] |
|
||||||
| [US-001] | US | [BC-001], [UCD-001], [MIL-001], [MIL-002], [MIL-003] | [UC-001] | [RC-001] |
|
| [US-001] | US | [BC-001], [UCD-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004] | [UC-001] | [RC-001] |
|
||||||
| [UC-001] | UC | [UCD-001], [US-001], [SA-001] | [SSD-001], [DM-001] | [RC-002] |
|
| [UC-001] | UC | [UCD-001], [US-001], [SA-001] | [SSD-001], [DM-001] | [RC-002] |
|
||||||
| [SSD-001] | SSD | [UC-001] | [OC-001] | [RC-003] |
|
| [SSD-001] | SSD | [UC-001] | [OC-001] | [RC-003] |
|
||||||
| [DM-001] | DM | [UC-001], [SSD-001] | [DM-002], [DICT-001], [OC-001] | [RC-004] |
|
| [DM-001] | DM | [UC-001], [SSD-001] | [DM-002], [DICT-001], [OC-001] | [RC-004] |
|
||||||
@@ -52,6 +54,8 @@ updated whenever an artifact instance is created or reviewed.
|
|||||||
[MIL-001]: ../milestones/mil-001-foundation.md
|
[MIL-001]: ../milestones/mil-001-foundation.md
|
||||||
[MIL-002]: ../milestones/mil-002-repositories-and-mirror.md
|
[MIL-002]: ../milestones/mil-002-repositories-and-mirror.md
|
||||||
[MIL-003]: ../milestones/mil-003-scaffold-and-release.md
|
[MIL-003]: ../milestones/mil-003-scaffold-and-release.md
|
||||||
|
[MIL-004]: ../milestones/mil-004-configurable-details.md
|
||||||
|
[RC-018]: ./reviews/rc-018-mil-004.md
|
||||||
[UCD-001]: ../use-case-diagram.md
|
[UCD-001]: ../use-case-diagram.md
|
||||||
[US-001]: ../user-stories.md
|
[US-001]: ../user-stories.md
|
||||||
[UC-001]: ../uc-001/uc.md
|
[UC-001]: ../uc-001/uc.md
|
||||||
@@ -77,4 +81,6 @@ updated whenever an artifact instance is created or reviewed.
|
|||||||
[RC-014]: ./reviews/rc-014-mil-002.md
|
[RC-014]: ./reviews/rc-014-mil-002.md
|
||||||
[RC-015]: ./reviews/rc-015-mil-003.md
|
[RC-015]: ./reviews/rc-015-mil-003.md
|
||||||
[RC-016]: ./reviews/rc-016-create-project-sh.md
|
[RC-016]: ./reviews/rc-016-create-project-sh.md
|
||||||
|
[RC-017]: ./reviews/rc-017-e2e-security-review.md
|
||||||
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
||||||
|
[2a6bb8e]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/2a6bb8e8afadfe6ca4a621da30e44a372898ca62
|
||||||
|
|||||||
+6
-2
@@ -10,6 +10,7 @@
|
|||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Initial version | [02875ae] |
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Initial version | [02875ae] |
|
||||||
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Configuration may hold preset project details | [2a6bb8e] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -31,7 +32,9 @@ class Project {
|
|||||||
description
|
description
|
||||||
visibility
|
visibility
|
||||||
}
|
}
|
||||||
class Configuration
|
class Configuration {
|
||||||
|
preset project details
|
||||||
|
}
|
||||||
class "Git Host" as GitHost {
|
class "Git Host" as GitHost {
|
||||||
name
|
name
|
||||||
web address
|
web address
|
||||||
@@ -115,7 +118,7 @@ Summary "1" --> "1" Project : reports on
|
|||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| Maintainer | The person who creates a new project (S01 or S02) | name | [UC-001] primary actor |
|
| Maintainer | The person who creates a new project (S01 or S02) | name | [UC-001] primary actor |
|
||||||
| Project | The new software project being set up | name, description, visibility | [UC-001] "new project", step 3 |
|
| Project | The new software project being set up | name, description, visibility | [UC-001] "new project", step 3 |
|
||||||
| Configuration | The service addresses and access tokens the Maintainer has set up before starting | none | [UC-001] precondition, step 2 "configuration and credentials" |
|
| Configuration | The service addresses and access tokens the Maintainer has set up before starting, and any project details preset in it | preset project details (optional) | [UC-001] precondition, steps 2 and 3 |
|
||||||
| Git Host | A service that holds repositories: Gitea or GitHub | name, web address, API address | [UC-001] steps 5 to 7 "GitHub", "Gitea" |
|
| Git Host | A service that holds repositories: Gitea or GitHub | name, web address, API address | [UC-001] steps 5 to 7 "GitHub", "Gitea" |
|
||||||
| Access Token | A secret that lets the Maintainer act on a Git Host; it is never part of an address | kind | [UC-001] precondition "Gitea token", "GitHub PAT" |
|
| Access Token | A secret that lets the Maintainer act on a Git Host; it is never part of an address | kind | [UC-001] precondition "Gitea token", "GitHub PAT" |
|
||||||
| Owner | The user or organization on a Git Host that owns repositories | name, kind (user or organization) | [UC-001] step 3 "owner" |
|
| Owner | The user or organization on a Git Host that owns repositories | name, kind (user or organization) | [UC-001] step 3 "owner" |
|
||||||
@@ -170,3 +173,4 @@ Summary "1" --> "1" Project : reports on
|
|||||||
[DICT-001]: ../dictionary.md
|
[DICT-001]: ../dictionary.md
|
||||||
[DM-002]: ../domain-model.md
|
[DM-002]: ../domain-model.md
|
||||||
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
||||||
|
[2a6bb8e]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/2a6bb8e8afadfe6ca4a621da30e44a372898ca62
|
||||||
|
|||||||
+6
-3
@@ -10,6 +10,7 @@
|
|||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Initial version | [02875ae] |
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Initial version | [02875ae] |
|
||||||
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Project details may be defined by the Configuration | [2a6bb8e] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ Concepts below use the IT terms of [DICT-001] for the PO concepts of [DM-001]. `
|
|||||||
**Postconditions**
|
**Postconditions**
|
||||||
|
|
||||||
- P1. A `Run` instance was created.
|
- P1. A `Run` instance was created.
|
||||||
- P2. A `Configuration` instance was created from `config.env` and `.env`, with every value validated and the credentials held only in memory.
|
- P2. A `Configuration` instance was created from `config.env` and `.env`, with every value validated (including the project details preset in `config.env`) and the credentials held only in memory.
|
||||||
- P3. A `ToolCheck` instance was created and associated with the `Run`, recording that `git` and `curl` are present and whether `jq` is present.
|
- P3. A `ToolCheck` instance was created and associated with the `Run`, recording that `git` and `curl` are present and whether `jq` is present.
|
||||||
- P4. The `Run` was associated with a `PromptSet` that is returned.
|
- P4. The `Run` was associated with a `PromptSet` that is returned.
|
||||||
|
|
||||||
@@ -38,7 +39,7 @@ Concepts below use the IT terms of [DICT-001] for the PO concepts of [DM-001]. `
|
|||||||
|
|
||||||
| Condition (failing precondition) | Outcome |
|
| Condition (failing precondition) | Outcome |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `config.env` or `.env` is missing, or a value is missing or malformed | The `Run` ends with an error naming the key, never its value; nothing was changed |
|
| `config.env` or `.env` is missing, or a value is missing or malformed (a preset project detail included) | The `Run` ends with an error naming the key, never its value; nothing was changed |
|
||||||
| `git` or `curl` is missing | The `Run` ends with an error naming the tool; nothing was changed |
|
| `git` or `curl` is missing | The `Run` ends with an error naming the tool; nothing was changed |
|
||||||
|
|
||||||
## Contract: provideProjectDetails
|
## Contract: provideProjectDetails
|
||||||
@@ -53,10 +54,11 @@ Concepts below use the IT terms of [DICT-001] for the PO concepts of [DM-001]. `
|
|||||||
|
|
||||||
- A `Run` exists and its `Configuration` is valid (from `startProjectCreation`).
|
- A `Run` exists and its `Configuration` is valid (from `startProjectCreation`).
|
||||||
- `githubOwner` is present exactly when the Maintainer chose GitHub.
|
- `githubOwner` is present exactly when the Maintainer chose GitHub.
|
||||||
|
- A detail that the `Configuration` defines is not asked: it is taken from the `Configuration`.
|
||||||
|
|
||||||
**Postconditions**
|
**Postconditions**
|
||||||
|
|
||||||
- P1. A `ProjectRequest` instance was created with the given attributes and associated with the `Run`.
|
- P1. A `ProjectRequest` instance was created with the attributes given by the Maintainer or defined by the `Configuration`, and associated with the `Run`.
|
||||||
- P2. A `PreflightResult` instance was created and associated with the `ProjectRequest`, recording that each token needed for the chosen hosts works, that each owner accepts new repositories, that the name is free on the chosen hosts, that `AGPL-3.0` is offered by Gitea when GitHub was chosen, and the outcome of the SSH test to Gitea on port 10022.
|
- P2. A `PreflightResult` instance was created and associated with the `ProjectRequest`, recording that each token needed for the chosen hosts works, that each owner accepts new repositories, that the name is free on the chosen hosts, that `AGPL-3.0` is offered by Gitea when GitHub was chosen, and the outcome of the SSH test to Gitea on port 10022.
|
||||||
- P3. A `GiteaRepository` instance was created under `giteaOwner` with the given name, description and visibility, and associated with the `ProjectRequest`.
|
- P3. A `GiteaRepository` instance was created under `giteaOwner` with the given name, description and visibility, and associated with the `ProjectRequest`.
|
||||||
- P4. If `githubOwner` is present, a `LicenseFile` instance for `AGPL-3.0` was created and associated with the `GiteaRepository`, so that repository is not empty. Otherwise the `GiteaRepository` has no `LicenseFile` and is empty.
|
- P4. If `githubOwner` is present, a `LicenseFile` instance for `AGPL-3.0` was created and associated with the `GiteaRepository`, so that repository is not empty. Otherwise the `GiteaRepository` has no `LicenseFile` and is empty.
|
||||||
@@ -89,3 +91,4 @@ Concepts below use the IT terms of [DICT-001] for the PO concepts of [DM-001]. `
|
|||||||
[DICT-001]: ../dictionary.md
|
[DICT-001]: ../dictionary.md
|
||||||
[SD-001]: ./sd.md
|
[SD-001]: ./sd.md
|
||||||
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
||||||
|
[2a6bb8e]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/2a6bb8e8afadfe6ca4a621da30e44a372898ca62
|
||||||
|
|||||||
+3
-1
@@ -10,6 +10,7 @@
|
|||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Initial version | [02875ae] |
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Initial version | [02875ae] |
|
||||||
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Note: preset project details are read by ConfigLoader | [2a6bb8e] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -66,7 +67,7 @@ destroy TC
|
|||||||
|
|
||||||
### Responsibility Check
|
### Responsibility Check
|
||||||
|
|
||||||
`ProjectCreator` only sequences two calls; parsing and validation sit in `ConfigLoader`, tool detection in `ToolChecker`. No object receives every message.
|
`ProjectCreator` only sequences two calls; parsing and validation sit in `ConfigLoader`, tool detection in `ToolChecker`. No object receives every message. Project details preset in `config.env` are read and validated by `ConfigLoader` as part of `configuration`; the second sequence is unchanged, because `provideProjectDetails` receives the same arguments whether they were asked or preset.
|
||||||
|
|
||||||
## Sequence: provideProjectDetails
|
## Sequence: provideProjectDetails
|
||||||
|
|
||||||
@@ -188,3 +189,4 @@ destroy SR
|
|||||||
|
|
||||||
[OC-001]: ./oc.md
|
[OC-001]: ./oc.md
|
||||||
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
||||||
|
[2a6bb8e]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/2a6bb8e8afadfe6ca4a621da30e44a372898ca62
|
||||||
|
|||||||
+3
-3
@@ -9,8 +9,8 @@
|
|||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-10-05 | Rejected | 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<br>Cited OC-001 and DM-001 | [02875ae] |
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Optional GitHub; choosing GitHub applies the AGPL license to the Gitea repository<br>Cited OC-001 and DM-001 | [02875ae] |
|
||||||
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Parameters may come from config.env; the message is unchanged | [2a6bb8e] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ S --> A : creation summary
|
|||||||
| Step | Message | Parameters | Return | Use case step |
|
| Step | Message | Parameters | Return | Use case step |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| 1 | startProjectCreation | none | prompts for project details (after configuration and tool checks) | 1, 2 |
|
| 1 | startProjectCreation | none | prompts for project details (after configuration and tool checks) | 1, 2 |
|
||||||
| 2 | provideProjectDetails | name, description, visibility, giteaOwner, githubOwner (optional; given means GitHub is chosen and the Gitea repository gets the AGPL license; omitted means no GitHub and no license), directory, enablePlanGate | checks passed, then a creation summary | 3 to 10 |
|
| 2 | provideProjectDetails | name, description, visibility, giteaOwner, githubOwner (optional; given means GitHub is chosen and the Gitea repository gets the AGPL license; omitted means no GitHub and no license), directory, enablePlanGate (each of these may come from `config.env` instead of the Maintainer; the message is unchanged) | checks passed, then a creation summary | 3 to 10 |
|
||||||
|
|
||||||
Steps 4 to 9 are internal to the system, so one operation covers them. A consent question (step 8a, 9a, 9b) is a prompt from the system and is out of scope for this diagram; failure flows are out of scope here.
|
Steps 4 to 9 are internal to the system, so one operation covers them. A consent question (step 8a, 9a, 9b) is a prompt from the system and is out of scope for this diagram; failure flows are out of scope here.
|
||||||
|
|
||||||
@@ -50,5 +50,5 @@ The system is one script run. It starts with the first operation and ends after
|
|||||||
[UC-001]: ./uc.md
|
[UC-001]: ./uc.md
|
||||||
[DM-001]: ./dm.md
|
[DM-001]: ./dm.md
|
||||||
[OC-001]: ./oc.md
|
[OC-001]: ./oc.md
|
||||||
[424f14f]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/424f14f4f5577bb47fea41c8f3a655dca953e6d8
|
|
||||||
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
||||||
|
[2a6bb8e]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/2a6bb8e8afadfe6ca4a621da30e44a372898ca62
|
||||||
|
|||||||
+9
-3
@@ -9,8 +9,8 @@
|
|||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| 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<br>Cited DM-001 and UCD-001 | [02875ae] |
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Optional GitHub; choosing GitHub applies the AGPL license to the Gitea repository<br>Cited DM-001 and UCD-001 | [02875ae] |
|
||||||
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Step 3: details set in config.env are not asked (extensions 3a, 3b) | [2a6bb8e] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
- S03 — the published procedure is documented and reusable
|
- S03 — the published procedure is documented and reusable
|
||||||
- **Preconditions:**
|
- **Preconditions:**
|
||||||
- `config.env` and `.env` exist and are valid.
|
- `config.env` and `.env` exist and are valid.
|
||||||
|
- `config.env` may preset any of the project details of step 3.
|
||||||
- `git` and `curl` are installed.
|
- `git` and `curl` are installed.
|
||||||
- The Maintainer has a Gitea token, a GitHub PAT (only when GitHub is chosen) and SSH access to Gitea on port 10022.
|
- The Maintainer has a Gitea token, a GitHub PAT (only when GitHub is chosen) and SSH access to Gitea on port 10022.
|
||||||
- **Postconditions (success guarantee):**
|
- **Postconditions (success guarantee):**
|
||||||
@@ -39,7 +40,7 @@
|
|||||||
|
|
||||||
1. The Maintainer starts the project creation.
|
1. The Maintainer starts the project creation.
|
||||||
2. The system loads and validates the configuration and credentials and checks that the required tools exist.
|
2. The system loads and validates the configuration and credentials and checks that the required tools exist.
|
||||||
3. The Maintainer provides the repository name, description, visibility, the Gitea owner, whether to also create a GitHub repository (and if so its owner), the local directory, and whether to enable the plan gate.
|
3. The Maintainer provides the repository name, description, visibility, the Gitea owner, whether to also create a GitHub repository (and if so its owner), the local directory, and whether to enable the plan gate. A detail that is set in `config.env` is not asked.
|
||||||
4. The system checks that the tokens needed for the chosen hosts work, that the owners accept new repositories, that the name is free on those hosts, and whether SSH to Gitea works.
|
4. The system checks that the tokens needed for the chosen hosts work, that the owners accept new repositories, that the name is free on those hosts, and whether SSH to Gitea works.
|
||||||
5. Optional: if the Maintainer chose GitHub, the system creates the empty GitHub repository.
|
5. Optional: if the Maintainer chose GitHub, the system creates the empty GitHub repository.
|
||||||
6. The system creates the Gitea repository. If the Maintainer chose GitHub, the repository is created with the AGPL license file and so is not empty; otherwise it is empty and has no license.
|
6. The system creates the Gitea repository. If the Maintainer chose GitHub, the repository is created with the AGPL license file and so is not empty; otherwise it is empty and has no license.
|
||||||
@@ -52,6 +53,10 @@
|
|||||||
|
|
||||||
- 2a. A required tool is missing, or a configuration value is missing or malformed:
|
- 2a. A required tool is missing, or a configuration value is missing or malformed:
|
||||||
1. The system stops before any change and names the problem without showing a credential.
|
1. The system stops before any change and names the problem without showing a credential.
|
||||||
|
- 3a. A project detail is set in `config.env`:
|
||||||
|
1. The system uses it and does not ask for it; the summary says it came from the configuration.
|
||||||
|
- 3b. A configured project detail is invalid:
|
||||||
|
1. The system stops before any request and names the key; it does not ask for the value instead.
|
||||||
- 4a. A token is invalid, an owner does not accept the repository, or the name is taken:
|
- 4a. A token is invalid, an owner does not accept the repository, or the name is taken:
|
||||||
1. The system stops before creating anything and says which check failed. The GitHub token is only checked when GitHub was chosen.
|
1. The system stops before creating anything and says which check failed. The GitHub token is only checked when GitHub was chosen.
|
||||||
- 4c. GitHub was chosen and the Gitea server does not offer the `AGPL-3.0` license:
|
- 4c. GitHub was chosen and the Gitea server does not offer the `AGPL-3.0` license:
|
||||||
@@ -71,6 +76,7 @@
|
|||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 2, 4 | A token never appears in output, logs, command lines, remote URLs or temporary files left behind |
|
| 2, 4 | A token never appears in output, logs, command lines, remote URLs or temporary files left behind |
|
||||||
| 3 | The GitHub owner and the Gitea owner are chosen separately; `GITHUB_USER` is only the authenticating account |
|
| 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, mirror or `github` remote is created and the GitHub credentials are not required |
|
||||||
| 6 | Choosing GitHub applies the AGPL license (key `AGPL-3.0`) to the Gitea repository when it is created, so that repository is not empty; without GitHub there is no license and the repository is empty |
|
| 6 | Choosing GitHub applies the AGPL license (key `AGPL-3.0`) to the Gitea repository when it is created, so that repository is not empty; without GitHub there is no license and the repository is empty |
|
||||||
| 7 | The mirror direction is Gitea to GitHub; the GitHub repository stays empty and receives its content from the mirror |
|
| 7 | The mirror direction is Gitea to GitHub; the GitHub repository stays empty and receives its content from the mirror |
|
||||||
@@ -87,5 +93,5 @@
|
|||||||
[US-001]: ../user-stories.md
|
[US-001]: ../user-stories.md
|
||||||
[SA-001]: ../stakeholder-analysis.md
|
[SA-001]: ../stakeholder-analysis.md
|
||||||
[DM-001]: ./dm.md
|
[DM-001]: ./dm.md
|
||||||
[424f14f]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/424f14f4f5577bb47fea41c8f3a655dca953e6d8
|
|
||||||
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
||||||
|
[2a6bb8e]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/2a6bb8e8afadfe6ca4a621da30e44a372898ca62
|
||||||
|
|||||||
+21
-5
@@ -4,13 +4,13 @@
|
|||||||
| Key | Value |
|
| Key | Value |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| ID | US-001 |
|
| ID | US-001 |
|
||||||
| CrossReference | [BC-001], [UCD-001], [MIL-001], [MIL-002], [MIL-003] |
|
| CrossReference | [BC-001], [UCD-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004] |
|
||||||
|
|
||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| 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<br>Cited UCD-001<br>Split the epic into three stories, one per milestone | [02875ae] |
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Optional GitHub; choosing GitHub applies the AGPL license to the Gitea repository<br>Cited UCD-001<br>Split the epic into three stories, one per milestone | [02875ae] |
|
||||||
|
| 2026-10-05 | Accepted | Jens Tirsvad Nielsen | S02 | Added US-001.04: project details preset in config.env | [2a6bb8e] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
One epic: "Create a new project" ([UC-001]), setting up a new project on Gitea, optionally on GitHub, with the SQA-QC-Framework in place. The actor is the Maintainer, as in [UCD-001] (S01 or S02; for now one person holds both roles).
|
One epic: "Create a new project" ([UC-001]), setting up a new project on Gitea, optionally on GitHub, with the SQA-QC-Framework in place. The actor is the Maintainer, as in [UCD-001] (S01 or S02; for now one person holds both roles).
|
||||||
|
|
||||||
The epic is split into three stories, one per milestone. Each story fits one two-week phase and can be shown working at the end of it.
|
The epic is split into four stories, one per milestone. Each story fits one two-week phase and can be shown working at the end of it.
|
||||||
|
|
||||||
## Story List
|
## Story List
|
||||||
|
|
||||||
@@ -64,9 +64,24 @@ The epic is split into three stories, one per milestone. Each story fits one two
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| [UC-001] steps 8 to 10, [MIL-003] | fits one phase | Independent: needs the repositories of US-001.02 |
|
| [UC-001] steps 8 to 10, [MIL-003] | fits one phase | Independent: needs the repositories of US-001.02 |
|
||||||
|
|
||||||
|
### US-001.04 — Create a new project: preset the details
|
||||||
|
|
||||||
|
**As a** Maintainer, **I want** to set project details in `config.env`, **so that** the script does not ask for the same answers every time I create a project.
|
||||||
|
|
||||||
|
**Acceptance Criteria**
|
||||||
|
|
||||||
|
- Given a detail is set in `config.env`, when the script collects the details, then it does not ask for it, and the summary shows the value as coming from the configuration.
|
||||||
|
- Given a detail is not set in `config.env`, when the script collects the details, then it asks for it as before.
|
||||||
|
- Given a configured value is invalid, when the script starts, then it stops before any request to a host and names the key; it does not ask for the value instead.
|
||||||
|
- Given every detail is set, when the script runs, then the only questions left are the confirmations: create now, reuse of an existing repository, directory, hooks path or file.
|
||||||
|
|
||||||
|
| Traces to | Size | INVEST exceptions |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| [UC-001] step 3, [MIL-004] | fits one phase | Independent: needs the prompts of US-001.01 |
|
||||||
|
|
||||||
## INVEST Check
|
## INVEST Check
|
||||||
|
|
||||||
Valuable, Negotiable, Estimable, Small and Testable hold for each story. Independent holds only in part: the stories are ordered, each using what the one before it delivers, which follows the milestone order in [PP-001]. This is flagged as an exception on US-001.02 and US-001.03.
|
Valuable, Negotiable, Estimable, Small and Testable hold for each story. Independent holds only in part: the stories are ordered, each using what the one before it delivers, which follows the milestone order in [PP-001]. This is flagged as an exception on US-001.02, US-001.03 and US-001.04.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -76,6 +91,7 @@ Valuable, Negotiable, Estimable, Small and Testable hold for each story. Indepen
|
|||||||
[MIL-001]: ./milestones/mil-001-foundation.md
|
[MIL-001]: ./milestones/mil-001-foundation.md
|
||||||
[MIL-002]: ./milestones/mil-002-repositories-and-mirror.md
|
[MIL-002]: ./milestones/mil-002-repositories-and-mirror.md
|
||||||
[MIL-003]: ./milestones/mil-003-scaffold-and-release.md
|
[MIL-003]: ./milestones/mil-003-scaffold-and-release.md
|
||||||
|
[MIL-004]: ./milestones/mil-004-configurable-details.md
|
||||||
[PP-001]: ./project-plan.md
|
[PP-001]: ./project-plan.md
|
||||||
[424f14f]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/424f14f4f5577bb47fea41c8f3a655dca953e6d8
|
|
||||||
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
[02875ae]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/02875aee5f2953473924074eea0056eb31af6b7a
|
||||||
|
[2a6bb8e]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/2a6bb8e8afadfe6ca4a621da30e44a372898ca62
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ run_framework_script() {
|
|||||||
abs="$(cd "$dir" && pwd)"
|
abs="$(cd "$dir" && pwd)"
|
||||||
make_temp_file
|
make_temp_file
|
||||||
out="$REPLY"
|
out="$REPLY"
|
||||||
if ! (cd "$abs" && env PROJECT_ROOT="$abs" bash "framework/scripts/$script" "$@") >"$out" 2>&1; then
|
if ! (cd "$abs" && env PROJECT_ROOT="$abs" bash "framework/scripts/$script" "$@" </dev/null) >"$out" 2>&1; then
|
||||||
die "the framework script $script failed: $(tail -n 3 "$out" | tr '\n' ' ')"
|
die "the framework script $script failed: $(tail -n 3 "$out" | tr '\n' ' ')"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -6,13 +6,14 @@
|
|||||||
#
|
#
|
||||||
# Provides: git_project, fetch_origin
|
# Provides: git_project, fetch_origin
|
||||||
|
|
||||||
# git_project DIR ARGS...: run git in DIR. Prompts are switched off, so a
|
# git_project DIR ARGS...: run git in DIR. Prompts are switched off and stdin
|
||||||
|
# is closed (git must not eat the answers meant for later prompts), so a
|
||||||
# missing credential or SSH key fails at once instead of waiting for input.
|
# missing credential or SSH key fails at once instead of waiting for input.
|
||||||
git_project() {
|
git_project() {
|
||||||
local dir="$1"
|
local dir="$1"
|
||||||
shift
|
shift
|
||||||
GIT_TERMINAL_PROMPT=0 GIT_SSH_COMMAND="${GIT_SSH_COMMAND:-ssh} -o BatchMode=yes" \
|
GIT_TERMINAL_PROMPT=0 GIT_SSH_COMMAND="${GIT_SSH_COMMAND:-ssh} -o BatchMode=yes" \
|
||||||
git -C "$dir" "$@"
|
git -C "$dir" "$@" </dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
# fetch_origin DIR: fetch the Gitea repository into the project. Over SSH the
|
# fetch_origin DIR: fetch the Gitea repository into the project. Over SSH the
|
||||||
|
|||||||
+1
-1
@@ -71,7 +71,7 @@ http_request() {
|
|||||||
# that never contains the request.
|
# that never contains the request.
|
||||||
HTTP_STATUS="$(curl --silent --max-time "$HTTP_TIMEOUT_SECONDS" \
|
HTTP_STATUS="$(curl --silent --max-time "$HTTP_TIMEOUT_SECONDS" \
|
||||||
--connect-timeout 10 --output "$out_file" --write-out '%{http_code}' \
|
--connect-timeout 10 --output "$out_file" --write-out '%{http_code}' \
|
||||||
--config "$config_file" "${data_args[@]}" 2>/dev/null)" || curl_status=$?
|
--config "$config_file" "${data_args[@]}" </dev/null 2>/dev/null)" || curl_status=$?
|
||||||
# The configuration file holds the token and the body may hold another one
|
# The configuration file holds the token and the body may hold another one
|
||||||
# (the mirror password): remove both now instead of at exit.
|
# (the mirror password): remove both now instead of at exit.
|
||||||
rm -f -- "$config_file" ${body_file:+"$body_file"}
|
rm -f -- "$config_file" ${body_file:+"$body_file"}
|
||||||
|
|||||||
+10
-6
@@ -28,7 +28,8 @@ check_gitea_license() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# inspect_repository HOST: record in STATE[HOST_repo] whether the repository
|
# inspect_repository HOST: record in STATE[HOST_repo] whether the repository
|
||||||
# is free (does not exist), empty, license_only or not_empty.
|
# is free (does not exist), empty, initial_only (just the LICENSE and the
|
||||||
|
# README.md Gitea adds) or not_empty.
|
||||||
inspect_repository() {
|
inspect_repository() {
|
||||||
local host="$1" owner name names
|
local host="$1" owner name names
|
||||||
owner="$(repo_owner "$host")"
|
owner="$(repo_owner "$host")"
|
||||||
@@ -45,10 +46,13 @@ inspect_repository() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
expect_status "cannot read the contents of the $(host_label "$host") repository $owner/$name" 200
|
expect_status "cannot read the contents of the $(host_label "$host") repository $owner/$name" 200
|
||||||
names="$(json_values "$HTTP_BODY_FILE" name)"
|
# Gitea adds a README.md of its own next to the LICENSE when it creates a
|
||||||
case "$names" in
|
# repository with a license (seen on a real server), so both count as the
|
||||||
|
# content this script creates.
|
||||||
|
names="$(json_values "$HTTP_BODY_FILE" name | sort | tr '\n' ' ')"
|
||||||
|
case "${names% }" in
|
||||||
"") STATE[${host}_repo]="empty" ;;
|
"") STATE[${host}_repo]="empty" ;;
|
||||||
LICENSE) STATE[${host}_repo]="license_only" ;;
|
"LICENSE" | "LICENSE README.md") STATE[${host}_repo]="initial_only" ;;
|
||||||
*) STATE[${host}_repo]="not_empty" ;;
|
*) STATE[${host}_repo]="not_empty" ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@@ -117,7 +121,7 @@ test_gitea_ssh() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
output="$(ssh -p "$port" -o BatchMode=yes -o ConnectTimeout=5 \
|
output="$(ssh -p "$port" -o BatchMode=yes -o ConnectTimeout=5 \
|
||||||
-o StrictHostKeyChecking=yes -T "git@$host" 2>&1)" || status=$?
|
-o StrictHostKeyChecking=yes -T "git@$host" </dev/null 2>&1)" || status=$?
|
||||||
if ((status == 0)) || [[ $output == *"successfully authenticated"* ]]; then
|
if ((status == 0)) || [[ $output == *"successfully authenticated"* ]]; then
|
||||||
STATE[is_ssh_ok]=1
|
STATE[is_ssh_ok]=1
|
||||||
STATE[ssh_note]="passed"
|
STATE[ssh_note]="passed"
|
||||||
@@ -138,7 +142,7 @@ decide_existing_repositories() {
|
|||||||
case "$state" in
|
case "$state" in
|
||||||
free) ;;
|
free) ;;
|
||||||
empty) STATE[reuse_$host]=1 ;;
|
empty) STATE[reuse_$host]=1 ;;
|
||||||
license_only)
|
initial_only)
|
||||||
if [[ $host == gitea ]] && ((PROJECT[has_github])); then
|
if [[ $host == gitea ]] && ((PROJECT[has_github])); then
|
||||||
STATE[reuse_$host]=1
|
STATE[reuse_$host]=1
|
||||||
else
|
else
|
||||||
|
|||||||
+1
-1
@@ -45,7 +45,7 @@ report_outcome() {
|
|||||||
say "The project is in ${PROJECT[directory]}. Nothing was committed there: review it, then work on a branch."
|
say "The project is in ${PROJECT[directory]}. Nothing was committed there: review it, then work on a branch."
|
||||||
else
|
else
|
||||||
say "To continue: fix the problem named above and run the same command again with --apply."
|
say "To continue: fix the problem named above and run the same command again with --apply."
|
||||||
say "A repository this run created is still empty (or holds only the license), so the next run offers to reuse it."
|
say "A repository this run created is still empty (or holds only the license and the README Gitea adds), so the next run offers to reuse it."
|
||||||
say "A directory, remotes and submodule created so far are used again by the next run; you are asked before an existing directory or file is touched."
|
say "A directory, remotes and submodule created so far are used again by the next run; you are asked before an existing directory or file is touched."
|
||||||
say "Nothing is deleted automatically. To start over, delete the repositories above in the web interface and the project directory by hand."
|
say "Nothing is deleted automatically. To start over, delete the repositories above in the web interface and the project directory by hand."
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -244,6 +244,9 @@ STUB
|
|||||||
write_ssh_stub() {
|
write_ssh_stub() {
|
||||||
cat >"$WORK/bin/ssh" <<STUB
|
cat >"$WORK/bin/ssh" <<STUB
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# The real ssh reads standard input until it ends; so does this stub. Whatever
|
||||||
|
# is left on the caller's stdin (the answers to later prompts) is lost to it.
|
||||||
|
cat >/dev/null
|
||||||
printf '%s\n' "\$@" >>"\$STUB_DIR/ssh.args"
|
printf '%s\n' "\$@" >>"\$STUB_DIR/ssh.args"
|
||||||
if [[ ${1:-0} == 0 ]]; then
|
if [[ ${1:-0} == 0 ]]; then
|
||||||
echo "Hi there, gitea-user! You've successfully authenticated, but Gitea does not provide shell access."
|
echo "Hi there, gitea-user! You've successfully authenticated, but Gitea does not provide shell access."
|
||||||
|
|||||||
+12
-1
@@ -158,10 +158,21 @@ test_example_files_hold_placeholders_only() {
|
|||||||
fail ".env.example has a value for ${line%%=*}; it must be empty"
|
fail ".env.example has a value for ${line%%=*}; it must be empty"
|
||||||
fi
|
fi
|
||||||
done < <(grep -E '^[A-Z_]+=' "$REPO_ROOT/.env.example")
|
done < <(grep -E '^[A-Z_]+=' "$REPO_ROOT/.env.example")
|
||||||
|
# The example holds a placeholder for the Gitea address, so it must be
|
||||||
|
# edited before use: as it is, it is refused with a clear message...
|
||||||
run_lib "" "parse_env_file \"$REPO_ROOT/config.env.example\" CONFIG_KEYS CONFIG
|
run_lib "" "parse_env_file \"$REPO_ROOT/config.env.example\" CONFIG_KEYS CONFIG
|
||||||
validate_config
|
validate_config
|
||||||
echo parsed"
|
echo parsed"
|
||||||
assert_contains "config.env.example is valid" "$OUT" "parsed"
|
assert_status "placeholder address is refused" 1 "$STATUS"
|
||||||
|
assert_contains "names the key" "$ERR" "GITEA_URL"
|
||||||
|
# ...and with a real address in its place the rest of the file is valid.
|
||||||
|
sed -e 's|^GITEA_URL=.*|GITEA_URL=https://git.example.test/|' \
|
||||||
|
-e 's|^GITEA_API_URL=.*|GITEA_API_URL=https://git.example.test/api/v1|' \
|
||||||
|
"$REPO_ROOT/config.env.example" >"$WORK/example.env"
|
||||||
|
run_lib "" "parse_env_file \"$WORK/example.env\" CONFIG_KEYS CONFIG
|
||||||
|
validate_config
|
||||||
|
echo parsed"
|
||||||
|
assert_contains "config.env.example is valid once the address is set" "$OUT" "parsed"
|
||||||
run_lib "" "parse_env_file \"$REPO_ROOT/.env.example\" CREDENTIAL_KEYS CREDENTIALS
|
run_lib "" "parse_env_file \"$REPO_ROOT/.env.example\" CREDENTIAL_KEYS CREDENTIALS
|
||||||
echo parsed"
|
echo parsed"
|
||||||
assert_contains ".env.example parses" "$OUT" "parsed"
|
assert_contains ".env.example parses" "$OUT" "parsed"
|
||||||
|
|||||||
@@ -476,3 +476,42 @@ mirror_field '$WORK/m.json' https://github.com/o/b.git sync_on_commit"
|
|||||||
assert_eq "the right mirror is chosen with jq" "true" "$OUT"
|
assert_eq "the right mirror is chosen with jq" "true" "$OUT"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------- found by the live e2e run
|
||||||
|
|
||||||
|
test_a_repository_this_script_created_earlier_can_be_reused() {
|
||||||
|
# Seen on a real Gitea: creating a repository with a license also adds a
|
||||||
|
# README.md. After a failed mirror step the next run must still reuse it.
|
||||||
|
setup_hosts
|
||||||
|
prepend_route 'GET|/api/v1/repos/TirSystem/my-app|200|{"empty":false}'
|
||||||
|
prepend_route 'GET|/api/v1/repos/TirSystem/my-app/contents|200|[{"name":"README.md","type":"file"},{"name":"LICENSE","type":"file"}]'
|
||||||
|
run_apply "$ANSWERS_GITHUB"$'y\ny\n'
|
||||||
|
assert_status "LICENSE and README.md" 0 "$STATUS"
|
||||||
|
assert_not_contains "not created again" "$(calls)" "$GITEA_REPO_CALL"
|
||||||
|
assert_contains "reported" "$OUT" "Gitea repository : reused"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_other_files_still_count_as_content() {
|
||||||
|
local listing
|
||||||
|
for listing in '[{"name":"README.md","type":"file"}]' \
|
||||||
|
'[{"name":"LICENSE","type":"file"},{"name":"README.md","type":"file"},{"name":"main.c","type":"file"}]' \
|
||||||
|
'[{"name":"LICENSE","type":"file"},{"name":"src","type":"dir"}]'; do
|
||||||
|
setup_hosts
|
||||||
|
prepend_route 'GET|/api/v1/repos/TirSystem/my-app|200|{"empty":false}'
|
||||||
|
prepend_route "GET|/api/v1/repos/TirSystem/my-app/contents|200|$listing"
|
||||||
|
run_dry "$ANSWERS_GITHUB"
|
||||||
|
assert_status "content: $listing" 1 "$STATUS"
|
||||||
|
assert_contains "refused" "$ERR" "already exists and has content"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
test_children_never_eat_the_answers_meant_for_later_prompts() {
|
||||||
|
# The real ssh reads standard input until it ends; the stub does too. The
|
||||||
|
# script closes stdin for ssh, git, curl and the framework scripts, so the
|
||||||
|
# answers that follow the SSH test still reach the later prompts.
|
||||||
|
setup_hosts
|
||||||
|
run_apply "$ANSWERS_GITHUB"$'y\n'
|
||||||
|
assert_status "the final question is still answered" 0 "$STATUS"
|
||||||
|
assert_contains "created" "$OUT" "Done. This is what exists now:"
|
||||||
|
assert_not_contains "no lost input" "$ERR" "no input available"
|
||||||
|
}
|
||||||
|
|||||||
+3
-3
@@ -217,13 +217,13 @@ test_an_existing_hooks_path_is_not_replaced_without_a_yes() {
|
|||||||
|
|
||||||
test_a_global_hooks_path_is_reported_not_changed() {
|
test_a_global_hooks_path_is_reported_not_changed() {
|
||||||
setup_hosts
|
setup_hosts
|
||||||
git config --file "$WORK/gitconfig" core.hooksPath /somewhere/global-hooks
|
git config --file "$WORK/gitconfig" core.hooksPath global-hooks-dir
|
||||||
local dir="$WORK/project"
|
local dir="$WORK/project"
|
||||||
local_answers "$dir" y n
|
local_answers "$dir" y n
|
||||||
run_apply "$LOCAL_ANSWERS"$'y\n'
|
run_apply "$LOCAL_ANSWERS"$'y\n'
|
||||||
assert_status "apply" 0 "$STATUS"
|
assert_status "apply" 0 "$STATUS"
|
||||||
assert_contains "warns" "$ERR" "your global core.hooksPath is '/somewhere/global-hooks'"
|
assert_contains "warns" "$ERR" "your global core.hooksPath is 'global-hooks-dir'"
|
||||||
assert_eq "the global setting is untouched" "/somewhere/global-hooks" "$(git config --file "$WORK/gitconfig" --get core.hooksPath)"
|
assert_eq "the global setting is untouched" "global-hooks-dir" "$(git config --file "$WORK/gitconfig" --get core.hooksPath)"
|
||||||
assert_eq "the project has its own" "framework/githooks" "$(project_git "$dir" config --local --get core.hooksPath)"
|
assert_eq "the project has its own" "framework/githooks" "$(project_git "$dir" config --local --get core.hooksPath)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user