Compare commits
10
Commits
f34affa071
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf265e8f66 | ||
|
|
55d9ca6eee | ||
|
|
6b1b9c6af4 | ||
|
|
4634048eab | ||
|
|
ceaa7d18d8 | ||
|
|
75e8e91f9a | ||
|
|
de78fb195f | ||
|
|
2a6bb8e8af | ||
|
|
c21a3c50f0 | ||
|
|
5584ddf397 |
@@ -12,6 +12,10 @@
|
|||||||
# chosen owner and to push to the new one. Prefer a fine-grained token.
|
# chosen owner and to push to the new one. Prefer a fine-grained token.
|
||||||
GITHUB_PAT=
|
GITHUB_PAT=
|
||||||
|
|
||||||
|
########################################
|
||||||
|
# Secrets for workframe
|
||||||
|
########################################
|
||||||
|
|
||||||
# GitHub account the token belongs to. It identifies who authenticates; it is
|
# GitHub account the token belongs to. It identifies who authenticates; it is
|
||||||
# only a default suggestion for the owner prompt, because the repository can
|
# only a default suggestion for the owner prompt, because the repository can
|
||||||
# belong to an organization.
|
# belong to an organization.
|
||||||
|
|||||||
@@ -187,3 +187,4 @@ repofoundry.*/
|
|||||||
|
|
||||||
|
|
||||||
!src/lib
|
!src/lib
|
||||||
|
config.env
|
||||||
|
|||||||
@@ -87,6 +87,44 @@ chmod 600 .env # Linux and macOS
|
|||||||
Every URL must start with `https://` and must not contain a user name,
|
Every URL must start with `https://` and must not contain a user name,
|
||||||
password, query string or fragment. A credential key in this file is rejected.
|
password, query string or fragment. A credential key in this file is rejected.
|
||||||
|
|
||||||
|
### `config.env` (project details, optional)
|
||||||
|
|
||||||
|
Any of the details the script asks for can be set in `config.env` instead.
|
||||||
|
A detail that is set is used and not asked; the summary marks it with
|
||||||
|
`(from config.env)`.
|
||||||
|
|
||||||
|
| Key | Detail | Accepted value |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `PROJECT_NAME` | repository name | letters, digits, `.`, `_`, `-`; at most 100; not ending in `.git` |
|
||||||
|
| `PROJECT_DESCRIPTION` | description | at most 350 characters; may be empty |
|
||||||
|
| `PROJECT_VISIBILITY` | visibility | `private` or `public` |
|
||||||
|
| `GITEA_OWNER` | Gitea user or organization | letters, digits, `.`, `_`, `-`; at most 39 |
|
||||||
|
| `USE_GITHUB` | also create a GitHub repository | `yes` or `no` |
|
||||||
|
| `GITHUB_OWNER` | GitHub user or organization | letters, digits, `-`; used only when GitHub is used |
|
||||||
|
| `PROJECT_DIRECTORY` | local directory | not empty, not starting with `-` |
|
||||||
|
| `ENABLE_PLAN_GATE` | enable the plan gate | `yes` or `no` |
|
||||||
|
|
||||||
|
- A key that is present counts as set, even when its value is empty. Only
|
||||||
|
`PROJECT_DESCRIPTION` may be empty (no description); an empty value for any
|
||||||
|
other key stops the run. Remove the line to be asked instead.
|
||||||
|
- An invalid value stops the run before any request to a host and names the
|
||||||
|
key. The script never falls back to asking for it.
|
||||||
|
- `USE_GITHUB=no` skips the GitHub owner and every GitHub step; a
|
||||||
|
`GITHUB_OWNER` set at the same time is ignored, with a warning.
|
||||||
|
- Only these eight details can be set. The confirmations stay questions that
|
||||||
|
default to no: create now, reusing an existing repository, an existing
|
||||||
|
directory, `core.hooksPath` and replacing a template file.
|
||||||
|
- These keys are accepted in `config.env` only, never in `.env`.
|
||||||
|
- A value is read as plain text: an unquoted ` #` starts a comment and cuts the
|
||||||
|
value there. Put a description that contains ` #` in double quotes, for
|
||||||
|
example `PROJECT_DESCRIPTION="Tool for #mirrors"`.
|
||||||
|
|
||||||
|
With all eight set, a run asks only the confirmations:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
src/create-project.sh --apply # asks only "Create these now (y/n) [n]"
|
||||||
|
```
|
||||||
|
|
||||||
### `.env` (credentials)
|
### `.env` (credentials)
|
||||||
|
|
||||||
| Key | Meaning |
|
| Key | Meaning |
|
||||||
@@ -109,7 +147,8 @@ src/create-project.sh --config /path/to/config.env --env /path/to/.env
|
|||||||
|
|
||||||
The script asks for, in this order: repository name, description, visibility,
|
The script asks for, in this order: repository name, description, visibility,
|
||||||
Gitea owner, whether to also create a GitHub repository (and its owner), the
|
Gitea owner, whether to also create a GitHub repository (and its owner), the
|
||||||
local directory and whether to enable the plan gate. It then checks both hosts
|
local directory and whether to enable the plan gate (a detail set in
|
||||||
|
[`config.env`](#configenv-project-details-optional) is not asked). It then checks both hosts
|
||||||
with read-only requests and prints a plan:
|
with read-only requests and prints a plan:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
|
|||||||
@@ -30,6 +30,22 @@ GITEA_API_URL=https://<your gitea instance>/api/v1
|
|||||||
# The server may enforce a minimum. Default: 10m0s.
|
# The server may enforce a minimum. Default: 10m0s.
|
||||||
#MIRROR_INTERVAL=10m0s
|
#MIRROR_INTERVAL=10m0s
|
||||||
|
|
||||||
|
# Optional. Project details that are set here are not asked. A key that is
|
||||||
|
# present counts as set, even when empty; only PROJECT_DESCRIPTION may be
|
||||||
|
# empty. An invalid value stops the run and names the key. Remove or comment
|
||||||
|
# out a line to be asked for it. The confirmations ("Create these now" and
|
||||||
|
# the questions about existing repositories, directories and files) are
|
||||||
|
# always asked. Put a value that contains " #" in double quotes: an unquoted
|
||||||
|
# " #" starts a comment.
|
||||||
|
#PROJECT_NAME=my-project
|
||||||
|
#PROJECT_DESCRIPTION=What the project is for
|
||||||
|
#PROJECT_VISIBILITY=private # private or public
|
||||||
|
#GITEA_OWNER=my-organization
|
||||||
|
#USE_GITHUB=yes # yes or no
|
||||||
|
#GITHUB_OWNER=my-organization # used only when USE_GITHUB is yes
|
||||||
|
#PROJECT_DIRECTORY=./my-project
|
||||||
|
#ENABLE_PLAN_GATE=no # yes or no
|
||||||
|
|
||||||
# Optional. OWNER/NAME of the SQA-QC-Framework repository on the Gitea server;
|
# Optional. OWNER/NAME of the SQA-QC-Framework repository on the Gitea server;
|
||||||
# it is added to the new project as a submodule over SSH.
|
# it is added to the new project as a submodule over SSH.
|
||||||
# Default: TirSystem/SQA-QC-Framework.
|
# Default: TirSystem/SQA-QC-Framework.
|
||||||
|
|||||||
@@ -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 | 020 |
|
||||||
| 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
|
||||||
|
|||||||
@@ -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,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
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
# SQA Review Record: Shell code review of the MIL-004 change
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | RC-019 |
|
||||||
|
| CrossReference | [MIL-004], [QC-SH-001], [RC-016] |
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| 2026-10-05 | Proposed | Jens Tirsvad Nielsen | S02 | Initial version | [ceaa7d1] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Artifact Under Review
|
||||||
|
|
||||||
|
- Instance reviewed: the MIL-004 change to `src/create-project.sh` and `src/lib/` (`config.sh`, `constants.sh`, `project.sh`), `tests/test-presets.sh`, the README and `config.env.example`, on branch `mil-004-configurable-details` (commit `75e8e91` plus the fixes listed below), tasks 1 to 5 (issues #27 to #31) of [MIL-004].
|
||||||
|
- Checklist used: [QC-SH-001]. The rest of the code was reviewed in [RC-016].
|
||||||
|
- Review date: 2026-10-05
|
||||||
|
- Tool versions: bash 5.2.37, shellcheck 0.11.0, shfmt 3.14.1 (Windows, Git Bash)
|
||||||
|
|
||||||
|
## Checklist Results
|
||||||
|
|
||||||
|
| # | Criterion | Status | Evidence/Notes |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 1 | Starts with `#!/usr/bin/env bash` and `set -euo pipefail` | Pass | Unchanged. |
|
||||||
|
| 2 | Every expansion is quoted; lists are arrays; tests use `[[ ]]` and `$(...)` | Pass | `shellcheck` is clean. Values from `config.env` are only ever compared, matched against validators or printed; none reaches `eval`, a command line or a file name before it passed a validator. |
|
||||||
|
| 3 | Names follow the conventions | Pass | `check_preset`, `preset_detail`, `source_note` and the `HINT_*` constants follow the rules. See finding F4 on the name `PROJECT_NAME`. |
|
||||||
|
| 4 | Passes `shellcheck` and `bash -n` with no unexplained `disable` comments | Pass | No new `disable`. |
|
||||||
|
| 5 | Errors go to standard error with an `error:` message and a non-zero exit code | Pass | Every refusal goes through `die`, names the key and the file, never the value. |
|
||||||
|
| 6 | Temporary files use `mktemp` with a `trap` cleanup | Pass | Not touched. |
|
||||||
|
| 7 | No secret is written in the script, echoed, or put on a command line | Pass | The new keys carry no credential; they are rejected in `.env`, and credential keys stay rejected in `config.env` (tests). The description is printed in the summary, as it was when asked. |
|
||||||
|
| 8 | A script that changes state defaults to a dry run | Pass | Unchanged: a preset never skips the dry run or "Create these now". Tests prove that with all eight keys set, an empty or missing answer creates nothing. |
|
||||||
|
| 9 | A header comment states purpose, usage, options, environment variables and exit codes | Pass | Fixed during this review: the header said only "asks for the project details"; it now says that details set in `config.env` are not asked. |
|
||||||
|
| 10 | The script implements a task or design it cites; deviations are recorded | Pass | Tasks 1 to 5 of [MIL-004] and extensions 3a and 3b of [UC-001]. Deviations: values are accepted in any case, and `USE_GITHUB`/`ENABLE_PLAN_GATE` take `yes` or `no` only; both are in the README. |
|
||||||
|
| 11 | Behaviour is tested for success, failure and any disabled or bypass path | Pass | 919 checks in the full suite before the review, 0 failed. New: each key set, absent, empty and invalid; mixed asked and preset; `USE_GITHUB` interplay; the summary marker; no prompt text for a preset; the confirmations. Mutation check: making the preset lookup always fail made the tests fail. |
|
||||||
|
| 12 | Formatted with `shfmt` | Pass | No difference. |
|
||||||
|
| 13 | Safe to re-run | Pass | No state is kept. |
|
||||||
|
| 14 | Bash version and external tools stated | Pass | Unchanged. |
|
||||||
|
|
||||||
|
## Findings
|
||||||
|
|
||||||
|
| # | Finding | Severity | Status |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| F1 | An unquoted `PROJECT_DESCRIPTION` containing ` #` is silently cut at the comment mark (`Tool # for mirrors` becomes `Tool`), with no message. This is how the parser reads every value, but a description is the one free-text key, so it is where it bites. A value with both kinds of quote cannot be set at all (it can still be typed at the prompt). | Low (surprise, no data loss or security effect) | Fixed: the README and `config.env.example` say to put such a value in double quotes; a test pins both behaviours. The both-quotes case is documented as a limit of the parser. |
|
||||||
|
| F2 | The header of `create-project.sh` and the README sentence "The script asks for, in this order" did not mention that preset details are not asked. | Low (documentation) | Fixed. |
|
||||||
|
| F3 | The summary marks the source after the value, so a fully preset run reads `my-app (from config.env) (private (from config.env))`. Correct but noisy, and `USE_GITHUB=yes` is not marked on the GitHub line (only the owner is). | Low (readability) | Accepted: the marker is asserted by the tests and the wording is not a requirement; revisit if the Maintainer wants a table layout. |
|
||||||
|
| F4 | The constant `PROJECT_NAME` (the name of this tool, `RepoFoundry`) and the config key `PROJECT_NAME` (the name of the new project) share a spelling. They never meet in code (the key lives in `CONFIG`), but a reader can confuse them. | Low (maintainability) | Open: renaming the constant is out of scope for this change; a candidate for a later clean-up. |
|
||||||
|
| F5 | A `config.env` that sets `PROJECT_NAME` and `GITEA_OWNER` makes every run use them. Existing repositories are still detected and need the reuse confirmation, so nothing is overwritten. | Info | Documented in the README (per-project configuration). |
|
||||||
|
|
||||||
|
No finding affects credentials, ownership, the mirror direction or the confirmations.
|
||||||
|
|
||||||
|
## Overall Verdict
|
||||||
|
|
||||||
|
Go — all mandatory criteria pass after the fixes for F1 and F2 (found and fixed during this review; the test for F1 was added; the full suite was rerun afterwards: 923 checks, 0 failed). F3 and F4 are recorded and not blocking. 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 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Decide whether to rename the constant `PROJECT_NAME` (F4) and whether to restyle the summary markers (F3) | S02 | 2026-10-30 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[MIL-004]: ../../milestones/mil-004-configurable-details.md
|
||||||
|
[UC-001]: ../../uc-001/uc.md
|
||||||
|
[RC-016]: ./rc-016-create-project-sh.md
|
||||||
|
[QC-SH-001]: ../../../framework/qc/qc-programming-shell.md
|
||||||
|
[ceaa7d1]: https://git.tirsystem.com/TirSystem-BashScript/repo_foundry/commit/ceaa7d18d8908b4d1e3fb089f238c99b883d71e0
|
||||||
@@ -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], [RC-019] |
|
||||||
| [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,9 @@ 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
|
||||||
|
[RC-019]: ./reviews/rc-019-mil-004-code.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 +82,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
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
# RepoFoundry creates a Gitea repository, optionally an empty GitHub
|
# RepoFoundry creates a Gitea repository, optionally an empty GitHub
|
||||||
# repository with a Gitea -> GitHub push mirror, and a local project with
|
# repository with a Gitea -> GitHub push mirror, and a local project with
|
||||||
# the SQA-QC-Framework. It validates the configuration and credentials,
|
# the SQA-QC-Framework. It validates the configuration and credentials,
|
||||||
# asks for the project details, checks both hosts with read-only requests
|
# asks for the project details (those set in config.env are not asked), checks both hosts with read-only requests
|
||||||
# (tokens, owners, names, license, SSH) and, with --apply, creates the
|
# (tokens, owners, names, license, SSH) and, with --apply, creates the
|
||||||
# repositories and the mirror, then the local project: its directory, git
|
# repositories and the mirror, then the local project: its directory, git
|
||||||
# repository, remotes (no credential in any address), the framework as a
|
# repository, remotes (no credential in any address), the framework as a
|
||||||
|
|||||||
+40
-1
@@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
# Part of create-project.sh: sourced by it, never run on its own.
|
# Part of create-project.sh: sourced by it, never run on its own.
|
||||||
#
|
#
|
||||||
# Provides: unquote_value, parse_env_file, parse_env_entry, validate_config, validate_credentials, require_github_credentials, warn_if_env_unsafe, load_configuration
|
# Provides: unquote_value, parse_env_file, parse_env_entry, validate_config, check_preset, check_preset_choice, validate_project_presets, validate_credentials, require_github_credentials, warn_if_env_unsafe, load_configuration
|
||||||
|
|
||||||
# unquote_value RAW: strip matching quotes (or a trailing " # comment" on an
|
# unquote_value RAW: strip matching quotes (or a trailing " # comment" on an
|
||||||
# unquoted value) and return the value in REPLY. Fails on unbalanced quotes.
|
# unquoted value) and return the value in REPLY. Fails on unbalanced quotes.
|
||||||
@@ -103,6 +103,45 @@ validate_config() {
|
|||||||
CONFIG[FRAMEWORK_REPO]="${CONFIG[FRAMEWORK_REPO]:-$DEFAULT_FRAMEWORK_REPO}"
|
CONFIG[FRAMEWORK_REPO]="${CONFIG[FRAMEWORK_REPO]:-$DEFAULT_FRAMEWORK_REPO}"
|
||||||
is_valid_framework_repo "${CONFIG[FRAMEWORK_REPO]}" ||
|
is_valid_framework_repo "${CONFIG[FRAMEWORK_REPO]}" ||
|
||||||
die "FRAMEWORK_REPO in $CONFIG_FILE must look like OWNER/NAME"
|
die "FRAMEWORK_REPO in $CONFIG_FILE must look like OWNER/NAME"
|
||||||
|
validate_project_presets
|
||||||
|
}
|
||||||
|
|
||||||
|
# check_preset KEY VALIDATOR HINT: when KEY is set in config.env its value must
|
||||||
|
# pass VALIDATOR. A key that is present counts as set; only the description
|
||||||
|
# may be empty. The message names the key, never the value.
|
||||||
|
check_preset() {
|
||||||
|
local key="$1" validator="$2" hint="$3"
|
||||||
|
[[ -n ${CONFIG[$key]+set} ]] || return 0
|
||||||
|
if [[ -z ${CONFIG[$key]} && $key != PROJECT_DESCRIPTION ]]; then
|
||||||
|
die "$key in $CONFIG_FILE is empty; remove the line to be asked, or give a value ($hint)"
|
||||||
|
fi
|
||||||
|
"$validator" "${CONFIG[$key]}" ||
|
||||||
|
die "$key in $CONFIG_FILE is not valid: $hint"
|
||||||
|
}
|
||||||
|
|
||||||
|
# check_preset_choice KEY CHOICE...: like check_preset for a fixed list of
|
||||||
|
# words; the value is stored in lower case.
|
||||||
|
check_preset_choice() {
|
||||||
|
local key="$1"
|
||||||
|
shift
|
||||||
|
[[ -n ${CONFIG[$key]+set} ]] || return 0
|
||||||
|
[[ -n ${CONFIG[$key]} ]] ||
|
||||||
|
die "$key in $CONFIG_FILE is empty; remove the line to be asked, or give one of: $*"
|
||||||
|
CONFIG[$key]="${CONFIG[$key],,}"
|
||||||
|
in_list "${CONFIG[$key]}" "$@" ||
|
||||||
|
die "$key in $CONFIG_FILE must be one of: $*"
|
||||||
|
}
|
||||||
|
|
||||||
|
# The optional project details that may be preset in config.env.
|
||||||
|
validate_project_presets() {
|
||||||
|
check_preset PROJECT_NAME is_valid_repo_name "$HINT_REPO_NAME"
|
||||||
|
check_preset PROJECT_DESCRIPTION is_valid_description "$HINT_DESCRIPTION"
|
||||||
|
check_preset_choice PROJECT_VISIBILITY private public
|
||||||
|
check_preset GITEA_OWNER is_valid_gitea_owner "$HINT_GITEA_OWNER"
|
||||||
|
check_preset_choice USE_GITHUB yes no
|
||||||
|
check_preset GITHUB_OWNER is_valid_github_owner "$HINT_GITHUB_OWNER"
|
||||||
|
check_preset PROJECT_DIRECTORY is_valid_directory "$HINT_DIRECTORY"
|
||||||
|
check_preset_choice ENABLE_PLAN_GATE yes no
|
||||||
}
|
}
|
||||||
|
|
||||||
validate_credentials() {
|
validate_credentials() {
|
||||||
|
|||||||
+12
-1
@@ -19,11 +19,20 @@ readonly DEFAULT_SSH_PORT=10022
|
|||||||
readonly DEFAULT_FRAMEWORK_REPO="TirSystem/SQA-QC-Framework"
|
readonly DEFAULT_FRAMEWORK_REPO="TirSystem/SQA-QC-Framework"
|
||||||
readonly AGPL_LICENSE_KEY="AGPL-3.0"
|
readonly AGPL_LICENSE_KEY="AGPL-3.0"
|
||||||
readonly DEFAULT_BRANCH="main"
|
readonly DEFAULT_BRANCH="main"
|
||||||
|
# What the prompts and the preset keys in config.env both tell the Maintainer
|
||||||
|
# when a value is refused.
|
||||||
|
readonly HINT_REPO_NAME="use letters, digits, '.', '_' or '-' (at most 100), not ending in .git"
|
||||||
|
readonly HINT_DESCRIPTION="at most $MAX_DESCRIPTION_LENGTH characters and no control characters"
|
||||||
|
readonly HINT_GITEA_OWNER="use letters, digits, '.', '_' or '-' (at most 39)"
|
||||||
|
readonly HINT_GITHUB_OWNER="use letters, digits or '-' (at most 39)"
|
||||||
|
readonly HINT_DIRECTORY="must not be empty, start with '-' or contain control characters"
|
||||||
readonly PLAN_STEPS=("GitHub repository" "Gitea repository" "Push mirror"
|
readonly PLAN_STEPS=("GitHub repository" "Gitea repository" "Push mirror"
|
||||||
"Local project" "Framework" "Skills and hooks" "Templates")
|
"Local project" "Framework" "Skills and hooks" "Templates")
|
||||||
# shellcheck disable=SC2034 # read through namerefs (parse_env_file)
|
# shellcheck disable=SC2034 # read through namerefs (parse_env_file)
|
||||||
readonly CONFIG_KEYS=(GITHUB_API_URL GITHUB_WEB_URL GITEA_URL GITEA_API_URL
|
readonly CONFIG_KEYS=(GITHUB_API_URL GITHUB_WEB_URL GITEA_URL GITEA_API_URL
|
||||||
GITEA_SSH_PORT MIRROR_INTERVAL FRAMEWORK_REPO)
|
GITEA_SSH_PORT MIRROR_INTERVAL FRAMEWORK_REPO
|
||||||
|
PROJECT_NAME PROJECT_DESCRIPTION PROJECT_VISIBILITY GITEA_OWNER USE_GITHUB
|
||||||
|
GITHUB_OWNER PROJECT_DIRECTORY ENABLE_PLAN_GATE)
|
||||||
readonly CREDENTIAL_KEYS=(GITHUB_PAT GITHUB_USER GITEA_TOKEN)
|
readonly CREDENTIAL_KEYS=(GITHUB_PAT GITHUB_USER GITEA_TOKEN)
|
||||||
|
|
||||||
CONFIG_FILE="$PROJECT_ROOT/config.env"
|
CONFIG_FILE="$PROJECT_ROOT/config.env"
|
||||||
@@ -41,6 +50,8 @@ TEMP_FILES=()
|
|||||||
declare -A CONFIG=()
|
declare -A CONFIG=()
|
||||||
declare -A CREDENTIALS=()
|
declare -A CREDENTIALS=()
|
||||||
declare -A PROJECT=()
|
declare -A PROJECT=()
|
||||||
|
# Project details that came from config.env instead of a prompt (PRESET[name]=1).
|
||||||
|
declare -A PRESET=()
|
||||||
# Facts found by the preflight checks (logins, owner kinds, repository state).
|
# Facts found by the preflight checks (logins, owner kinds, repository state).
|
||||||
declare -A STATE=()
|
declare -A STATE=()
|
||||||
# Outcome of each step in PLAN_STEPS, for the final report.
|
# Outcome of each step in PLAN_STEPS, for the final report.
|
||||||
|
|||||||
+54
-22
@@ -4,34 +4,59 @@
|
|||||||
#
|
#
|
||||||
# Part of create-project.sh: sourced by it, never run on its own.
|
# Part of create-project.sh: sourced by it, never run on its own.
|
||||||
#
|
#
|
||||||
# Provides: collect_project_details, yes_no, credential_state, print_summary
|
# Provides: preset_detail, collect_project_details, collect_github_details, source_note, yes_no, credential_state, print_summary
|
||||||
|
|
||||||
|
# preset_detail KEY NAME: a detail set in config.env is used and not asked;
|
||||||
|
# the value is returned in REPLY and marked in PRESET[NAME].
|
||||||
|
preset_detail() {
|
||||||
|
[[ -n ${CONFIG[$1]+set} ]] || return 1
|
||||||
|
REPLY="${CONFIG[$1]}"
|
||||||
|
PRESET[$2]=1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ask for each project detail, except those set in config.env.
|
||||||
collect_project_details() {
|
collect_project_details() {
|
||||||
prompt_value "Repository name" "" is_valid_repo_name \
|
preset_detail PROJECT_NAME name ||
|
||||||
"use letters, digits, '.', '_' or '-' (at most 100), not ending in .git"
|
prompt_value "Repository name" "" is_valid_repo_name "$HINT_REPO_NAME"
|
||||||
PROJECT[name]="$REPLY"
|
PROJECT[name]="$REPLY"
|
||||||
prompt_value "Description (optional)" "" is_valid_description \
|
preset_detail PROJECT_DESCRIPTION description ||
|
||||||
"at most $MAX_DESCRIPTION_LENGTH characters and no control characters"
|
prompt_value "Description (optional)" "" is_valid_description "$HINT_DESCRIPTION"
|
||||||
PROJECT[description]="$REPLY"
|
PROJECT[description]="$REPLY"
|
||||||
|
preset_detail PROJECT_VISIBILITY visibility ||
|
||||||
prompt_choice "Visibility" private private public
|
prompt_choice "Visibility" private private public
|
||||||
PROJECT[visibility]="$REPLY"
|
PROJECT[visibility]="$REPLY"
|
||||||
prompt_value "Gitea owner (user or organization)" "" is_valid_gitea_owner \
|
preset_detail GITEA_OWNER gitea_owner ||
|
||||||
"use letters, digits, '.', '_' or '-' (at most 39)"
|
prompt_value "Gitea owner (user or organization)" "" is_valid_gitea_owner "$HINT_GITEA_OWNER"
|
||||||
PROJECT[gitea_owner]="$REPLY"
|
PROJECT[gitea_owner]="$REPLY"
|
||||||
|
collect_github_details
|
||||||
|
preset_detail PROJECT_DIRECTORY directory ||
|
||||||
|
prompt_value "Local directory" "./${PROJECT[name]}" is_valid_directory "$HINT_DIRECTORY"
|
||||||
|
PROJECT[directory]="$REPLY"
|
||||||
|
if preset_detail ENABLE_PLAN_GATE is_plan_gate_enabled; then
|
||||||
|
[[ $REPLY == yes ]] && REPLY=1 || REPLY=0
|
||||||
|
else
|
||||||
|
prompt_yes_no "Enable the plan gate" n
|
||||||
|
fi
|
||||||
|
PROJECT[is_plan_gate_enabled]="$REPLY"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Whether GitHub is used, and its owner. A GITHUB_OWNER set while GitHub is
|
||||||
|
# not used is ignored, with a warning.
|
||||||
|
collect_github_details() {
|
||||||
|
if preset_detail USE_GITHUB has_github; then
|
||||||
|
[[ $REPLY == yes ]] && REPLY=1 || REPLY=0
|
||||||
|
else
|
||||||
prompt_yes_no "Also create a GitHub repository (applies the AGPL license)" y
|
prompt_yes_no "Also create a GitHub repository (applies the AGPL license)" y
|
||||||
|
fi
|
||||||
PROJECT[has_github]="$REPLY"
|
PROJECT[has_github]="$REPLY"
|
||||||
PROJECT[github_owner]=""
|
PROJECT[github_owner]=""
|
||||||
if ((PROJECT[has_github])); then
|
if ((PROJECT[has_github])); then
|
||||||
prompt_value "GitHub owner (user or organization)" \
|
preset_detail GITHUB_OWNER github_owner ||
|
||||||
"${CREDENTIALS[GITHUB_USER]:-}" is_valid_github_owner \
|
prompt_value "GitHub owner (user or organization)" "${CREDENTIALS[GITHUB_USER]:-}" is_valid_github_owner "$HINT_GITHUB_OWNER"
|
||||||
"use letters, digits or '-' (at most 39)"
|
|
||||||
PROJECT[github_owner]="$REPLY"
|
PROJECT[github_owner]="$REPLY"
|
||||||
|
elif [[ -n ${CONFIG[GITHUB_OWNER]+set} ]]; then
|
||||||
|
warn "GITHUB_OWNER in $CONFIG_FILE is ignored because GitHub is not used"
|
||||||
fi
|
fi
|
||||||
prompt_value "Local directory" "./${PROJECT[name]}" is_valid_directory \
|
|
||||||
"must not be empty, start with '-' or contain control characters"
|
|
||||||
PROJECT[directory]="$REPLY"
|
|
||||||
prompt_yes_no "Enable the plan gate" n
|
|
||||||
PROJECT[is_plan_gate_enabled]="$REPLY"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
yes_no() {
|
yes_no() {
|
||||||
@@ -50,20 +75,27 @@ credential_state() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# source_note NAME: the marker shown after a value that came from config.env.
|
||||||
|
source_note() {
|
||||||
|
if [[ -n ${PRESET[$1]:-} ]]; then
|
||||||
|
printf ' (from config.env)'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
print_summary() {
|
print_summary() {
|
||||||
say ""
|
say ""
|
||||||
say "$PROJECT_NAME $VERSION"
|
say "$PROJECT_NAME $VERSION"
|
||||||
say "Collected details:"
|
say "Collected details:"
|
||||||
say " Repository : ${PROJECT[name]} (${PROJECT[visibility]})"
|
say " Repository : ${PROJECT[name]}$(source_note name) (${PROJECT[visibility]}$(source_note visibility))"
|
||||||
say " Description : ${PROJECT[description]:-(none)}"
|
say " Description : ${PROJECT[description]:-(none)}$(source_note description)"
|
||||||
say " Gitea : ${CONFIG[GITEA_URL]}/${PROJECT[gitea_owner]}/${PROJECT[name]}"
|
say " Gitea : ${CONFIG[GITEA_URL]}/${PROJECT[gitea_owner]}/${PROJECT[name]}$(source_note gitea_owner)"
|
||||||
if ((PROJECT[has_github])); then
|
if ((PROJECT[has_github])); then
|
||||||
say " GitHub : ${CONFIG[GITHUB_WEB_URL]}/${PROJECT[github_owner]}/${PROJECT[name]} (AGPL license applied)"
|
say " GitHub : ${CONFIG[GITHUB_WEB_URL]}/${PROJECT[github_owner]}/${PROJECT[name]} (AGPL license applied)$(source_note github_owner)"
|
||||||
else
|
else
|
||||||
say " GitHub : not used"
|
say " GitHub : not used$(source_note has_github)"
|
||||||
fi
|
fi
|
||||||
say " Directory : ${PROJECT[directory]}"
|
say " Directory : ${PROJECT[directory]}$(source_note directory)"
|
||||||
say " Plan gate : $(yes_no "${PROJECT[is_plan_gate_enabled]}")"
|
say " Plan gate : $(yes_no "${PROJECT[is_plan_gate_enabled]}")$(source_note is_plan_gate_enabled)"
|
||||||
say "Credentials : GITEA_TOKEN $(credential_state GITEA_TOKEN)," \
|
say "Credentials : GITEA_TOKEN $(credential_state GITEA_TOKEN)," \
|
||||||
"GITHUB_PAT $(credential_state GITHUB_PAT)"
|
"GITHUB_PAT $(credential_state GITHUB_PAT)"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,275 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# test-presets.sh - tests for the project details preset in config.env
|
||||||
|
# (MIL-004): a detail that is set there is not asked, an invalid one stops
|
||||||
|
# the run, and the confirmations stay interactive. Sourced by run-tests.sh.
|
||||||
|
|
||||||
|
# shellcheck disable=SC2016 # snippet and fixture text is literal on purpose
|
||||||
|
|
||||||
|
# The eight keys with a value that differs from the answer given when asked.
|
||||||
|
readonly PRESET_ALL='PROJECT_NAME=preset-app
|
||||||
|
PROJECT_DESCRIPTION=From the config
|
||||||
|
PROJECT_VISIBILITY=public
|
||||||
|
GITEA_OWNER=PresetOrg
|
||||||
|
USE_GITHUB=yes
|
||||||
|
GITHUB_OWNER=preset-gh
|
||||||
|
PROJECT_DIRECTORY=./preset-dir
|
||||||
|
ENABLE_PLAN_GATE=yes'
|
||||||
|
|
||||||
|
# The same details as ANSWERS_GITHUB, so a run with all of them preset is the
|
||||||
|
# same run with no answers.
|
||||||
|
readonly PRESET_LIKE_ANSWERS='PROJECT_NAME=my-app
|
||||||
|
PROJECT_DESCRIPTION=A test app
|
||||||
|
PROJECT_VISIBILITY=private
|
||||||
|
GITEA_OWNER=TirSystem
|
||||||
|
USE_GITHUB=yes
|
||||||
|
GITHUB_OWNER=acme-org
|
||||||
|
PROJECT_DIRECTORY=./my-app
|
||||||
|
ENABLE_PLAN_GATE=no'
|
||||||
|
|
||||||
|
# collect_with PRESET_LINES INPUT: parse a config holding the preset lines,
|
||||||
|
# collect the details and print them one per line.
|
||||||
|
collect_with() {
|
||||||
|
printf '%s\n' "$1" >"$WORK/preset.env"
|
||||||
|
run_lib "$2" 'parse_env_file "'"$WORK"'/preset.env" CONFIG_KEYS CONFIG
|
||||||
|
validate_project_presets
|
||||||
|
collect_project_details
|
||||||
|
for k in name description visibility gitea_owner has_github github_owner directory is_plan_gate_enabled; do
|
||||||
|
printf "%s=%s\n" "$k" "${PROJECT[$k]}"
|
||||||
|
done'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Each key, the answers a run gives for the other seven details, and the
|
||||||
|
# prompt that must not be shown for the key.
|
||||||
|
test_each_key_is_used_and_not_asked() {
|
||||||
|
local key value field label line input
|
||||||
|
local -A answer=([PROJECT_NAME]=asked-app [PROJECT_DESCRIPTION]="Asked description"
|
||||||
|
[PROJECT_VISIBILITY]=private [GITEA_OWNER]=AskedOrg [USE_GITHUB]=y
|
||||||
|
[GITHUB_OWNER]=asked-gh [PROJECT_DIRECTORY]=./asked-dir [ENABLE_PLAN_GATE]=n)
|
||||||
|
local order=(PROJECT_NAME PROJECT_DESCRIPTION PROJECT_VISIBILITY GITEA_OWNER
|
||||||
|
USE_GITHUB GITHUB_OWNER PROJECT_DIRECTORY ENABLE_PLAN_GATE)
|
||||||
|
while IFS='|' read -r key value field label; do
|
||||||
|
input=""
|
||||||
|
for line in "${order[@]}"; do
|
||||||
|
if [[ $line != "$key" ]]; then
|
||||||
|
input+="${answer[$line]}"$'\n'
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
collect_with "$key=$value" "$input"
|
||||||
|
assert_status "$key preset" 0 "$STATUS"
|
||||||
|
assert_contains "$key value used" "$OUT" "$field"
|
||||||
|
assert_not_contains "$key not asked" "$ERR" "$label"
|
||||||
|
assert_contains "other details still asked" "$OUT" "asked"
|
||||||
|
done <<'EOF'
|
||||||
|
PROJECT_NAME|preset-app|name=preset-app|Repository name
|
||||||
|
PROJECT_DESCRIPTION|From the config|description=From the config|Description
|
||||||
|
PROJECT_VISIBILITY|public|visibility=public|Visibility
|
||||||
|
GITEA_OWNER|PresetOrg|gitea_owner=PresetOrg|Gitea owner
|
||||||
|
USE_GITHUB|yes|has_github=1|Also create a GitHub
|
||||||
|
GITHUB_OWNER|preset-gh|github_owner=preset-gh|GitHub owner
|
||||||
|
PROJECT_DIRECTORY|./preset-dir|directory=./preset-dir|Local directory
|
||||||
|
ENABLE_PLAN_GATE|yes|is_plan_gate_enabled=1|Enable the plan gate
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
test_all_keys_set_asks_nothing() {
|
||||||
|
collect_with "$PRESET_ALL" ""
|
||||||
|
assert_status "no input needed" 0 "$STATUS"
|
||||||
|
assert_eq "every value from the config" $'name=preset-app\ndescription=From the config\nvisibility=public\ngitea_owner=PresetOrg\nhas_github=1\ngithub_owner=preset-gh\ndirectory=./preset-dir\nis_plan_gate_enabled=1' "$OUT"
|
||||||
|
assert_eq "no prompt text at all" "" "$ERR"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_absent_keys_are_asked_as_before() {
|
||||||
|
collect_with "PROJECT_NAME=preset-app" $'\n\nTirSystem\nn\n\nn\n'
|
||||||
|
assert_status "mixed" 0 "$STATUS"
|
||||||
|
assert_contains "preset name" "$OUT" "name=preset-app"
|
||||||
|
assert_contains "default directory from the preset name" "$OUT" "directory=./preset-app"
|
||||||
|
assert_contains "other details asked" "$ERR" "Gitea owner"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_values_are_taken_in_any_case() {
|
||||||
|
collect_with $'PROJECT_VISIBILITY=PUBLIC\nUSE_GITHUB=No\nENABLE_PLAN_GATE=YES' $'x-app\n\nTirSystem\n\n'
|
||||||
|
assert_status "case ignored" 0 "$STATUS"
|
||||||
|
assert_contains "visibility" "$OUT" "visibility=public"
|
||||||
|
assert_contains "no GitHub" "$OUT" "has_github=0"
|
||||||
|
assert_contains "plan gate" "$OUT" "is_plan_gate_enabled=1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------- empty and invalid
|
||||||
|
|
||||||
|
test_empty_value_counts_as_set_only_for_the_description() {
|
||||||
|
collect_with "PROJECT_DESCRIPTION=" $'my-app\npublic\nTirSystem\nn\n\nn\n'
|
||||||
|
assert_status "empty description accepted" 0 "$STATUS"
|
||||||
|
assert_contains "description empty" "$OUT" "description="
|
||||||
|
assert_not_contains "description not asked" "$ERR" "Description"
|
||||||
|
local key
|
||||||
|
for key in PROJECT_NAME PROJECT_VISIBILITY GITEA_OWNER USE_GITHUB GITHUB_OWNER \
|
||||||
|
PROJECT_DIRECTORY ENABLE_PLAN_GATE; do
|
||||||
|
printf '%s=\n' "$key" >"$WORK/preset.env"
|
||||||
|
run_lib "" 'parse_env_file "'"$WORK"'/preset.env" CONFIG_KEYS CONFIG
|
||||||
|
validate_project_presets'
|
||||||
|
assert_status "$key empty" 1 "$STATUS"
|
||||||
|
assert_contains "$key named" "$ERR" "$key in"
|
||||||
|
assert_contains "$key says empty" "$ERR" "is empty"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
test_invalid_values_are_refused_naming_the_key() {
|
||||||
|
local key value
|
||||||
|
while IFS='|' read -r key value; do
|
||||||
|
printf '%s=%s\n' "$key" "$value" >"$WORK/preset.env"
|
||||||
|
run_lib "" 'parse_env_file "'"$WORK"'/preset.env" CONFIG_KEYS CONFIG
|
||||||
|
validate_project_presets'
|
||||||
|
assert_status "$key=$value" 1 "$STATUS"
|
||||||
|
assert_contains "$key=$value named" "$ERR" "$key in"
|
||||||
|
done <<'EOF'
|
||||||
|
PROJECT_NAME|bad name
|
||||||
|
PROJECT_NAME|x.git
|
||||||
|
PROJECT_VISIBILITY|internal
|
||||||
|
GITEA_OWNER|-lead
|
||||||
|
USE_GITHUB|maybe
|
||||||
|
USE_GITHUB|1
|
||||||
|
GITHUB_OWNER|octo_user
|
||||||
|
PROJECT_DIRECTORY|-rf
|
||||||
|
ENABLE_PLAN_GATE|true
|
||||||
|
EOF
|
||||||
|
# A description over the limit (350 characters) is refused too.
|
||||||
|
printf 'PROJECT_DESCRIPTION=%s\n' "$(printf 'a%.0s' $(seq 1 351))" >"$WORK/preset.env"
|
||||||
|
run_lib "" 'parse_env_file "'"$WORK"'/preset.env" CONFIG_KEYS CONFIG
|
||||||
|
validate_project_presets'
|
||||||
|
assert_status "long description" 1 "$STATUS"
|
||||||
|
assert_contains "named" "$ERR" "PROJECT_DESCRIPTION in"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_invalid_value_stops_before_any_request_and_never_asks() {
|
||||||
|
setup_hosts
|
||||||
|
printf 'PROJECT_NAME=bad name\n' >>"$WORK/config.env"
|
||||||
|
run_apply ""
|
||||||
|
assert_status "stopped" 1 "$STATUS"
|
||||||
|
assert_contains "key named" "$ERR" "PROJECT_NAME in"
|
||||||
|
assert_not_contains "no value asked instead" "$ERR" "Repository name:"
|
||||||
|
assert_eq "no request made" "" "$(calls)"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_new_keys_are_rejected_in_env_and_credentials_in_config() {
|
||||||
|
setup_hosts
|
||||||
|
printf 'PROJECT_NAME=my-app\n' >>"$WORK/.env"
|
||||||
|
run_dry ""
|
||||||
|
assert_status ".env with a project key" 1 "$STATUS"
|
||||||
|
assert_contains "unknown in .env" "$ERR" "unknown key 'PROJECT_NAME'"
|
||||||
|
setup_hosts
|
||||||
|
printf 'GITEA_TOKEN=abcdefgh12345\n' >>"$WORK/config.env"
|
||||||
|
run_dry ""
|
||||||
|
assert_status "config.env with a credential" 1 "$STATUS"
|
||||||
|
assert_contains "credential refused" "$ERR" "is a credential"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------- GitHub
|
||||||
|
|
||||||
|
test_use_github_no_skips_the_owner_and_warns_about_a_stray_one() {
|
||||||
|
collect_with $'USE_GITHUB=no\nGITHUB_OWNER=acme-org' $'my-app\n\n\nTirSystem\n\nn\n'
|
||||||
|
assert_status "GitHub off" 0 "$STATUS"
|
||||||
|
assert_contains "no GitHub" "$OUT" "has_github=0"
|
||||||
|
assert_contains "no owner" "$OUT" "github_owner="
|
||||||
|
assert_not_contains "owner not asked" "$ERR" "GitHub owner ("
|
||||||
|
assert_contains "ignored with a warning" "$ERR" "GITHUB_OWNER in"
|
||||||
|
assert_contains "says why" "$ERR" "ignored because GitHub is not used"
|
||||||
|
collect_with "USE_GITHUB=no" $'my-app\n\n\nTirSystem\n\nn\n'
|
||||||
|
assert_not_contains "no warning without the key" "$ERR" "ignored"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_github_owner_preset_is_used_when_github_is_asked_for() {
|
||||||
|
collect_with "GITHUB_OWNER=preset-gh" $'my-app\n\n\nTirSystem\ny\n\nn\n'
|
||||||
|
assert_contains "owner from the config" "$OUT" "github_owner=preset-gh"
|
||||||
|
assert_not_contains "owner not asked" "$ERR" "GitHub owner ("
|
||||||
|
collect_with "GITHUB_OWNER=preset-gh" $'my-app\n\n\nTirSystem\nn\n\nn\n'
|
||||||
|
assert_contains "ignored when answered no" "$ERR" "ignored because GitHub is not used"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_use_github_no_makes_no_github_call() {
|
||||||
|
setup_hosts
|
||||||
|
printf '%s\n' "$PRESET_LIKE_ANSWERS" | sed 's/^USE_GITHUB=.*/USE_GITHUB=no/' >>"$WORK/config.env"
|
||||||
|
run_dry ""
|
||||||
|
assert_status "dry run" 0 "$STATUS"
|
||||||
|
assert_contains "GitHub not used" "$OUT" "GitHub repository : not used"
|
||||||
|
assert_not_contains "no GitHub call" "$(calls)" "api.github.com"
|
||||||
|
assert_not_contains "no GitHub owner asked" "$ERR" "GitHub owner ("
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------ the summary
|
||||||
|
|
||||||
|
test_summary_marks_the_values_from_config_env() {
|
||||||
|
setup_hosts
|
||||||
|
printf '%s\n' "$PRESET_LIKE_ANSWERS" >>"$WORK/config.env"
|
||||||
|
run_dry ""
|
||||||
|
assert_status "all preset" 0 "$STATUS"
|
||||||
|
assert_contains "name" "$OUT" "Repository : my-app (from config.env) (private (from config.env))"
|
||||||
|
assert_contains "description" "$OUT" "Description : A test app (from config.env)"
|
||||||
|
assert_contains "Gitea" "$OUT" "/TirSystem/my-app (from config.env)"
|
||||||
|
assert_contains "GitHub" "$OUT" "(AGPL license applied) (from config.env)"
|
||||||
|
assert_contains "directory" "$OUT" "Directory : ./my-app (from config.env)"
|
||||||
|
assert_contains "plan gate" "$OUT" "Plan gate : no (from config.env)"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_summary_marks_nothing_when_everything_is_asked() {
|
||||||
|
setup_hosts
|
||||||
|
run_dry "$ANSWERS_GITHUB"
|
||||||
|
assert_status "all asked" 0 "$STATUS"
|
||||||
|
assert_not_contains "no marker" "$OUT" "(from config.env)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ----------------------------------------------------- the confirmations
|
||||||
|
|
||||||
|
test_with_every_detail_set_only_the_confirmations_are_asked() {
|
||||||
|
setup_hosts
|
||||||
|
run_apply "$ANSWERS_GITHUB"y$'\n'
|
||||||
|
local asked_calls
|
||||||
|
asked_calls="$(calls)"
|
||||||
|
remove_workdir
|
||||||
|
new_workdir
|
||||||
|
setup_hosts
|
||||||
|
printf '%s\n' "$PRESET_LIKE_ANSWERS" >>"$WORK/config.env"
|
||||||
|
run_apply $'y\n'
|
||||||
|
assert_status "run with presets" 0 "$STATUS"
|
||||||
|
assert_eq "same requests as the run that was asked" "$asked_calls" "$(calls)"
|
||||||
|
assert_contains "created" "$OUT" "This is what exists now"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_with_every_detail_set_create_now_is_still_asked_and_defaults_to_no() {
|
||||||
|
setup_hosts
|
||||||
|
printf '%s\n' "$PRESET_LIKE_ANSWERS" >>"$WORK/config.env"
|
||||||
|
run_apply $'n\n'
|
||||||
|
assert_status "declined" 0 "$STATUS"
|
||||||
|
assert_contains "says so" "$OUT" "Nothing was created."
|
||||||
|
assert_not_contains "nothing created" "$(calls)" "POST"
|
||||||
|
setup_hosts
|
||||||
|
printf '%s\n' "$PRESET_LIKE_ANSWERS" >>"$WORK/config.env"
|
||||||
|
run_apply $'\n'
|
||||||
|
assert_contains "empty answer means no" "$OUT" "Nothing was created."
|
||||||
|
assert_not_contains "no POST on the default" "$(calls)" "POST"
|
||||||
|
setup_hosts
|
||||||
|
printf '%s\n' "$PRESET_LIKE_ANSWERS" >>"$WORK/config.env"
|
||||||
|
run_apply ""
|
||||||
|
assert_contains "no answer means no" "$OUT" "Nothing was created."
|
||||||
|
assert_not_contains "nothing created without an answer" "$(calls)" "POST"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_with_every_detail_set_an_existing_directory_is_not_replaced() {
|
||||||
|
setup_hosts
|
||||||
|
printf '%s\n' "$PRESET_LIKE_ANSWERS" >>"$WORK/config.env"
|
||||||
|
mkdir -p "$WORK/my-app"
|
||||||
|
printf 'keep\n' >"$WORK/my-app/mine.txt"
|
||||||
|
run_apply $'y\n\n'
|
||||||
|
assert_file_exists "existing file kept" "$WORK/my-app/mine.txt"
|
||||||
|
assert_eq "content kept" "keep" "$(cat "$WORK/my-app/mine.txt")"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_a_quoted_description_may_contain_a_hash() {
|
||||||
|
local answers=$'my-app\npublic\nTirSystem\nn\n\nn\n'
|
||||||
|
collect_with 'PROJECT_DESCRIPTION="Tool for #mirrors"' "$answers"
|
||||||
|
assert_status "quoted" 0 "$STATUS"
|
||||||
|
assert_contains "whole value kept" "$OUT" "description=Tool for #mirrors"
|
||||||
|
# Unquoted, the same text is cut at the comment mark, as documented.
|
||||||
|
collect_with 'PROJECT_DESCRIPTION=Tool for #mirrors' "$answers"
|
||||||
|
assert_contains "cut at the comment" "$OUT" "description=Tool for"
|
||||||
|
assert_not_contains "comment dropped" "$OUT" "mirrors"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user