Compare commits
123
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97ffa49aae | ||
|
|
8b972b33e9 | ||
|
|
be147af60c | ||
|
|
27abd226c4 | ||
|
|
9ccefa5e3b | ||
|
|
dbaf272fe5 | ||
|
|
d9cd3c67d4 | ||
|
|
afb1e219db | ||
|
|
2cf59b96bd | ||
|
|
4cf52afe00 | ||
|
|
297095bdfb | ||
|
|
930e67ad7e | ||
|
|
b1515b26e1 | ||
|
|
a04b578d70 | ||
|
|
044d8ba21f | ||
|
|
aa18811003 | ||
|
|
23abcd9491 | ||
|
|
e6db4b56d3 | ||
|
|
ac20d1c2a1 | ||
|
|
2ce02698e5 | ||
|
|
820f05c0bd | ||
|
|
cbf4460289 | ||
|
|
f69b38c228 | ||
|
|
3b8681d023 | ||
|
|
4910a5b3fd | ||
|
|
45219a19f6 | ||
|
|
00970dd909 | ||
|
|
92a8b32f0e | ||
|
|
385d2fb7cb | ||
|
|
bf077b1910 | ||
|
|
9c357f79ca | ||
|
|
616c5d2e48 | ||
|
|
da53cceb7c | ||
|
|
f8879fcf06 | ||
|
|
b3f006f7a4 | ||
|
|
f99c8d545f | ||
|
|
e2c6bedb26 | ||
|
|
ea06eaaa69 | ||
|
|
5608630d3d | ||
|
|
dc572470e7 | ||
|
|
a2bf2d4204 | ||
|
|
e73975e3a6 | ||
|
|
b240ceb9f1 | ||
|
|
2dbc2819d4 | ||
|
|
de2e28e637 | ||
|
|
e530ecd99d | ||
|
|
c4bbea4a2b | ||
|
|
439de4ac60 | ||
|
|
92396e23c9 | ||
|
|
b22a2cd592 | ||
|
|
0230ed8c08 | ||
|
|
bf11aa25db | ||
|
|
676a262405 | ||
|
|
8d0fab71b5 | ||
|
|
be53de8f57 | ||
|
|
6b8e36d67a | ||
|
|
e5b326213e | ||
|
|
0ecdcbe804 | ||
|
|
b0dffbc1c3 | ||
|
|
c0a0a10c4b | ||
|
|
7b37e40a79 | ||
|
|
0439867e89 | ||
|
|
b282e10741 | ||
|
|
ebf9ce9a1c | ||
|
|
a26a491737 | ||
|
|
1d2829d6e1 | ||
|
|
481a381fbc | ||
|
|
bc3bd07b29 | ||
|
|
1a9c9a32e7 | ||
|
|
0135b2763c | ||
|
|
2eb852cfc6 | ||
|
|
3e18c991ce | ||
|
|
081c6b58f7 | ||
|
|
0ddef2b695 | ||
|
|
cf31238271 | ||
|
|
d0618d929f | ||
|
|
8767741c0c | ||
|
|
20e02535bc | ||
|
|
f5fb0238f3 | ||
|
|
611d665508 | ||
|
|
1472513421 | ||
|
|
334b214a12 | ||
|
|
80853e76f2 | ||
|
|
5ef76ec263 | ||
|
|
8d62ea0d56 | ||
|
|
bef58e75c7 | ||
|
|
3ab0a9789c | ||
|
|
20361e881e | ||
|
|
5a38842e4d | ||
|
|
1114b742dc | ||
|
|
77c52779c4 | ||
|
|
bfd5be2b88 | ||
|
|
d6fe7c60ab | ||
|
|
fb502ce871 | ||
|
|
dd9f407131 | ||
|
|
ae4e257236 | ||
|
|
5137ce23ae | ||
|
|
49a5b0ef8e | ||
|
|
08ef26a6d3 | ||
|
|
975291092d | ||
|
|
5f5e9cfced | ||
|
|
0799b43888 | ||
|
|
bc914904d0 | ||
|
|
ba1c6bea74 | ||
|
|
a7b2035441 | ||
|
|
aa3f08876d | ||
|
|
f01d0f7caa | ||
|
|
c017c06789 | ||
|
|
fde03660da | ||
|
|
ec0f6e2cf8 | ||
|
|
0c06789a27 | ||
|
|
ab122d2073 | ||
|
|
a1561e2c6c | ||
|
|
7dcb9c4dfc | ||
|
|
16b9060d4c | ||
|
|
10074323f0 | ||
|
|
2228c49f29 | ||
|
|
cbb9688ed4 | ||
|
|
0d25344fdb | ||
|
|
72d2671978 | ||
|
|
4de5438a88 | ||
|
|
62eac8b7cf | ||
|
|
9e5dd4f1dd |
@@ -0,0 +1,7 @@
|
||||
# Copy to .env and fill in real values. .env is gitignored - never commit it.
|
||||
|
||||
# Gitea personal access token (Settings -> Applications -> Generate New Token),
|
||||
# scoped to issues only if your Gitea version supports scoped tokens.
|
||||
# Used by framework/scripts/sync-project.sh --apply against a Gitea remote.
|
||||
# NOT a deploy key - deploy keys authenticate git-over-SSH only, not the API.
|
||||
GITEA_TOKEN=
|
||||
@@ -0,0 +1,42 @@
|
||||
name: Publish wiki
|
||||
|
||||
# Shared through scoped delivery: it runs in every repository of an
|
||||
# organization, but writes only where the repository has opted in with
|
||||
# wiki/.publish (ADR-0004). TOKEN_FOR_GITEA_WIKI is read from the organization
|
||||
# secrets; there is no fallback to the read-only sync token. The script is a
|
||||
# file of TirSystem/github-action (tools/publish_wiki.py), fetched with a
|
||||
# second checkout so that it is readable, lintable and tested as a file
|
||||
# (MIL-004 task 6).
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- "wiki/**"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: publish-wiki
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
publish-wiki:
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out the repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Fetch the shared script
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: TirSystem/github-action
|
||||
ref: main
|
||||
path: shared-scripts
|
||||
|
||||
- name: Publish the pages to the wiki
|
||||
env:
|
||||
GITEA_API_URL: ${{ gitea.api_url }}
|
||||
SOURCE_REPOSITORY: ${{ gitea.repository }}
|
||||
WIKI_CREDENTIALS: ${{ secrets.TOKEN_FOR_GITEA_WIKI }}
|
||||
run: python3 shared-scripts/tools/publish_wiki.py
|
||||
@@ -0,0 +1,33 @@
|
||||
name: Sync GitHub mirror metadata
|
||||
|
||||
# Scoped workflow: it runs in every repository of an organization. The script
|
||||
# is a file of TirSystem/github-action (tools/sync_github_metadata.py), fetched
|
||||
# with a checkout so that it is readable, lintable and tested as a file
|
||||
# (MIL-004 task 6). The repository is public, so no token is needed.
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "17 3 * * *"
|
||||
|
||||
jobs:
|
||||
sync-metadata:
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Fetch the shared script
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: TirSystem/github-action
|
||||
ref: main
|
||||
path: shared-scripts
|
||||
|
||||
- name: Sync description and topics
|
||||
env:
|
||||
GITEA_API_URL: ${{ gitea.api_url }}
|
||||
GITEA_CREDENTIALS: ${{ secrets.TOKEN_FOR_GITEA }}
|
||||
SOURCE_REPOSITORY: ${{ gitea.repository }}
|
||||
PAT_FOR_GITHUB: ${{ secrets.PAT_FOR_GITHUB }}
|
||||
run: python3 shared-scripts/tools/sync_github_metadata.py
|
||||
@@ -0,0 +1,153 @@
|
||||
name: Quality checks
|
||||
|
||||
# Reusable workflow (ADR-0005). A repository calls it with
|
||||
#
|
||||
# jobs:
|
||||
# quality:
|
||||
# uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@main
|
||||
#
|
||||
# It checks the Python and shell files of the repository with pinned tools,
|
||||
# changes no file and needs no secret.
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
languages:
|
||||
description: "Comma list of the languages to check: python, shell"
|
||||
type: string
|
||||
default: "python,shell"
|
||||
working-directory:
|
||||
description: "Directory, relative to the repository root, whose files are checked"
|
||||
type: string
|
||||
default: "."
|
||||
ruff-version:
|
||||
description: "Version of ruff (Python lint and format)"
|
||||
type: string
|
||||
default: "0.6.9"
|
||||
mypy-version:
|
||||
description: "Version of mypy (Python types, --strict)"
|
||||
type: string
|
||||
default: "1.11.2"
|
||||
shellcheck-py-version:
|
||||
description: "Version of the shellcheck-py package (ShellCheck 0.10.0)"
|
||||
type: string
|
||||
default: "0.10.0.1"
|
||||
shfmt-py-version:
|
||||
description: "Version of the shfmt-py package (shfmt 3.11.0)"
|
||||
type: string
|
||||
default: "3.11.0.2"
|
||||
|
||||
jobs:
|
||||
quality-checks:
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
LANGUAGES: ${{ inputs.languages }}
|
||||
WORKING_DIRECTORY: ${{ inputs.working-directory }}
|
||||
RUFF_VERSION: ${{ inputs.ruff-version }}
|
||||
MYPY_VERSION: ${{ inputs.mypy-version }}
|
||||
SHELLCHECK_PY_VERSION: ${{ inputs.shellcheck-py-version }}
|
||||
SHFMT_PY_VERSION: ${{ inputs.shfmt-py-version }}
|
||||
QC_VENV: /tmp/quality-tools
|
||||
steps:
|
||||
- name: Validate the inputs
|
||||
run: |
|
||||
set -u
|
||||
IFS=',' read -ra langs <<< "${LANGUAGES// /}"
|
||||
if [ "${#langs[@]}" -eq 0 ]; then
|
||||
echo "::error::[configuration] languages is empty; use python, shell or both, comma separated."
|
||||
exit 1
|
||||
fi
|
||||
for lang in "${langs[@]}"; do
|
||||
case "$lang" in
|
||||
python | shell) ;;
|
||||
*)
|
||||
echo "::error::[configuration] Unknown language '$lang'; use python and shell, comma separated."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
case "$WORKING_DIRECTORY" in
|
||||
"" | /* | .. | ../* | */.. | */../*)
|
||||
echo "::error::[configuration] working-directory must be a relative path inside the repository."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
echo "Checking ${LANGUAGES} in ${WORKING_DIRECTORY}"
|
||||
|
||||
- name: Check out the repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install the tools
|
||||
run: |
|
||||
set -eu
|
||||
IFS=',' read -ra langs <<< "${LANGUAGES// /}"
|
||||
packages=()
|
||||
for lang in "${langs[@]}"; do
|
||||
case "$lang" in
|
||||
python) packages+=("ruff==${RUFF_VERSION}" "mypy==${MYPY_VERSION}") ;;
|
||||
shell) packages+=("shellcheck-py==${SHELLCHECK_PY_VERSION}" "shfmt-py==${SHFMT_PY_VERSION}") ;;
|
||||
esac
|
||||
done
|
||||
python3 -m venv "$QC_VENV"
|
||||
"$QC_VENV/bin/pip" install --quiet "${packages[@]}"
|
||||
|
||||
- name: Run the checks
|
||||
run: |
|
||||
set -u
|
||||
QC_BIN="${QC_BIN:-$QC_VENV/bin}"
|
||||
if [ ! -d "$WORKING_DIRECTORY" ]; then
|
||||
echo "::error::[configuration] working-directory '$WORKING_DIRECTORY' does not exist."
|
||||
exit 1
|
||||
fi
|
||||
cd "$WORKING_DIRECTORY"
|
||||
|
||||
failed=()
|
||||
run_tool() {
|
||||
local name="$1"
|
||||
shift
|
||||
echo "::group::$name"
|
||||
if "$@"; then
|
||||
echo "::endgroup::"
|
||||
echo "PASS $name"
|
||||
else
|
||||
echo "::endgroup::"
|
||||
echo "FAIL $name"
|
||||
failed+=("$name")
|
||||
fi
|
||||
}
|
||||
wanted() {
|
||||
local lang
|
||||
IFS=',' read -ra langs <<< "${LANGUAGES// /}"
|
||||
for lang in "${langs[@]}"; do
|
||||
[ "$lang" = "$1" ] && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
if wanted python; then
|
||||
mapfile -t files < <(git ls-files -- '*.py')
|
||||
if [ "${#files[@]}" -eq 0 ]; then
|
||||
echo "::notice::No python files in '$WORKING_DIRECTORY'; nothing was checked."
|
||||
else
|
||||
run_tool "ruff check" "$QC_BIN/ruff" check "${files[@]}"
|
||||
run_tool "ruff format --check" "$QC_BIN/ruff" format --check "${files[@]}"
|
||||
run_tool "mypy --strict" "$QC_BIN/mypy" --strict "${files[@]}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if wanted shell; then
|
||||
mapfile -t files < <(git ls-files -- '*.sh')
|
||||
if [ "${#files[@]}" -eq 0 ]; then
|
||||
echo "::notice::No shell files in '$WORKING_DIRECTORY'; nothing was checked."
|
||||
else
|
||||
run_tool "shellcheck" "$QC_BIN/shellcheck" "${files[@]}"
|
||||
run_tool "shfmt -d" "$QC_BIN/shfmt" -d "${files[@]}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${#failed[@]}" -gt 0 ]; then
|
||||
echo "::error::Quality checks failed: ${failed[*]}"
|
||||
exit 1
|
||||
fi
|
||||
echo "All selected checks passed."
|
||||
@@ -0,0 +1,41 @@
|
||||
name: Release
|
||||
|
||||
# Releases this repository (ADR-0006, ADR-0007, MIL-004 task 5). It is started
|
||||
# by hand with the version to release; it creates the version tag, the release
|
||||
# page from the changelog entry and moves the major tag, and only when the
|
||||
# commit is the tip of main, its validation run is green and the changelog has
|
||||
# an entry for the version. dry_run defaults to true: it checks and prints and
|
||||
# writes nothing, so a release is a deliberate second run with dry_run false.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: "Version to release, MAJOR.MINOR.PATCH without a leading v"
|
||||
required: true
|
||||
dry_run:
|
||||
description: "true checks only; false creates the tag, the release page and the major tag"
|
||||
required: false
|
||||
default: "true"
|
||||
|
||||
concurrency:
|
||||
group: release
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
release:
|
||||
permissions:
|
||||
contents: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out the repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Check and publish the release
|
||||
env:
|
||||
GITEA_API_URL: ${{ gitea.api_url }}
|
||||
SOURCE_REPOSITORY: ${{ gitea.repository }}
|
||||
RELEASE_CREDENTIALS: ${{ secrets.TOKEN_FOR_GITEA_RELEASE || github.token }}
|
||||
RELEASE_VERSION: ${{ inputs.version }}
|
||||
RELEASE_DRY_RUN: ${{ inputs.dry_run }}
|
||||
RELEASE_SHA: ${{ gitea.sha }}
|
||||
run: python3 tools/release.py
|
||||
@@ -0,0 +1,24 @@
|
||||
name: Validate workflows
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: [ main ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out the repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Create a virtual environment and install test dependencies
|
||||
run: |
|
||||
python3 -m venv .venv
|
||||
.venv/bin/python -m pip install --quiet -r tests/requirements.txt
|
||||
|
||||
- name: Validate workflow files and run the offline tests
|
||||
run: .venv/bin/python -m pytest -q tests
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
# Local secrets - never commit these
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Local, per-clone files generated/copied from framework/ - never commit
|
||||
# these (see framework/README.md "Using it in a project"):
|
||||
# .agents/skills/ <- install-skills.sh's copy of framework/.agents/skills/
|
||||
# .claude/skills/ <- same copy, for the standalone Claude Code CLI
|
||||
/.agents/
|
||||
/.claude/
|
||||
|
||||
# Python virtual environment and caches
|
||||
.venv/
|
||||
__pycache__/
|
||||
.pytest_cache/
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "framework"]
|
||||
path = framework
|
||||
url = ssh://git@git.tirsystem.com:10022/TirSystem/SQA-QC-Framework.git
|
||||
@@ -0,0 +1,61 @@
|
||||
# AGENTS.md
|
||||
|
||||
This project uses the SQA and QC framework mounted at `framework/`.
|
||||
|
||||
For any document under `docs/` (create, edit or review) use the `artifact`
|
||||
skill. For planning a project or a phase into tasks, and syncing phases and
|
||||
tasks to Gitea/GitHub as Milestones and Issues, use the `project-planning`
|
||||
skill. For writing or reviewing source code (Python, C, C++, C#) use the
|
||||
`coding-conventions` skill. Skills are read from `.agents/skills/` (this harness and Codex CLI)
|
||||
and `.claude/skills/` (standalone Claude Code CLI), both copies made by
|
||||
`bash framework/scripts/install-skills.sh` — re-run it after updating the
|
||||
framework.
|
||||
|
||||
**Never commit, push or open a PR unless asked.** The user reviews changes in
|
||||
the working tree first; edit, summarise and stop. The commit/PR rules below
|
||||
apply once a commit has been asked for.
|
||||
|
||||
## Workflow order
|
||||
|
||||
Business Case, Stakeholder Analysis, Project Plan, milestones, tasks synced as
|
||||
issues, then code. Nothing goes under `src/` or `tests/` unless a milestone
|
||||
document (`MIL-*`) is accepted and the task is a row in it (ideally a synced
|
||||
issue). If those are missing, plan with the `project-planning` skill, show the
|
||||
dry-run output of `bash framework/scripts/sync-project.sh`, and stop. The rule
|
||||
is defined once in `framework/process/plan-first-gate.md`.
|
||||
|
||||
A "build X" request is planning-first: produce the plan and issues, then ask
|
||||
for a go-ahead. Only the user can waive the plan, in chat, for that request.
|
||||
Before planning, find the Product Owner's language (the prompt, or the
|
||||
`Languages` section of `docs/artifact-registry.md`); if neither states it, ask.
|
||||
|
||||
To enforce the gate at commit time, run
|
||||
`bash framework/scripts/install-git-hooks.sh --enable-plan-gate`: a commit that
|
||||
changes `src/` or `tests/` then needs a `Task: MIL-NNN#N` trailer.
|
||||
|
||||
Rules that apply to every document:
|
||||
|
||||
1. Get the short name from `framework/registry/artifact-catalog.md` and the
|
||||
next version from `docs/artifact-registry.md`. Create files with
|
||||
`bash framework/scripts/new-artifact.sh <SHORT>`.
|
||||
2. Owners, reviewers and RACI use stakeholder IDs from the project's
|
||||
Stakeholder Analysis, never invented role names.
|
||||
3. Every QC criterion is tagged with an ISO/IEC 25010:2023 characteristic.
|
||||
4. Every reviewed instance gets an `RC-*` record in `docs/sqa/reviews/`.
|
||||
5. Do not edit `framework/` from this project; propose changes upstream.
|
||||
6. Every PR description closes the issues its work completes, one
|
||||
`Closes #N` per line (`Refs #N` for partial work); see the
|
||||
`project-planning` skill.
|
||||
7. Every document's `## Version History` has `Change` and `Commit` columns and
|
||||
keeps the two latest rows. After committing, run
|
||||
`framework/scripts/resolve-pending-commits.sh` and commit the result before
|
||||
opening the PR (no amend). Never ask for or perform the merge: a reviewer
|
||||
merges.
|
||||
8. Keep the wiki current. A PR that changes a workflow under `.gitea/`, a file
|
||||
in `guides/` or `README.md` also updates the matching pages in `wiki/`:
|
||||
run `python tools/build_wiki.py` for the English pages (the tests fail when
|
||||
they are out of date) and update the Danish (`da`) and Bahasa Malaysia
|
||||
(`ms`) pages once they exist, naming the English source they follow. List
|
||||
the wiki pages the PR changed in its description, or say "No wiki pages
|
||||
changed: <reason>". Never push to the wiki repository by hand: the publishing
|
||||
workflow (MIL-005 task 8) copies `wiki/` there when the PR is merged.
|
||||
@@ -0,0 +1,56 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to the shared workflows of this repository. The format and
|
||||
the version rules are those of the release process (`guides/release-process.md`,
|
||||
ADR-0006): one version for the whole repository, tags `vMAJOR.MINOR.PATCH`
|
||||
and a moving major tag `vMAJOR`.
|
||||
|
||||
Each release lists its changes in these groups, in this order:
|
||||
|
||||
- **Breaking**: a renamed or removed workflow, input, secret name or output; a
|
||||
raised default tool version or changed default that can turn a green
|
||||
consumer red; a changed meaning of pass or fail. A release with a Breaking
|
||||
entry has a new major version.
|
||||
- **Added**: a new optional input, workflow or capability.
|
||||
- **Changed**: a change with no visible effect for existing callers.
|
||||
- **Fixed**: a fix.
|
||||
|
||||
`python tools/changelog.py check` verifies the file, and
|
||||
`python tools/changelog.py notes <version>` prints the text of a release page.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.0.0] - 2026-10-10
|
||||
|
||||
First release. The reusable workflow can be pinned at `v1` or `v1.0.0`. The
|
||||
scoped workflows are delivered by the instance from `main` and cannot be pinned.
|
||||
|
||||
### Added
|
||||
|
||||
- Workflow `release.yml`: started by hand with a version, it releases only the
|
||||
tip of `main` whose validation run is green and whose changelog entry exists,
|
||||
creates the version tag, the release page and the major tag, and does nothing
|
||||
but check until `dry_run` is set to `false`.
|
||||
- Scoped workflow `sync-github-metadata.yml`: copies the description and topics
|
||||
of a Gitea repository to its GitHub push mirror on every push to `main`, by
|
||||
hand and daily at 03:17 UTC. A repository without a GitHub mirror is skipped
|
||||
successfully.
|
||||
- A credential preflight before any change, and failure messages that name
|
||||
their category (`configuration`, `credentials`, `permissions`, `api`).
|
||||
- Scoped workflow `publish-wiki.yml`: publishes `wiki/` to the repository wiki
|
||||
when a repository has opted in with `wiki/.publish`; the word `prune` in that
|
||||
file also deletes pages that are not in `wiki/`.
|
||||
- Reusable workflow `quality-checks.yml`: `ruff`, `mypy --strict`, `shellcheck`
|
||||
and `shfmt` on the tracked Python and shell files, with the inputs
|
||||
`languages`, `working-directory` and one pinned version per tool.
|
||||
- Guides for onboarding a repository, workflow credentials, troubleshooting,
|
||||
reading quality-check results and releasing, and the same pages on the wiki in
|
||||
English, Danish and Bahasa Malaysia.
|
||||
|
||||
### Changed
|
||||
|
||||
- The scripts of the scoped workflows are files under `tools/`, fetched by a
|
||||
checkout of this repository, instead of Python embedded in the YAML.
|
||||
- Secrets hold the bare token as clear text: `TOKEN_FOR_GITEA`,
|
||||
`PAT_FOR_GITHUB` and `TOKEN_FOR_GITEA_WIKI`. They replace the JSON secret
|
||||
`CREDENTIALS_FOR_GITHUB`, which is no longer read.
|
||||
@@ -0,0 +1,661 @@
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
@@ -0,0 +1,147 @@
|
||||
# 🚀 TirSystem GitHub Actions
|
||||
|
||||
A collection of reusable Gitea Actions workflows for DevOps professionals and software engineers working on TirSystem projects.
|
||||
|
||||
## 📚 Table of Contents
|
||||
|
||||
- [Overview](#-overview)
|
||||
- [Requirements](#-requirements)
|
||||
- [Setup](#-setup)
|
||||
- [Run](#-run)
|
||||
- [Tests](#-tests)
|
||||
- [License](#-license)
|
||||
- [Links](#-links)
|
||||
|
||||
## 🧭 Overview
|
||||
|
||||
This repository is the central collection of reusable automation for TirSystem repositories. The primary repository lives at `git.tirsystem.com` (Gitea) and is push-mirrored to GitHub.
|
||||
|
||||
It currently contains the Gitea workflow [`sync-github-metadata.yml`](.gitea/scoped_workflows/sync-github-metadata.yml), which copies the repository description and topics from Gitea to the GitHub mirror on every push to `main`, on manual dispatch, and daily at 03:17 UTC.
|
||||
|
||||
## 📋 Requirements
|
||||
|
||||
- A Gitea instance with Actions enabled and a runner providing `ubuntu-latest` with `python3`
|
||||
- A configured GitHub push mirror on the Gitea repository (at most one; repositories without a mirror are skipped successfully)
|
||||
- Repository secrets:
|
||||
- `TOKEN_FOR_GITEA`: Gitea API token (the token only, no JSON)
|
||||
- `PAT_FOR_GITHUB`: a GitHub personal access token allowed to edit the mirror repository (the token only, no JSON)
|
||||
- `TOKEN_FOR_GITEA_WIKI` (only for repositories that publish a wiki, see the [onboarding guide](guides/onboarding.md)): a Gitea token that can write the wiki, stored as a secret of the repository's organization; there is no fallback to `TOKEN_FOR_GITEA`
|
||||
|
||||
## 🛠️ Setup
|
||||
|
||||
No dependencies need to be installed; the workflow uses only the Python standard library.
|
||||
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone ssh://git@git.tirsystem.com:10022/TirSystem/github-action.git
|
||||
```
|
||||
2. Add the secrets listed under [Requirements](#-requirements) to the repository settings in Gitea.
|
||||
3. Configure the GitHub push mirror in the repository settings.
|
||||
|
||||
## ▶️ Run
|
||||
|
||||
Workflows run automatically on push to `main` and on the daily schedule. To run manually, trigger **Sync GitHub mirror metadata** via `workflow_dispatch` from the Actions tab in Gitea.
|
||||
|
||||
## 🧪 Tests
|
||||
|
||||
The workflow files and the scripts in `tools/` are validated by offline tests that need no network access and no secrets:
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate # Windows PowerShell: .venv\Scripts\Activate.ps1
|
||||
python -m pip install -r tests/requirements.txt
|
||||
python -m pytest -q tests
|
||||
```
|
||||
|
||||
The same checks run on every pull request and push to `main` through [`validate-workflows.yml`](.gitea/workflows/validate-workflows.yml). They parse every workflow as YAML, check that none embeds Python, compile the scripts in `tools/`, require explicit job permissions, and test credential parsing, push mirror address parsing and the sync and publish flows against a fake API.
|
||||
|
||||
After a change to the sync workflow, also trigger **Sync GitHub mirror metadata** manually in Gitea and compare the description and topics on the GitHub mirror.
|
||||
|
||||
## 🟢 Capabilities
|
||||
|
||||
Rows that say Implemented or Guides written exist today. The rest is planned and tracked in the [Project Plan](docs/project-plan.md), which also describes each use case.
|
||||
|
||||
| Capability | Status |
|
||||
| --- | --- |
|
||||
| Synchronize repository metadata (Gitea to GitHub mirror) | Implemented in `.gitea/scoped_workflows/`, with offline tests and a validation workflow |
|
||||
| Configure and validate workflow credentials | Implemented for the sync workflow: preflight checks both tokens before any change ([guide](guides/credentials.md)) |
|
||||
| Onboard a repository, manage runners, diagnose failures | Guides written ([onboarding](guides/onboarding.md), [troubleshooting](guides/troubleshooting.md)); scoped delivery to other repositories not yet verified; brief use cases open (MIL-002) |
|
||||
| Publish a repository wiki from `wiki/` (opt-in, delivered to every organization) | Implemented in `.gitea/scoped_workflows/publish-wiki.yml`, with offline tests; the pilot in a second repository is pending (MIL-006) |
|
||||
| Shared quality checks (Python and shell) | Implemented as the reusable workflow `.gitea/workflows/quality-checks.yml`, with offline tests and a trial in a second organization; adoption in RepoFoundry is in review ([guide](guides/quality-checks.md)) |
|
||||
| Versioned release and publishing | Release process, changelog and upgrade guide defined; the release workflow exists; the first release `v1.0.0` is pending (MIL-004) ([guide](guides/upgrading.md)) |
|
||||
|
||||
### 🔄 Sync GitHub metadata
|
||||
|
||||
Syncs the Gitea repository description and topics to the GitHub push mirror.
|
||||
|
||||
#### 🕒 Cron
|
||||
|
||||
Daily at 03:17 UTC (`17 3 * * *`), plus every push to `main` and manual `workflow_dispatch`.
|
||||
|
||||
#### 🔀 Workflow
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
title Sync Gitea repository description and topics to GitHub
|
||||
|
||||
autonumber
|
||||
|
||||
actor "Push to main,\nmanual trigger, or schedule" as Trigger
|
||||
participant "Gitea Actions\nsync-github-metadata" as Workflow
|
||||
participant "Gitea REST API" as Gitea
|
||||
participant "GitHub REST API" as GitHub
|
||||
|
||||
Trigger -> Workflow: Start workflow
|
||||
activate Workflow
|
||||
|
||||
Workflow -> Workflow: Read and validate secrets
|
||||
note right
|
||||
TOKEN_FOR_GITEA
|
||||
PAT_FOR_GITHUB
|
||||
end note
|
||||
|
||||
alt secret validation failed
|
||||
Workflow --> Trigger: workflow failed
|
||||
end
|
||||
|
||||
|
||||
Workflow -> Gitea: GET /repos/{owner}/{repo}
|
||||
Gitea --> Workflow: Description and topics
|
||||
|
||||
Workflow -> Gitea: GET /repos/{owner}/{repo}/push_mirrors
|
||||
Gitea --> Workflow: Push mirror response
|
||||
|
||||
alt mirrors is not a list
|
||||
Workflow --> Trigger: Log a warning and succeed\n(GitHub metadata not synced)
|
||||
else mirrors is a list with no GitHub mirror
|
||||
Workflow --> Trigger: Log that there is nothing to sync and succeed
|
||||
else mirrors is a list
|
||||
Workflow -> Workflow: Find GitHub owner and repo from remote_address
|
||||
|
||||
Workflow -> GitHub: PATCH /repos/{owner}/{repo}\n{description}
|
||||
GitHub --> Workflow: Repository updated
|
||||
|
||||
Workflow -> GitHub: PUT /repos/{owner}/{repo}/topics\n{names}
|
||||
GitHub --> Workflow: Topics updated
|
||||
|
||||
Workflow --> Trigger: Sync completed
|
||||
else Gitea API denies access
|
||||
Gitea --> Workflow: HTTP 403 Forbidden
|
||||
Workflow --> Trigger: Workflow fails
|
||||
else GitHub API denies access
|
||||
GitHub --> Workflow: HTTP error
|
||||
Workflow --> Trigger: Workflow fails
|
||||
end
|
||||
deactivate Workflow
|
||||
@enduml
|
||||
```
|
||||
|
||||
## 📄 License
|
||||
|
||||
Licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See [LICENSE](LICENSE).
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
- [Repository](https://git.tirsystem.com/TirSystem/github-action)
|
||||
- [Documentation](https://git.tirsystem.com/TirSystem/github-action#readme)
|
||||
- [Issue tracker](https://git.tirsystem.com/TirSystem/github-action/issues)
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="90" height="20" role="img" aria-label="code files: 12"><title>code files: 12</title><rect width="60" height="20" fill="#555"/><rect x="60" width="30" height="20" fill="#007ec6"/><text x="5" y="14" fill="#fff" font-size="11">files</text><text x="65" y="14" fill="#fff" font-size="11">12</text></svg>
|
||||
|
Before Width: | Height: | Size: 346 B |
@@ -0,0 +1,106 @@
|
||||
# ADR-0001: Wiki structure, page names and languages
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | ADR-0001 |
|
||||
| CrossReference | [MIL-005], [BC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S01 | Initial version | [f5fb023] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Reviewed (RC-012): decision stated in two sentences, rules moved below it | [d0618d9] |
|
||||
|
||||
Allowed Status values: `Proposed`, `Accepted`, `Rejected`, `Deprecated`, `Superseded by ADR-NNNN`.
|
||||
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
MIL-005 puts the documentation on the Gitea wiki in English, Danish and
|
||||
Bahasa Malaysia. Before translations are written, three things must be fixed,
|
||||
because the generator, the publishing workflow and the translators all depend
|
||||
on them: which pages exist, how a translated page is named, and which copy is
|
||||
authoritative.
|
||||
|
||||
Forces:
|
||||
|
||||
- The Gitea wiki is a flat list of pages; a hyphen in a page name is shown as
|
||||
a space, and a `/` in a name needs encoding in links and in the REST API.
|
||||
- The English pages are generated from `README.md` and `guides/`
|
||||
(`tools/build_wiki.py`) and published only by the workflow from `main`
|
||||
(task 8). A translation must therefore live in this repository too, so it is
|
||||
reviewed like any other change.
|
||||
- A translation silently goes stale when the English page changes. Rule 8 of
|
||||
`AGENTS.md` requires each translated page to name the English source it
|
||||
follows, so staleness must be detectable without the network.
|
||||
- The Business Case sets no deadline and the Product Owner language is
|
||||
English, so English stays the single authoritative text.
|
||||
|
||||
Options for the page name of a translation:
|
||||
|
||||
1. **Suffix with a dot:** `Home` (English), `Home.da`, `Home.ms`. One flat
|
||||
namespace, English has no suffix, and the files are `wiki/Home.da.md`.
|
||||
2. **Folder per language:** `da/Home`, `ms/Home`. Mirrors the repository
|
||||
layout but needs encoded links and an encoded API path.
|
||||
3. **Suffix with a hyphen:** `Home-da`. Simple, but Gitea reads the hyphen as
|
||||
a space, so the title shows as "Home da".
|
||||
|
||||
Options for the source of truth of a translation:
|
||||
|
||||
1. **Generated by machine on every change.** No stale pages, but no review by
|
||||
a native reader and wording that changes between runs.
|
||||
2. **Written once, kept in `wiki/`, reviewed, and checked for staleness.**
|
||||
Reviewed wording is stable; staleness is flagged by a check.
|
||||
|
||||
## Decision
|
||||
|
||||
A translation is named `<Page>.da` or `<Page>.ms`, written by hand in
|
||||
`wiki/<Page>.<lang>.md`, reviewed by a native reader and checked against a
|
||||
recorded hash of the English page. The English page has no suffix, is
|
||||
generated, and stays authoritative.
|
||||
|
||||
The rules that follow from it:
|
||||
|
||||
- The wiki has five pages: Home, Onboarding, Credentials, Troubleshooting and
|
||||
Capabilities, each also as `.da` and `.ms` (15 files in `wiki/`).
|
||||
- Each translation starts with the comment
|
||||
`<!-- translation of <Page>.md, source sha256 <first 12 hex of the English file> -->`,
|
||||
so a check can report a translation whose English source has changed.
|
||||
- Code blocks, commands, file names and the workflows' error messages stay in
|
||||
English.
|
||||
- Terms are kept consistent through a term list (`docs/wiki-terms.md`, created
|
||||
in MIL-005 task 4).
|
||||
|
||||
## Consequences
|
||||
|
||||
**Positive:**
|
||||
|
||||
- One flat set of 15 pages that the existing generator and publisher handle
|
||||
without a new code path.
|
||||
- A stale translation is detectable offline from the recorded hash.
|
||||
- Translations are reviewed and stable, and reach the wiki only by merge.
|
||||
|
||||
**Negative:**
|
||||
|
||||
- Dots in page names are not yet verified on this wiki; MIL-005 task 7 (#38)
|
||||
must publish and open them. The fallback is `Home_da`, which changes only
|
||||
the file names and links.
|
||||
- A translation is not updated by itself; a person must re-translate when the
|
||||
check reports it stale, so the translations can lag the English pages.
|
||||
- The check, and the language switcher line at the top of each page, are
|
||||
still to be built in task 4.
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- [MIL-005] — closes task 1 (issue #32) and defines the naming that tasks 4
|
||||
and 5 follow.
|
||||
- [BC-001] — the wiki in three languages is in its scope list.
|
||||
|
||||
---
|
||||
|
||||
[MIL-005]: ../milestones/mil-005-wiki-and-translations.md
|
||||
[BC-001]: ../business-case.md
|
||||
[f5fb023]: https://git.tirsystem.com/TirSystem/github-action/commit/f5fb0238f36cbb98de482c68842fc60c7ce959e2
|
||||
[d0618d9]: https://git.tirsystem.com/TirSystem/github-action/commit/d0618d929f2ec274d30b10bb1be306e1f04c31ee
|
||||
@@ -0,0 +1,70 @@
|
||||
# ADR-0002: S01 approves as stand-in for other reviewers
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | ADR-0002 |
|
||||
| CrossReference | [SA-001], [RC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [bc3bd07] |
|
||||
|
||||
Allowed Status values: `Proposed`, `Accepted`, `Rejected`, `Deprecated`, `Superseded by ADR-NNNN`.
|
||||
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
The project plan names reviewers by stakeholder ID: S01 (Product Owner) is
|
||||
the approving reviewer, S05 (DevOps owner and security authority) owns the
|
||||
milestones, and S03 operates runners and secrets. The Stakeholder Analysis
|
||||
([SA-001]) says credential, token and permission design cannot be accepted
|
||||
without S05, and the Business Case lists S05's review of every security-relevant
|
||||
change as the mitigation for a risk. In practice S01 has been approving
|
||||
documents and has stood in for S05 and S03 (the first time is recorded in
|
||||
[RC-001]), because there is currently one person doing all three roles. The
|
||||
framework also requires that a reviewer is not the author of an artifact.
|
||||
|
||||
Options:
|
||||
|
||||
1. **Require each named person to review.** The record is independent, but
|
||||
work waits for a person who is not available in the project's current
|
||||
setup, and the S05 actions in RC-001 and RC-011 stayed open.
|
||||
2. **S01 approves for everyone and the records say so.** Work continues, and
|
||||
each record names who really approved.
|
||||
3. **Drop the other reviewers from the documents.** Simple, but it hides who
|
||||
is accountable and removes the way back to independent review.
|
||||
|
||||
## Decision
|
||||
|
||||
An artifact approved by S01 counts as approved for the stakeholders named
|
||||
as its reviewers or action owners (S05, S03), and the record says that S01
|
||||
stood in. This applies to every artifact of this project, including the review
|
||||
records themselves, until a named stakeholder asks to review in their own
|
||||
right; that person's review then replaces the stand-in for later changes.
|
||||
|
||||
## Consequences
|
||||
|
||||
**Positive:**
|
||||
|
||||
- Work is not blocked by a reviewer who is not present, and the records stay honest about who approved.
|
||||
- The way back to independent review is kept: the stakeholder IDs stay in the documents.
|
||||
|
||||
**Negative:**
|
||||
|
||||
- No independent check: the author, the approving reviewer and the stand-in are the same person, so a security-relevant change (credentials, tokens, permissions, workflow code) has had no second reader.
|
||||
- It conflicts with the text of [SA-001] (S05 must accept credential, token and permission design) and with the Business Case mitigation "S05 reviews every change"; both still say so and need an amendment, or S05 needs to be told.
|
||||
- The framework rule that the reviewer must not be the author is not met; this is a project deviation to be taken upstream, not a framework change.
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- [SA-001] — the statement that credential, token and permission design cannot be accepted without S05 no longer holds.
|
||||
- [RC-001] — its action item for an independent S05 review is closed by this decision; the other records that refer to it follow.
|
||||
|
||||
---
|
||||
|
||||
[SA-001]: ../stakeholder-analysis.md
|
||||
[RC-001]: ../sqa/reviews/rc-001-business-case.md
|
||||
[bc3bd07]: https://git.tirsystem.com/TirSystem/github-action/commit/bc3bd07b29a0a3dcf45045b9baac64c36144c6d1
|
||||
@@ -0,0 +1,71 @@
|
||||
# ADR-0003: Wiki publish token and dot-named page titles
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | ADR-0003 |
|
||||
| CrossReference | [MIL-005], [ADR-0001], [RC-011] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [bc3bd07] |
|
||||
|
||||
Allowed Status values: `Proposed`, `Accepted`, `Rejected`, `Deprecated`, `Superseded by ADR-NNNN`.
|
||||
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
The Publish wiki workflow (MIL-005 task 8) writes the Gitea wiki and so
|
||||
needs a token that can write to the repository. The existing `TOKEN_FOR_GITEA`
|
||||
only reads (`read:repository`) and is used by the metadata sync, so raising its
|
||||
scope would also give the sync write access. Gitea has no wiki-only scope.
|
||||
After the first publish two open points from [ADR-0001] and [RC-011] were
|
||||
answered: pages with a dot in the title are accepted, and the stored secret
|
||||
must hold the bare token string (a value of the form `NAME=token` is rejected
|
||||
with HTTP 401).
|
||||
|
||||
Options:
|
||||
|
||||
1. **Reuse `TOKEN_FOR_GITEA` and raise its scope.** One secret, but the
|
||||
metadata sync gets write access it does not need.
|
||||
2. **A separate `TOKEN_FOR_GITEA_WIKI` for a dedicated user.** One more
|
||||
secret to store and rotate, and the sync token stays read-only.
|
||||
3. **Push to the wiki repository by hand.** No secret, but unreviewed content
|
||||
and no record of who published.
|
||||
|
||||
## Decision
|
||||
|
||||
The wiki is published with a separate secret, `TOKEN_FOR_GITEA_WIKI`, holding
|
||||
a bare Gitea token with scope `write:repository` for a dedicated user that has
|
||||
write access to this repository only; the workflow falls back to
|
||||
`TOKEN_FOR_GITEA` only when it is absent. Dot-named titles (`Home.da`,
|
||||
`Home.ms`) are kept as ADR-0001 decided.
|
||||
|
||||
## Consequences
|
||||
|
||||
**Positive:**
|
||||
|
||||
- The metadata sync token stays read-only, so a leak of it cannot change the wiki or the code.
|
||||
- The first publish (run 65) created all 15 pages and a read-back matched `wiki/` byte for byte.
|
||||
- A rejected token is diagnosed from the log (length and shape, never the value).
|
||||
|
||||
**Negative:**
|
||||
|
||||
- One more secret to store and rotate, at organisation level for now; scoping it to this repository is a follow-up for the person who administers the secrets.
|
||||
- The fallback to `TOKEN_FOR_GITEA` can hide a missing wiki secret until a write is refused (HTTP 403).
|
||||
- The credentials guide and MIL-005 task 2 still say that S05 decides which token to use; the decision is recorded here.
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- [MIL-005] — task 2 and task 8 (issues #33 and #42) are settled by this decision.
|
||||
- [ADR-0001] — its negative consequence about dot-named titles is resolved: they work.
|
||||
- [RC-011] — its action items for the secret scope (S05) and for storing the secret (S03) are done.
|
||||
|
||||
---
|
||||
|
||||
[MIL-005]: ../milestones/mil-005-wiki-and-translations.md
|
||||
[ADR-0001]: ./adr-0001-wiki-structure-and-languages.md
|
||||
[RC-011]: ../sqa/reviews/rc-011-mil-005-wiki-publishing.md
|
||||
[bc3bd07]: https://git.tirsystem.com/TirSystem/github-action/commit/bc3bd07b29a0a3dcf45045b9baac64c36144c6d1
|
||||
@@ -0,0 +1,117 @@
|
||||
# ADR-0004: Opt-in rule and secret handling of the shared wiki publisher
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | ADR-0004 |
|
||||
| CrossReference | [MIL-006], [ADR-0003], [ADR-0002] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S01 | Initial version | [b22a2cd] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Reviewed (RC-018): the `prune` variant added to the evaluated options | [b22a2cd] |
|
||||
|
||||
Allowed Status values: `Proposed`, `Accepted`, `Rejected`, `Deprecated`, `Superseded by ADR-NNNN`.
|
||||
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
MIL-006 turns the Publish wiki workflow into a scoped workflow, which Gitea
|
||||
runs in every repository of every organisation on the instance (verified,
|
||||
issue #9). The publisher writes to a repository's wiki and removes pages that
|
||||
are not in `wiki/`. Without a gate, any of the 26 repositories of
|
||||
`Tirsvad-Udemy-100-days-of-code`, or any other repository, that happens to
|
||||
have a `wiki/` folder would have its wiki overwritten or emptied by a
|
||||
workflow it never asked for. The secret is also per organisation, so the
|
||||
shared workflow must say what happens where it is missing, and
|
||||
[ADR-0003] let this repository fall back to `TOKEN_FOR_GITEA`.
|
||||
|
||||
Options for how a repository opts in:
|
||||
|
||||
1. **A marker file `wiki/.publish`** on the default branch. Visible in the
|
||||
repository, reviewed in a pull request, and nothing to configure in an
|
||||
organisation. It comes in two forms:
|
||||
- **(a) the marker alone** makes the wiki equal `wiki/`, so pages that are
|
||||
not in the folder are deleted, as in ADR-0003;
|
||||
- **(b) the marker plus the word `prune`** in it: without the word the
|
||||
workflow only creates and updates pages, and deleting is a second,
|
||||
explicit choice.
|
||||
2. **A repository variable** (for example `PUBLISH_WIKI=true`). Not part of
|
||||
the repository content, so it is not reviewed or versioned, and it has to
|
||||
be set in the web interface once per repository.
|
||||
3. **An allow list** in this repository. One place to read, but every
|
||||
repository in every organisation has to ask this repository for a change.
|
||||
4. **Publish whenever `wiki/` exists.** No setup, which is the risk the gate
|
||||
is meant to remove.
|
||||
|
||||
Option 1(b) is chosen for the reason in the first paragraph: a repository
|
||||
that adds `wiki/` to a wiki it wrote by hand should not lose that wiki by
|
||||
opting in.
|
||||
|
||||
Options for the secret:
|
||||
|
||||
1. **`TOKEN_FOR_GITEA_WIKI` of the organisation only.** The sync token stays
|
||||
read-only everywhere.
|
||||
2. **Fall back to `TOKEN_FOR_GITEA`** as in ADR-0003. A missing wiki secret is
|
||||
hidden until a write is refused (HTTP 403).
|
||||
|
||||
## Decision
|
||||
|
||||
A repository opts in by committing `wiki/.publish` on its default branch; the
|
||||
file may contain the single word `prune`, which is the only thing that lets the
|
||||
workflow delete wiki pages that are not in `wiki/`, and without the marker the
|
||||
workflow ends successfully without any request. The shared workflow uses the
|
||||
organisation's `TOKEN_FOR_GITEA_WIKI` only, and fails with a configuration
|
||||
error when a repository has opted in and the secret is missing.
|
||||
|
||||
The rules that follow from it:
|
||||
|
||||
- Without `prune` the workflow only creates and updates pages.
|
||||
- An empty `wiki/` (no Markdown page) never deletes anything, with or without
|
||||
`prune`.
|
||||
- A repository that has not opted in is skipped with one log line, so its
|
||||
runs stay green.
|
||||
- This repository commits `wiki/.publish` containing `prune`, because its wiki
|
||||
must equal `wiki/` (ADR-0001, ADR-0003).
|
||||
- The fallback to `TOKEN_FOR_GITEA` of ADR-0003 is removed from the shared
|
||||
workflow; the sync token is read-only everywhere.
|
||||
|
||||
## Consequences
|
||||
|
||||
**Positive:**
|
||||
|
||||
- A repository that did not opt in is never written to, and the marker is a
|
||||
reviewed change in the repository that wants it.
|
||||
- Deleting pages is a second, explicit choice, so adopting the workflow in a
|
||||
repository with hand-written wiki pages loses nothing.
|
||||
- A missing wiki secret is reported where it happens, in the repository that
|
||||
opted in, and the sync token never gets write access.
|
||||
|
||||
**Negative:**
|
||||
|
||||
- Each organisation that wants this needs its own `TOKEN_FOR_GITEA_WIKI`; it
|
||||
cannot borrow the sync token.
|
||||
- A repository that opts in without `prune` keeps pages that were removed from
|
||||
`wiki/`, so its wiki can drift from the folder until someone adds `prune`.
|
||||
- Anyone with write access to a repository can opt it in and, with `prune`,
|
||||
make the workflow delete its wiki pages; that is the intended scope of write
|
||||
access, but it is not a separate approval.
|
||||
- The change supersedes the fallback part of [ADR-0003], so the credentials
|
||||
guide and the wiki pages that mention it need an update (MIL-006 task 5).
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- [MIL-006] — tasks 2, 3 and 4 (issues #57 to #59) implement and pilot this
|
||||
decision.
|
||||
- [ADR-0003] — its fallback to `TOKEN_FOR_GITEA` no longer applies to the
|
||||
shared workflow.
|
||||
- [ADR-0002] — the stand-in rule applies to the review of this ADR.
|
||||
|
||||
---
|
||||
|
||||
[MIL-006]: ../milestones/mil-006-shared-wiki-publishing.md
|
||||
[ADR-0003]: ./adr-0003-wiki-publish-token.md
|
||||
[ADR-0002]: ./adr-0002-s01-approves-as-stand-in.md
|
||||
[b22a2cd]: https://git.tirsystem.com/TirSystem/github-action/commit/b22a2cd59235078656c4440b945b787f88fbd345
|
||||
@@ -0,0 +1,124 @@
|
||||
# ADR-0005: Contract of the shared quality-check workflow
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | ADR-0005 |
|
||||
| CrossReference | [MIL-003], [UC-005], [US-001], [ADR-0004] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S01 | Initial version | [385d2fb] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Reviewed (RC-038): the security impact of installing the tools from PyPI named | [385d2fb] |
|
||||
|
||||
Allowed Status values: `Proposed`, `Accepted`, `Rejected`, `Deprecated`, `Superseded by ADR-NNNN`.
|
||||
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
MIL-003 offers one workflow that any repository calls to run lint, format and
|
||||
type checks. Before it is built (task 3) its inputs and the meaning of a pass
|
||||
and a fail must be fixed, because consumers in four organizations will depend
|
||||
on them and MIL-004 will version them. Facts found on 2026-10-10:
|
||||
|
||||
- The runner image (Ubuntu 24.04, Python 3.12, `git`, Node.js, `jq`, `make`,
|
||||
run as `root`) has **none** of ruff, mypy, pytest, shellcheck or shfmt.
|
||||
- PyPI is reachable, and a virtual environment installs all four tools with
|
||||
pinned versions: `ruff` 0.6.9, `mypy` 1.11.2, `shellcheck-py` 0.10.0.1
|
||||
(ShellCheck 0.10.0) and `shfmt-py` 3.11.0.2 (shfmt 3.11.0).
|
||||
- Each tool exits non-zero on a finding and prints `path:line` and a message.
|
||||
`shellcheck` also exits 1 on an empty file, so a language with no files must
|
||||
be skipped before the tool runs.
|
||||
- Reusable workflows work from the same repository and from other
|
||||
organizations (issue #15). Secrets passing is untested, and the checks need
|
||||
none.
|
||||
- The conventions name the tools: ruff and `mypy --strict` for Python
|
||||
(QC-PY-001) and shellcheck and shfmt for shell (QC-SH-001).
|
||||
|
||||
Options for the shape of the workflow:
|
||||
|
||||
1. **One reusable workflow with a `languages` input** that selects the tool
|
||||
sets, defaults that work with no configuration, and one version input per
|
||||
tool.
|
||||
2. **One reusable workflow per language** (`python-checks.yml`,
|
||||
`shell-checks.yml`). Simple, but a mixed repository calls two workflows and
|
||||
the contract exists twice.
|
||||
3. **Detect the languages from the files and take no inputs.** Zero
|
||||
configuration, but a repository cannot opt out of a tool, and versions
|
||||
change only with the workflow.
|
||||
4. **The consumer passes its own commands.** Most flexible, but it is not a
|
||||
shared check any more and defeats the point of a contract.
|
||||
|
||||
## Decision
|
||||
|
||||
The shared workflow `quality-checks.yml` is one reusable workflow with the
|
||||
inputs `languages` (a comma list of `python` and `shell`, default both),
|
||||
`working-directory` (default `.`) and one version input per tool whose
|
||||
defaults are the pinned versions above, and it installs the tools from PyPI
|
||||
into a virtual environment. A run passes when every selected tool exits 0 and
|
||||
fails when any exits non-zero, and a language with no files is skipped with a
|
||||
notice and counts as a pass.
|
||||
|
||||
The rules that follow from it:
|
||||
|
||||
- **Python:** `ruff check`, `ruff format --check` and `mypy --strict`, run on
|
||||
the files under `working-directory`.
|
||||
- **Shell:** the tracked `*.sh` files are checked with `shellcheck` and
|
||||
`shfmt -d`.
|
||||
- **Configuration:** projects configure the tools in the standard way
|
||||
(`pyproject.toml`, `.shellcheckrc`, `.editorconfig`); the workflow adds none
|
||||
and changes no file.
|
||||
- **Reporting:** each tool runs in its own log group named after the tool, and
|
||||
its own output carries `path:line` and the message; the job status is the
|
||||
pull request status.
|
||||
- **Out of scope for the first version:** running the project's tests
|
||||
(`pytest` needs the project's dependencies), auto-fixing, and other
|
||||
languages.
|
||||
|
||||
## Consequences
|
||||
|
||||
**Positive:**
|
||||
|
||||
- A repository gets the checks with one `uses:` and no configuration, and a
|
||||
mixed repository gets both language sets from one call.
|
||||
- Tool versions are explicit and reviewed, so a new tool release cannot turn
|
||||
every consumer red overnight.
|
||||
- A failure is read from the tool's own message, so the workflow needs no
|
||||
parser of its own.
|
||||
|
||||
**Negative:**
|
||||
|
||||
- Every run installs the tools from PyPI (about half a minute) and depends on
|
||||
PyPI being reachable; caching is not part of the first version.
|
||||
- Projects that need their tests or their own dependencies in the type check
|
||||
(`mypy` with third-party stubs) must configure that themselves or wait for a
|
||||
later version.
|
||||
- `mypy --strict` on an existing codebase is likely to fail at first; a
|
||||
project that cannot meet it has to configure the tool, which weakens the
|
||||
shared meaning of "pass".
|
||||
- Pinned versions need a release (MIL-004) to move; until then they are
|
||||
updated by changing the workflow on `main`.
|
||||
- **Security:** the tools are downloaded from PyPI on every run and execute
|
||||
with the consumer's repository content on a runner that runs as `root`.
|
||||
Versions are pinned but the packages are not hash-pinned, so a
|
||||
compromised release of one of the four packages would reach every
|
||||
consumer; hash pinning is a later hardening step.
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- [MIL-003] — tasks 3 to 5 (issues #17 to #19) implement, adopt and document
|
||||
this contract.
|
||||
- [UC-005] — the use case this contract serves.
|
||||
- [US-001] — stories US-001.09 and US-001.10 state its acceptance criteria.
|
||||
- [ADR-0004] — the same pattern of a shared scoped or reusable workflow with an
|
||||
explicit gate; this ADR does not change it.
|
||||
|
||||
---
|
||||
|
||||
[MIL-003]: ../milestones/mil-003-quality-checks.md
|
||||
[UC-005]: ../uc-005/uc.md
|
||||
[US-001]: ../user-stories.md
|
||||
[ADR-0004]: ./adr-0004-shared-wiki-publishing-opt-in.md
|
||||
[385d2fb]: https://git.tirsystem.com/TirSystem/github-action/commit/385d2fb7cb9be1fdc8fd3503d0af624fa38eafc7
|
||||
@@ -0,0 +1,137 @@
|
||||
# ADR-0006: Release process and version pinning
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | ADR-0006 |
|
||||
| CrossReference | [MIL-004], [UC-006], [US-001], [ADR-0004], [ADR-0005] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S01 | Initial version | [044d8ba] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Reviewed (RC-043): SemVer expanded at first use | [044d8ba] |
|
||||
|
||||
Allowed Status values: `Proposed`, `Accepted`, `Rejected`, `Deprecated`, `Superseded by ADR-NNNN`.
|
||||
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
Every consumer of the shared workflows runs this repository's code, and today
|
||||
that code is whatever `main` holds: the scoped workflows (sync and publish
|
||||
wiki) are delivered from `main` and fetch their scripts at `ref: main`, and
|
||||
the reusable quality-check workflow is called as `@main` in the guide. A merge
|
||||
to `main` therefore changes the pipelines of repositories in four
|
||||
organizations at their next run, with no version, no changelog and no way to
|
||||
stay on the previous behaviour. MIL-004 gives releases a version.
|
||||
|
||||
Facts that shape the decision:
|
||||
|
||||
- A reusable workflow is referenced with `@<ref>` where the ref may be a
|
||||
branch or a tag (verified on 2026-10-10), and a tag is not deleted when a
|
||||
pull request is merged, unlike the branch the first trial used.
|
||||
- A **scoped** workflow is delivered by the instance from `main` of this
|
||||
repository; a consumer cannot pin it. Only what the workflow fetches (the
|
||||
script files) and what a consumer calls explicitly (the reusable workflow)
|
||||
can be pinned.
|
||||
- The repository has a validation run (YAML parse, offline tests, wiki
|
||||
freshness) that is green or red per commit, and no release process, no
|
||||
changelog and no tags yet.
|
||||
|
||||
Options for the unit and the scheme of a version:
|
||||
|
||||
1. **One version for the whole repository** with a semantic version (SemVer) tag `vMAJOR.MINOR.PATCH`
|
||||
and a moving major tag `vMAJOR`. One changelog, one release page.
|
||||
2. **One version per workflow** (`quality-checks/v1.2.0`). Precise, but five
|
||||
moving parts for one maintainer, and the scripts and guides span several
|
||||
workflows.
|
||||
3. **Date-based tags** (`2026.10.10`). Simple, but they say nothing about
|
||||
whether a change is breaking.
|
||||
4. **No versions; consumers copy the files.** The situation MIL-002 moved away
|
||||
from.
|
||||
|
||||
Options for how a consumer pins:
|
||||
|
||||
a. **Exact tag** (`@v1.2.0`): never changes, never receives fixes.
|
||||
b. **Moving major tag** (`@v1`): receives compatible releases only.
|
||||
c. **`@main`**: always the newest, unreviewed by the consumer.
|
||||
|
||||
## Decision
|
||||
|
||||
The repository is released as a whole with a SemVer tag `vMAJOR.MINOR.PATCH`
|
||||
and a moving major tag `vMAJOR` that always points to the latest compatible
|
||||
release, and consumers pin `@vMAJOR` or an exact tag and never `@main`. A
|
||||
release is created from `main` only when the validation run of that exact
|
||||
commit is green and `CHANGELOG.md` has an entry for the version that marks
|
||||
each breaking change, and it is announced by a release page generated from
|
||||
that entry.
|
||||
|
||||
The rules that follow from it:
|
||||
|
||||
- **Breaking (new major):** renaming or removing a workflow, an input, a
|
||||
secret name or an output; raising a default tool version or changing a
|
||||
default so that a previously green consumer can turn red; changing the
|
||||
meaning of a pass or a fail (ADR-0005).
|
||||
- **Minor:** a new optional input, a new workflow or a new capability that
|
||||
changes nothing for existing callers. **Patch:** a fix, or a change of
|
||||
documentation or tests, with no visible change for consumers.
|
||||
- **First release:** `v1.0.0`, with `v1` pointing to it.
|
||||
- **Tags are not deleted or moved,** except that the major tag moves forward
|
||||
with each compatible release and may be moved back to the previous exact
|
||||
tag when a release proves faulty.
|
||||
- **Who:** the DevOps Professional (S05) cuts the release and S01 approves it;
|
||||
a release that touches credentials, tokens or permissions says so in the
|
||||
changelog.
|
||||
- **Scripts:** once `v1` exists the scoped workflows fetch their scripts at
|
||||
`ref: v1` instead of `main`, so that a merge to `main` stops reaching
|
||||
consumers until it is released.
|
||||
- **Not automated yet:** the steps are a checklist in
|
||||
`guides/release-process.md`; the release workflow is task 5 of MIL-004.
|
||||
|
||||
## Consequences
|
||||
|
||||
**Positive:**
|
||||
|
||||
- A consumer chooses between "never changes" (`@v1.2.0`) and "compatible
|
||||
fixes only" (`@v1`), and a breaking change cannot reach a pipeline that
|
||||
pins a major version.
|
||||
- A merge to `main` no longer reaches consumers of the scripts and the
|
||||
reusable workflow until it is released, so a faulty merge costs a revert,
|
||||
not an incident in four organizations.
|
||||
- The changelog gives S02 and S03 one place to see what changed and whether
|
||||
credentials or permissions are involved.
|
||||
|
||||
**Negative:**
|
||||
|
||||
- **A scoped workflow file is still delivered from `main`:** a consumer cannot
|
||||
pin it, so a bad merge of `sync-github-metadata.yml` or `publish-wiki.yml`
|
||||
still reaches every repository at its next run. Review of `main` is the only
|
||||
protection for those two files, and the release process cannot change that.
|
||||
- Moving the major tag needs permission to force-update a tag, which is a
|
||||
second sensitive permission next to merging.
|
||||
- One version for the whole repository means a fix to one workflow produces a
|
||||
release for all, and a consumer of one workflow sees changelog entries that
|
||||
concern another.
|
||||
- Raising a default tool version is treated as breaking, so keeping the
|
||||
quality checks current costs a major version each time.
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- [MIL-004] — tasks 2 to 5 (issues #21 to #24) implement the changelog and tag
|
||||
convention, the upgrade guide, the publish destination and the release
|
||||
workflow on this decision.
|
||||
- [UC-006] — the use case this process serves.
|
||||
- [US-001] — stories US-001.11 to US-001.13 state its acceptance criteria.
|
||||
- [ADR-0005] — its pinned tool versions become defaults that a release moves.
|
||||
- [ADR-0004] — the scoped publish-wiki workflow is covered by the limitation
|
||||
above.
|
||||
|
||||
---
|
||||
|
||||
[MIL-004]: ../milestones/mil-004-versioned-release.md
|
||||
[UC-006]: ../uc-006/uc.md
|
||||
[US-001]: ../user-stories.md
|
||||
[ADR-0004]: ./adr-0004-shared-wiki-publishing-opt-in.md
|
||||
[ADR-0005]: ./adr-0005-quality-check-contract.md
|
||||
[044d8ba]: https://git.tirsystem.com/TirSystem/github-action/commit/044d8ba21f96f4aceb807d62addc35cdcbb56051
|
||||
@@ -0,0 +1,107 @@
|
||||
# ADR-0007: Publish destination and token scope of a release
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | ADR-0007 |
|
||||
| CrossReference | [MIL-004], [UC-006], [ADR-0006] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version (RC-047) | [d9cd3c6] |
|
||||
|
||||
Allowed Status values: `Proposed`, `Accepted`, `Rejected`, `Deprecated`, `Superseded by ADR-NNNN`.
|
||||
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
ADR-0006 decides that this repository is released as a whole with a version
|
||||
tag and a release page generated from `CHANGELOG.md`. Task 4 of MIL-004 asks
|
||||
where a release is published and which permission publishing needs, before the
|
||||
release workflow (task 5) is written.
|
||||
|
||||
Facts that shape the decision:
|
||||
|
||||
- This repository contains workflows, scripts and guides. Nothing is compiled
|
||||
or packaged: a consumer receives a release by referencing the tag
|
||||
(`uses: ...@v1`), not by downloading a file.
|
||||
- The Gitea instance (1.27.3) offers, through its REST API, creation of tags
|
||||
and of releases, deletion of a tag, and attachments on a release.
|
||||
- The repository is mirrored to GitHub, but the shared workflows are called
|
||||
from Gitea runners of four organizations, so consumers read the Gitea copy.
|
||||
- Creating a release and moving the major tag are the two sensitive writes of
|
||||
the release process (ADR-0006).
|
||||
|
||||
Options for the destination:
|
||||
|
||||
1. **The release page of this repository** (tag plus notes from the changelog).
|
||||
2. **A package in the Gitea package registry** (for example a generic package
|
||||
holding an archive of the repository).
|
||||
3. **A release page on the GitHub mirror** in addition to option 1.
|
||||
4. **Tags only**, without a release page.
|
||||
|
||||
Options for the permission:
|
||||
|
||||
a. **The token the job receives for its own run**, limited to this repository.
|
||||
b. **A dedicated secret** with a personal access token that may write to this
|
||||
repository only.
|
||||
c. **The existing `TOKEN_FOR_GITEA`** of the organization.
|
||||
|
||||
## Decision
|
||||
|
||||
A release is published as the release page of `TirSystem/github-action` on
|
||||
Gitea, created from the changelog entry for the tag, with no package and no
|
||||
attachments, and the release workflow publishes it with the token its own run
|
||||
receives (options 1 and a). If that token proves unable to create the tag or
|
||||
to move the major tag, the fallback is a dedicated secret
|
||||
`TOKEN_FOR_GITEA_RELEASE` that may write to this repository only (option b).
|
||||
`TOKEN_FOR_GITEA` is not used for releases.
|
||||
|
||||
The rules that follow from it:
|
||||
|
||||
- **What is published:** the tag `vMAJOR.MINOR.PATCH`, the major tag, and one
|
||||
release page whose body is the output of
|
||||
`python tools/changelog.py notes x.y.z`.
|
||||
- **Permission needed:** write access to the contents of this repository
|
||||
(create a tag, create and edit a release, delete and recreate the major
|
||||
tag), nothing else. It needs no access to other repositories, to the wiki or
|
||||
to organization settings.
|
||||
- **The GitHub mirror** receives the tags through its normal mirroring and has
|
||||
no release page of its own; the changelog file is the same on both.
|
||||
- **A package registry is reconsidered** only if a release ever contains a
|
||||
built file that consumers download.
|
||||
|
||||
## Consequences
|
||||
|
||||
**Positive:**
|
||||
|
||||
- One place, the release page, shows what changed and whether to act, next to
|
||||
the tag consumers pin.
|
||||
- No new secret is stored while the job token is enough, and the permission is
|
||||
limited to one repository and the lifetime of one run.
|
||||
- Nothing to build, sign or version besides the tag.
|
||||
|
||||
**Negative:**
|
||||
|
||||
- The job token may not be allowed to move a tag where tag protection is set;
|
||||
this is not verified until the release workflow of task 5 runs, and the
|
||||
fallback needs a secret that someone must create and rotate.
|
||||
- Consumers on GitHub see tags but no release page.
|
||||
- Without attachments a consumer cannot download a release as a file; the tag
|
||||
is the only form.
|
||||
|
||||
## Affected Artifacts
|
||||
|
||||
- [MIL-004] — decides criterion 4 of its Go/No-Go table and unlocks task 5.
|
||||
- [UC-006] — "the release page for the tag is created from the changelog
|
||||
entry" states where.
|
||||
- [ADR-0006] — whose release steps this publishes.
|
||||
|
||||
---
|
||||
|
||||
[MIL-004]: ../milestones/mil-004-versioned-release.md
|
||||
[UC-006]: ../uc-006/uc.md
|
||||
[ADR-0006]: ./adr-0006-release-process-and-version-pinning.md
|
||||
[d9cd3c6]: https://git.tirsystem.com/TirSystem/github-action/commit/d9cd3c67d4017984af8958f32240d3d66217e153
|
||||
@@ -0,0 +1,48 @@
|
||||
# Artifact Registry
|
||||
|
||||
This project's artifact state. Types, short names and `CrossReference
|
||||
Candidates` come from the framework catalog
|
||||
(`framework/registry/artifact-catalog.md`); this file only records where
|
||||
each document lives in *this* project and the next version to use.
|
||||
|
||||
| Short Name | Artifact Type | Primary File | Next Available Version |
|
||||
| --- | --- | --- | --- |
|
||||
| BC | Business Case | docs/business-case.md | 002 |
|
||||
| SA | Stakeholder Analysis | docs/stakeholder-analysis.md | 002 |
|
||||
| PP | Project Plan | docs/project-plan.md | 002 |
|
||||
| MIL | Milestone / Gateway | docs/milestones/*.md | 007 |
|
||||
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 048 |
|
||||
| TM | Traceability Matrix | docs/sqa/traceability-matrix.md | 002 |
|
||||
| ADR | Architecture Decision Record | docs/adr/adr-NNNN-*.md | 0008 |
|
||||
| UCD | Use Case Diagram | docs/use-case-diagram.md | 002 |
|
||||
| US | User Story | docs/user-stories.md | 002 |
|
||||
| UC | Use Case | docs/uc-NNN/uc.md | 008 |
|
||||
|
||||
## Languages
|
||||
|
||||
| Setting | Value |
|
||||
| --- | --- |
|
||||
| PO language | en (English, IT) |
|
||||
| High-level register | IT Executive English |
|
||||
| Technical register | IT Professional English |
|
||||
|
||||
The PO language is English, so no PO-language translations are kept.
|
||||
|
||||
The Gitea wiki (MIL-005) is the one exception: its pages are kept in English
|
||||
(authoritative), Danish (`da`) and Bahasa Malaysia (`ms`). A translation is named
|
||||
`<Page>.<lang>` (`Home.da`) and names the English source it follows; see
|
||||
`docs/adr/adr-0001-wiki-structure-and-languages.md`.
|
||||
|
||||
| Artifact types | Register | Also kept as a PO-language file |
|
||||
| --- | --- | --- |
|
||||
| BC, KPI, PP, MIL | IT Executive English | No (PO language is English) |
|
||||
| SA, BMC, BPMN, UCD, US, UC, SSD, DM, RA, GOV, DICT | IT Professional English | No (PO language is English) |
|
||||
| OC, SD, DCD, ERD, ADR, TM, RC, QC, source code | IT Professional English | No |
|
||||
|
||||
## Notes
|
||||
|
||||
- "Next Available Version" is the zero-padded (3-digit) version to use the
|
||||
*next* time a new document of that type is created. Increment it only when
|
||||
a brand-new document is created, not when an existing document's
|
||||
`## Version History` gets a row.
|
||||
- `ADR` uses 4 digits (`0001`); `RC` is sequential across all artifact types.
|
||||
@@ -0,0 +1,153 @@
|
||||
# Business Case: TirSystem Reusable Workflows
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | BC-001 |
|
||||
| CrossReference | [SA-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S01 | A mirrored repository has at most one GitHub push mirror; repositories without one are skipped | [0c06789] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Scope: wiki pages in English, Danish and Bahasa Malaysia | [08ef26a] |
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
TirSystem repositories are hosted on a self-hosted Gitea instance and
|
||||
push-mirrored to GitHub. Automation that every repository needs is currently
|
||||
copied by hand. This project turns this repository into the single, reviewed
|
||||
collection of reusable Gitea Actions workflows for DevOps professionals and
|
||||
software engineers. Today it contains one workflow, which copies repository
|
||||
description and topics from Gitea to the GitHub mirror. The proposal is to
|
||||
harden that workflow first, document how repositories adopt it, and then add
|
||||
shared quality-check and release workflows in priority order.
|
||||
|
||||
## Methodological and Standards Foundation
|
||||
|
||||
Documents follow the SQA and QC framework in `framework/` (use cases after
|
||||
Larman, *Applying UML and Patterns*). Quality criteria are tagged with
|
||||
ISO/IEC 25010:2023 characteristics. The domain language is English (IT).
|
||||
|
||||
## Problem Statement
|
||||
|
||||
- The only workflow exists as three diverging copies (`src/`,
|
||||
`.gitea/scoped_workflows/`, and others), and the scoped copy
|
||||
currently contains a Python syntax error (`exit 0`).
|
||||
- There is no automated check of workflow files, so defects such as that one
|
||||
are found only when the workflow runs.
|
||||
- There is no documented way to onboard a repository, set up credentials,
|
||||
choose runners or diagnose a failed run.
|
||||
- Quality checks and release steps are not shared, so each project would
|
||||
reinvent them.
|
||||
|
||||
## Business Opportunity
|
||||
|
||||
A small, versioned, documented workflow collection lets every TirSystem
|
||||
repository adopt the same secure automation in minutes, and lets a fix be
|
||||
made once.
|
||||
|
||||
## Objectives
|
||||
|
||||
- **O1:** Keep the existing metadata sync correct, tested and documented as
|
||||
the single implemented capability.
|
||||
- **O2:** Provide one canonical copy of each workflow with a defined way to
|
||||
reach consuming repositories (scoped workflow or copy).
|
||||
- **O3:** Document and validate credentials, runner labels and failure
|
||||
diagnosis for every workflow.
|
||||
- **O4:** Offer shared quality-check and release workflows, versioned so
|
||||
consumers can adopt changes deliberately.
|
||||
|
||||
## Scope
|
||||
|
||||
### In Scope
|
||||
|
||||
- Gitea Actions workflows (and GitHub-compatible syntax where it is the same).
|
||||
- Documentation for DevOps professionals and software engineers.
|
||||
- A Gitea wiki with the same documentation in English, Danish and Bahasa Malaysia (MIL-005).
|
||||
- Validation of workflow files and their documentation.
|
||||
|
||||
### Out of Scope
|
||||
|
||||
- Operating the Gitea instance or runners themselves.
|
||||
- Application code of consuming repositories.
|
||||
- Features not backed by an accepted milestone task.
|
||||
- Behavior that is only proposed: documentation describes implemented
|
||||
workflows only; planned ones are marked as planned.
|
||||
|
||||
## Expected Benefits
|
||||
|
||||
### Tangible Benefits
|
||||
|
||||
- One fix reaches all consuming repositories.
|
||||
- Fewer failed runs caused by missing or over-broad credentials.
|
||||
- Less time to onboard a repository.
|
||||
|
||||
### Intangible Benefits
|
||||
|
||||
- Consistent, reviewable automation across TirSystem projects.
|
||||
- Higher trust in automation that touches credentials.
|
||||
|
||||
## Strategic Alignment
|
||||
|
||||
Supports TirSystem's practice of a self-hosted primary repository with
|
||||
public GitHub mirrors, and its SQA framework requirement that code follows
|
||||
accepted plans.
|
||||
|
||||
## Success Criteria
|
||||
|
||||
| # | Criterion | Target | Measure |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Workflow files that fail static validation | 0 on the default branch | Result of the validation task in MIL-001 |
|
||||
| 2 | Canonical copies per workflow | 1 | Count of files per workflow name |
|
||||
| 3 | Documented use cases that are implemented or marked planned | 100% | README capability table against workflows present |
|
||||
| 4 | Repositories consuming a shared workflow | At least 1 besides this one by MIL-002 | Consumer list in README |
|
||||
|
||||
## Risks
|
||||
|
||||
| Risk | Impact | Mitigation |
|
||||
| --- | --- | --- |
|
||||
| Gitea scoped workflows behave differently from assumption (feature and version not verified) | Onboarding design is wrong | Verify against the actual instance in MIL-002 before documenting it as supported. |
|
||||
| Token with excess scope is stored in secrets | Compromise of repositories | Document minimum scope; validate token permissions before use. |
|
||||
| A breaking change reaches consumers unannounced | Consumer pipelines fail | Version and changelog every release (MIL-004). |
|
||||
| Security-relevant change accepted without security review | Credential or permission defect reaches production | S05 reviews every change to credentials, tokens, permissions and workflow code. |
|
||||
|
||||
## Assumptions
|
||||
|
||||
- The Gitea instance has Actions enabled and an `ubuntu-latest` runner with `python3`.
|
||||
- A mirrored repository has at most one GitHub push mirror. Repositories without a GitHub mirror are skipped successfully.
|
||||
- S01 (Product Owner) and S05 (DevOps owner and security authority) are both maintainers.
|
||||
|
||||
## Constraints
|
||||
|
||||
- Workflows use only tools available on the runner; the current workflow uses the Python standard library only.
|
||||
- Secrets are supplied as repository or organization secrets, never committed.
|
||||
- Nothing is written under `src/` or `tests/` before the matching milestone is accepted.
|
||||
|
||||
## Cost–Benefit Assessment
|
||||
|
||||
| Costs | Benefits |
|
||||
| --- | --- |
|
||||
| Maintainer time for planning, documentation and tests (qualitative; no external cost) | Avoided duplication and fewer credential and configuration failures across repositories |
|
||||
|
||||
## Stakeholders
|
||||
|
||||
| Stakeholder ID (SA) | Interest in this project |
|
||||
| --- | --- |
|
||||
| S01 | Owns scope, accepts the documents and co-maintains the workflows |
|
||||
| S02 | Consumes shared workflows |
|
||||
| S03 | Operates runners and secrets |
|
||||
| S05 | Co-maintains the workflows and reviews their security |
|
||||
| S04 | Sees mirror metadata |
|
||||
|
||||
## Recommendation
|
||||
|
||||
Proceed — the first milestone fixes a known defect in the only existing workflow and the later ones add value only after it is accepted.
|
||||
|
||||
---
|
||||
|
||||
[SA-001]: ./stakeholder-analysis.md
|
||||
[0c06789]: https://git.tirsystem.com/TirSystem/github-action/commit/0c06789a2779382672712cd483f4964b28a0ebe9
|
||||
[08ef26a]: https://git.tirsystem.com/TirSystem/github-action/commit/08ef26a6d3eb98c066b45634c2271e578e6c0a0b
|
||||
@@ -0,0 +1,78 @@
|
||||
# MIL-001: Stabilise the metadata sync
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | MIL-001 |
|
||||
| CrossReference | [BC-001], [ADR-0002] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S01 | Task 1 decision amended: zero GitHub mirrors is a successful skip<br>Task 5 tests cover zero or several mirrors accordingly | [0c06789] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Target date 2026-10-17 confirmed on 2026-10-10 by S01 (stand-in for S05) | [ea06eaa] |
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
Decide whether the only implemented workflow is correct, tested and has one
|
||||
canonical copy, so later milestones build on a sound base.
|
||||
|
||||
## Deliverable
|
||||
|
||||
A single canonical metadata-sync workflow that passes automated validation
|
||||
and tests, a README that separates implemented from planned behavior, and a
|
||||
successful manual run on the Gitea instance.
|
||||
|
||||
## Go / No-Go Criteria
|
||||
|
||||
| # | Criterion (objectively checkable) | Go | No-Go |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | The embedded Python compiles and every workflow YAML parses in an automated check | Check passes | Any failure |
|
||||
| 2 | Exactly one canonical source per workflow; other copies are generated or removed | Count is 1 | Count above 1 |
|
||||
| 3 | Unit tests cover credential parsing and push mirror URL parsing, and run without network access or `.env` | Tests pass | Missing or failing |
|
||||
| 4 | README capability table matches the workflows present | Matches | Claims unimplemented behavior |
|
||||
| 5 | Manual `workflow_dispatch` run on Gitea succeeds and the GitHub description and topics match | Match | Mismatch or failure |
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Depends on | Reason |
|
||||
| --- | --- |
|
||||
| None | First milestone |
|
||||
|
||||
## Traceability
|
||||
|
||||
| Business Case objective / KPI / user story | Reference |
|
||||
| --- | --- |
|
||||
| O1, O2 | [BC-001] |
|
||||
|
||||
## Ownership
|
||||
|
||||
| Role | Stakeholder ID (SA) |
|
||||
| --- | --- |
|
||||
| Owner | S05 |
|
||||
| Approving reviewer | S01 |
|
||||
|
||||
## Target Date
|
||||
|
||||
2026-10-17 — confirmed on 2026-10-10 by S01, standing in for S05 (ADR-0002); the Business Case sets no deadline.
|
||||
|
||||
## Tasks
|
||||
|
||||
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | Decide behavior for an invalid push mirror response | The committed workflow fails with an error when Gitea returns a non-list push mirror response. The uncommitted scoped copy instead prints a message and tries to exit successfully, and the README diagram showed that. Choose fail or skip, record the decision, and align code and README. Decision: skip with a visible warning and a successful run, following the maintainer's edit to the scoped copy; several or malformed GitHub mirrors still fail. Amended 2026-10-10: zero GitHub mirrors is also a successful skip, because not every Gitea repository has a mirror; the GitHub secret is then not read. | No | |
|
||||
| 2 | Fix the Python syntax error in the scoped workflow | `exit 0` is not valid Python, so the whole embedded script fails to compile in the scoped copy. Replace it according to the decision in task 1 (`sys.exit(0)` also needs `import sys`). | No | |
|
||||
| 3 | Reduce the workflow to one canonical source | The same workflow exists in `src/` and `.gitea/scoped_workflows/` (and a legacy copy that is no longer documented), and the scoped copy has diverged. Choose the canonical location, and generate or remove the others. Decision: `.gitea/scoped_workflows/` is canonical because the script must be embedded in the YAML to work as a scoped workflow; the `src/` copy is removed. | No | |
|
||||
| 4 | Add static validation of workflow files | Parse each workflow YAML and compile its embedded Python in an automated check that runs on pull requests, so defects such as task 2 fail before merge. | No | |
|
||||
| 5 | Add offline unit tests for the sync logic | Move credential and mirror URL parsing into testable code and test bare token, JSON token, SSH and HTTPS mirror addresses, zero mirrors (skipped successfully) and several mirrors (fail). Replace `tests/test_.ps1`, which probes a hard-coded real repository and reads `.env`. | No | |
|
||||
| 6 | Keep the README accurate | Maintain the capability table (implemented, partial, planned), and align the sequence diagram with the final behavior from task 1. | No | |
|
||||
| 7 | Verify a live run | Trigger the workflow manually on Gitea and compare the GitHub description and topics with the Gitea repository. | No | |
|
||||
|
||||
---
|
||||
|
||||
[BC-001]: ../business-case.md
|
||||
[0c06789]: https://git.tirsystem.com/TirSystem/github-action/commit/0c06789a2779382672712cd483f4964b28a0ebe9
|
||||
[ADR-0002]: ../adr/adr-0002-s01-approves-as-stand-in.md
|
||||
[ea06eaa]: https://git.tirsystem.com/TirSystem/github-action/commit/ea06eaaa698247d20e4a8e2694d7acbb1de58b63
|
||||
@@ -0,0 +1,78 @@
|
||||
# MIL-002: Onboarding and operations guide
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | MIL-002 |
|
||||
| CrossReference | [BC-001], [ADR-0002] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-03 | Deprecated | Jens Tirsvad Nielsen | S01 | Recorded verification results for task 2 | [7dcb9c4] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Target date 2026-10-31 confirmed on 2026-10-10 by S01 (stand-in for S05) | [ea06eaa] |
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
Decide whether a DevOps professional can onboard a repository, set up
|
||||
credentials, choose runners and diagnose a failed run from the documentation
|
||||
alone.
|
||||
|
||||
## Deliverable
|
||||
|
||||
An onboarding and operations guide verified against the real Gitea instance,
|
||||
a credential validation step in the workflow, and categorized failure messages.
|
||||
|
||||
## Go / No-Go Criteria
|
||||
|
||||
| # | Criterion (objectively checkable) | Go | No-Go |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Support for scoped workflows on the instance is verified and the Gitea version is recorded | Recorded | Unverified |
|
||||
| 2 | A second repository is onboarded by following only the guide | Run succeeds | Needs undocumented steps |
|
||||
| 3 | Minimum token permissions are documented for both secrets and checked by the workflow before use | Documented and checked | Missing |
|
||||
| 4 | Every failure message names its category: configuration, credentials, permissions, API response or runner | Verified for all messages | Uncategorized message exists |
|
||||
| 5 | Supported runner labels and prerequisites are listed | Listed | Missing |
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Depends on | Reason |
|
||||
| --- | --- |
|
||||
| MIL-001 | The guide describes the stabilised workflow |
|
||||
|
||||
## Traceability
|
||||
|
||||
| Business Case objective / KPI / user story | Reference |
|
||||
| --- | --- |
|
||||
| O2, O3 | [BC-001] |
|
||||
|
||||
## Ownership
|
||||
|
||||
| Role | Stakeholder ID (SA) |
|
||||
| --- | --- |
|
||||
| Owner | S05 |
|
||||
| Approving reviewer | S01 |
|
||||
|
||||
## Target Date
|
||||
|
||||
2026-10-31 — confirmed on 2026-10-10 by S01, standing in for S05 (ADR-0002); the Business Case sets no deadline.
|
||||
|
||||
## Tasks
|
||||
|
||||
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | Write brief use cases for the P1 candidates | Turn the DevOps use cases in the Project Plan appendix into use case documents under `docs/uc-NNN/`, after a use case diagram and user stories exist. | No | |
|
||||
| 2 | Verify scoped workflow support on the instance | The Business Case lists this as an unverified assumption. Check the Gitea version and how a scoped workflow reaches a repository, then record the result. Result: Gitea 1.27.3 runs the scoped sync workflow in this repository (run 16); delivery to other repositories is not yet verified and is recorded in `guides/onboarding.md`. | No | |
|
||||
| 3 | Write the repository onboarding steps | Describe how to consume the workflow (scoped or copied), which secrets to set and how to test the first run. | No | |
|
||||
| 4 | Document least-privilege tokens | Determine the minimum Gitea token scope and GitHub fine-grained token permission that the sync needs, and document them. | No | |
|
||||
| 5 | Add a credential preflight step | Before the sync, check that both tokens authenticate and have the needed access, and report the result without printing any secret. | No | |
|
||||
| 6 | Categorize failure messages | Group the error messages and HTTP errors into configuration, credentials, permissions, API response and runner, and write the diagnosis table. | No | |
|
||||
| 7 | Document runner labels and prerequisites | State the supported labels (`ubuntu-latest`), the required `python3`, and how to recognize an offline or incompatible runner. | No | |
|
||||
|
||||
---
|
||||
|
||||
[BC-001]: ../business-case.md
|
||||
[7dcb9c4]: https://git.tirsystem.com/TirSystem/github-action/commit/7dcb9c4dfce712572aced281d0dfdfa435283646
|
||||
[ADR-0002]: ../adr/adr-0002-s01-approves-as-stand-in.md
|
||||
[ea06eaa]: https://git.tirsystem.com/TirSystem/github-action/commit/ea06eaaa698247d20e4a8e2694d7acbb1de58b63
|
||||
@@ -0,0 +1,124 @@
|
||||
# MIL-003: Shared quality checks
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | MIL-003 |
|
||||
| CrossReference | [BC-001], [ADR-0002] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S01 | Task 1 verified: workflow_call and uses work from the same repository, the same organization and another organization (RC-033) | [b3f006f] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Task 4 recorded: adoption in RepoFoundry, the shfmt .editorconfig gap and the other findings (RC-039) | [3b8681d] |
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
Decide whether a software engineer can run the same quality checks on any
|
||||
TirSystem project through a shared workflow.
|
||||
|
||||
## Deliverable
|
||||
|
||||
A reusable quality-check workflow for Python and shell, used by at least one
|
||||
other repository, and a guide for reading its results.
|
||||
|
||||
## Go / No-Go Criteria
|
||||
|
||||
| # | Criterion (objectively checkable) | Go | No-Go |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | The instance supports reusable workflows (`workflow_call`), verified and recorded | Verified | Unsupported (re-plan as a copied template) |
|
||||
| 2 | One other repository runs the workflow and its status check appears on pull requests | Appears | Does not run |
|
||||
| 3 | A failing check shows the tool, file and message in the log | Verified with a seeded failure | Cause not visible |
|
||||
| 4 | Inputs and defaults are documented | Documented | Missing |
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Depends on | Reason |
|
||||
| --- | --- |
|
||||
| MIL-002 | Uses the onboarding guide and runner list |
|
||||
|
||||
## Traceability
|
||||
|
||||
| Business Case objective / KPI / user story | Reference |
|
||||
| --- | --- |
|
||||
| O4 | [BC-001] |
|
||||
|
||||
## Ownership
|
||||
|
||||
| Role | Stakeholder ID (SA) |
|
||||
| --- | --- |
|
||||
| Owner | S05 |
|
||||
| Approving reviewer | S01 |
|
||||
|
||||
## Target Date
|
||||
|
||||
2026-11-14 — confirmed on 2026-10-10 by S01, standing in for S05 (ADR-0002); the Business Case sets no deadline.
|
||||
|
||||
## Tasks
|
||||
|
||||
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | Verify reusable workflow support | Check whether this Gitea version supports `workflow_call` and cross-repository `uses`; if not, choose a copied template instead. Verified on 2026-10-10: supported, so no copied template is needed (see Verification results). | No | Verification results |
|
||||
| 2 | Define the quality-check contract | Decide the inputs (language, tool versions, working directory) and what a pass and a fail mean. Start with Python and shell. This is something an engineer does, so it needs a use case first. | Yes | Use case candidate: run project quality checks |
|
||||
| 3 | Implement the reusable quality workflow | Create the workflow in the canonical location with pinned tool versions and least-privilege permissions. | No | |
|
||||
| 4 | Adopt it in one other repository | Onboard a real project and fix the gaps in the guide that appear. Adopted in `TirSystem-BashScript/RepoFoundry` (its PR 76, run passes); see Adoption in a real repository. | No | Adoption in a real repository |
|
||||
| 5 | Write the guide for reading results | Explain status checks, logs and typical fixes so an engineer can make a failing check pass. | No | |
|
||||
|
||||
## Verification results
|
||||
|
||||
Task 1 was run on 2026-10-10 on the instance (Gitea 1.27.3) with a throwaway
|
||||
branch, `verify-reusable-workflows`, in `TirSystem/github-action`. The called
|
||||
workflow declared `on: workflow_call` with one input and printed it; the
|
||||
callers used `jobs.<job_id>.uses`. All branches were deleted afterwards.
|
||||
|
||||
| Call | Caller | Result |
|
||||
| --- | --- | --- |
|
||||
| `uses: ./.gitea/workflows/reuse-callee.yml` | `TirSystem/github-action` (same repository) | Called job ran; input received |
|
||||
| `uses: TirSystem/github-action/.gitea/workflows/reuse-callee.yml@<branch>` | `TirSystem/github-action` | Called job ran; input received |
|
||||
| the same, from another repository of the organization | `TirSystem/sqa-qc-checklists` | Called job ran; `gitea.repository` was the caller |
|
||||
| the same, from a repository of another organization | `TirSystem-BashScript/RepoFoundry` | Called job ran; `gitea.repository` was the caller |
|
||||
|
||||
What the test did not cover: a provider repository that is private (the
|
||||
provider here is public), passing secrets to a called workflow
|
||||
(`secrets:` or `secrets: inherit`), and a reference by tag instead of a
|
||||
branch. The quality checks of this milestone need none of the secrets; a
|
||||
private provider and tag references are for the release milestone (MIL-004).
|
||||
|
||||
## Adoption in a real repository (task 4)
|
||||
|
||||
On 2026-10-10 the workflow was run against `TirSystem-BashScript/RepoFoundry`
|
||||
(another organization; 39 shell files, no Python), first on a throwaway
|
||||
branch and then as a pull request, RepoFoundry PR 76.
|
||||
|
||||
| Run | `shellcheck` | `shfmt -d` | Python |
|
||||
| --- | --- | --- | --- |
|
||||
| Unchanged repository | PASS on all 39 files | FAIL on 10 files | skipped with a notice (no files) |
|
||||
| With `switch_case_indent = true` under `[*.sh]` in `.editorconfig` | PASS | PASS | skipped |
|
||||
| The pull request itself (`languages: shell`) | PASS | PASS | not selected |
|
||||
|
||||
What the run showed:
|
||||
|
||||
- **`shellcheck` needs no help** when the project has a `.shellcheckrc`: the
|
||||
workflow runs from the repository root, so the project's own settings
|
||||
(`external-sources`, `source-path=SCRIPTDIR`) applied and files that share
|
||||
variables across `src/lib/*.sh` produced no false positives.
|
||||
- **`shfmt` follows the project's style only through `.editorconfig`.** All ten
|
||||
differences were the indentation of `case` patterns: the workflow uses shfmt
|
||||
defaults, the project's own check is `shfmt -i 2 -ci`. One `.editorconfig`
|
||||
line fixed it without changing a script. A shell project with its own shfmt
|
||||
flags should expect a first formatting failure and express the flags there.
|
||||
- **Paths in the log are relative to `working-directory`**, and a caller must
|
||||
reference the workflow at `main` or a tag, not at a branch that is deleted
|
||||
when its pull request merges (the first trial lost its reference that way).
|
||||
|
||||
The task closes when RepoFoundry PR 76 is merged. The gaps above are for the
|
||||
guide of task 5 (issue #19).
|
||||
|
||||
---
|
||||
|
||||
[BC-001]: ../business-case.md
|
||||
[ADR-0002]: ../adr/adr-0002-s01-approves-as-stand-in.md
|
||||
[b3f006f]: https://git.tirsystem.com/TirSystem/github-action/commit/b3f006f7a482392189a46c324ad4f28c4c3a2d2a
|
||||
[3b8681d]: https://git.tirsystem.com/TirSystem/github-action/commit/3b8681d0236c669b794ffbba725433fff600a2d2
|
||||
@@ -0,0 +1,80 @@
|
||||
# MIL-004: Versioned release and publishing
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | MIL-004 |
|
||||
| CrossReference | [BC-001], [ADR-0002] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Target date 2026-11-28 confirmed on 2026-10-10 by S01 (stand-in for S05) | [ea06eaa] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Added task 6 (embedded scripts to files) and Go/No-Go criterion 5; traceability adds O2 (RC-034) | [616c5d2] |
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
Decide whether workflow updates can be released with a version and adopted
|
||||
safely, and whether a project can publish an artifact through a shared
|
||||
workflow.
|
||||
|
||||
## Deliverable
|
||||
|
||||
A documented release process for this repository (validation, version tag,
|
||||
changelog), a consumer upgrade guide and a reusable release workflow. The
|
||||
scoped workflows run scripts that are files in this repository, fetched at a
|
||||
reference that a release can pin, instead of Python embedded in their YAML.
|
||||
|
||||
## Go / No-Go Criteria
|
||||
|
||||
| # | Criterion (objectively checkable) | Go | No-Go |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A release is validated by the MIL-001 checks before a tag is created | Enforced | Tag possible without checks |
|
||||
| 2 | Each release has a version tag and a changelog entry that marks breaking changes | Present | Missing |
|
||||
| 3 | A consumer pinned to the previous version keeps working after a release | Verified | Breaks |
|
||||
| 4 | The publish destination (release page or package registry) is decided and its token scope documented | Decided | Open |
|
||||
| 5 | The sync and publish-wiki workflows contain no embedded Python; each runs a script file of this repository, and the tests exercise the files | Count of embedded scripts is 0 and a run in another organization passes | Embedded script remains or a consumer run fails |
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Depends on | Reason |
|
||||
| --- | --- |
|
||||
| MIL-003 | Reuses the reusable workflow mechanism |
|
||||
|
||||
## Traceability
|
||||
|
||||
| Business Case objective / KPI / user story | Reference |
|
||||
| --- | --- |
|
||||
| O2, O4 | [BC-001] |
|
||||
|
||||
## Ownership
|
||||
|
||||
| Role | Stakeholder ID (SA) |
|
||||
| --- | --- |
|
||||
| Owner | S05 |
|
||||
| Approving reviewer | S01 |
|
||||
|
||||
## Target Date
|
||||
|
||||
2026-11-28 — confirmed on 2026-10-10 by S01, standing in for S05 (ADR-0002); the Business Case sets no deadline.
|
||||
|
||||
## Tasks
|
||||
|
||||
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | Define the release process for this repository | Describe how a workflow change is validated, tagged and announced, and how consumers pin a version. | Yes | Use case candidate: release a reusable workflow |
|
||||
| 2 | Add a changelog and tag convention | Create `CHANGELOG.md` and a tag scheme (for example `v1` plus `v1.2.3`) that separates breaking from compatible changes. | No | |
|
||||
| 3 | Write the consumer upgrade guide | Explain how to read a changelog entry, test an update in one repository and roll back. | Yes | Use case candidate: consume a workflow update |
|
||||
| 4 | Decide the publish destination | Choose the release or package destination for built artifacts and document the token scope it needs. | No | |
|
||||
| 5 | Implement the reusable release workflow | Validate the version, build release notes from the changelog and publish to the chosen destination. | Yes | Use case candidate: publish a release |
|
||||
| 6 | Move the embedded scripts of the scoped workflows to files | The sync (`sync-github-metadata.yml`) and publish-wiki workflows embed 200 to 300 lines of Python in their YAML, which is hard to read, lint and review. Move the code to `tools/sync_github_metadata.py` and `tools/publish_wiki.py`; each scoped workflow then checks out `TirSystem/github-action` into its own folder with `actions/checkout` and runs the file, as verified on 2026-10-10 from repositories of two organizations. Keep the behaviour, the messages and the offline tests, which import the files instead of executing the YAML; use `ref: main` first, and let the release process of task 1 define how a consumer pins a tag. | No | |
|
||||
|
||||
---
|
||||
|
||||
[BC-001]: ../business-case.md
|
||||
[4de5438]: https://git.tirsystem.com/TirSystem/github-action/commit/4de5438a88b4bbf18b165f52f797d1a52af89f6d
|
||||
[ADR-0002]: ../adr/adr-0002-s01-approves-as-stand-in.md
|
||||
[ea06eaa]: https://git.tirsystem.com/TirSystem/github-action/commit/ea06eaaa698247d20e4a8e2694d7acbb1de58b63
|
||||
[616c5d2]: https://git.tirsystem.com/TirSystem/github-action/commit/616c5d2e48f0d76399a6f78923891fc7f50c8e22
|
||||
@@ -0,0 +1,84 @@
|
||||
# MIL-005: Wiki and translations
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | MIL-005 |
|
||||
| CrossReference | [BC-001], [ADR-0002] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S01 | Decided how the wiki is published: source in `wiki/`, published by a workflow on merge<br>Added task 8 | [77c5277] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Target date 2026-12-12 confirmed on 2026-10-10 by S01 (stand-in for S05) | [ea06eaa] |
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
Decide whether a reader can find the workflow documentation on the Gitea wiki
|
||||
in English, Danish and Bahasa Malaysia, and whether the wiki stays current
|
||||
because every pull request updates it.
|
||||
|
||||
## Deliverable
|
||||
|
||||
A Gitea wiki with the pages Home, Onboarding, Credentials, Troubleshooting
|
||||
and Capabilities in English (authoritative), Danish and Bahasa Malaysia. The
|
||||
page source lives in `wiki/` in this repository and is reviewed through pull
|
||||
requests. A script builds the English pages from `README.md` and `guides/`,
|
||||
a workflow publishes `wiki/` to the wiki repository when a change is merged
|
||||
to `main`, and a pull request rule in `AGENTS.md` keeps the wiki current.
|
||||
|
||||
## Go / No-Go Criteria
|
||||
|
||||
| # | Criterion (objectively checkable) | Go | No-Go |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | The wiki is enabled and contains the five pages in all three languages | 15 pages present | Any page missing |
|
||||
| 2 | Each English page is generated from `README.md` or `guides/`, and a check reports a page that differs from its source | Check passes | Hand-edited page drifts |
|
||||
| 3 | Each Danish and Bahasa Malaysia page names the English source version it follows | Named on every page | Missing |
|
||||
| 4 | A native reader of each language has reviewed the translations | Review recorded | Unreviewed |
|
||||
| 5 | `AGENTS.md` requires a wiki update in every pull request that changes a workflow, a guide or the README, and the PR description lists the pages changed | Rule present and used by one PR | Missing |
|
||||
| 6 | The wiki is published only by the workflow from `main`; no agent or person pushes to the wiki repository by hand | Last wiki commit is by the workflow | A manual push exists |
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Depends on | Reason |
|
||||
| --- | --- |
|
||||
| MIL-002 | The wiki pages are built from the onboarding, credentials and troubleshooting guides |
|
||||
|
||||
## Traceability
|
||||
|
||||
| Business Case objective / KPI / user story | Reference |
|
||||
| --- | --- |
|
||||
| O3 | [BC-001] |
|
||||
|
||||
## Ownership
|
||||
|
||||
| Role | Stakeholder ID (SA) |
|
||||
| --- | --- |
|
||||
| Owner | S05 |
|
||||
| Approving reviewer | S01 |
|
||||
|
||||
## Target Date
|
||||
|
||||
2026-12-12 — confirmed on 2026-10-10 by S01, standing in for S05 (ADR-0002); the Business Case sets no deadline.
|
||||
|
||||
## Tasks
|
||||
|
||||
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | Decide wiki structure, languages and source of truth | Fix the page list, the page naming for `da` and `ms` (for example `Home`, `Home.da`, `Home.ms`) and that the English wiki pages are generated from `README.md` and `guides/`. Record the wiki languages in the `Languages` section of `docs/artifact-registry.md`, since the registry currently says no translations are kept. | No | |
|
||||
| 2 | Enable the Gitea wiki and agree access | Decision (2026-10-10): the page source lives in `wiki/` in this repository and reaches the wiki repository (`github-action.wiki.git`) only through a workflow that runs on merge to `main`; the agent edits `wiki/` on a branch and opens a pull request and never pushes to the wiki repository. This task enables the wiki on the repository and creates a secret that can write to the wiki repository only, approved by S05 and stored by S03. Edits made in the Gitea web UI are overwritten on the next publish, and the wiki home page says so. | No | |
|
||||
| 3 | Generate the English wiki pages | Add a script that builds the five pages into `wiki/` from `README.md` and `guides/`, rewrites links so they work inside the wiki, and reports a page that differs from its source. | No | |
|
||||
| 4 | Draft the Danish and Bahasa Malaysia pages | Translate each page and name the English source version at the top of the page. Keep technical terms (workflow, secret, runner, mirror) consistent through a small term list. | No | |
|
||||
| 5 | Have the translations reviewed | A native reader of Danish and of Bahasa Malaysia reviews the drafts and the findings are fixed before publishing. | No | |
|
||||
| 6 | Add the wiki update rule to the pull request process | Add a rule to `AGENTS.md`: a pull request that changes a workflow, a guide or the README also updates the matching wiki pages in all three languages, and its description lists the pages changed. | No | |
|
||||
| 7 | Publish and verify | Publish the pages, open them in the browser in each language and check that links, code blocks and the capability table render. | No | |
|
||||
| 8 | Add the wiki publishing workflow | Add a Gitea workflow, canonical in `.gitea/scoped_workflows/`, that runs on push to `main` when `wiki/` changes and copies `wiki/` to the wiki repository with the secret from task 2. It needs least-privilege permissions, must not print the secret, and gets offline tests like the metadata sync, with the same categorized error messages. | No | |
|
||||
|
||||
---
|
||||
|
||||
[BC-001]: ../business-case.md
|
||||
[77c5277]: https://git.tirsystem.com/TirSystem/github-action/commit/77c52779c46bca35dee4d73e587ca7b611373790
|
||||
[ADR-0002]: ../adr/adr-0002-s01-approves-as-stand-in.md
|
||||
[ea06eaa]: https://git.tirsystem.com/TirSystem/github-action/commit/ea06eaaa698247d20e4a8e2694d7acbb1de58b63
|
||||
@@ -0,0 +1,80 @@
|
||||
# MIL-006: Shared wiki publishing
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | MIL-006 |
|
||||
| CrossReference | [BC-001], [MIL-005], [ADR-0003], [ADR-0002] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S01 | Initial version | [6b8e36d] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Target date 2026-12-26 confirmed on 2026-10-10 by S01 (stand-in for S05) | [ea06eaa] |
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
Decide whether any repository on the instance can publish its own wiki from a
|
||||
`wiki/` folder through one shared workflow, without a copy of the workflow and
|
||||
without risk to repositories that did not ask for it.
|
||||
|
||||
## Deliverable
|
||||
|
||||
A scoped workflow `publish-wiki.yml` in `.gitea/scoped_workflows/` with its
|
||||
publish script embedded, an opt-in rule that leaves every repository without
|
||||
it untouched, offline tests, updated guides and wiki pages, and one
|
||||
repository other than this one that publishes its wiki through it.
|
||||
|
||||
## Go / No-Go Criteria
|
||||
|
||||
| # | Criterion (objectively checkable) | Go | No-Go |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A repository without the opt-in marker is never written to, shown by offline tests and by a run in one such repository | No request writes to its wiki | Any write |
|
||||
| 2 | The workflow exists once: the copy in `.gitea/workflows/` is removed and no script is needed from `tools/` | Count is 1 | A second copy exists |
|
||||
| 3 | One repository outside this one publishes its wiki through the shared workflow | Pages on the wiki equal its `wiki/` | Pages differ or run fails |
|
||||
| 4 | An empty or missing `wiki/` never deletes pages, and a failure names its category | Verified by tests | A wiki was emptied |
|
||||
| 5 | The per-organisation secret `TOKEN_FOR_GITEA_WIKI` is documented, and stored in the pilot's organisation | Documented and stored | Missing |
|
||||
| 6 | The onboarding and credentials guides and their three wiki languages describe opting in | Pages updated | Out of date |
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Depends on | Reason |
|
||||
| --- | --- |
|
||||
| MIL-005 | The publisher, the page layout and the wiki rules come from it |
|
||||
| MIL-002 | Scoped delivery across organisations was verified there (issue #9) |
|
||||
|
||||
## Traceability
|
||||
|
||||
| Business Case objective / KPI / user story | Reference |
|
||||
| --- | --- |
|
||||
| O2, O3 | [BC-001] |
|
||||
|
||||
## Ownership
|
||||
|
||||
| Role | Stakeholder ID (SA) |
|
||||
| --- | --- |
|
||||
| Owner | S05 |
|
||||
| Approving reviewer | S01 |
|
||||
|
||||
## Target Date
|
||||
|
||||
2026-12-26 — confirmed on 2026-10-10 by S01, standing in for S05 (ADR-0002); the Business Case sets no deadline.
|
||||
|
||||
## Tasks
|
||||
|
||||
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | Decide the opt-in rule and the secret handling | A scoped workflow runs in every repository of an organisation, and the publisher deletes pages that are not in `wiki/`. Choose how a repository opts in (a marker file such as `wiki/.publish`, a repository variable, or an allow list), what happens when the secret is missing, and whether the pilot uses `TOKEN_FOR_GITEA_WIKI` or the fallback. Record it as an ADR that refines ADR-0003. | No | |
|
||||
| 2 | Make the publisher a scoped workflow | Embed the publish script in `.gitea/scoped_workflows/publish-wiki.yml` as the metadata sync does, so it needs nothing from `tools/` in the target repository, and run it only on a change under `wiki/`. Remove `.gitea/workflows/publish-wiki.yml` and `tools/publish_wiki.py` so the workflow has one source, and keep this repository's drift check in the validation tests. | No | |
|
||||
| 3 | Implement the opt-in gate and the safety limits | Skip, successfully and with a log line, any repository that has not opted in. Keep the refusal on an empty `wiki/` and the categorised errors, and add offline tests with a fake Gitea for opted-in, not opted-in and missing-secret runs. | No | |
|
||||
| 4 | Pilot in one other repository | Choose one repository outside this one, add a `wiki/` folder with the marker, store `TOKEN_FOR_GITEA_WIKI` in its organisation (S03), publish, and read the pages back. Also confirm that a repository without the marker was not touched. | No | |
|
||||
| 5 | Update the guides and the wiki | Describe how a repository opts in and which secrets its organisation needs in the onboarding and credentials guides, regenerate the wiki pages and update the Danish and Bahasa Malaysia translations (rule 8 of `AGENTS.md`). | No | |
|
||||
|
||||
---
|
||||
|
||||
[BC-001]: ../business-case.md
|
||||
[6b8e36d]: https://git.tirsystem.com/TirSystem/github-action/commit/6b8e36d67ac9af165b180bc0045289e41cfd1fc3
|
||||
[ADR-0002]: ../adr/adr-0002-s01-approves-as-stand-in.md
|
||||
[ea06eaa]: https://git.tirsystem.com/TirSystem/github-action/commit/ea06eaaa698247d20e4a8e2694d7acbb1de58b63
|
||||
@@ -0,0 +1,261 @@
|
||||
# Project Plan: TirSystem Reusable Workflows
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | PP-001 |
|
||||
| CrossReference | [BC-001], [SA-001], [ADR-0002], [US-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S01 | P1 use cases written and accepted (UCD-001, US-001, UC-001 to UC-004): Open Issues updated | [a2bf2d4] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Dates confirmed by S01 (stand-in for S05); the confirmation item is removed from Open Issues | [ea06eaa] |
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
This plan schedules six milestones that move the repository from one
|
||||
workflow with known defects to a documented, versioned collection of shared
|
||||
workflows. The Business Case sets no deadline, so the dates are the plan's own; they were confirmed on 2026-10-10 by S01, standing in for S05 (ADR-0002).
|
||||
|
||||
## Planning Assumptions
|
||||
|
||||
- Week 1 starts 2026-10-05; phases are two weeks long; the last decision is 2026-12-26.
|
||||
- Work on a milestone starts only after its `MIL-*` document is `Accepted`.
|
||||
- Dates were confirmed on 2026-10-10 by S01, standing in for S05 (ADR-0002).
|
||||
|
||||
## Gateway Schedule
|
||||
|
||||
| Gateway | Document | Window | Decision date | Owner | Stories | Main deliverable | Milestone |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| Stabilise the metadata sync | [MIL-001] | 2026-10-05 to 2026-10-17 | 2026-10-17 | S05 | None yet | Single tested workflow, accurate README | [Milestone MIL-001] |
|
||||
| Onboarding and operations guide | [MIL-002] | 2026-10-19 to 2026-10-31 | 2026-10-31 | S05 | None yet | Verified onboarding, credential and diagnosis guide | [Milestone MIL-002] |
|
||||
| Shared quality checks | [MIL-003] | 2026-11-02 to 2026-11-14 | 2026-11-14 | S05 | None yet | Reusable quality-check workflow | [Milestone MIL-003] |
|
||||
| Versioned release and publishing | [MIL-004] | 2026-11-16 to 2026-11-28 | 2026-11-28 | S05 | None yet | Release process and reusable release workflow | [Milestone MIL-004] |
|
||||
| Wiki and translations | [MIL-005] | 2026-11-30 to 2026-12-12 | 2026-12-12 | S05 | None yet | Wiki pages in English, Danish and Bahasa Malaysia, kept current by every pull request | [Milestone MIL-005] |
|
||||
| Shared wiki publishing | [MIL-006] | 2026-12-14 to 2026-12-26 | 2026-12-26 | S05 | None yet | Scoped publish-wiki workflow with opt-in, piloted in one other repository | [Milestone MIL-006] |
|
||||
|
||||
```plantuml
|
||||
@startgantt
|
||||
Project starts 2026-10-05
|
||||
[MIL-001 Stabilise] starts 2026-10-05 and ends 2026-10-17
|
||||
[MIL-002 Onboarding] starts 2026-10-19 and ends 2026-10-31
|
||||
[MIL-003 Quality checks] starts 2026-11-02 and ends 2026-11-14
|
||||
[MIL-004 Release] starts 2026-11-16 and ends 2026-11-28
|
||||
[MIL-001 Go/No-Go] happens 2026-10-17
|
||||
[MIL-002 Go/No-Go] happens 2026-10-31
|
||||
[MIL-003 Go/No-Go] happens 2026-11-14
|
||||
[MIL-004 Go/No-Go] happens 2026-11-28
|
||||
[MIL-005 Wiki] starts 2026-11-30 and ends 2026-12-12
|
||||
[MIL-005 Go/No-Go] happens 2026-12-12
|
||||
[MIL-006 Shared wiki] starts 2026-12-14 and ends 2026-12-26
|
||||
[MIL-006 Go/No-Go] happens 2026-12-26
|
||||
@endgantt
|
||||
```
|
||||
|
||||
## Scope Coverage
|
||||
|
||||
| Business Case scope item | Gateway |
|
||||
| --- | --- |
|
||||
| Validation of workflow files and their documentation | [MIL-001] |
|
||||
| Documentation for DevOps professionals | [MIL-002] |
|
||||
| Gitea Actions workflows for software engineers (quality checks) | [MIL-003] |
|
||||
| Gitea Actions workflows for software engineers (release and publishing) | [MIL-004] |
|
||||
| Wiki pages in English, Danish and Bahasa Malaysia | [MIL-005] |
|
||||
| The wiki publisher shared with other repositories through scoped delivery | [MIL-006] |
|
||||
|
||||
## Dependencies
|
||||
|
||||
```
|
||||
MIL-001 → MIL-002 → MIL-003 → MIL-004
|
||||
MIL-002 → MIL-005 → MIL-006
|
||||
```
|
||||
|
||||
A No-Go moves every later window by the rework time of the failed milestone.
|
||||
|
||||
## Plan Risks
|
||||
|
||||
| Risk | Impact | Mitigation |
|
||||
| --- | --- | --- |
|
||||
| Reusable workflow support is missing on the instance | MIL-003 and MIL-004 change shape | Verify first in each milestone (MIL-002 task 2, MIL-003 task 1); fall back to copied templates. |
|
||||
| Security review by S05 is a bottleneck | Milestone decisions slip | Keep milestones small and plan review time before each decision date. |
|
||||
|
||||
## Open Issues
|
||||
|
||||
- No QC checklist exists for the Project Plan.
|
||||
- The P1 candidates are written as brief use cases (UC-001 to UC-004) with a use case diagram (UCD-001) and user stories (US-001). The P2 and P3 candidates have no use case document yet.
|
||||
|
||||
## Appendix: Use Case Candidates and Prioritisation
|
||||
|
||||
This appendix evaluates the candidate use cases against the repository as it
|
||||
is today. It is analysis, not a use case document; formal use cases follow in
|
||||
MIL-002 task 1. Priority: P1 do first, P2 next, P3 later.
|
||||
|
||||
**Recommended order:** (1) Synchronize repository metadata, because it is
|
||||
the only implemented capability and has a defect, (2) Configure workflow
|
||||
credentials, (3) Onboard a repository, (4) Diagnose a failed workflow, then
|
||||
(5) Run project quality checks and (6) Release a reusable workflow. The first
|
||||
four make the existing workflow dependable and adoptable; the others add new
|
||||
workflows and only pay off once adoption works.
|
||||
|
||||
Current repository state used for the status column: one workflow
|
||||
(`sync-github-metadata`), one manual probe script (`tests/test_.ps1`), no CI,
|
||||
no tests, no release process.
|
||||
|
||||
| # | Use case | Actor | Priority | Status today |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | Synchronize repository metadata | DevOps professional (S05) | P1 | Implemented in `.gitea/scoped_workflows/`; script has a syntax error |
|
||||
| 2 | Configure workflow credentials | DevOps professional (S05, S03) | P1 | Partial: secrets are format-checked only |
|
||||
| 3 | Onboard a repository to standard workflows | DevOps professional (S05) | P1 | Not documented; scoped workflow support unverified |
|
||||
| 4 | Diagnose a failed workflow | DevOps professional (S05, S03) | P1 | Partial: errors are messages only, uncategorized |
|
||||
| 5 | Run project quality checks | Software engineer (S02) | P2 | Planned |
|
||||
| 6 | Release a reusable workflow | DevOps professional (S05) | P2 | Planned |
|
||||
| 7 | Manage workflow runners | DevOps professional (S03, S05) | P2 | Partial: only `ubuntu-latest` with `python3` assumed |
|
||||
| 8 | Consume a workflow update | Software engineer (S02) | P2 | Planned; needs versioning |
|
||||
| 9 | Review workflow results | Software engineer (S02) | P3 | Gitea provides logs; guidance planned |
|
||||
| 10 | Create a project workflow | Software engineer (S02) | P3 | Planned; needs MIL-003 |
|
||||
| 11 | Build and publish an artifact | Software engineer (S02) | P3 | Planned; destination undecided |
|
||||
| 12 | Publish a release | Software engineer (S02) | P3 | Planned; overlaps with use case 6 and 11 |
|
||||
|
||||
### UC candidate 1: Synchronize repository metadata (P1)
|
||||
|
||||
- **Actor:** DevOps professional. **Goal:** the GitHub mirror shows the Gitea description and topics.
|
||||
- **Trigger:** push to `main`, manual dispatch, or daily at 03:17 UTC.
|
||||
- **Preconditions:** both secrets set; at most one GitHub push mirror configured (none: the run is skipped successfully); runner available.
|
||||
- **Success:** description and topics on GitHub equal those on Gitea.
|
||||
- **Main flow:** the workflow validates the secrets, reads description and topics from Gitea, finds the GitHub mirror (if none, ends successfully without syncing), updates the description, replaces the topics.
|
||||
- **Alternatives and failures:** missing or invalid secret: fail with a message; no GitHub mirror: successful run, nothing synced; several GitHub mirrors: fail; non-list mirror response: behavior undecided (MIL-001 task 1); Gitea or GitHub API error: fail with the HTTP code.
|
||||
- **Dependencies:** none.
|
||||
|
||||
### UC candidate 2: Configure workflow credentials (P1)
|
||||
|
||||
- **Actor:** DevOps professional. **Goal:** least-privilege tokens that a workflow accepts.
|
||||
- **Trigger:** onboarding a repository or rotating a token.
|
||||
- **Preconditions:** access to Gitea and GitHub settings.
|
||||
- **Success:** a workflow run passes credential checks with the documented minimum permissions.
|
||||
- **Main flow:** create the tokens, store `TOKEN_FOR_GITEA` and `PAT_FOR_GITHUB`, run the workflow, read the validation result.
|
||||
- **Alternatives and failures:** empty value, wrong or expired token (rejected with HTTP 401), missing permission: the check names the category without printing the secret.
|
||||
- **Dependencies:** use case 1.
|
||||
|
||||
### UC candidate 3: Onboard a repository to standard workflows (P1)
|
||||
|
||||
- **Actor:** DevOps professional. **Goal:** a repository consumes the shared workflows.
|
||||
- **Trigger:** a new or existing repository needs standard automation.
|
||||
- **Preconditions:** Actions enabled; runner available; secrets possible to set.
|
||||
- **Success:** the first run in the repository passes using only the guide.
|
||||
- **Main flow:** choose scoped or copied delivery, set secrets, configure the push mirror, trigger a run.
|
||||
- **Alternatives and failures:** scoped workflows unsupported: use a copied template; no runner: see use case 7.
|
||||
- **Dependencies:** use cases 1 and 2; verification of scoped workflow support.
|
||||
|
||||
### UC candidate 4: Diagnose a failed workflow (P1)
|
||||
|
||||
- **Actor:** DevOps professional. **Goal:** find the cause of a failed run.
|
||||
- **Trigger:** a failed or missing run.
|
||||
- **Preconditions:** access to the run log.
|
||||
- **Success:** the cause is placed in one category: configuration, credentials, permissions, API response or runner.
|
||||
- **Main flow:** open the log, read the categorized message, look up the category in the guide, apply the fix, re-run.
|
||||
- **Alternatives and failures:** no run starts: check runner and trigger; message uncategorized: raise as a defect.
|
||||
- **Dependencies:** use cases 1 and 2.
|
||||
|
||||
### UC candidate 5: Run project quality checks (P2)
|
||||
|
||||
- **Actor:** software engineer. **Goal:** tests, lint, format and type checks run on every change.
|
||||
- **Trigger:** pull request or push.
|
||||
- **Preconditions:** shared workflow available; project onboarded.
|
||||
- **Success:** a status check reports pass or fail.
|
||||
- **Main flow:** the shared workflow detects inputs, runs the checks, reports the result.
|
||||
- **Alternatives and failures:** a check fails: the log names tool, file and message; unsupported language: workflow fails with a clear message.
|
||||
- **Dependencies:** use case 3; reusable workflow support.
|
||||
|
||||
### UC candidate 6: Release a reusable workflow (P2)
|
||||
|
||||
- **Actor:** DevOps professional. **Goal:** a validated, versioned workflow update that consumers can pin.
|
||||
- **Trigger:** a workflow change is ready.
|
||||
- **Preconditions:** validation checks exist; version scheme defined.
|
||||
- **Success:** a tag and changelog entry exist and pinned consumers are unaffected.
|
||||
- **Main flow:** run validation, update the changelog, tag, announce.
|
||||
- **Alternatives and failures:** validation fails: no tag; breaking change: new major version.
|
||||
- **Dependencies:** use case 1 (validation from MIL-001).
|
||||
|
||||
### UC candidate 7: Manage workflow runners (P2)
|
||||
|
||||
- **Actor:** DevOps professional (runner operator). **Goal:** workflows run on a supported runner.
|
||||
- **Trigger:** a job waits, fails to start, or a new label is needed.
|
||||
- **Preconditions:** access to the runner list.
|
||||
- **Success:** a runner with the required label and tools is online.
|
||||
- **Main flow:** compare the workflow's `runs-on` label with online runners, check prerequisites such as `python3`, fix or register a runner.
|
||||
- **Alternatives and failures:** runner offline: restart or replace; label missing: add the label or change the workflow.
|
||||
- **Dependencies:** use case 3.
|
||||
|
||||
### UC candidate 8: Consume a workflow update (P2)
|
||||
|
||||
- **Actor:** software engineer. **Goal:** adopt a new workflow version safely.
|
||||
- **Trigger:** a new release or a changelog notice.
|
||||
- **Preconditions:** releases are versioned and have a changelog.
|
||||
- **Success:** the project uses the new version and its pipeline still passes.
|
||||
- **Main flow:** read the changelog, change the pinned version in one branch, run, merge.
|
||||
- **Alternatives and failures:** breaking change: follow upgrade notes; failure: roll back to the previous pin.
|
||||
- **Dependencies:** use case 6.
|
||||
|
||||
### UC candidate 9: Review workflow results (P3)
|
||||
|
||||
- **Actor:** software engineer. **Goal:** understand a failed check and make it pass.
|
||||
- **Trigger:** a failed status check on a pull request.
|
||||
- **Preconditions:** a run exists.
|
||||
- **Success:** the next run passes.
|
||||
- **Main flow:** open the check, read the failing step, fix locally, push.
|
||||
- **Alternatives and failures:** the cause is infrastructure, not code: hand over to use case 4.
|
||||
- **Dependencies:** use case 5.
|
||||
|
||||
### UC candidate 10: Create a project workflow (P3)
|
||||
|
||||
- **Actor:** software engineer. **Goal:** compose shared workflows into a project pipeline.
|
||||
- **Trigger:** a project needs build and delivery steps.
|
||||
- **Preconditions:** shared workflows are documented with inputs.
|
||||
- **Success:** the project workflow runs the chosen shared workflows in order.
|
||||
- **Main flow:** pick workflows, set inputs, set triggers and permissions, test.
|
||||
- **Alternatives and failures:** missing input: the workflow fails with the input name.
|
||||
- **Dependencies:** use cases 5 and 8.
|
||||
|
||||
### UC candidate 11: Build and publish an artifact (P3)
|
||||
|
||||
- **Actor:** software engineer. **Goal:** a package or binary is built and published.
|
||||
- **Trigger:** a tag or a manual run.
|
||||
- **Preconditions:** destination decided; token with write access.
|
||||
- **Success:** the artifact is available at the destination with a version.
|
||||
- **Main flow:** build, test, package, publish, report the location.
|
||||
- **Alternatives and failures:** publish denied: permission failure; version exists: fail without overwrite.
|
||||
- **Dependencies:** use cases 5 and 6; destination decision (MIL-004 task 4).
|
||||
|
||||
### UC candidate 12: Publish a release (P3)
|
||||
|
||||
- **Actor:** software engineer. **Goal:** a release with validated version and notes.
|
||||
- **Trigger:** a version tag.
|
||||
- **Preconditions:** changelog entry exists.
|
||||
- **Success:** a release page with notes from the changelog.
|
||||
- **Main flow:** validate the version, build notes, create the release.
|
||||
- **Alternatives and failures:** invalid version or missing notes: fail. This overlaps with use cases 6 and 11 and should be merged with one of them when the use cases are written.
|
||||
- **Dependencies:** use cases 6 and 11.
|
||||
|
||||
---
|
||||
|
||||
[BC-001]: ./business-case.md
|
||||
[SA-001]: ./stakeholder-analysis.md
|
||||
[US-001]: ./user-stories.md
|
||||
[ADR-0002]: ./adr/adr-0002-s01-approves-as-stand-in.md
|
||||
[MIL-001]: ./milestones/mil-001-stabilise-metadata-sync.md
|
||||
[MIL-002]: ./milestones/mil-002-onboarding-and-operations.md
|
||||
[MIL-003]: ./milestones/mil-003-quality-checks.md
|
||||
[MIL-004]: ./milestones/mil-004-versioned-release.md
|
||||
[MIL-005]: ./milestones/mil-005-wiki-and-translations.md
|
||||
[MIL-006]: ./milestones/mil-006-shared-wiki-publishing.md
|
||||
[Milestone MIL-001]: https://git.tirsystem.com/TirSystem/github-action/milestone/18
|
||||
[Milestone MIL-002]: https://git.tirsystem.com/TirSystem/github-action/milestone/19
|
||||
[Milestone MIL-003]: https://git.tirsystem.com/TirSystem/github-action/milestone/20
|
||||
[Milestone MIL-004]: https://git.tirsystem.com/TirSystem/github-action/milestone/21
|
||||
[Milestone MIL-005]: https://git.tirsystem.com/TirSystem/github-action/milestone/93
|
||||
[Milestone MIL-006]: https://git.tirsystem.com/TirSystem/github-action/milestone/94
|
||||
[a2bf2d4]: https://git.tirsystem.com/TirSystem/github-action/commit/a2bf2d420416f7aff2badc6fe32a7690e2e523fd
|
||||
[ea06eaa]: https://git.tirsystem.com/TirSystem/github-action/commit/ea06eaaa698247d20e4a8e2694d7acbb1de58b63
|
||||
@@ -0,0 +1,50 @@
|
||||
# Review Record: BC-001 Business Case
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-001 |
|
||||
| CrossReference | [BC-001], [QC-BC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S05 | S05 review approved (reported by S01)<br>Independence action item closed | [ba1c6be] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S05 | S01 stood in for S05<br>Independence of the review is still open | [0799b43] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [BC-001]
|
||||
- Checklist used: [QC-BC-001] (`QC-BC-001`)
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | ROI/Cost-Benefit analysis is quantitative, or where qualitative, is explicitly justified | Pass | The Cost–Benefit Assessment states costs as qualitative with no external cost and lists benefits; the qualitative form is labelled. |
|
||||
| 2 | Risks are identified with documented impact and mitigation | Pass | Risks table has Risk, Impact and Mitigation for every row. |
|
||||
| 3 | Success criteria are measurable, stating explicit targets rather than vague aspirations | Pass | Four criteria, each with a target and a measure. |
|
||||
| 4 | Scope explicitly separates In Scope vs Out of Scope | Pass | Scope has separate In Scope and Out of Scope lists. |
|
||||
| 5 | Stakeholders are cross-referenced to Stakeholder Analysis IDs rather than re-described inline | Pass | Stakeholders table uses S01 to S05; the ID, not a role description, identifies each. |
|
||||
| 6 | Methodology and quality-standard foundation are stated explicitly (e.g. ISO/IEC 25010, Larman) | Pass | Methodological and Standards Foundation cites the framework, Larman and ISO/IEC 25010:2023. |
|
||||
| 7 | Assumptions and constraints are explicit and clearly distinguished from one another | Pass | Separate Assumptions and Constraints sections. The 2026-10-10 change edits the mirror assumption only. |
|
||||
| 8 | Document supports executive decision-making with a clear, unambiguous recommendation | Pass | Recommendation section: Proceed, with the reason. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go — all eight criteria pass. S01 gave the Go in chat on 2026-10-10 for the revision that changes the mirror assumption to at most one GitHub push mirror. The author and the approving reviewer are the same person (S01); S01 stood in for S05 on 2026-10-10; this is not an independent review because the author and S01 are the same person.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Independent review of this record and of BC-001 by a person other than the author (the rule that the reviewer must not be the author) | S05 | 2026-10-17 |
|
||||
|
||||
---
|
||||
|
||||
[BC-001]: ../../business-case.md
|
||||
[QC-BC-001]: ../../../framework/qc/qc-business-case.md
|
||||
[ba1c6be]: https://git.tirsystem.com/TirSystem/github-action/commit/ba1c6bea7491884899d55a3f86364c6a7811649a
|
||||
[0799b43]: https://git.tirsystem.com/TirSystem/github-action/commit/0799b43888a1fef02fe135818a4a38eff3452a09
|
||||
@@ -0,0 +1,50 @@
|
||||
# Review Record: PP-001 Project Plan
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-002 |
|
||||
| CrossReference | [PP-001], [BC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S05 | Initial version | [c017c06] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S05 | S01 stood in for S05<br>Independence of the review is still open | [0799b43] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [PP-001]
|
||||
- Checklist used: none: the Project Plan has no QC checklist (catalog and `PP.md` reference). Validated against the Business Case [BC-001] constraints and the Go / No-Go criteria of each listed milestone, as `PP.md` prescribes.
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Every milestone in the plan has a `MIL-*` document and the plan's dates equal that document's target date | Pass | MIL-001 to MIL-004 exist; decision dates 2026-10-17, 10-31, 11-14, 11-28 match the Target Date of each milestone. |
|
||||
| 2 | Every Business Case scope item is covered by a gateway | Pass | Scope Coverage maps validation, documentation, quality checks and release to MIL-001 to MIL-004. |
|
||||
| 3 | The schedule respects the Business Case constraints | Pass | The Business Case sets no deadline; the plan states its dates are proposals. The constraint that nothing is written before a milestone is accepted is repeated in Planning Assumptions. |
|
||||
| 4 | Dependencies between milestones are stated | Pass | Dependencies section gives MIL-001 to MIL-002 to MIL-003 to MIL-004. |
|
||||
| 5 | Every gateway has an owner who is a stakeholder ID | Pass | All four gateways are owned by S05. |
|
||||
| 6 | Plan content is consistent with the revised mirror behaviour | Pass | UC candidate 1 now describes no GitHub mirror as a successful skip and several mirrors as a failure. |
|
||||
| 7 | Open Issues are current | Fail | Open Issues still lists the decisions for MIL-001 task 1 and task 3 as open; both were decided and recorded in MIL-001. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go — S01 gave the Go in chat on 2026-10-10 for the revision to UC candidate 1. One stale entry in Open Issues does not affect the schedule or the changed use case; it is recorded as an action item. The author and the approving reviewer are the same person (S01); the S05 stand-in review is recorded in RC-001 and applies here too; independence is still open.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Remove the answered MIL-001 task 1 and task 3 items from Open Issues in PP-001, with a Version History row | S01 | 2026-10-17 |
|
||||
| Confirm the proposed dates and the start week (already listed in Open Issues) | S01 | 2026-10-17 |
|
||||
|
||||
---
|
||||
|
||||
[PP-001]: ../../project-plan.md
|
||||
[BC-001]: ../../business-case.md
|
||||
[c017c06]: https://git.tirsystem.com/TirSystem/github-action/commit/c017c06789424305b31f19e48238ad14231e8113
|
||||
[0799b43]: https://git.tirsystem.com/TirSystem/github-action/commit/0799b43888a1fef02fe135818a4a38eff3452a09
|
||||
@@ -0,0 +1,48 @@
|
||||
# Review Record: MIL-001 Stabilise the metadata sync
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-003 |
|
||||
| CrossReference | [MIL-001], [QC-MIL-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S05 | Initial version | [c017c06] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S05 | S01 stood in for S05<br>Independence of the review is still open | [0799b43] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [MIL-001]
|
||||
- Checklist used: [QC-MIL-001] (`QC-MIL-001`)
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable section: one canonical workflow, passing validation and tests, an accurate README and a manual run. |
|
||||
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Five criteria, each with an objectively checkable Go and No-Go column. |
|
||||
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies: none, first milestone. |
|
||||
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability maps MIL-001 to O1 and O2 of BC-001. |
|
||||
| 5 | Milestone owner and approving reviewer are identified | Pass | Owner S05 and approving reviewer S01. |
|
||||
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date 2026-10-17, marked proposed; the Business Case sets no deadline, so there is nothing to contradict. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go — all six criteria pass. S01 gave the Go in chat on 2026-10-10 for the amendment of the task 1 decision (zero GitHub mirrors is a successful skip) and the matching task 5 test scope. Go / No-Go criterion 5 (manual run on Gitea) is still open as task 7 (issue 7) and is not changed by this amendment. The author and the approving reviewer are the same person (S01); the S05 stand-in review is recorded in RC-001 and applies here too; independence is still open.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Run the manual `workflow_dispatch` check on Gitea for the amended behaviour: a repository with a GitHub mirror and one without (task 7) | S05 | 2026-10-17 |
|
||||
|
||||
---
|
||||
|
||||
[MIL-001]: ../../milestones/mil-001-stabilise-metadata-sync.md
|
||||
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||
[c017c06]: https://git.tirsystem.com/TirSystem/github-action/commit/c017c06789424305b31f19e48238ad14231e8113
|
||||
[0799b43]: https://git.tirsystem.com/TirSystem/github-action/commit/0799b43888a1fef02fe135818a4a38eff3452a09
|
||||
@@ -0,0 +1,51 @@
|
||||
# Review Record: SA-001 Stakeholder Analysis
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-004 |
|
||||
| CrossReference | [SA-001], [QC-SA-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S05 | Initial version | [aa3f088] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S05 | S01 stood in for S05<br>Independence of the review is still open | [0799b43] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [SA-001]
|
||||
- Checklist used: [QC-SA-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Power/Interest grid is filled for every stakeholder, with no gaps or unclassified entries | Pass | S01 to S05 each have Power, Interest and Quadrant. |
|
||||
| 2 | Each stakeholder is assigned a unique, stable ID reusable for RACI assignments in other artifacts | Pass | IDs S01 to S05 are used by BC-001, PP-001 and the milestones. |
|
||||
| 3 | Roles and organizational context are defined with explicit Power and Interest levels, not just narrative description | Pass | Role, organization and HIGH/MEDIUM/LOW levels per stakeholder, with a rationale section. |
|
||||
| 4 | Communication needs (channel, frequency, deliverable type) are mapped to project phases or milestones | Pass | Communication Requirements table maps each stakeholder to a milestone. |
|
||||
| 5 | Conflicting stakeholder interests are identified with documented mitigation or resolution strategies | Pass | Four conflicts, each with stakeholders and a mitigation. |
|
||||
| 6 | Stakeholder concerns are explicitly traced to Business Case objectives | Pass | Business Goal Alignment maps each concern to O1 to O4 of BC-001. |
|
||||
| 7 | Primary concerns are expressed in both business language and a recognized quality-attribute mapping (e.g. FURPS+) | Pass | Primary Concern column plus a FURPS+ mapping table. |
|
||||
| 8 | Document is understandable and navigable by non-technical stakeholders reviewing their own entry | Pass | Plain-language summary table and one section per topic. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go — all eight criteria pass, with two follow-ups that do not affect the criteria. Retrospective review prepared 2026-10-10 at the request of S01; the instance has been `Accepted` since 2026-10-03 and this record confirms it against the checklist. The author and the approving reviewer are the same person (S01); the S05 stand-in review is recorded in RC-001 and applies here too; independence is still open.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Update the Sign-Off section, which still says 'Pending review by S01 and S05', with a Version History row | S01 | 2026-10-17 |
|
||||
| Identify the holders of the S03 role (listed as 'holders to be confirmed') | S01 | 2026-10-17 |
|
||||
|
||||
---
|
||||
|
||||
[SA-001]: ../../stakeholder-analysis.md
|
||||
[QC-SA-001]: ../../../framework/qc/qc-stakeholder-analysis.md
|
||||
[aa3f088]: https://git.tirsystem.com/TirSystem/github-action/commit/aa3f08876d55fa5f008e93f65176a496601c00ca
|
||||
[0799b43]: https://git.tirsystem.com/TirSystem/github-action/commit/0799b43888a1fef02fe135818a4a38eff3452a09
|
||||
@@ -0,0 +1,48 @@
|
||||
# Review Record: MIL-002
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-005 |
|
||||
| CrossReference | [MIL-002], [QC-MIL-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S05 | Initial version | [aa3f088] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S05 | S01 stood in for S05<br>Independence of the review is still open | [0799b43] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [MIL-002]
|
||||
- Checklist used: [QC-MIL-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable: verified onboarding and operations guide, credential validation step and categorized failure messages. |
|
||||
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Five criteria, each with an objectively checkable Go and No-Go column. |
|
||||
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies: depends on MIL-001, with the reason stated. |
|
||||
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability maps MIL-002 to O2 and O3 of BC-001. |
|
||||
| 5 | Milestone owner and approving reviewer are identified | Pass | Owner S05 and approving reviewer S01. |
|
||||
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date 2026-10-31, marked proposed; the Business Case sets no deadline, so nothing contradicts it. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go — all six criteria pass. Retrospective review prepared 2026-10-10 at the request of S01; the instance has been `Accepted` since 2026-10-03 and this record confirms it against the checklist. The author and the approving reviewer are the same person (S01); the S05 stand-in review is recorded in RC-001 and applies here too; independence is still open.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Confirm the proposed target date with S01 and S05 (the date is still marked proposed) | S05 | 2026-10-17 |
|
||||
|
||||
---
|
||||
|
||||
[MIL-002]: ../../milestones/mil-002-onboarding-and-operations.md
|
||||
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||
[aa3f088]: https://git.tirsystem.com/TirSystem/github-action/commit/aa3f08876d55fa5f008e93f65176a496601c00ca
|
||||
[0799b43]: https://git.tirsystem.com/TirSystem/github-action/commit/0799b43888a1fef02fe135818a4a38eff3452a09
|
||||
@@ -0,0 +1,48 @@
|
||||
# Review Record: MIL-003
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-006 |
|
||||
| CrossReference | [MIL-003], [QC-MIL-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S05 | Initial version | [aa3f088] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S05 | S01 stood in for S05<br>Independence of the review is still open | [0799b43] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [MIL-003]
|
||||
- Checklist used: [QC-MIL-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable: a reusable quality-check workflow used by one other repository, and a results guide. |
|
||||
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Four criteria, each with an objectively checkable Go and No-Go column. |
|
||||
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies: depends on MIL-002, with the reason stated. |
|
||||
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability maps MIL-003 to O4 of BC-001. |
|
||||
| 5 | Milestone owner and approving reviewer are identified | Pass | Owner S05 and approving reviewer S01. |
|
||||
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date 2026-11-14, marked proposed; the Business Case sets no deadline, so nothing contradicts it. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go — all six criteria pass. Retrospective review prepared 2026-10-10 at the request of S01; the instance has been `Accepted` since 2026-10-03 and this record confirms it against the checklist. The author and the approving reviewer are the same person (S01); the S05 stand-in review is recorded in RC-001 and applies here too; independence is still open.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Confirm the proposed target date with S01 and S05 (the date is still marked proposed) | S05 | 2026-10-17 |
|
||||
|
||||
---
|
||||
|
||||
[MIL-003]: ../../milestones/mil-003-quality-checks.md
|
||||
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||
[aa3f088]: https://git.tirsystem.com/TirSystem/github-action/commit/aa3f08876d55fa5f008e93f65176a496601c00ca
|
||||
[0799b43]: https://git.tirsystem.com/TirSystem/github-action/commit/0799b43888a1fef02fe135818a4a38eff3452a09
|
||||
@@ -0,0 +1,48 @@
|
||||
# Review Record: MIL-004
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-007 |
|
||||
| CrossReference | [MIL-004], [QC-MIL-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S05 | Initial version | [aa3f088] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S05 | S01 stood in for S05<br>Independence of the review is still open | [0799b43] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [MIL-004]
|
||||
- Checklist used: [QC-MIL-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A concrete deliverable is defined for every gate | Pass | Deliverable: documented release process, consumer upgrade guide and a reusable release workflow. |
|
||||
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Four criteria, each with an objectively checkable Go and No-Go column. |
|
||||
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Dependencies: depends on MIL-003, with the reason stated. |
|
||||
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability maps MIL-004 to O4 of BC-001. |
|
||||
| 5 | Milestone owner and approving reviewer are identified | Pass | Owner S05 and approving reviewer S01. |
|
||||
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date 2026-11-28, marked proposed; the Business Case sets no deadline, so nothing contradicts it. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go — all six criteria pass. Retrospective review prepared 2026-10-10 at the request of S01; the instance has been `Accepted` since 2026-10-03 and this record confirms it against the checklist. The author and the approving reviewer are the same person (S01); the S05 stand-in review is recorded in RC-001 and applies here too; independence is still open.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Confirm the proposed target date with S01 and S05 (the date is still marked proposed) | S05 | 2026-10-17 |
|
||||
|
||||
---
|
||||
|
||||
[MIL-004]: ../../milestones/mil-004-versioned-release.md
|
||||
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||
[aa3f088]: https://git.tirsystem.com/TirSystem/github-action/commit/aa3f08876d55fa5f008e93f65176a496601c00ca
|
||||
[0799b43]: https://git.tirsystem.com/TirSystem/github-action/commit/0799b43888a1fef02fe135818a4a38eff3452a09
|
||||
@@ -0,0 +1,48 @@
|
||||
# Review Record: BC-001 Business Case (wiki scope)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-008 |
|
||||
| CrossReference | [BC-001], [QC-BC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [ae4e257] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [BC-001]
|
||||
- Checklist used: [QC-BC-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | ROI/Cost-Benefit analysis is quantitative, or where qualitative, is explicitly justified | Pass | Unchanged; the Cost-Benefit Assessment labels its qualitative form. |
|
||||
| 2 | Risks are identified with documented impact and mitigation | Pass | Unchanged; every risk has an impact and a mitigation. |
|
||||
| 3 | Success criteria are measurable, stating explicit targets rather than vague aspirations | Pass | Unchanged; four criteria with targets and measures. None measures the wiki; MIL-005 traces it to O3. |
|
||||
| 4 | Scope explicitly separates In Scope vs Out of Scope | Pass | The wiki in three languages is a new In Scope bullet; Out of Scope is unchanged and does not contradict it. |
|
||||
| 5 | Stakeholders are cross-referenced to Stakeholder Analysis IDs rather than re-described inline | Pass | Unchanged. |
|
||||
| 6 | Methodology and quality-standard foundation are stated explicitly (e.g. ISO/IEC 25010, Larman) | Pass | Unchanged. |
|
||||
| 7 | Assumptions and constraints are explicit and clearly distinguished from one another | Pass | Unchanged. |
|
||||
| 8 | Document supports executive decision-making with a clear, unambiguous recommendation | Pass | Unchanged: Proceed. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all eight criteria pass for the revision that adds the wiki (English, Danish, Bahasa Malaysia) to the in-scope list. S01 gave the Go in chat on 2026-10-10. The author and S01 are the same person, so the independent S05 review recorded in RC-001 is still open.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[BC-001]: ../../business-case.md
|
||||
[QC-BC-001]: ../../../framework/qc/qc-business-case.md
|
||||
[ae4e257]: https://git.tirsystem.com/TirSystem/github-action/commit/ae4e257236095e76132980fad1e9a661b1d082c7
|
||||
@@ -0,0 +1,47 @@
|
||||
# Review Record: PP-001 Project Plan (MIL-005)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-009 |
|
||||
| CrossReference | [PP-001], [BC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [ae4e257] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [PP-001]
|
||||
- Checklist used: none: the Project Plan has no QC checklist. Validated against the Business Case [BC-001] and the Go / No-Go criteria of each listed milestone, as `PP.md` prescribes.
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Every milestone in the plan has a `MIL-*` document and the plan's dates equal that document's target date | Pass | MIL-001 to MIL-005 exist; the MIL-005 decision date 2026-12-12 equals its Target Date. |
|
||||
| 2 | Every Business Case scope item is covered by a gateway | Pass | The new scope item (wiki in three languages) maps to MIL-005 in Scope Coverage. |
|
||||
| 3 | The schedule respects the Business Case constraints | Pass | The Business Case sets no deadline. MIL-005 is scheduled after MIL-004 although it only depends on MIL-002. |
|
||||
| 4 | Dependencies between milestones are stated | Pass | The Dependencies diagram adds MIL-002 to MIL-005. |
|
||||
| 5 | Every gateway has an owner who is a stakeholder ID | Pass | MIL-005 is owned by S05. |
|
||||
| 6 | Plan content is internally consistent | Pass | Finding fixed during this review: Planning Assumptions still said the last decision is 2026-11-28; it now says 2026-12-12. The purpose text says five milestones. |
|
||||
| 7 | Open Issues are current | Fail | Open Issues still lists the answered MIL-001 task 1 and task 3 decisions (carried over from RC-002). |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - S01 gave the Go in chat on 2026-10-10 for the revision that adds MIL-005. The open-issues finding is carried over from RC-002 and does not affect MIL-005. The author and S01 are the same person, so the independent S05 review recorded in RC-001 is still open.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Remove the answered MIL-001 task 1 and task 3 items from Open Issues in PP-001, with a Version History row | S01 | 2026-10-17 |
|
||||
|
||||
---
|
||||
|
||||
[PP-001]: ../../project-plan.md
|
||||
[BC-001]: ../../business-case.md
|
||||
[ae4e257]: https://git.tirsystem.com/TirSystem/github-action/commit/ae4e257236095e76132980fad1e9a661b1d082c7
|
||||
@@ -0,0 +1,47 @@
|
||||
# Review Record: MIL-005 Wiki and translations
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-010 |
|
||||
| CrossReference | [MIL-005], [QC-MIL-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [ae4e257] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [MIL-005]
|
||||
- Checklist used: [QC-MIL-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A concrete deliverable is defined for every gate | Pass | Fifteen wiki pages, a generation script and the `AGENTS.md` rule. |
|
||||
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Five criteria, each with a checkable Go and No-Go column. |
|
||||
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Depends on MIL-002, with the reason. |
|
||||
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability maps MIL-005 to O3 of BC-001. |
|
||||
| 5 | Milestone owner and approving reviewer are identified | Pass | Owner S05, approving reviewer S01. |
|
||||
| 6 | Milestone has a defined target date consistent with project constraints | Pass | 2026-12-12, marked proposed; the Business Case sets no deadline. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all six criteria pass. S01 gave the Go in chat on 2026-10-10. Accepting the milestone is what unlocks its tasks under the plan-first gate; the issues are still to be created with `sync-project.sh --apply`. The author and S01 are the same person, so the independent S05 review recorded in RC-001 is still open.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Decide how the agent publishes to the wiki repository (task 2): push with a token or prepare changes for review | S01 | 2026-10-17 |
|
||||
| Confirm the proposed target date with S01 and S05 | S05 | 2026-10-17 |
|
||||
|
||||
---
|
||||
|
||||
[MIL-005]: ../../milestones/mil-005-wiki-and-translations.md
|
||||
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||
[ae4e257]: https://git.tirsystem.com/TirSystem/github-action/commit/ae4e257236095e76132980fad1e9a661b1d082c7
|
||||
@@ -0,0 +1,47 @@
|
||||
# Review Record: MIL-005 Wiki and translations (publishing decision)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-011 |
|
||||
| CrossReference | [MIL-005], [QC-MIL-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [20361e8] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [MIL-005]
|
||||
- Checklist used: [QC-MIL-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A concrete deliverable is defined for every gate | Pass | Fifteen wiki pages in `wiki/`, the generation script, the publishing workflow and the `AGENTS.md` rule. |
|
||||
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Six criteria, each checkable. The new criterion 6 is checked by the author of the last wiki commit. |
|
||||
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Depends on MIL-002; task 8 adds no new milestone dependency. |
|
||||
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Traceability maps MIL-005 to O3 of BC-001; the wiki is in the BC-001 scope list. |
|
||||
| 5 | Milestone owner and approving reviewer are identified | Pass | Owner S05, approving reviewer S01. |
|
||||
| 6 | Milestone has a defined target date consistent with project constraints | Pass | 2026-12-12, marked proposed; the Business Case sets no deadline. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all six criteria pass for the amendment that records how the wiki is published (source in `wiki/`, workflow on merge, no direct push) and adds task 8. S01 gave the Go in chat on 2026-10-10. The author and S01 are the same person, so the independent S05 review recorded in RC-001 is still open. This review closes the RC-010 action item to decide how the agent publishes.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Approve the scope of the wiki publish secret (write access to the wiki repository only) and store it (task 2) | S05 | 2026-10-17 |
|
||||
| Store the approved secret on the Gitea repository (task 2) | S03 | 2026-10-24 |
|
||||
|
||||
---
|
||||
|
||||
[MIL-005]: ../../milestones/mil-005-wiki-and-translations.md
|
||||
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||
[20361e8]: https://git.tirsystem.com/TirSystem/github-action/commit/20361e881ebd0dc52e1d1c358ceb792c41b76c60
|
||||
@@ -0,0 +1,51 @@
|
||||
# Review Record: ADR-0001 Wiki structure, page names and languages
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-012 |
|
||||
| CrossReference | [ADR-0001], [QC-ADR-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [d0618d9] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [ADR-0001]
|
||||
- Checklist used: [QC-ADR-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | The ID (`ADR-NNNN`, 4-digit) matches the filename number and is unique and sequential | Pass | ADR-0001 in `adr-0001-wiki-structure-and-languages.md`; the first ADR. |
|
||||
| 2 | Context states the problem, the forces (cost, risk, constraints) and the options evaluated | Pass | Names the three things to fix, the forces and the options. |
|
||||
| 3 | At least two options were considered, or the absence of alternatives is justified | Pass | Three naming options and two source-of-truth options. |
|
||||
| 4 | Decision is stated in one or two unhedged sentences and matches one of the evaluated options | Pass | Finding fixed during this review: the decision ran to several sentences. It is now two sentences (naming option 1, source option 2), and the details are listed under it as rules. |
|
||||
| 5 | Consequences list both Positive and Negative outcomes | Pass | Three positive and three negative. |
|
||||
| 6 | Quality-attribute impacts (performance, security, portability, etc.) are named where the decision affects them | Pass | Maintainability is the affected attribute and is named: stale translations are detectable but not self-updating. Performance and security are not affected. |
|
||||
| 7 | Affected Artifacts are listed as links, and each is also in CrossReference | Pass | MIL-005 and BC-001 are linked and cited. |
|
||||
| 8 | Status changes are recorded as new Version History rows with a Change summary and Commit link; retained rows are never rewritten | Pass | The earlier row is kept and only its status changed. |
|
||||
| 9 | A superseded or deprecated ADR names its successor, and the successor links back | N-A | Nothing is superseded. |
|
||||
| 10 | Written in business or technical language of the domain, with no unexplained abbreviations | Pass | IT Professional English; `da`, `ms` and `sha256` are explained in the text. |
|
||||
| 11 | Status is one of `Proposed`, `Accepted`, `Rejected`, `Deprecated` or `Superseded by ADR-NNNN`, and every Version History row uses only these | Pass | Rows use Deprecated and Accepted only. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all applicable criteria pass; the one finding (criterion 4) was fixed during the review. S01 gave the Go in chat on 2026-10-10. The author and S01 are the same person, so the independent S05 review recorded in RC-001 is still open.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Publish and open a page with a dot in its name (`Home.da`) on the wiki; if Gitea rejects it, supersede this ADR with the `Home_da` form (MIL-005 task 7) | S05 | 2026-12-12 |
|
||||
|
||||
---
|
||||
|
||||
[ADR-0001]: ../../adr/adr-0001-wiki-structure-and-languages.md
|
||||
[QC-ADR-001]: ../../../framework/qc/qc-adr.md
|
||||
[d0618d9]: https://git.tirsystem.com/TirSystem/github-action/commit/d0618d929f2ec274d30b10bb1be306e1f04c31ee
|
||||
@@ -0,0 +1,51 @@
|
||||
# Review Record: ADR-0002 S01 approves as stand-in
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-013 |
|
||||
| CrossReference | [ADR-0002], [QC-ADR-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [bc3bd07] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [ADR-0002]
|
||||
- Checklist used: [QC-ADR-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | The ID (`ADR-NNNN`, 4-digit) matches the filename number and is unique and sequential | Pass | ADR-0002 in `adr-0002-s01-approves-as-stand-in.md`. |
|
||||
| 2 | Context states the problem, the forces (cost, risk, constraints) and the options evaluated | Pass | Names the roles, the conflicting text in SA-001 and the Business Case, and the framework rule. |
|
||||
| 3 | At least two options were considered, or the absence of alternatives is justified | Pass | Three options. |
|
||||
| 4 | Decision is stated in one or two unhedged sentences and matches one of the evaluated options | Pass | Two sentences; matches option 2. |
|
||||
| 5 | Consequences list both Positive and Negative outcomes | Pass | Two positive, three negative. |
|
||||
| 6 | Quality-attribute impacts (performance, security, portability, etc.) are named where the decision affects them | Pass | Security and accountability impacts are named; the missing second reader is the first negative. |
|
||||
| 7 | Affected Artifacts are listed as links, and each is also in CrossReference | Pass | SA-001 and RC-001 are linked and cited. |
|
||||
| 8 | Status changes are recorded as new Version History rows with a Change summary and Commit link; retained rows are never rewritten | Pass | Initial row only. |
|
||||
| 9 | A superseded or deprecated ADR names its successor, and the successor links back | N-A | Nothing is superseded. |
|
||||
| 10 | Written in business or technical language of the domain, with no unexplained abbreviations | Pass | IT Professional English; roles are given by ID. |
|
||||
| 11 | Status is one of `Proposed`, `Accepted`, `Rejected`, `Deprecated` or `Superseded by ADR-NNNN`, and every Version History row uses only these | Pass | Accepted only. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all applicable criteria pass. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader. This record is itself approved under the rule it records, which is the weakness the ADR lists.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Tell S05 (Michael Kragh) about this ADR, and amend SA-001 and the Business Case mitigation, or have S05 accept the stand-in rule | S01 | 2026-10-17 |
|
||||
|
||||
---
|
||||
|
||||
[ADR-0002]: ../../adr/adr-0002-s01-approves-as-stand-in.md
|
||||
[QC-ADR-001]: ../../../framework/qc/qc-adr.md
|
||||
[bc3bd07]: https://git.tirsystem.com/TirSystem/github-action/commit/bc3bd07b29a0a3dcf45045b9baac64c36144c6d1
|
||||
@@ -0,0 +1,51 @@
|
||||
# Review Record: ADR-0003 Wiki publish token
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-014 |
|
||||
| CrossReference | [ADR-0003], [QC-ADR-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [bc3bd07] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [ADR-0003]
|
||||
- Checklist used: [QC-ADR-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | The ID (`ADR-NNNN`, 4-digit) matches the filename number and is unique and sequential | Pass | ADR-0003 in `adr-0003-wiki-publish-token.md`; follows ADR-0002. |
|
||||
| 2 | Context states the problem, the forces (cost, risk, constraints) and the options evaluated | Pass | States the need, the scope problem, the two answered open points and the options. |
|
||||
| 3 | At least two options were considered, or the absence of alternatives is justified | Pass | Three options. |
|
||||
| 4 | Decision is stated in one or two unhedged sentences and matches one of the evaluated options | Pass | Finding fixed during this review: the decision had three sentences. It is now two sentences (option 2). |
|
||||
| 5 | Consequences list both Positive and Negative outcomes | Pass | Three positive, three negative. |
|
||||
| 6 | Quality-attribute impacts (performance, security, portability, etc.) are named where the decision affects them | Pass | Security is named: sync token stays read-only; fallback may hide a missing secret. |
|
||||
| 7 | Affected Artifacts are listed as links, and each is also in CrossReference | Pass | MIL-005, ADR-0001 and RC-011 are linked and cited. |
|
||||
| 8 | Status changes are recorded as new Version History rows with a Change summary and Commit link; retained rows are never rewritten | Pass | Initial row only. |
|
||||
| 9 | A superseded or deprecated ADR names its successor, and the successor links back | N-A | Nothing is superseded. |
|
||||
| 10 | Written in business or technical language of the domain, with no unexplained abbreviations | Pass | IT Professional English; `NAME=token`, `HTTP 401` and `403` are explained. |
|
||||
| 11 | Status is one of `Proposed`, `Accepted`, `Rejected`, `Deprecated` or `Superseded by ADR-NNNN`, and every Version History row uses only these | Pass | Accepted only. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all applicable criteria pass; the one finding (criterion 4) was fixed during the review. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Scope `TOKEN_FOR_GITEA_WIKI` to this repository instead of the organisation, and update the credentials guide and MIL-005 task 2 text (new version rows, retranslated wiki pages) | S03 | 2026-10-24 |
|
||||
|
||||
---
|
||||
|
||||
[ADR-0003]: ../../adr/adr-0003-wiki-publish-token.md
|
||||
[QC-ADR-001]: ../../../framework/qc/qc-adr.md
|
||||
[bc3bd07]: https://git.tirsystem.com/TirSystem/github-action/commit/bc3bd07b29a0a3dcf45045b9baac64c36144c6d1
|
||||
@@ -0,0 +1,47 @@
|
||||
# Review Record: PP-001 Project Plan (PAT_FOR_GITHUB, open issues)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-015 |
|
||||
| CrossReference | [PP-001], [BC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [b282e10] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [PP-001]
|
||||
- Checklist used: none: the Project Plan has no QC checklist. Validated against the Business Case [BC-001] and the Go / No-Go criteria of each listed milestone, as `PP.md` prescribes.
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Every milestone in the plan has a `MIL-*` document and the plan's dates equal that document's target date | Pass | MIL-001 to MIL-005 exist; decision dates equal each Target Date. |
|
||||
| 2 | Every Business Case scope item is covered by a gateway | Pass | Unchanged; Scope Coverage maps all items. |
|
||||
| 3 | The schedule respects the Business Case constraints | Pass | The Business Case sets no deadline; dates are marked as proposals. |
|
||||
| 4 | Dependencies between milestones are stated | Pass | Unchanged. |
|
||||
| 5 | Every gateway has an owner who is a stakeholder ID | Pass | All five gateways are owned by S05. |
|
||||
| 6 | Plan content is internally consistent | Pass | Finding fixed during this review: UC candidate 2 still listed "malformed JSON" as a credential failure although no secret is JSON any more. It now lists the empty value, a wrong or expired token (HTTP 401) and a missing permission. The secret names match the code and the guides. |
|
||||
| 7 | Open Issues are current | Pass | Finding fixed during this review: the MIL-001 task 1 and task 3 decisions were made and are recorded in MIL-001, so they are removed. The remaining items are still open: confirm dates, no QC checklist for the Project Plan, formal use cases wait for a diagram and user stories. This closes the RC-009 action item. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all seven criteria pass; the two findings were fixed during the review. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Confirm the proposed dates and the start week (already in Open Issues) | S01 | 2026-10-17 |
|
||||
|
||||
---
|
||||
|
||||
[PP-001]: ../../project-plan.md
|
||||
[BC-001]: ../../business-case.md
|
||||
[b282e10]: https://git.tirsystem.com/TirSystem/github-action/commit/b282e107416a890d6df27e6bdf23ab8a65e17123
|
||||
@@ -0,0 +1,47 @@
|
||||
# Review Record: MIL-006 Shared wiki publishing
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-016 |
|
||||
| CrossReference | [MIL-006], [QC-MIL-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [676a262] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [MIL-006]
|
||||
- Checklist used: [QC-MIL-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A concrete deliverable is defined for every gate | Pass | A scoped `publish-wiki.yml` with embedded script, an opt-in rule, tests, guides and one pilot repository. |
|
||||
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Six criteria, each with a checkable Go and No-Go column. |
|
||||
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Depends on MIL-005 (publisher and wiki rules) and MIL-002 (scoped delivery verified, #9), with reasons. |
|
||||
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Maps to O2 (a defined way to reach consuming repositories) and O3 of BC-001; also cites MIL-005 and ADR-0003. |
|
||||
| 5 | Milestone owner and approving reviewer are identified | Pass | Owner S05, approving reviewer S01. |
|
||||
| 6 | Milestone has a defined target date consistent with project constraints | Pass | 2026-12-26, marked proposed; the Business Case sets no deadline. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all six criteria pass. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader. Accepting the milestone unlocks its tasks under the plan-first gate; the issues are still to be created with `sync-project.sh --apply`. The PP-001 row that adds MIL-006 is `Proposed` and was not part of this review.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Decide the opt-in mechanism (recommended: a `wiki/.publish` marker file) and the pilot repository (task 1) | S01 | 2026-12-14 |
|
||||
| Store `TOKEN_FOR_GITEA_WIKI` in the pilot repository's organisation (task 4) | S03 | 2026-12-21 |
|
||||
|
||||
---
|
||||
|
||||
[MIL-006]: ../../milestones/mil-006-shared-wiki-publishing.md
|
||||
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||
[676a262]: https://git.tirsystem.com/TirSystem/github-action/commit/676a26240563338307c0454c3bf15b960bdb58ca
|
||||
@@ -0,0 +1,47 @@
|
||||
# Review Record: PP-001 Project Plan (MIL-006)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-017 |
|
||||
| CrossReference | [PP-001], [BC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [676a262] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [PP-001]
|
||||
- Checklist used: none: the Project Plan has no QC checklist. Validated against the Business Case [BC-001] and the Go / No-Go criteria of each listed milestone, as `PP.md` prescribes.
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Every milestone in the plan has a `MIL-*` document and the plan's dates equal that document's target date | Pass | MIL-001 to MIL-006 exist; the MIL-006 decision date 2026-12-26 equals its Target Date. |
|
||||
| 2 | Every Business Case scope item is covered by a gateway | Pass | The shared publisher (O2, O3) is mapped to MIL-006 in Scope Coverage; the wiki scope item stays on MIL-005. |
|
||||
| 3 | The schedule respects the Business Case constraints | Pass | The Business Case sets no deadline; the dates are proposals and the plan says so. |
|
||||
| 4 | Dependencies between milestones are stated | Pass | The Dependencies diagram shows MIL-002 to MIL-005 to MIL-006; MIL-006 also lists them in its own document. |
|
||||
| 5 | Every gateway has an owner who is a stakeholder ID | Pass | MIL-006 is owned by S05. |
|
||||
| 6 | Plan content is internally consistent | Pass | "Six milestones", the last decision date 2026-12-26, the Gantt entries and the Gateway Schedule agree. |
|
||||
| 7 | Open Issues are current | Pass | Three items remain and are all still open: confirm dates, no QC checklist for the Project Plan, formal use cases wait for a diagram and user stories. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all seven criteria pass; no findings. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Confirm the proposed dates and the start week (already in Open Issues) | S01 | 2026-12-14 |
|
||||
|
||||
---
|
||||
|
||||
[PP-001]: ../../project-plan.md
|
||||
[BC-001]: ../../business-case.md
|
||||
[676a262]: https://git.tirsystem.com/TirSystem/github-action/commit/676a26240563338307c0454c3bf15b960bdb58ca
|
||||
@@ -0,0 +1,52 @@
|
||||
# Review Record: ADR-0004 Opt-in rule and secret handling of the shared wiki publisher
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-018 |
|
||||
| CrossReference | [ADR-0004], [QC-ADR-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [b22a2cd] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [ADR-0004]
|
||||
- Checklist used: [QC-ADR-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | The ID (`ADR-NNNN`, 4-digit) matches the filename number and is unique and sequential | Pass | ADR-0004 in `adr-0004-shared-wiki-publishing-opt-in.md`; follows ADR-0003. |
|
||||
| 2 | Context states the problem, the forces (cost, risk, constraints) and the options evaluated | Pass | States the scoped delivery, the deletion risk, the per-organisation secret and the fallback. |
|
||||
| 3 | At least two options were considered, or the absence of alternatives is justified | Pass | Four options for opting in (one with two forms) and two for the secret. |
|
||||
| 4 | Decision is stated in one or two unhedged sentences and matches one of the evaluated options | Pass | Finding fixed during this review: the `prune` form was not among the evaluated options. It is now option 1(b), with the reason. The decision is two sentences. |
|
||||
| 5 | Consequences list both Positive and Negative outcomes | Pass | Three positive, four negative. |
|
||||
| 6 | Quality-attribute impacts (performance, security, portability, etc.) are named where the decision affects them | Pass | Security is named: no write without opt-in, no write access for the sync token, write access of anyone with repository write rights. |
|
||||
| 7 | Affected Artifacts are listed as links, and each is also in CrossReference | Pass | MIL-006, ADR-0003 and ADR-0002 are linked and cited. |
|
||||
| 8 | Status changes are recorded as new Version History rows with a Change summary and Commit link; retained rows are never rewritten | Pass | The earlier row is kept and only its status changed. |
|
||||
| 9 | A superseded or deprecated ADR names its successor, and the successor links back | N-A | ADR-0003 is superseded only in part and stays in force for this repository's local workflow until MIL-006 task 2 lands; see the action item. |
|
||||
| 10 | Written in business or technical language of the domain, with no unexplained abbreviations | Pass | IT Professional English; `prune` and the marker are explained where they are introduced. |
|
||||
| 11 | Status is one of `Proposed`, `Accepted`, `Rejected`, `Deprecated` or `Superseded by ADR-NNNN`, and every Version History row uses only these | Pass | Deprecated and Accepted only. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all applicable criteria pass; the one finding (criterion 4) was fixed during the review. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| When MIL-006 task 2 (#57) merges, mark ADR-0003 as superseded by ADR-0004 for the shared workflow (new version row and review record) | S01 | 2026-12-26 |
|
||||
| Choose the pilot repository (MIL-006 task 4, already an action item in RC-016) | S01 | 2026-12-14 |
|
||||
|
||||
---
|
||||
|
||||
[ADR-0004]: ../../adr/adr-0004-shared-wiki-publishing-opt-in.md
|
||||
[QC-ADR-001]: ../../../framework/qc/qc-adr.md
|
||||
[b22a2cd]: https://git.tirsystem.com/TirSystem/github-action/commit/b22a2cd59235078656c4440b945b787f88fbd345
|
||||
@@ -0,0 +1,48 @@
|
||||
# Review Record: UCD-001
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-019 |
|
||||
| CrossReference | [UCD-001], [QC-UCD-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [a2bf2d4] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [UCD-001]
|
||||
- Checklist used: [QC-UCD-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Actors are defined with correct UML stereotypes (e.g. `<<System>>`, `<<Actor>>`) | Pass | DevOps Professional and Platform Operator are `<<Actor>>`; Gitea Instance and GitHub are `<<System>>`. |
|
||||
| 2 | System boundary is clearly drawn and labeled | Pass | Boundary "Reusable Workflow Collection". |
|
||||
| 3 | Include/extend relationships are used correctly per UML 2.5.1, not as generic "uses" arrows | Pass | One include and one extend, each with a justification in the Relationships table; the extend applies only on failure. |
|
||||
| 4 | Every actor participates in at least one use case (no orphan actors) | Pass | All four actors appear in the Actor Table with goals. |
|
||||
| 5 | Diagram is traceable to a documented stakeholder need | Pass | S05, S03 and S04 in the Actor Table; SA-001 and BC-001 cited. |
|
||||
| 6 | Use case names are verb phrases describing actor goals, not internal system operations | Pass | Four goal names, none a system operation. |
|
||||
| 7 | Diagram is free of implementation detail (e.g. UI widgets, database tables) | Pass | No tool, file or UI detail. |
|
||||
| 8 | Actor and use case naming is consistent with corresponding Use Case and User Story documents | Pass | Checked mechanically: all four titles and both story roles match. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all eight criteria pass. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[UCD-001]: ../../use-case-diagram.md
|
||||
[QC-UCD-001]: ../../../framework/qc/qc-use-case-diagram.md
|
||||
[a2bf2d4]: https://git.tirsystem.com/TirSystem/github-action/commit/a2bf2d420416f7aff2badc6fe32a7690e2e523fd
|
||||
@@ -0,0 +1,47 @@
|
||||
# Review Record: US-001
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-020 |
|
||||
| CrossReference | [US-001], [QC-US-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [a2bf2d4] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [US-001]
|
||||
- Checklist used: [QC-US-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Follows INVEST criteria (Independent, Negotiable, Valuable, Estimable, Small, Testable) | Pass | INVEST check present; US-001.05 and US-001.06 depend on US-001.04 and say so. |
|
||||
| 2 | Written in "As a / I want / So that" form | Pass | All eight. |
|
||||
| 3 | Clear, testable acceptance criteria are included | Pass | Two Given/When/Then criteria per story, each checked by a run or the guide. |
|
||||
| 4 | Traceable to a use case or epic | Pass | Each story traces to one of UC-001 to UC-004 and to MIL-002. |
|
||||
| 5 | Story is sized to fit within a single iteration | Pass | Each is one goal; two are already implemented and only tested. |
|
||||
| 6 | Story statement avoids technical implementation detail | Pass | Domain terms only (mirror, token, runner). |
|
||||
| 7 | Role named in the story matches an actor defined in the Use Case Diagram | Pass | DevOps Professional and Platform Operator both appear in UCD-001. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all seven criteria pass. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[US-001]: ../../user-stories.md
|
||||
[QC-US-001]: ../../../framework/qc/qc-user-story.md
|
||||
[a2bf2d4]: https://git.tirsystem.com/TirSystem/github-action/commit/a2bf2d420416f7aff2badc6fe32a7690e2e523fd
|
||||
@@ -0,0 +1,52 @@
|
||||
# Review Record: UC-001
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-021 |
|
||||
| CrossReference | [UC-001], [QC-UC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [a2bf2d4] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [UC-001]
|
||||
- Checklist used: [QC-UC-001] (Brief format)
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Consists of a single, concise paragraph summarizing only the primary success scenario | Pass | Finding fixed during this review: the paragraph also described the no-mirror alternative; it now summarizes only the main success scenario (the alternative is US-001.02). |
|
||||
| 2 | Written as an informal multi-paragraph narrative; may mention some alternate flows without formal structure | N-A | Format is Brief. |
|
||||
| 3 | All standard sections are present: actors, preconditions, postconditions, main success scenario, alternative/exception flows | N-A | Format is Brief; the sections of a Brief use case are present (actor, stakeholders, pre- and postconditions, paragraph). |
|
||||
| 4 | Preconditions and postconditions are explicitly defined | Pass | Both stated. |
|
||||
| 5 | Primary actor is explicitly stated | Pass | DevOps Professional. |
|
||||
| 6 | Stakeholders and their interests are stated | Pass | S-IDs from SA-001 with an interest each. |
|
||||
| 7 | Main success scenario is written as clear, numbered steps | N-A | Format is Brief: one paragraph. |
|
||||
| 8 | Alternative/exception flows correctly reference `<<include>>`/`<<extend>>` use cases where relevant, per UML 2.5.1 | N-A | No alternative flows in a Brief use case; the relationships are in UCD-001. |
|
||||
| 9 | Explicit business rules are captured per step where applicable, rather than embedded loosely in narrative text | N-A | No steps in a Brief use case. |
|
||||
| 10 | Naming of actors and use case title is consistent with the corresponding Use Case Diagram and User Stories | Pass | Title and actor match UCD-001 and US-001 exactly. |
|
||||
| 11 | Scope/level (e.g. summary, user-goal, subfunction) is explicitly stated | Pass | Scope and user-goal level stated. |
|
||||
| 12 | Use case is written from the actor's goal perspective, free of UI or implementation detail | Pass | Goal wording; the guides and secrets are named, no UI. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all applicable criteria pass; the one finding (criterion 1) was fixed during the review. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[UC-001]: ../../uc-001/uc.md
|
||||
[QC-UC-001]: ../../../framework/qc/qc-use-case.md
|
||||
[a2bf2d4]: https://git.tirsystem.com/TirSystem/github-action/commit/a2bf2d420416f7aff2badc6fe32a7690e2e523fd
|
||||
@@ -0,0 +1,52 @@
|
||||
# Review Record: UC-002
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-022 |
|
||||
| CrossReference | [UC-002], [QC-UC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [a2bf2d4] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [UC-002]
|
||||
- Checklist used: [QC-UC-001] (Brief format)
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Consists of a single, concise paragraph summarizing only the primary success scenario | Pass | Finding fixed during this review: the paragraph also described the failure alternatives; it now summarizes only the main success scenario (the alternatives are in US-001.03). |
|
||||
| 2 | Written as an informal multi-paragraph narrative; may mention some alternate flows without formal structure | N-A | Format is Brief. |
|
||||
| 3 | All standard sections are present: actors, preconditions, postconditions, main success scenario, alternative/exception flows | N-A | Format is Brief; the sections of a Brief use case are present (actor, stakeholders, pre- and postconditions, paragraph). |
|
||||
| 4 | Preconditions and postconditions are explicitly defined | Pass | Both stated. |
|
||||
| 5 | Primary actor is explicitly stated | Pass | DevOps Professional. |
|
||||
| 6 | Stakeholders and their interests are stated | Pass | S-IDs from SA-001 with an interest each. |
|
||||
| 7 | Main success scenario is written as clear, numbered steps | N-A | Format is Brief: one paragraph. |
|
||||
| 8 | Alternative/exception flows correctly reference `<<include>>`/`<<extend>>` use cases where relevant, per UML 2.5.1 | N-A | No alternative flows in a Brief use case; the relationships are in UCD-001. |
|
||||
| 9 | Explicit business rules are captured per step where applicable, rather than embedded loosely in narrative text | N-A | No steps in a Brief use case. |
|
||||
| 10 | Naming of actors and use case title is consistent with the corresponding Use Case Diagram and User Stories | Pass | Title and actor match UCD-001 and US-001 exactly. |
|
||||
| 11 | Scope/level (e.g. summary, user-goal, subfunction) is explicitly stated | Pass | Scope and user-goal level stated. |
|
||||
| 12 | Use case is written from the actor's goal perspective, free of UI or implementation detail | Pass | Goal wording; the guides and secrets are named, no UI. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all applicable criteria pass; the one finding (criterion 1) was fixed during the review. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[UC-002]: ../../uc-002/uc.md
|
||||
[QC-UC-001]: ../../../framework/qc/qc-use-case.md
|
||||
[a2bf2d4]: https://git.tirsystem.com/TirSystem/github-action/commit/a2bf2d420416f7aff2badc6fe32a7690e2e523fd
|
||||
@@ -0,0 +1,52 @@
|
||||
# Review Record: UC-003
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-023 |
|
||||
| CrossReference | [UC-003], [QC-UC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [a2bf2d4] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [UC-003]
|
||||
- Checklist used: [QC-UC-001] (Brief format)
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Consists of a single, concise paragraph summarizing only the primary success scenario | Pass | Finding fixed during this review: the paragraph also described the defect alternative; it now summarizes only the main success scenario (see US-001.06). |
|
||||
| 2 | Written as an informal multi-paragraph narrative; may mention some alternate flows without formal structure | N-A | Format is Brief. |
|
||||
| 3 | All standard sections are present: actors, preconditions, postconditions, main success scenario, alternative/exception flows | N-A | Format is Brief; the sections of a Brief use case are present (actor, stakeholders, pre- and postconditions, paragraph). |
|
||||
| 4 | Preconditions and postconditions are explicitly defined | Pass | Both stated. |
|
||||
| 5 | Primary actor is explicitly stated | Pass | DevOps Professional. |
|
||||
| 6 | Stakeholders and their interests are stated | Pass | S-IDs from SA-001 with an interest each. |
|
||||
| 7 | Main success scenario is written as clear, numbered steps | N-A | Format is Brief: one paragraph. |
|
||||
| 8 | Alternative/exception flows correctly reference `<<include>>`/`<<extend>>` use cases where relevant, per UML 2.5.1 | N-A | No alternative flows in a Brief use case; the relationships are in UCD-001. |
|
||||
| 9 | Explicit business rules are captured per step where applicable, rather than embedded loosely in narrative text | N-A | No steps in a Brief use case. |
|
||||
| 10 | Naming of actors and use case title is consistent with the corresponding Use Case Diagram and User Stories | Pass | Title and actor match UCD-001 and US-001 exactly. |
|
||||
| 11 | Scope/level (e.g. summary, user-goal, subfunction) is explicitly stated | Pass | Scope and user-goal level stated. |
|
||||
| 12 | Use case is written from the actor's goal perspective, free of UI or implementation detail | Pass | Goal wording; the guides and secrets are named, no UI. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all applicable criteria pass; the one finding (criterion 1) was fixed during the review. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[UC-003]: ../../uc-003/uc.md
|
||||
[QC-UC-001]: ../../../framework/qc/qc-use-case.md
|
||||
[a2bf2d4]: https://git.tirsystem.com/TirSystem/github-action/commit/a2bf2d420416f7aff2badc6fe32a7690e2e523fd
|
||||
@@ -0,0 +1,52 @@
|
||||
# Review Record: UC-004
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-024 |
|
||||
| CrossReference | [UC-004], [QC-UC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [a2bf2d4] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [UC-004]
|
||||
- Checklist used: [QC-UC-001] (Brief format)
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Consists of a single, concise paragraph summarizing only the primary success scenario | Pass | Finding fixed during this review: the paragraph also described the runner and no-category alternatives; it now summarizes only the main success scenario (the alternatives are in US-001.07 and US-001.08). |
|
||||
| 2 | Written as an informal multi-paragraph narrative; may mention some alternate flows without formal structure | N-A | Format is Brief. |
|
||||
| 3 | All standard sections are present: actors, preconditions, postconditions, main success scenario, alternative/exception flows | N-A | Format is Brief; the sections of a Brief use case are present (actor, stakeholders, pre- and postconditions, paragraph). |
|
||||
| 4 | Preconditions and postconditions are explicitly defined | Pass | Both stated. |
|
||||
| 5 | Primary actor is explicitly stated | Pass | DevOps Professional. |
|
||||
| 6 | Stakeholders and their interests are stated | Pass | S-IDs from SA-001 with an interest each. |
|
||||
| 7 | Main success scenario is written as clear, numbered steps | N-A | Format is Brief: one paragraph. |
|
||||
| 8 | Alternative/exception flows correctly reference `<<include>>`/`<<extend>>` use cases where relevant, per UML 2.5.1 | N-A | No alternative flows in a Brief use case; the relationships are in UCD-001. |
|
||||
| 9 | Explicit business rules are captured per step where applicable, rather than embedded loosely in narrative text | N-A | No steps in a Brief use case. |
|
||||
| 10 | Naming of actors and use case title is consistent with the corresponding Use Case Diagram and User Stories | Pass | Title and actor match UCD-001 and US-001 exactly. |
|
||||
| 11 | Scope/level (e.g. summary, user-goal, subfunction) is explicitly stated | Pass | Scope and user-goal level stated. |
|
||||
| 12 | Use case is written from the actor's goal perspective, free of UI or implementation detail | Pass | Goal wording; the guides and secrets are named, no UI. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all applicable criteria pass; the one finding (criterion 1) was fixed during the review. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[UC-004]: ../../uc-004/uc.md
|
||||
[QC-UC-001]: ../../../framework/qc/qc-use-case.md
|
||||
[a2bf2d4]: https://git.tirsystem.com/TirSystem/github-action/commit/a2bf2d420416f7aff2badc6fe32a7690e2e523fd
|
||||
@@ -0,0 +1,47 @@
|
||||
# Review Record: PP-001 Project Plan (P1 use cases)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-025 |
|
||||
| CrossReference | [PP-001], [BC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [a2bf2d4] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [PP-001]
|
||||
- Checklist used: none: the Project Plan has no QC checklist. Validated against the Business Case [BC-001] and the Go / No-Go criteria of each listed milestone, as `PP.md` prescribes.
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Every milestone in the plan has a `MIL-*` document and the plan's dates equal that document's target date | Pass | Unchanged. |
|
||||
| 2 | Every Business Case scope item is covered by a gateway | Pass | Unchanged. |
|
||||
| 3 | The schedule respects the Business Case constraints | Pass | Unchanged. |
|
||||
| 4 | Dependencies between milestones are stated | Pass | Unchanged. |
|
||||
| 5 | Every gateway has an owner who is a stakeholder ID | Pass | Unchanged. |
|
||||
| 6 | Plan content is internally consistent | Pass | The appendix's use case candidates 1 to 4 correspond to UC-001 to UC-004; the plan cites US-001. |
|
||||
| 7 | Open Issues are current | Pass | Finding fixed during this review: the item about use cases said the documents "need review". It now states that the P1 candidates are written as UC-001 to UC-004 with UCD-001 and US-001, and that P2 and P3 have none. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all seven criteria pass; the one finding was fixed during the review. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[PP-001]: ../../project-plan.md
|
||||
[BC-001]: ../../business-case.md
|
||||
[a2bf2d4]: https://git.tirsystem.com/TirSystem/github-action/commit/a2bf2d420416f7aff2badc6fe32a7690e2e523fd
|
||||
@@ -0,0 +1,46 @@
|
||||
# Review Record: MIL-001 (target date)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-026 |
|
||||
| CrossReference | [MIL-001], [QC-MIL-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [ea06eaa] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [MIL-001]
|
||||
- Checklist used: [QC-MIL-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A concrete deliverable is defined for every gate | Pass | Unchanged. |
|
||||
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Unchanged. |
|
||||
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Unchanged. |
|
||||
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Unchanged. |
|
||||
| 5 | Milestone owner and approving reviewer are identified | Pass | Unchanged. |
|
||||
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date 2026-10-17 is now confirmed on 2026-10-10 by S01, standing in for S05 (ADR-0002); it was marked proposed. The Business Case sets no deadline. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all six criteria pass; the only change reviewed is the confirmation of the target date. This closes the earlier action item to confirm it. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[MIL-001]: ../../milestones/mil-001-stabilise-metadata-sync.md
|
||||
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||
[ea06eaa]: https://git.tirsystem.com/TirSystem/github-action/commit/ea06eaaa698247d20e4a8e2694d7acbb1de58b63
|
||||
@@ -0,0 +1,46 @@
|
||||
# Review Record: MIL-002 (target date)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-027 |
|
||||
| CrossReference | [MIL-002], [QC-MIL-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [ea06eaa] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [MIL-002]
|
||||
- Checklist used: [QC-MIL-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A concrete deliverable is defined for every gate | Pass | Unchanged. |
|
||||
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Unchanged. |
|
||||
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Unchanged. |
|
||||
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Unchanged. |
|
||||
| 5 | Milestone owner and approving reviewer are identified | Pass | Unchanged. |
|
||||
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date 2026-10-31 is now confirmed on 2026-10-10 by S01, standing in for S05 (ADR-0002); it was marked proposed. The Business Case sets no deadline. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all six criteria pass; the only change reviewed is the confirmation of the target date. This closes the earlier action item to confirm it. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[MIL-002]: ../../milestones/mil-002-onboarding-and-operations.md
|
||||
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||
[ea06eaa]: https://git.tirsystem.com/TirSystem/github-action/commit/ea06eaaa698247d20e4a8e2694d7acbb1de58b63
|
||||
@@ -0,0 +1,46 @@
|
||||
# Review Record: MIL-003 (target date)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-028 |
|
||||
| CrossReference | [MIL-003], [QC-MIL-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [ea06eaa] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [MIL-003]
|
||||
- Checklist used: [QC-MIL-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A concrete deliverable is defined for every gate | Pass | Unchanged. |
|
||||
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Unchanged. |
|
||||
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Unchanged. |
|
||||
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Unchanged. |
|
||||
| 5 | Milestone owner and approving reviewer are identified | Pass | Unchanged. |
|
||||
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date 2026-11-14 is now confirmed on 2026-10-10 by S01, standing in for S05 (ADR-0002); it was marked proposed. The Business Case sets no deadline. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all six criteria pass; the only change reviewed is the confirmation of the target date. This closes the earlier action item to confirm it. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[MIL-003]: ../../milestones/mil-003-quality-checks.md
|
||||
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||
[ea06eaa]: https://git.tirsystem.com/TirSystem/github-action/commit/ea06eaaa698247d20e4a8e2694d7acbb1de58b63
|
||||
@@ -0,0 +1,46 @@
|
||||
# Review Record: MIL-004 (target date)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-029 |
|
||||
| CrossReference | [MIL-004], [QC-MIL-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [ea06eaa] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [MIL-004]
|
||||
- Checklist used: [QC-MIL-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A concrete deliverable is defined for every gate | Pass | Unchanged. |
|
||||
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Unchanged. |
|
||||
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Unchanged. |
|
||||
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Unchanged. |
|
||||
| 5 | Milestone owner and approving reviewer are identified | Pass | Unchanged. |
|
||||
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date 2026-11-28 is now confirmed on 2026-10-10 by S01, standing in for S05 (ADR-0002); it was marked proposed. The Business Case sets no deadline. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all six criteria pass; the only change reviewed is the confirmation of the target date. This closes the earlier action item to confirm it. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[MIL-004]: ../../milestones/mil-004-versioned-release.md
|
||||
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||
[ea06eaa]: https://git.tirsystem.com/TirSystem/github-action/commit/ea06eaaa698247d20e4a8e2694d7acbb1de58b63
|
||||
@@ -0,0 +1,46 @@
|
||||
# Review Record: MIL-005 (target date)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-030 |
|
||||
| CrossReference | [MIL-005], [QC-MIL-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [ea06eaa] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [MIL-005]
|
||||
- Checklist used: [QC-MIL-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A concrete deliverable is defined for every gate | Pass | Unchanged. |
|
||||
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Unchanged. |
|
||||
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Unchanged. |
|
||||
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Unchanged. |
|
||||
| 5 | Milestone owner and approving reviewer are identified | Pass | Unchanged. |
|
||||
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date 2026-12-12 is now confirmed on 2026-10-10 by S01, standing in for S05 (ADR-0002); it was marked proposed. The Business Case sets no deadline. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all six criteria pass; the only change reviewed is the confirmation of the target date. This closes the earlier action item to confirm it. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[MIL-005]: ../../milestones/mil-005-wiki-and-translations.md
|
||||
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||
[ea06eaa]: https://git.tirsystem.com/TirSystem/github-action/commit/ea06eaaa698247d20e4a8e2694d7acbb1de58b63
|
||||
@@ -0,0 +1,46 @@
|
||||
# Review Record: MIL-006 (target date)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-031 |
|
||||
| CrossReference | [MIL-006], [QC-MIL-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [ea06eaa] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [MIL-006]
|
||||
- Checklist used: [QC-MIL-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A concrete deliverable is defined for every gate | Pass | Unchanged. |
|
||||
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Unchanged. |
|
||||
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Unchanged. |
|
||||
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Unchanged. |
|
||||
| 5 | Milestone owner and approving reviewer are identified | Pass | Unchanged. |
|
||||
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Target date 2026-12-26 is now confirmed on 2026-10-10 by S01, standing in for S05 (ADR-0002); it was marked proposed. The Business Case sets no deadline. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all six criteria pass; the only change reviewed is the confirmation of the target date. This closes the earlier action item to confirm it. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[MIL-006]: ../../milestones/mil-006-shared-wiki-publishing.md
|
||||
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||
[ea06eaa]: https://git.tirsystem.com/TirSystem/github-action/commit/ea06eaaa698247d20e4a8e2694d7acbb1de58b63
|
||||
@@ -0,0 +1,47 @@
|
||||
# Review Record: PP-001 Project Plan (dates confirmed)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-032 |
|
||||
| CrossReference | [PP-001], [BC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [ea06eaa] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [PP-001]
|
||||
- Checklist used: none: the Project Plan has no QC checklist. Validated against the Business Case [BC-001] and the Go / No-Go criteria of each listed milestone, as `PP.md` prescribes.
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Every milestone in the plan has a `MIL-*` document and the plan's dates equal that document's target date | Pass | MIL-001 to MIL-006 now state their target dates as confirmed (RC-026 to RC-031). |
|
||||
| 2 | Every Business Case scope item is covered by a gateway | Pass | Unchanged. |
|
||||
| 3 | The schedule respects the Business Case constraints | Pass | The Business Case sets no deadline. |
|
||||
| 4 | Dependencies between milestones are stated | Pass | Unchanged. |
|
||||
| 5 | Every gateway has an owner who is a stakeholder ID | Pass | Unchanged. |
|
||||
| 6 | Plan content is internally consistent | Pass | Purpose and Planning Assumptions say the dates were confirmed; no remaining text calls them proposals. |
|
||||
| 7 | Open Issues are current | Pass | The item to confirm the proposed dates is removed; the two remaining items are still open (no QC checklist for the Project Plan; P2 and P3 use cases). |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all seven criteria pass. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[PP-001]: ../../project-plan.md
|
||||
[BC-001]: ../../business-case.md
|
||||
[ea06eaa]: https://git.tirsystem.com/TirSystem/github-action/commit/ea06eaaa698247d20e4a8e2694d7acbb1de58b63
|
||||
@@ -0,0 +1,46 @@
|
||||
# Review Record: MIL-003 (reusable workflow support verified)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-033 |
|
||||
| CrossReference | [MIL-003], [QC-MIL-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [b3f006f] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [MIL-003]
|
||||
- Checklist used: [QC-MIL-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A concrete deliverable is defined for every gate | Pass | Unchanged. |
|
||||
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Unchanged; criterion 1 (reusable workflows verified and recorded) is now evidenced by the Verification results. |
|
||||
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Unchanged. |
|
||||
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Unchanged. |
|
||||
| 5 | Milestone owner and approving reviewer are identified | Pass | Unchanged. |
|
||||
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Unchanged. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all six criteria pass; the reviewed change records the result of task 1 and its limits (private provider, secrets, tag references not tested). S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Test a private provider repository, `secrets: inherit` and a tag reference before MIL-004 relies on them | S05 | 2026-11-28 |
|
||||
|
||||
---
|
||||
|
||||
[MIL-003]: ../../milestones/mil-003-quality-checks.md
|
||||
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||
[b3f006f]: https://git.tirsystem.com/TirSystem/github-action/commit/b3f006f7a482392189a46c324ad4f28c4c3a2d2a
|
||||
@@ -0,0 +1,46 @@
|
||||
# Review Record: MIL-004 (scripts as files)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-034 |
|
||||
| CrossReference | [MIL-004], [QC-MIL-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [616c5d2] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [MIL-004]
|
||||
- Checklist used: [QC-MIL-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A concrete deliverable is defined for every gate | Pass | The deliverable now also names scripts as files fetched at a pinnable reference. |
|
||||
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | New criterion 5 is checkable: the count of embedded scripts is 0 and a run in another organization passes. |
|
||||
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Unchanged (MIL-003); task 6 needs no other milestone, because the checkout of a script repository was verified on 2026-10-10. |
|
||||
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Finding fixed during this review: task 6 serves O2 (one canonical copy and a defined way to reach consuming repositories) and the Traceability table listed only O4. It now lists O2 and O4. |
|
||||
| 5 | Milestone owner and approving reviewer are identified | Pass | Unchanged: owner S05, approving reviewer S01. |
|
||||
| 6 | Milestone has a defined target date consistent with project constraints | Pass | 2026-11-28, confirmed (RC-029). |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all six criteria pass; the one finding (criterion 4) was fixed during the review. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader. Accepting the amendment unlocks task 6 under the plan-first gate; the issue is still to be created with `sync-project.sh --apply`.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Decide whether consumers pin a tag or follow `main` for the shared scripts (task 1 of this milestone) | S01 | 2026-11-16 |
|
||||
|
||||
---
|
||||
|
||||
[MIL-004]: ../../milestones/mil-004-versioned-release.md
|
||||
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||
[616c5d2]: https://git.tirsystem.com/TirSystem/github-action/commit/616c5d2e48f0d76399a6f78923891fc7f50c8e22
|
||||
@@ -0,0 +1,48 @@
|
||||
# Review Record: UCD-001 (quality checks)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-035 |
|
||||
| CrossReference | [UCD-001], [QC-UCD-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [385d2fb] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [UCD-001]
|
||||
- Checklist used: [QC-UCD-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Actors are defined with correct UML stereotypes (e.g. `<<System>>`, `<<Actor>>`) | Pass | Software Engineer is `<<Actor>>`, like the others. |
|
||||
| 2 | System boundary is clearly drawn and labeled | Pass | Unchanged. |
|
||||
| 3 | Include/extend relationships are used correctly per UML 2.5.1, not as generic "uses" arrows | Pass | Unchanged; the new use case has none. |
|
||||
| 4 | Every actor participates in at least one use case (no orphan actors) | Pass | Software Engineer reaches Run Project Quality Checks. |
|
||||
| 5 | Diagram is traceable to a documented stakeholder need | Pass | S02 in the Actor Table. |
|
||||
| 6 | Use case names are verb phrases describing actor goals, not internal system operations | Pass | "Run Project Quality Checks". |
|
||||
| 7 | Diagram is free of implementation detail (e.g. UI widgets, database tables) | Pass | No tool or file named. |
|
||||
| 8 | Actor and use case naming is consistent with corresponding Use Case and User Story documents | Pass | Checked mechanically: UC-005's title and the story role match. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all eight criteria pass for the amendment (the actor and use case of UC-005). S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[UCD-001]: ../../use-case-diagram.md
|
||||
[QC-UCD-001]: ../../../framework/qc/qc-use-case-diagram.md
|
||||
[385d2fb]: https://git.tirsystem.com/TirSystem/github-action/commit/385d2fb7cb9be1fdc8fd3503d0af624fa38eafc7
|
||||
@@ -0,0 +1,47 @@
|
||||
# Review Record: US-001 (quality checks)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-036 |
|
||||
| CrossReference | [US-001], [QC-US-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [385d2fb] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [US-001]
|
||||
- Checklist used: [QC-US-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Follows INVEST criteria (Independent, Negotiable, Valuable, Estimable, Small, Testable) | Pass | INVEST check updated to ten stories; the two new ones are independent of the others. |
|
||||
| 2 | Written in "As a / I want / So that" form | Pass | US-001.09 and US-001.10. |
|
||||
| 3 | Clear, testable acceptance criteria are included | Pass | Two Given/When/Then criteria each, matching the ADR-0005 contract. |
|
||||
| 4 | Traceable to a use case or epic | Pass | UC-005 and MIL-003. |
|
||||
| 5 | Story is sized to fit within a single iteration | Pass | One goal each. |
|
||||
| 6 | Story statement avoids technical implementation detail | Pass | No tool named in the statements. |
|
||||
| 7 | Role named in the story matches an actor defined in the Use Case Diagram | Pass | Software Engineer is in UCD-001. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all seven criteria pass for the two added stories. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[US-001]: ../../user-stories.md
|
||||
[QC-US-001]: ../../../framework/qc/qc-user-story.md
|
||||
[385d2fb]: https://git.tirsystem.com/TirSystem/github-action/commit/385d2fb7cb9be1fdc8fd3503d0af624fa38eafc7
|
||||
@@ -0,0 +1,52 @@
|
||||
# Review Record: UC-005 (quality checks)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-037 |
|
||||
| CrossReference | [UC-005], [QC-UC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [385d2fb] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [UC-005]
|
||||
- Checklist used: [QC-UC-001] (Brief format)
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Consists of a single, concise paragraph summarizing only the primary success scenario | Pass | Finding fixed during this review: the paragraph also described the failure output; it now summarizes only the main success scenario (the failure is US-001.10). |
|
||||
| 2 | Written as an informal multi-paragraph narrative; may mention some alternate flows without formal structure | N-A | Format is Brief. |
|
||||
| 3 | All standard sections are present: actors, preconditions, postconditions, main success scenario, alternative/exception flows | N-A | Format is Brief; actor, stakeholders, pre- and postconditions and the paragraph are present. |
|
||||
| 4 | Preconditions and postconditions are explicitly defined | Pass | Both stated. |
|
||||
| 5 | Primary actor is explicitly stated | Pass | Software Engineer. |
|
||||
| 6 | Stakeholders and their interests are stated | Pass | S02 and S05. |
|
||||
| 7 | Main success scenario is written as clear, numbered steps | N-A | Format is Brief. |
|
||||
| 8 | Alternative/exception flows correctly reference `<<include>>`/`<<extend>>` use cases where relevant, per UML 2.5.1 | N-A | No alternative flows in a Brief use case. |
|
||||
| 9 | Explicit business rules are captured per step where applicable, rather than embedded loosely in narrative text | N-A | No steps in a Brief use case. |
|
||||
| 10 | Naming of actors and use case title is consistent with the corresponding Use Case Diagram and User Stories | Pass | Title and actor match UCD-001 and US-001. |
|
||||
| 11 | Scope/level (e.g. summary, user-goal, subfunction) is explicitly stated | Pass | Scope and user-goal level. |
|
||||
| 12 | Use case is written from the actor's goal perspective, free of UI or implementation detail | Pass | Goal wording; no tool named. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all applicable criteria pass; the one finding (criterion 1) was fixed during the review. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[UC-005]: ../../uc-005/uc.md
|
||||
[QC-UC-001]: ../../../framework/qc/qc-use-case.md
|
||||
[385d2fb]: https://git.tirsystem.com/TirSystem/github-action/commit/385d2fb7cb9be1fdc8fd3503d0af624fa38eafc7
|
||||
@@ -0,0 +1,51 @@
|
||||
# Review Record: ADR-0005 (quality checks)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-038 |
|
||||
| CrossReference | [ADR-0005], [QC-ADR-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [385d2fb] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [ADR-0005]
|
||||
- Checklist used: [QC-ADR-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | The ID (`ADR-NNNN`, 4-digit) matches the filename number and is unique and sequential | Pass | ADR-0005 in `adr-0005-quality-check-contract.md`. |
|
||||
| 2 | Context states the problem, the forces (cost, risk, constraints) and the options evaluated | Pass | Facts measured on the runner on 2026-10-10 and four options. |
|
||||
| 3 | At least two options were considered, or the absence of alternatives is justified | Pass | Four options. |
|
||||
| 4 | Decision is stated in one or two unhedged sentences and matches one of the evaluated options | Pass | Two sentences; option 1. |
|
||||
| 5 | Consequences list both Positive and Negative outcomes | Pass | Three positive and five negative after the fix. |
|
||||
| 6 | Quality-attribute impacts (performance, security, portability, etc.) are named where the decision affects them | Pass | Finding fixed during this review: the security impact (tools downloaded from PyPI on every run, versions pinned but not hash-pinned, runner runs as root) was not named. It is now a negative consequence; performance and reliability were already named. |
|
||||
| 7 | Affected Artifacts are listed as links, and each is also in CrossReference | Pass | MIL-003, UC-005, US-001 and ADR-0004 are linked and cited. |
|
||||
| 8 | Status changes are recorded as new Version History rows with a Change summary and Commit link; retained rows are never rewritten | Pass | The earlier row is kept and only its status changed. |
|
||||
| 9 | A superseded or deprecated ADR names its successor, and the successor links back | N-A | Nothing is superseded. |
|
||||
| 10 | Written in business or technical language of the domain, with no unexplained abbreviations | Pass | PyPI, venv and the tools are named where used. |
|
||||
| 11 | Status is one of `Proposed`, `Accepted`, `Rejected`, `Deprecated` or `Superseded by ADR-NNNN`, and every Version History row uses only these | Pass | Deprecated and Accepted only. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all applicable criteria pass; the one finding (criterion 6) was fixed during the review. The contract unlocks tasks 3 to 5 of MIL-003 under the plan-first gate. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Decide whether to hash-pin the tool packages before consumers outside this organization rely on the workflow (MIL-004) | S05 | 2026-11-28 |
|
||||
|
||||
---
|
||||
|
||||
[ADR-0005]: ../../adr/adr-0005-quality-check-contract.md
|
||||
[QC-ADR-001]: ../../../framework/qc/qc-adr.md
|
||||
[385d2fb]: https://git.tirsystem.com/TirSystem/github-action/commit/385d2fb7cb9be1fdc8fd3503d0af624fa38eafc7
|
||||
@@ -0,0 +1,47 @@
|
||||
# Review Record: MIL-003 (adoption in RepoFoundry)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-039 |
|
||||
| CrossReference | [MIL-003], [QC-MIL-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [3b8681d] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [MIL-003]
|
||||
- Checklist used: [QC-MIL-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | A concrete deliverable is defined for every gate | Pass | Unchanged. |
|
||||
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Unchanged; criterion 2 (another repository runs the workflow and its status check appears on pull requests) is evidenced by the pull-request run in RepoFoundry. |
|
||||
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Unchanged. |
|
||||
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Unchanged. |
|
||||
| 5 | Milestone owner and approving reviewer are identified | Pass | Unchanged. |
|
||||
| 6 | Milestone has a defined target date consistent with project constraints | Pass | Unchanged. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all six criteria pass; the reviewed change records the adoption trial and its findings. The adoption is not complete until RepoFoundry PR 76 is merged, and the record says so. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Merge RepoFoundry PR 76 (its maintainers), then close issue #18 | S01 | 2026-11-14 |
|
||||
| Put the three findings (shfmt style in `.editorconfig`, relative paths, reference `main` or a tag) in the results guide (issue #19) | S01 | 2026-11-14 |
|
||||
|
||||
---
|
||||
|
||||
[MIL-003]: ../../milestones/mil-003-quality-checks.md
|
||||
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
|
||||
[3b8681d]: https://git.tirsystem.com/TirSystem/github-action/commit/3b8681d0236c669b794ffbba725433fff600a2d2
|
||||
@@ -0,0 +1,48 @@
|
||||
# Review Record: UCD-001 (release process)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-040 |
|
||||
| CrossReference | [UCD-001], [QC-UCD-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [044d8ba] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [UCD-001]
|
||||
- Checklist used: [QC-UCD-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Actors are defined with correct UML stereotypes (e.g. `<<System>>`, `<<Actor>>`) | Pass | Unchanged actors. |
|
||||
| 2 | System boundary is clearly drawn and labeled | Pass | Unchanged. |
|
||||
| 3 | Include/extend relationships are used correctly per UML 2.5.1, not as generic "uses" arrows | Pass | The new use case has none. |
|
||||
| 4 | Every actor participates in at least one use case (no orphan actors) | Pass | DevOps Professional reaches Release a Reusable Workflow. |
|
||||
| 5 | Diagram is traceable to a documented stakeholder need | Pass | S05 in the Actor Table. |
|
||||
| 6 | Use case names are verb phrases describing actor goals, not internal system operations | Pass | "Release a Reusable Workflow". |
|
||||
| 7 | Diagram is free of implementation detail (e.g. UI widgets, database tables) | Pass | No tool or file named. |
|
||||
| 8 | Actor and use case naming is consistent with corresponding Use Case and User Story documents | Pass | UC-006's title and the story roles match. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all eight criteria pass for the amendment (the use case of UC-006). S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[UCD-001]: ../../use-case-diagram.md
|
||||
[QC-UCD-001]: ../../../framework/qc/qc-use-case-diagram.md
|
||||
[044d8ba]: https://git.tirsystem.com/TirSystem/github-action/commit/044d8ba21f96f4aceb807d62addc35cdcbb56051
|
||||
@@ -0,0 +1,47 @@
|
||||
# Review Record: US-001 (release process)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-041 |
|
||||
| CrossReference | [US-001], [QC-US-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [044d8ba] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [US-001]
|
||||
- Checklist used: [QC-US-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Follows INVEST criteria (Independent, Negotiable, Valuable, Estimable, Small, Testable) | Pass | INVEST check updated to thirteen stories. |
|
||||
| 2 | Written in "As a / I want / So that" form | Pass | US-001.11 to US-001.13. |
|
||||
| 3 | Clear, testable acceptance criteria are included | Pass | Two Given/When/Then criteria each, matching ADR-0006. |
|
||||
| 4 | Traceable to a use case or epic | Pass | Finding fixed during this review: US-001.13 is a consumer's goal (pin a version) but traced to UC-006, whose actor is the DevOps Professional. It now traces to the epic MIL-004 and names its use case, Consume a Workflow Update, as not yet written; UC-006 lists only US-001.11 and US-001.12. |
|
||||
| 5 | Story is sized to fit within a single iteration | Pass | One goal each. |
|
||||
| 6 | Story statement avoids technical implementation detail | Pass | Tags are named only in the criteria, as the observable result. |
|
||||
| 7 | Role named in the story matches an actor defined in the Use Case Diagram | Pass | DevOps Professional and Software Engineer are in UCD-001. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all seven criteria pass; the one finding (criterion 4) was fixed during the review. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[US-001]: ../../user-stories.md
|
||||
[QC-US-001]: ../../../framework/qc/qc-user-story.md
|
||||
[044d8ba]: https://git.tirsystem.com/TirSystem/github-action/commit/044d8ba21f96f4aceb807d62addc35cdcbb56051
|
||||
@@ -0,0 +1,52 @@
|
||||
# Review Record: UC-006
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-042 |
|
||||
| CrossReference | [UC-006], [QC-UC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [044d8ba] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [UC-006]
|
||||
- Checklist used: [QC-UC-001] (Brief format)
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Consists of a single, concise paragraph summarizing only the primary success scenario | Pass | The paragraph describes the main flow: validation, changelog, tags, release page. The failure and undo paths are in the process guide and the stories. |
|
||||
| 2 | Written as an informal multi-paragraph narrative; may mention some alternate flows without formal structure | N-A | Format is Brief. |
|
||||
| 3 | All standard sections are present: actors, preconditions, postconditions, main success scenario, alternative/exception flows | N-A | Format is Brief; actor, stakeholders, pre- and postconditions and the paragraph are present. |
|
||||
| 4 | Preconditions and postconditions are explicitly defined | Pass | Both stated. |
|
||||
| 5 | Primary actor is explicitly stated | Pass | DevOps Professional. |
|
||||
| 6 | Stakeholders and their interests are stated | Pass | S05, S02 and S03. |
|
||||
| 7 | Main success scenario is written as clear, numbered steps | N-A | Format is Brief. |
|
||||
| 8 | Alternative/exception flows correctly reference `<<include>>`/`<<extend>>` use cases where relevant, per UML 2.5.1 | N-A | No alternative flows in a Brief use case. |
|
||||
| 9 | Explicit business rules are captured per step where applicable, rather than embedded loosely in narrative text | N-A | No steps in a Brief use case. |
|
||||
| 10 | Naming of actors and use case title is consistent with the corresponding Use Case Diagram and User Stories | Pass | Title and actor match UCD-001; its stories are US-001.11 and US-001.12. |
|
||||
| 11 | Scope/level (e.g. summary, user-goal, subfunction) is explicitly stated | Pass | Scope and user-goal level. |
|
||||
| 12 | Use case is written from the actor's goal perspective, free of UI or implementation detail | Pass | Goal wording; tags and the changelog are domain terms. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all applicable criteria pass. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[UC-006]: ../../uc-006/uc.md
|
||||
[QC-UC-001]: ../../../framework/qc/qc-use-case.md
|
||||
[044d8ba]: https://git.tirsystem.com/TirSystem/github-action/commit/044d8ba21f96f4aceb807d62addc35cdcbb56051
|
||||
@@ -0,0 +1,52 @@
|
||||
# Review Record: ADR-0006
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-043 |
|
||||
| CrossReference | [ADR-0006], [QC-ADR-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [044d8ba] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [ADR-0006]
|
||||
- Checklist used: [QC-ADR-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | The ID (`ADR-NNNN`, 4-digit) matches the filename number and is unique and sequential | Pass | ADR-0006 in `adr-0006-release-process-and-version-pinning.md`. |
|
||||
| 2 | Context states the problem, the forces (cost, risk, constraints) and the options evaluated | Pass | Names that every consumer runs `main`, what can and cannot be pinned, and the options. |
|
||||
| 3 | At least two options were considered, or the absence of alternatives is justified | Pass | Four options for the version unit and three for the pin. |
|
||||
| 4 | Decision is stated in one or two unhedged sentences and matches one of the evaluated options | Pass | Two sentences; options 1 and b. |
|
||||
| 5 | Consequences list both Positive and Negative outcomes | Pass | Three positive and four negative. |
|
||||
| 6 | Quality-attribute impacts (performance, security, portability, etc.) are named where the decision affects them | Pass | Reliability for consumers and the security of tag permissions and of a bad merge of a scoped file are named. |
|
||||
| 7 | Affected Artifacts are listed as links, and each is also in CrossReference | Pass | MIL-004, UC-006, US-001, ADR-0005 and ADR-0004 are linked and cited. |
|
||||
| 8 | Status changes are recorded as new Version History rows with a Change summary and Commit link; retained rows are never rewritten | Pass | The earlier row is kept and only its status changed. |
|
||||
| 9 | A superseded or deprecated ADR names its successor, and the successor links back | N-A | Nothing is superseded. |
|
||||
| 10 | Written in business or technical language of the domain, with no unexplained abbreviations | Pass | Finding fixed during this review: SemVer was used without being expanded; it is now introduced as semantic version (SemVer). |
|
||||
| 11 | Status is one of `Proposed`, `Accepted`, `Rejected`, `Deprecated` or `Superseded by ADR-NNNN`, and every Version History row uses only these | Pass | Deprecated and Accepted only. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all applicable criteria pass; the one finding (criterion 10) was fixed during the review. It unlocks tasks 2 to 5 of MIL-004 (#21 to #24) under the plan-first gate. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Pin the scripts fetched by the two scoped workflows to `v1` once it exists (the workflows still say `ref: main`) | S05 | 2026-11-28 |
|
||||
| Review who may merge to `main` and who may move tags, since a scoped workflow file cannot be pinned by consumers | S01 | 2026-11-14 |
|
||||
|
||||
---
|
||||
|
||||
[ADR-0006]: ../../adr/adr-0006-release-process-and-version-pinning.md
|
||||
[QC-ADR-001]: ../../../framework/qc/qc-adr.md
|
||||
[044d8ba]: https://git.tirsystem.com/TirSystem/github-action/commit/044d8ba21f96f4aceb807d62addc35cdcbb56051
|
||||
@@ -0,0 +1,52 @@
|
||||
# Review Record: UC-007
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-044 |
|
||||
| CrossReference | [UC-007], [QC-UC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [4cf52af] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [UC-007]
|
||||
- Checklist used: [QC-UC-001] (Brief format)
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Consists of a single, concise paragraph summarizing only the primary success scenario | Pass | The paragraph describes read, try in one repository, read the run, roll out; the rollback and the failures are in the stories and the guide. |
|
||||
| 2 | Written as an informal multi-paragraph narrative; may mention some alternate flows without formal structure | N-A | Format is Brief. |
|
||||
| 3 | All standard sections are present: actors, preconditions, postconditions, main success scenario, alternative/exception flows | N-A | Format is Brief; actor, stakeholders, pre- and postconditions and the paragraph are present. |
|
||||
| 4 | Preconditions and postconditions are explicitly defined | Pass | Both stated; the precondition names the release process of UC-006. |
|
||||
| 5 | Primary actor is explicitly stated | Pass | Software Engineer. |
|
||||
| 6 | Stakeholders and their interests are stated | Pass | S02 and S05. |
|
||||
| 7 | Main success scenario is written as clear, numbered steps | N-A | Format is Brief. |
|
||||
| 8 | Alternative/exception flows correctly reference `<<include>>`/`<<extend>>` use cases where relevant, per UML 2.5.1 | N-A | No alternative flows in a Brief use case. |
|
||||
| 9 | Explicit business rules are captured per step where applicable, rather than embedded loosely in narrative text | N-A | No steps in a Brief use case. |
|
||||
| 10 | Naming of actors and use case title is consistent with the corresponding Use Case Diagram and User Stories | Pass | Title and actor match UCD-001 (checked mechanically); stories are US-001.13 to US-001.15. |
|
||||
| 11 | Scope/level (e.g. summary, user-goal, subfunction) is explicitly stated | Pass | Scope and user-goal level. |
|
||||
| 12 | Use case is written from the actor's goal perspective, free of UI or implementation detail | Pass | Goal wording; no tool named. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all applicable criteria pass. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[UC-007]: ../../uc-007/uc.md
|
||||
[QC-UC-001]: ../../../framework/qc/qc-use-case.md
|
||||
[4cf52af]: https://git.tirsystem.com/TirSystem/github-action/commit/4cf52afe00f546c6b20424fb8dfc12796ffd9296
|
||||
@@ -0,0 +1,48 @@
|
||||
# Review Record: UCD-001 (consume an update)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-045 |
|
||||
| CrossReference | [UCD-001], [QC-UCD-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [4cf52af] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [UCD-001]
|
||||
- Checklist used: [QC-UCD-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Actors are defined with correct UML stereotypes (e.g. `<<System>>`, `<<Actor>>`) | Pass | Unchanged actors. |
|
||||
| 2 | System boundary is clearly drawn and labeled | Pass | Unchanged. |
|
||||
| 3 | Include/extend relationships are used correctly per UML 2.5.1, not as generic "uses" arrows | Pass | The new use case has none; its dependency on UC-006 is a precondition. |
|
||||
| 4 | Every actor participates in at least one use case (no orphan actors) | Pass | Software Engineer now reaches two use cases. |
|
||||
| 5 | Diagram is traceable to a documented stakeholder need | Pass | S02 in the Actor Table. |
|
||||
| 6 | Use case names are verb phrases describing actor goals, not internal system operations | Pass | "Consume a Workflow Update". |
|
||||
| 7 | Diagram is free of implementation detail (e.g. UI widgets, database tables) | Pass | No tool or file named. |
|
||||
| 8 | Actor and use case naming is consistent with corresponding Use Case and User Story documents | Pass | UC-007's title and the story roles match. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all eight criteria pass for the amendment (the use case of UC-007). S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[UCD-001]: ../../use-case-diagram.md
|
||||
[QC-UCD-001]: ../../../framework/qc/qc-use-case-diagram.md
|
||||
[4cf52af]: https://git.tirsystem.com/TirSystem/github-action/commit/4cf52afe00f546c6b20424fb8dfc12796ffd9296
|
||||
@@ -0,0 +1,47 @@
|
||||
# Review Record: US-001 (consume an update)
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-046 |
|
||||
| CrossReference | [US-001], [QC-US-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [4cf52af] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [US-001]
|
||||
- Checklist used: [QC-US-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Follows INVEST criteria (Independent, Negotiable, Valuable, Estimable, Small, Testable) | Pass | INVEST check updated to fifteen stories. |
|
||||
| 2 | Written in "As a / I want / So that" form | Pass | US-001.14 and US-001.15. |
|
||||
| 3 | Clear, testable acceptance criteria are included | Pass | Two Given/When/Then criteria each; both are checked by reading the changelog or a run. |
|
||||
| 4 | Traceable to a use case or epic | Pass | UC-007 and MIL-004; US-001.13 is now traced to UC-007 as well, closing the gap noted in RC-041. |
|
||||
| 5 | Story is sized to fit within a single iteration | Pass | One goal each. |
|
||||
| 6 | Story statement avoids technical implementation detail | Pass | No tool named in the statements. |
|
||||
| 7 | Role named in the story matches an actor defined in the Use Case Diagram | Pass | Software Engineer is in UCD-001. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all seven criteria pass. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| None | - | - |
|
||||
|
||||
---
|
||||
|
||||
[US-001]: ../../user-stories.md
|
||||
[QC-US-001]: ../../../framework/qc/qc-user-story.md
|
||||
[4cf52af]: https://git.tirsystem.com/TirSystem/github-action/commit/4cf52afe00f546c6b20424fb8dfc12796ffd9296
|
||||
@@ -0,0 +1,51 @@
|
||||
# Review Record: ADR-0007
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | RC-047 |
|
||||
| CrossReference | [ADR-0007], [QC-ADR-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [d9cd3c6] |
|
||||
|
||||
---
|
||||
|
||||
## Artifact Under Review
|
||||
|
||||
- Instance reviewed: [ADR-0007]
|
||||
- Checklist used: [QC-ADR-001]
|
||||
|
||||
## Checklist Results
|
||||
|
||||
| # | Criterion | Status | Evidence/Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | The ID (`ADR-NNNN`, 4-digit) matches the filename number and is unique and sequential | Pass | ADR-0007 in `adr-0007-release-publish-destination.md`, after ADR-0006. |
|
||||
| 2 | Context states the problem, the forces (cost, risk, constraints) and the options evaluated | Pass | States what the repository contains, what the API offers and the two sensitive writes. |
|
||||
| 3 | At least two options were considered, or the absence of alternatives is justified | Pass | Four options for the destination and three for the permission. |
|
||||
| 4 | Decision is stated in one or two unhedged sentences and matches one of the evaluated options | Pass | Options 1 and a, with a named fallback b; the fallback is conditional on a fact the ADR says is unverified. |
|
||||
| 5 | Consequences list both Positive and Negative outcomes | Pass | Three positive and three negative. |
|
||||
| 6 | Quality-attribute impacts (performance, security, portability, etc.) are named where the decision affects them | Pass | Security (permission scope and secret) and portability (no release page on GitHub) are named. |
|
||||
| 7 | Affected Artifacts are listed as links, and each is also in CrossReference | Pass | MIL-004, UC-006 and ADR-0006 are linked and cited. |
|
||||
| 8 | Status changes are recorded as new Version History rows with a Change summary and Commit link; retained rows are never rewritten | Pass | Initial row only. |
|
||||
| 9 | A superseded or deprecated ADR names its successor, and the successor links back | N-A | Nothing is superseded. |
|
||||
| 10 | Written in business or technical language of the domain, with no unexplained abbreviations | Pass | No abbreviation without expansion. |
|
||||
| 11 | Status is one of `Proposed`, `Accepted`, `Rejected`, `Deprecated` or `Superseded by ADR-NNNN`, and every Version History row uses only these | Pass | Accepted. |
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
Go - all applicable criteria pass. The behaviour of the job token is an assumption that the first run of the release workflow (task 5) verifies, with the fallback already named. S01 gave the Go in chat on 2026-10-10, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
|
||||
|
||||
## Action Items
|
||||
|
||||
| Action | Owner | Due |
|
||||
| --- | --- | --- |
|
||||
| Verify in the first run of the release workflow that the job token creates the tag and moves the major tag; if not, create `TOKEN_FOR_GITEA_RELEASE` | S05 | 2026-11-28 |
|
||||
|
||||
---
|
||||
|
||||
[ADR-0007]: ../../adr/adr-0007-release-publish-destination.md
|
||||
[QC-ADR-001]: ../../../framework/qc/qc-adr.md
|
||||
[d9cd3c6]: https://git.tirsystem.com/TirSystem/github-action/commit/d9cd3c67d4017984af8958f32240d3d66217e153
|
||||
@@ -0,0 +1,182 @@
|
||||
# Traceability Matrix
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | TM-001 |
|
||||
| CrossReference | [BC-001], [SA-001], [PP-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [RC-001], [RC-002], [RC-003], [RC-004], [RC-005], [RC-006], [RC-007], [RC-008], [RC-009], [RC-010], [RC-011], [RC-012], [RC-013], [RC-014], [RC-015], [RC-016], [RC-017], [RC-018], [RC-019], [RC-020], [RC-021], [RC-022], [RC-023], [RC-024], [RC-025], [RC-026], [RC-027], [RC-028], [RC-029], [RC-030], [RC-031], [RC-032], [RC-033], [RC-034], [RC-035], [RC-036], [RC-037], [RC-038], [RC-039], [RC-040], [RC-041], [RC-042], [RC-043], [RC-044], [RC-045], [RC-046], [RC-047], [ADR-0007], [UC-007], [UC-006], [ADR-0006], [UC-005], [ADR-0005], [UCD-001], [US-001], [UC-001], [UC-002], [UC-003], [UC-004], [ADR-0001], [ADR-0002], [ADR-0003], [ADR-0004] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S01 | Added UC-007 and RC-044 to RC-046 | [4cf52af] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Added ADR-0007 and RC-047 | [d9cd3c6] |
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
Tracks backward/forward links between artifact instances so that the Business Case's
|
||||
cross-artifact traceability success criterion is measurable. A row is added or
|
||||
updated whenever an artifact instance is created or reviewed.
|
||||
|
||||
## Traceability Table
|
||||
|
||||
| Artifact Instance | Type | Upstream (Backward Link) | Downstream (Forward Link) | Last Reviewed (RC-ID) |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| [SA-001] | SA | - | [BC-001], [UCD-001] | [RC-004] |
|
||||
| [BC-001] | BC | [SA-001] | [PP-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006] | [RC-001], [RC-008] |
|
||||
| [PP-001] | PP | [BC-001], [SA-001] | [MIL-001], [MIL-002], [MIL-003], [MIL-004], [MIL-005], [MIL-006], [US-001] | [RC-002], [RC-009], [RC-015], [RC-017], [RC-025], [RC-032] |
|
||||
| [MIL-001] | MIL | [BC-001], [PP-001] | [MIL-002] | [RC-003], [RC-026] |
|
||||
| [MIL-002] | MIL | [BC-001], [PP-001], [MIL-001] | [MIL-003], [MIL-005] | [RC-005], [RC-027] |
|
||||
| [MIL-003] | MIL | [BC-001], [PP-001], [MIL-002] | [MIL-004] | [RC-006], [RC-028], [RC-033], [RC-039] |
|
||||
| [MIL-004] | MIL | [BC-001], [PP-001], [MIL-003] | - | [RC-007], [RC-029], [RC-034] |
|
||||
| [RC-001] | RC | [BC-001] | - | - |
|
||||
| [RC-002] | RC | [PP-001] | - | - |
|
||||
| [RC-003] | RC | [MIL-001] | - | - |
|
||||
| [RC-004] | RC | [SA-001] | - | - |
|
||||
| [RC-005] | RC | [MIL-002] | - | - |
|
||||
| [RC-006] | RC | [MIL-003] | - | - |
|
||||
| [MIL-005] | MIL | [BC-001], [PP-001], [MIL-002] | [MIL-006] | [RC-010], [RC-011], [RC-030] |
|
||||
| [MIL-006] | MIL | [BC-001], [PP-001], [MIL-002], [MIL-005] | - | [RC-016], [RC-031] |
|
||||
| [RC-007] | RC | [MIL-004] | - | - |
|
||||
| [RC-008] | RC | [BC-001] | - | - |
|
||||
| [RC-009] | RC | [PP-001] | - | - |
|
||||
| [RC-010] | RC | [MIL-005] | - | - |
|
||||
| [ADR-0001] | ADR | [BC-001], [MIL-005] | [ADR-0003] | [RC-012] |
|
||||
| [ADR-0002] | ADR | [SA-001], [RC-001] | - | [RC-013] |
|
||||
| [ADR-0003] | ADR | [MIL-005], [ADR-0001], [RC-011] | [ADR-0004] | [RC-014] |
|
||||
| [ADR-0004] | ADR | [MIL-006], [ADR-0003], [ADR-0002] | - | [RC-018] |
|
||||
| [RC-011] | RC | [MIL-005] | - | - |
|
||||
| [RC-012] | RC | [ADR-0001] | - | - |
|
||||
| [RC-013] | RC | [ADR-0002] | - | - |
|
||||
| [RC-014] | RC | [ADR-0003] | - | - |
|
||||
| [RC-015] | RC | [PP-001] | - | - |
|
||||
| [RC-016] | RC | [MIL-006] | - | - |
|
||||
| [RC-017] | RC | [PP-001] | - | - |
|
||||
| [RC-018] | RC | [ADR-0004] | - | - |
|
||||
| [UCD-001] | UCD | [SA-001], [BC-001] | [US-001], [UC-001], [UC-002], [UC-003], [UC-004], [UC-005], [UC-006], [UC-007] | [RC-019], [RC-035], [RC-040], [RC-045] |
|
||||
| [US-001] | US | [UCD-001], [BC-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004] | [UC-001], [UC-002], [UC-003], [UC-004], [UC-005], [UC-006], [UC-007] | [RC-020], [RC-036], [RC-041], [RC-046] |
|
||||
| [UC-001] | UC | [UCD-001], [US-001], [SA-001] | - | [RC-021] |
|
||||
| [UC-002] | UC | [UCD-001], [US-001], [SA-001] | - | [RC-022] |
|
||||
| [UC-003] | UC | [UCD-001], [US-001], [SA-001] | - | [RC-023] |
|
||||
| [UC-004] | UC | [UCD-001], [US-001], [SA-001] | - | [RC-024] |
|
||||
| [UC-005] | UC | [UCD-001], [US-001], [SA-001] | [ADR-0005] | [RC-037] |
|
||||
| [ADR-0005] | ADR | [MIL-003], [UC-005], [US-001], [ADR-0004] | - | [RC-038] |
|
||||
| [UC-006] | UC | [UCD-001], [US-001], [SA-001] | [ADR-0006] | [RC-042] |
|
||||
| [ADR-0006] | ADR | [MIL-004], [UC-006], [US-001], [ADR-0004], [ADR-0005] | - | [RC-043] |
|
||||
| [ADR-0007] | ADR | [MIL-004], [UC-006], [ADR-0006] | - | [RC-047] |
|
||||
| [UC-007] | UC | [UCD-001], [US-001], [SA-001] | - | [RC-044] |
|
||||
| [RC-019] | RC | [UCD-001] | - | - |
|
||||
| [RC-020] | RC | [US-001] | - | - |
|
||||
| [RC-021] | RC | [UC-001] | - | - |
|
||||
| [RC-022] | RC | [UC-002] | - | - |
|
||||
| [RC-023] | RC | [UC-003] | - | - |
|
||||
| [RC-024] | RC | [UC-004] | - | - |
|
||||
| [RC-025] | RC | [PP-001] | - | - |
|
||||
| [RC-026] | RC | [MIL-001] | - | - |
|
||||
| [RC-027] | RC | [MIL-002] | - | - |
|
||||
| [RC-028] | RC | [MIL-003] | - | - |
|
||||
| [RC-029] | RC | [MIL-004] | - | - |
|
||||
| [RC-030] | RC | [MIL-005] | - | - |
|
||||
| [RC-031] | RC | [MIL-006] | - | - |
|
||||
| [RC-032] | RC | [PP-001] | - | - |
|
||||
| [RC-033] | RC | [MIL-003] | - | - |
|
||||
| [RC-034] | RC | [MIL-004] | - | - |
|
||||
| [RC-035] | RC | [UCD-001] | - | - |
|
||||
| [RC-036] | RC | [US-001] | - | - |
|
||||
| [RC-037] | RC | [UC-005] | - | - |
|
||||
| [RC-038] | RC | [ADR-0005] | - | - |
|
||||
| [RC-039] | RC | [MIL-003] | - | - |
|
||||
| [RC-040] | RC | [UCD-001] | - | - |
|
||||
| [RC-041] | RC | [US-001] | - | - |
|
||||
| [RC-042] | RC | [UC-006] | - | - |
|
||||
| [RC-043] | RC | [ADR-0006] | - | - |
|
||||
| [RC-044] | RC | [UC-007] | - | - |
|
||||
| [RC-045] | RC | [UCD-001] | - | - |
|
||||
| [RC-046] | RC | [US-001] | - | - |
|
||||
| [RC-047] | RC | [ADR-0007] | - | - |
|
||||
|
||||
## Coverage Notes
|
||||
|
||||
- `-` in Upstream means foundational (SA-001 has no prerequisite). In Downstream it means nothing is built on the instance yet. In Last Reviewed it means no `RC-*` exists (review records are not themselves reviewed).
|
||||
- Types with no instance yet: KPI, BMC, BPMN, SSD, DM, OC, SD, DCD, ERD, GOV, DICT. The four P1 use case candidates are written as brief use cases (UC-001 to UC-004); the P2 and P3 candidates have no use case document yet.
|
||||
- PP-001 and TM-001 have no QC checklist; RC-002 validated PP-001 against its Business Case constraints and the milestone Go / No-Go criteria. TM-001 has no review record.
|
||||
- All review records are `Accepted` after S01 stood in for S05 on 2026-10-10. The author and S01 are the same person, so an independent review by S05 is still open (see RC-001).
|
||||
|
||||
---
|
||||
|
||||
[BC-001]: ../business-case.md
|
||||
[SA-001]: ../stakeholder-analysis.md
|
||||
[PP-001]: ../project-plan.md
|
||||
[MIL-001]: ../milestones/mil-001-stabilise-metadata-sync.md
|
||||
[MIL-002]: ../milestones/mil-002-onboarding-and-operations.md
|
||||
[MIL-003]: ../milestones/mil-003-quality-checks.md
|
||||
[MIL-004]: ../milestones/mil-004-versioned-release.md
|
||||
[MIL-005]: ../milestones/mil-005-wiki-and-translations.md
|
||||
[MIL-006]: ../milestones/mil-006-shared-wiki-publishing.md
|
||||
[RC-001]: ./reviews/rc-001-business-case.md
|
||||
[RC-002]: ./reviews/rc-002-project-plan.md
|
||||
[RC-003]: ./reviews/rc-003-mil-001.md
|
||||
[RC-004]: ./reviews/rc-004-stakeholder-analysis.md
|
||||
[RC-005]: ./reviews/rc-005-mil-002.md
|
||||
[RC-006]: ./reviews/rc-006-mil-003.md
|
||||
[RC-007]: ./reviews/rc-007-mil-004.md
|
||||
[RC-008]: ./reviews/rc-008-business-case-wiki-scope.md
|
||||
[RC-009]: ./reviews/rc-009-project-plan-mil-005.md
|
||||
[RC-010]: ./reviews/rc-010-mil-005.md
|
||||
[RC-011]: ./reviews/rc-011-mil-005-wiki-publishing.md
|
||||
[RC-012]: ./reviews/rc-012-adr-0001.md
|
||||
[ADR-0001]: ../adr/adr-0001-wiki-structure-and-languages.md
|
||||
[ADR-0002]: ../adr/adr-0002-s01-approves-as-stand-in.md
|
||||
[ADR-0003]: ../adr/adr-0003-wiki-publish-token.md
|
||||
[ADR-0004]: ../adr/adr-0004-shared-wiki-publishing-opt-in.md
|
||||
[RC-013]: ./reviews/rc-013-adr-0002.md
|
||||
[RC-014]: ./reviews/rc-014-adr-0003.md
|
||||
[RC-015]: ./reviews/rc-015-project-plan-pat.md
|
||||
[RC-016]: ./reviews/rc-016-mil-006.md
|
||||
[RC-017]: ./reviews/rc-017-project-plan-mil-006.md
|
||||
[RC-018]: ./reviews/rc-018-adr-0004.md
|
||||
[UCD-001]: ../use-case-diagram.md
|
||||
[US-001]: ../user-stories.md
|
||||
[UC-001]: ../uc-001/uc.md
|
||||
[UC-002]: ../uc-002/uc.md
|
||||
[UC-003]: ../uc-003/uc.md
|
||||
[UC-004]: ../uc-004/uc.md
|
||||
[RC-019]: ./reviews/rc-019-ucd-001.md
|
||||
[RC-020]: ./reviews/rc-020-us-001.md
|
||||
[RC-021]: ./reviews/rc-021-uc-001.md
|
||||
[RC-022]: ./reviews/rc-022-uc-002.md
|
||||
[RC-023]: ./reviews/rc-023-uc-003.md
|
||||
[RC-024]: ./reviews/rc-024-uc-004.md
|
||||
[RC-025]: ./reviews/rc-025-pp-001-use-cases.md
|
||||
[RC-026]: ./reviews/rc-026-mil-001-date.md
|
||||
[RC-027]: ./reviews/rc-027-mil-002-date.md
|
||||
[RC-028]: ./reviews/rc-028-mil-003-date.md
|
||||
[RC-029]: ./reviews/rc-029-mil-004-date.md
|
||||
[RC-030]: ./reviews/rc-030-mil-005-date.md
|
||||
[RC-031]: ./reviews/rc-031-mil-006-date.md
|
||||
[RC-032]: ./reviews/rc-032-pp-001-dates.md
|
||||
[RC-033]: ./reviews/rc-033-mil-003-reusable-workflows.md
|
||||
[RC-034]: ./reviews/rc-034-mil-004-scripts.md
|
||||
[RC-035]: ./reviews/rc-035-ucd-001.md
|
||||
[RC-036]: ./reviews/rc-036-us-001.md
|
||||
[RC-037]: ./reviews/rc-037-uc-005.md
|
||||
[RC-038]: ./reviews/rc-038-adr-0005.md
|
||||
[RC-039]: ./reviews/rc-039-mil-003-adoption.md
|
||||
[RC-040]: ./reviews/rc-040-ucd-001-release.md
|
||||
[RC-041]: ./reviews/rc-041-us-001-release.md
|
||||
[RC-042]: ./reviews/rc-042-uc-006.md
|
||||
[RC-043]: ./reviews/rc-043-adr-0006.md
|
||||
[RC-044]: ./reviews/rc-044-uc-007.md
|
||||
[RC-045]: ./reviews/rc-045-ucd-001-consume.md
|
||||
[RC-046]: ./reviews/rc-046-us-001-consume.md
|
||||
[RC-047]: ./reviews/rc-047-adr-0007.md
|
||||
[ADR-0007]: ../adr/adr-0007-release-publish-destination.md
|
||||
[UC-007]: ../uc-007/uc.md
|
||||
[UC-006]: ../uc-006/uc.md
|
||||
[ADR-0006]: ../adr/adr-0006-release-process-and-version-pinning.md
|
||||
[UC-005]: ../uc-005/uc.md
|
||||
[ADR-0005]: ../adr/adr-0005-quality-check-contract.md
|
||||
[4cf52af]: https://git.tirsystem.com/TirSystem/github-action/commit/4cf52afe00f546c6b20424fb8dfc12796ffd9296
|
||||
[d9cd3c6]: https://git.tirsystem.com/TirSystem/github-action/commit/d9cd3c67d4017984af8958f32240d3d66217e153
|
||||
@@ -0,0 +1,104 @@
|
||||
# Stakeholder Analysis: TirSystem Reusable Workflows
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | SA-001 |
|
||||
| CrossReference | [BC-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-03 | Rejected | Jens Tirsvad Nielsen | S01 | Initial version | [4de5438] |
|
||||
| 2026-10-03 | Accepted | Jens Tirsvad Nielsen | S01 | Added S05 Michael Kragh (DevOps owner, maintainer, cyber security)<br>S01 stays Product Owner and maintainer | [4de5438] |
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
This analysis identifies who depends on, operates or is affected by the
|
||||
TirSystem reusable workflow collection, so that scope, priorities and
|
||||
communication follow real needs. It uses a power/interest grid and maps
|
||||
each concern to a FURPS+ attribute.
|
||||
|
||||
## Stakeholder Summary Table
|
||||
|
||||
| ID | Name | Role/Title | Organization | Power Level | Interest Level | Quadrant | Primary Concern (Business Language) |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| S01 | Jens Tirsvad Nielsen | Product Owner and maintainer | TirSystem | HIGH | HIGH | Manage Closely | TirSystem repositories get the same automation without per-repository copy and paste, and scope follows business needs. |
|
||||
| S02 | Software engineers on TirSystem projects | Consumers of shared workflows (group) | TirSystem | MEDIUM | HIGH | Keep Informed | Quality checks, builds and releases work out of the box, and failures say what to fix. |
|
||||
| S03 | Gitea instance and runner operator | Platform operator (group; holders to be confirmed) | TirSystem | HIGH | MEDIUM | Keep Satisfied | Workflows run only on supported runners, use least-privilege tokens and never leak secrets. |
|
||||
| S04 | GitHub mirror audience | Visitors of the GitHub push mirrors (group) | Public | LOW | LOW | Monitor | The mirror shows the same description and topics as the primary Gitea repository. |
|
||||
| S05 | Michael Kragh | DevOps owner, maintainer and cyber security | TirSystem | HIGH | HIGH | Manage Closely | Shared automation is maintainable, and credentials, tokens and workflow permissions meet security requirements. |
|
||||
|
||||
## Power/Interest Classification Rationale
|
||||
|
||||
- **Manage Closely (S01):** decides scope and priorities, accepts documents and co-maintains the workflows.
|
||||
- **Manage Closely (S05):** owns and co-maintains the workflows and is the security
|
||||
authority; credential, token and permission design cannot be accepted
|
||||
without this role.
|
||||
- **Keep Informed (S02):** does not decide scope, but adoption by these
|
||||
engineers is the success measure; a breaking workflow change hits them first.
|
||||
- **Keep Satisfied (S03):** controls runners, secrets and Gitea features
|
||||
(Actions, scoped workflows) that the workflows rely on; an incompatible
|
||||
change can be blocked here.
|
||||
- **Monitor (S04):** passive consumers of mirror metadata; no action needed
|
||||
beyond keeping the metadata correct.
|
||||
|
||||
## Primary Concerns and FURPS+ Mapping
|
||||
|
||||
| ID | Concern | FURPS+ attribute |
|
||||
| --- | --- | --- |
|
||||
| S01 | One reviewed source of truth for shared automation | Supportability |
|
||||
| S01 | Documentation never claims behavior that is not implemented | Functionality |
|
||||
| S05 | One maintainable, reviewed source of truth for shared automation | Supportability |
|
||||
| S05 | Least-privilege tokens, no secret in logs, pinned and reviewed workflow code | Functionality (security) |
|
||||
| S02 | Clear failure messages that name the cause | Usability |
|
||||
| S02 | Pinned, versioned workflows with a changelog | Supportability |
|
||||
| S03 | Least-privilege tokens and no secret in logs | Functionality (security) |
|
||||
| S03 | Declared runner labels and prerequisites | Supportability |
|
||||
| S04 | Correct, current mirror description and topics | Functionality |
|
||||
|
||||
## Communication Requirements
|
||||
|
||||
| ID | Channel | Frequency | Deliverable | Phase / Milestone |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| S01 | Pull request review and chat | Per milestone | Accepted documents, issue list | All milestones |
|
||||
| S02 | README and changelog in the repository | Per workflow release | Usage guide, upgrade notes | MIL-002 onward |
|
||||
| S05 | Pull request review and issue tracker | Per change to workflows, credentials or runners | Security-reviewed changes, token scope list | All milestones |
|
||||
| S03 | Issue tracker | Per change to credentials or runners | Prerequisites and token scope list | MIL-001, MIL-002 |
|
||||
| S04 | None (mirror metadata only) | Daily sync | Updated description and topics | MIL-001 |
|
||||
|
||||
## Conflicting Interests and Mitigations
|
||||
|
||||
| Conflict | Stakeholders | Mitigation |
|
||||
| --- | --- | --- |
|
||||
| Fast adoption of new workflow behavior versus stable consuming repositories | S01, S02 | Version every shared workflow and document breaking changes before release (MIL-004). |
|
||||
| Convenient broad tokens versus least privilege | S02, S03 | Document the minimum token scope per workflow and validate it before use (MIL-002). |
|
||||
| Delivery speed versus security review | S01, S05 | S05 reviews every change to credentials, tokens, permissions and workflow code before the milestone is accepted by S01. |
|
||||
| Operator role holder not yet identified | S03, S05 | Confirm who operates runners and the Gitea instance; until then S05 is the contact. |
|
||||
|
||||
## Traceability Analysis
|
||||
|
||||
### Business Goal Alignment
|
||||
|
||||
| Stakeholder | Concern | Business Case objective |
|
||||
| --- | --- | --- |
|
||||
| S01 | One source of truth for shared automation | O1, O2 |
|
||||
| S02 | Clear failures, versioned updates | O3, O4 |
|
||||
| S03 | Least privilege, runner compatibility | O3 |
|
||||
| S05 | Maintainable shared automation, security | O1, O2, O3 |
|
||||
| S04 | Correct mirror metadata | O1 |
|
||||
|
||||
Objectives are defined in [BC-001]. Use-case mapping: S05 and S03 are the
|
||||
primary actors of the DevOps use cases, S02 of the software engineer use
|
||||
cases; both are listed in the Project Plan appendix.
|
||||
|
||||
## Sign-Off
|
||||
|
||||
Pending review by S01 and S05.
|
||||
|
||||
---
|
||||
|
||||
[BC-001]: ./business-case.md
|
||||
[4de5438]: https://git.tirsystem.com/TirSystem/github-action/commit/4de5438a88b4bbf18b165f52f797d1a52af89f6d
|
||||
@@ -0,0 +1,43 @@
|
||||
# UC-001: Synchronize Repository Metadata
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | UC-001 |
|
||||
| CrossReference | [UCD-001], [US-001], [SA-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [a2bf2d4] |
|
||||
|
||||
---
|
||||
|
||||
**Format:** Brief
|
||||
|
||||
**Title:** Synchronize Repository Metadata
|
||||
**Scope:** Reusable Workflow Collection
|
||||
**Level:** user-goal
|
||||
**Primary Actor:** DevOps Professional
|
||||
**Stakeholders:** S05, S04 (interests below)
|
||||
**Stories:** US-001.01, US-001.02
|
||||
|
||||
## Brief
|
||||
|
||||
A push to `main`, a manual run or the daily schedule starts the workflow. It checks that both tokens are accepted and that the GitHub token can administer the mirror, reads the description and topics from Gitea, finds the single GitHub push mirror, and sets the description and replaces the topics on GitHub. The run ends with a line that names the repository it synchronized.
|
||||
|
||||
**Stakeholder interests**
|
||||
|
||||
- S05 — the mirror shows what the primary repository shows, with no manual copying
|
||||
- S04 — the description and topics on the mirror are correct and current
|
||||
|
||||
**Preconditions:** The repository has Actions enabled and a runner, both secrets are stored, and at most one GitHub push mirror is configured.
|
||||
|
||||
**Postconditions (success guarantee):** The description and topics of the GitHub mirror equal those of the Gitea repository, or the run ended without a change and said why.
|
||||
|
||||
---
|
||||
|
||||
[UCD-001]: ../use-case-diagram.md
|
||||
[US-001]: ../user-stories.md
|
||||
[SA-001]: ../stakeholder-analysis.md
|
||||
[a2bf2d4]: https://git.tirsystem.com/TirSystem/github-action/commit/a2bf2d420416f7aff2badc6fe32a7690e2e523fd
|
||||
@@ -0,0 +1,44 @@
|
||||
# UC-002: Configure Workflow Credentials
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | UC-002 |
|
||||
| CrossReference | [UCD-001], [US-001], [SA-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [a2bf2d4] |
|
||||
|
||||
---
|
||||
|
||||
**Format:** Brief
|
||||
|
||||
**Title:** Configure Workflow Credentials
|
||||
**Scope:** Reusable Workflow Collection
|
||||
**Level:** user-goal
|
||||
**Primary Actor:** DevOps Professional
|
||||
**Stakeholders:** S05, S03, S02 (interests below)
|
||||
**Stories:** US-001.03, US-001.04
|
||||
|
||||
## Brief
|
||||
|
||||
The DevOps Professional creates a Gitea token and a GitHub fine-grained token with the minimum permissions in the credentials guide, and the Platform Operator stores them once as secrets of the organization, each holding only the token. A run of the workflow checks that each token is accepted and, for GitHub, that it can administer the mirror, and reports `Preflight passed` without printing any secret value.
|
||||
|
||||
**Stakeholder interests**
|
||||
|
||||
- S05 — credentials are least-privilege and checked before use
|
||||
- S03 — tokens are scoped, stored as secrets and never printed
|
||||
- S02 — a failed credential check says which secret to fix
|
||||
|
||||
**Preconditions:** The actor has access to the Gitea and GitHub settings and can store secrets for the organization.
|
||||
|
||||
**Postconditions (success guarantee):** Both secrets hold only a token, a run passes the credential check with the documented minimum permissions, and no secret value appeared in a log.
|
||||
|
||||
---
|
||||
|
||||
[UCD-001]: ../use-case-diagram.md
|
||||
[US-001]: ../user-stories.md
|
||||
[SA-001]: ../stakeholder-analysis.md
|
||||
[a2bf2d4]: https://git.tirsystem.com/TirSystem/github-action/commit/a2bf2d420416f7aff2badc6fe32a7690e2e523fd
|
||||
@@ -0,0 +1,44 @@
|
||||
# UC-003: Onboard a Repository
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | UC-003 |
|
||||
| CrossReference | [UCD-001], [US-001], [SA-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [a2bf2d4] |
|
||||
|
||||
---
|
||||
|
||||
**Format:** Brief
|
||||
|
||||
**Title:** Onboard a Repository
|
||||
**Scope:** Reusable Workflow Collection
|
||||
**Level:** user-goal
|
||||
**Primary Actor:** DevOps Professional
|
||||
**Stakeholders:** S05, S02, S03 (interests below)
|
||||
**Stories:** US-001.05, US-001.06
|
||||
|
||||
## Brief
|
||||
|
||||
The DevOps Professional follows the onboarding guide for a repository: checks that Actions and a runner are available, configures the GitHub push mirror, includes the credential configuration for the organization if it is not done yet, sets a description and topics, and triggers a first run. Scoped delivery runs the shared workflow in the repository without a copy, and the log ends with the synchronized repository.
|
||||
|
||||
**Stakeholder interests**
|
||||
|
||||
- S05 — a repository gets the standard automation without copying workflow files
|
||||
- S02 — onboarding is quick and needs no undocumented step
|
||||
- S03 — a repository uses only supported runners and its organization's secrets
|
||||
|
||||
**Preconditions:** Actions are enabled in the repository, a runner with the needed label is online, and the secrets can be stored for the repository's organization.
|
||||
|
||||
**Postconditions (success guarantee):** The first run in the repository passes using only the onboarding guide, and the repository needs no copy of the workflow.
|
||||
|
||||
---
|
||||
|
||||
[UCD-001]: ../use-case-diagram.md
|
||||
[US-001]: ../user-stories.md
|
||||
[SA-001]: ../stakeholder-analysis.md
|
||||
[a2bf2d4]: https://git.tirsystem.com/TirSystem/github-action/commit/a2bf2d420416f7aff2badc6fe32a7690e2e523fd
|
||||
@@ -0,0 +1,43 @@
|
||||
# UC-004: Diagnose a Failed Workflow
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | UC-004 |
|
||||
| CrossReference | [UCD-001], [US-001], [SA-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [a2bf2d4] |
|
||||
|
||||
---
|
||||
|
||||
**Format:** Brief
|
||||
|
||||
**Title:** Diagnose a Failed Workflow
|
||||
**Scope:** Reusable Workflow Collection
|
||||
**Level:** user-goal
|
||||
**Primary Actor:** DevOps Professional
|
||||
**Stakeholders:** S05, S03 (interests below)
|
||||
**Stories:** US-001.07, US-001.08
|
||||
|
||||
## Brief
|
||||
|
||||
The DevOps Professional or the Platform Operator opens the failed run, reads the last lines of the failing step and takes the category from the message. The troubleshooting guide maps that category and message to a cause and a fix, which is applied, and the workflow is run again.
|
||||
|
||||
**Stakeholder interests**
|
||||
|
||||
- S05 — the cause of a failure is found quickly and fixed once
|
||||
- S03 — a runner or secret problem is recognised as such and not blamed on the workflow
|
||||
|
||||
**Preconditions:** A run failed or did not start, and the actor can read the run log.
|
||||
|
||||
**Postconditions (success guarantee):** The cause is placed in one category (configuration, credentials, permissions, API response or runner) and the fix from the guide is applied or a defect is raised.
|
||||
|
||||
---
|
||||
|
||||
[UCD-001]: ../use-case-diagram.md
|
||||
[US-001]: ../user-stories.md
|
||||
[SA-001]: ../stakeholder-analysis.md
|
||||
[a2bf2d4]: https://git.tirsystem.com/TirSystem/github-action/commit/a2bf2d420416f7aff2badc6fe32a7690e2e523fd
|
||||
@@ -0,0 +1,44 @@
|
||||
# UC-005: Run Project Quality Checks
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | UC-005 |
|
||||
| CrossReference | [UCD-001], [US-001], [SA-001], [ADR-0005] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [385d2fb] |
|
||||
|
||||
---
|
||||
|
||||
**Format:** Brief
|
||||
|
||||
**Title:** Run Project Quality Checks
|
||||
**Scope:** Reusable Workflow Collection
|
||||
**Level:** user-goal
|
||||
**Primary Actor:** Software Engineer
|
||||
**Stakeholders:** S02, S05 (interests below)
|
||||
**Stories:** US-001.09, US-001.10
|
||||
|
||||
## Brief
|
||||
|
||||
A Software Engineer opens a pull request in a repository that calls the shared quality-check workflow. The workflow installs the pinned tools, runs the checks for each selected language on the files of the repository (lint, format and types for Python; lint and format for shell), and reports one status for the pull request. When every selected tool passes, the status is green.
|
||||
|
||||
**Stakeholder interests**
|
||||
|
||||
- S02 — checks run the same way in every project without writing a pipeline, and a failure says what to fix
|
||||
- S05 — the checks and their tool versions are defined once and change through a reviewed release
|
||||
|
||||
**Preconditions:** The repository is onboarded, the shared workflow is available through reusable workflow delivery, and the repository has files of at least one supported language.
|
||||
|
||||
**Postconditions (success guarantee):** The pull request has a pass or fail status that comes from every selected tool, and no file of the repository was changed.
|
||||
|
||||
---
|
||||
|
||||
[UCD-001]: ../use-case-diagram.md
|
||||
[US-001]: ../user-stories.md
|
||||
[SA-001]: ../stakeholder-analysis.md
|
||||
[ADR-0005]: ../adr/adr-0005-quality-check-contract.md
|
||||
[385d2fb]: https://git.tirsystem.com/TirSystem/github-action/commit/385d2fb7cb9be1fdc8fd3503d0af624fa38eafc7
|
||||
@@ -0,0 +1,45 @@
|
||||
# UC-006: Release a Reusable Workflow
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | UC-006 |
|
||||
| CrossReference | [UCD-001], [US-001], [SA-001], [ADR-0006] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [044d8ba] |
|
||||
|
||||
---
|
||||
|
||||
**Format:** Brief
|
||||
|
||||
**Title:** Release a Reusable Workflow
|
||||
**Scope:** Reusable Workflow Collection
|
||||
**Level:** user-goal
|
||||
**Primary Actor:** DevOps Professional
|
||||
**Stakeholders:** S05, S02, S03 (interests below)
|
||||
**Stories:** US-001.11, US-001.12
|
||||
|
||||
## Brief
|
||||
|
||||
When a change to the workflows or their scripts is ready on the default branch, the DevOps Professional checks that the repository's validation run on that commit is green, adds the version to the changelog with each breaking change marked, and creates the version tag and moves the major tag of the same major version. The release page for the tag is created from the changelog entry and announces what changed and whether consumers need to act. Consumers pinned to the previous version are not affected.
|
||||
|
||||
**Stakeholder interests**
|
||||
|
||||
- S05 — a release is a deliberate, validated, reviewed step, and a faulty one can be undone
|
||||
- S02 — a pinned pipeline never changes under them, and a changelog tells them whether to act
|
||||
- S03 — a change to credentials, tokens or permissions is visible in the changelog before it reaches runners
|
||||
|
||||
**Preconditions:** The repository's validation run exists and is green on the commit to be released, and the version scheme of ADR-0006 is defined.
|
||||
|
||||
**Postconditions (success guarantee):** A version tag and a changelog entry exist for the commit, the major tag points to the latest compatible release, the release page announces it, and pipelines pinned to earlier versions run unchanged.
|
||||
|
||||
---
|
||||
|
||||
[UCD-001]: ../use-case-diagram.md
|
||||
[US-001]: ../user-stories.md
|
||||
[SA-001]: ../stakeholder-analysis.md
|
||||
[ADR-0006]: ../adr/adr-0006-release-process-and-version-pinning.md
|
||||
[044d8ba]: https://git.tirsystem.com/TirSystem/github-action/commit/044d8ba21f96f4aceb807d62addc35cdcbb56051
|
||||
@@ -0,0 +1,43 @@
|
||||
# UC-007: Consume a Workflow Update
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | UC-007 |
|
||||
| CrossReference | [UCD-001], [US-001], [SA-001] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [4cf52af] |
|
||||
|
||||
---
|
||||
|
||||
**Format:** Brief
|
||||
|
||||
**Title:** Consume a Workflow Update
|
||||
**Scope:** Reusable Workflow Collection
|
||||
**Level:** user-goal
|
||||
**Primary Actor:** Software Engineer
|
||||
**Stakeholders:** S02, S05 (interests below)
|
||||
**Stories:** US-001.13, US-001.14, US-001.15
|
||||
|
||||
## Brief
|
||||
|
||||
When a new release of the shared workflows is announced, the Software Engineer reads its changelog entry to see whether it is breaking, changes the pinned version in one repository on a branch, opens a pull request and reads the run, and, when it is green, makes the same change in the other repositories.
|
||||
|
||||
**Stakeholder interests**
|
||||
|
||||
- S02 — an update is adopted deliberately, in one place first, and can be undone
|
||||
- S05 — consumers move to supported versions without a support request
|
||||
|
||||
**Preconditions:** Releases are versioned with a changelog (the release process), and the repository calls the shared workflow at a version tag.
|
||||
|
||||
**Postconditions (success guarantee):** The repository calls the new version, its pipeline still passes, and the previous version remains the way back.
|
||||
|
||||
---
|
||||
|
||||
[UCD-001]: ../use-case-diagram.md
|
||||
[US-001]: ../user-stories.md
|
||||
[SA-001]: ../stakeholder-analysis.md
|
||||
[4cf52af]: https://git.tirsystem.com/TirSystem/github-action/commit/4cf52afe00f546c6b20424fb8dfc12796ffd9296
|
||||
@@ -0,0 +1,109 @@
|
||||
# Use Case Diagram
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | UCD-001 |
|
||||
| CrossReference | [SA-001], [BC-001], [US-001], [UC-001], [UC-002], [UC-003], [UC-004], [UC-005], [UC-006], [UC-007] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S01 | Added the use case Release a Reusable Workflow (UC-006) | [044d8ba] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Added the use case Consume a Workflow Update (UC-007) (RC-045) | [4cf52af] |
|
||||
|
||||
---
|
||||
|
||||
## Purpose and Scope
|
||||
|
||||
The boundary is the reusable workflow collection of this repository: the
|
||||
Gitea Actions workflows, their credential checks and the guides that go with
|
||||
them. Inside it are the four P1 goals of the Project Plan: keeping the GitHub
|
||||
mirror's description and topics equal to Gitea's, configuring the credentials
|
||||
a workflow needs, bringing a repository onto the shared workflows, and finding
|
||||
the cause of a failed run. Gitea and GitHub are outside the boundary and are
|
||||
shown as external systems. Running quality checks is the first software engineer goal
|
||||
(P2). Releases and the other P2 and P3 use cases are not drawn yet.
|
||||
|
||||
## Diagram
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
left to right direction
|
||||
skinparam packageStyle rectangle
|
||||
|
||||
actor "DevOps Professional" as DevOps <<Actor>>
|
||||
actor "Platform Operator" as Operator <<Actor>>
|
||||
actor "Software Engineer" as Engineer <<Actor>>
|
||||
actor "Gitea Instance" as Gitea <<System>>
|
||||
actor "GitHub" as GitHub <<System>>
|
||||
|
||||
rectangle "Reusable Workflow Collection" <<System>> {
|
||||
usecase "Synchronize Repository Metadata" as UC1
|
||||
usecase "Configure Workflow Credentials" as UC2
|
||||
usecase "Onboard a Repository" as UC3
|
||||
usecase "Diagnose a Failed Workflow" as UC4
|
||||
usecase "Run Project Quality Checks" as UC5
|
||||
usecase "Release a Reusable Workflow" as UC6
|
||||
usecase "Consume a Workflow Update" as UC7
|
||||
}
|
||||
|
||||
DevOps --> UC1
|
||||
DevOps --> UC2
|
||||
DevOps --> UC3
|
||||
DevOps --> UC4
|
||||
DevOps --> UC6
|
||||
Operator --> UC2
|
||||
Operator --> UC4
|
||||
Engineer --> UC5
|
||||
Engineer --> UC7
|
||||
UC1 --> Gitea
|
||||
UC1 --> GitHub
|
||||
UC3 ..> UC2 : <<include>>
|
||||
UC4 ..> UC1 : <<extend>>
|
||||
@enduml
|
||||
```
|
||||
|
||||
## Actor Table
|
||||
|
||||
| Actor | Stereotype | Stakeholder ID (SA) | Goals (use cases) |
|
||||
| --- | --- | --- | --- |
|
||||
| DevOps Professional | `<<Actor>>` | S05 | Synchronize Repository Metadata, Configure Workflow Credentials, Onboard a Repository, Diagnose a Failed Workflow, Release a Reusable Workflow |
|
||||
| Platform Operator | `<<Actor>>` | S03 | Configure Workflow Credentials, Diagnose a Failed Workflow |
|
||||
| Software Engineer | `<<Actor>>` | S02 | Run Project Quality Checks, Consume a Workflow Update |
|
||||
| Gitea Instance | `<<System>>` | - | Synchronize Repository Metadata (source of description and topics) |
|
||||
| GitHub | `<<System>>` | S04 (audience of the mirror) | Synchronize Repository Metadata (target) |
|
||||
|
||||
## Use Case Table
|
||||
|
||||
| Use Case | Actor(s) | Goal |
|
||||
| --- | --- | --- |
|
||||
| Synchronize Repository Metadata | DevOps Professional | The GitHub mirror shows the Gitea description and topics |
|
||||
| Configure Workflow Credentials | DevOps Professional, Platform Operator | Least-privilege tokens that a workflow accepts |
|
||||
| Onboard a Repository | DevOps Professional | A repository consumes the shared workflows |
|
||||
| Diagnose a Failed Workflow | DevOps Professional, Platform Operator | The cause of a failed run is found and placed in a category |
|
||||
| Run Project Quality Checks | Software Engineer | Lint, format and type checks run on every change and report a pass or a fail |
|
||||
| Release a Reusable Workflow | DevOps Professional | A validated, versioned update that consumers can pin |
|
||||
| Consume a Workflow Update | Software Engineer | A new version is adopted safely, one repository first |
|
||||
|
||||
## Relationships
|
||||
|
||||
| Relationship | Justification |
|
||||
| --- | --- |
|
||||
| Onboard a Repository `<<include>>` Configure Workflow Credentials | Every onboarding needs working credentials; the behaviour is always part of it and is also used on its own when a token is rotated. |
|
||||
| Diagnose a Failed Workflow `<<extend>>` Synchronize Repository Metadata | The extension applies only when a run of the synchronization has failed; the synchronization is complete without it. |
|
||||
|
||||
---
|
||||
|
||||
[SA-001]: ./stakeholder-analysis.md
|
||||
[BC-001]: ./business-case.md
|
||||
[US-001]: ./user-stories.md
|
||||
[UC-001]: ./uc-001/uc.md
|
||||
[UC-002]: ./uc-002/uc.md
|
||||
[UC-003]: ./uc-003/uc.md
|
||||
[UC-004]: ./uc-004/uc.md
|
||||
[UC-005]: ./uc-005/uc.md
|
||||
[UC-006]: ./uc-006/uc.md
|
||||
[044d8ba]: https://git.tirsystem.com/TirSystem/github-action/commit/044d8ba21f96f4aceb807d62addc35cdcbb56051
|
||||
[UC-007]: ./uc-007/uc.md
|
||||
[4cf52af]: https://git.tirsystem.com/TirSystem/github-action/commit/4cf52afe00f546c6b20424fb8dfc12796ffd9296
|
||||
@@ -0,0 +1,247 @@
|
||||
# User Story
|
||||
|
||||
## Metadata
|
||||
| Key | Value |
|
||||
| --- | --- |
|
||||
| ID | US-001 |
|
||||
| CrossReference | [UCD-001], [BC-001], [MIL-001], [MIL-002], [MIL-003], [MIL-004], [UC-001], [UC-002], [UC-003], [UC-004], [UC-005], [UC-006], [UC-007] |
|
||||
|
||||
## Version History
|
||||
| Date | Status | Author | Reviewer | Change | Commit |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S01 | Added US-001.11 to US-001.13 (releases, UC-006); US-001.13 traced to the epic (RC-041) | [044d8ba] |
|
||||
| 2026-10-10 | Accepted | Jens Tirsvad Nielsen | S01 | Added US-001.14 and US-001.15 (UC-007); US-001.13 traced to UC-007 (RC-046) | [4cf52af] |
|
||||
|
||||
---
|
||||
|
||||
## Purpose and Scope
|
||||
|
||||
These stories cover the P1 use cases of the Project Plan that MIL-002 delivers
|
||||
(O1 to O3 of [BC-001]): keeping the mirror metadata correct, configuring
|
||||
credentials, onboarding a repository and diagnosing a failed run. Roles are the
|
||||
actors of [UCD-001]. Stories for quality checks and releases (MIL-004) and for the wiki (MIL-005, MIL-006) are not written yet.
|
||||
|
||||
## Story List
|
||||
|
||||
### US-001.01 — Mirror shows the Gitea metadata
|
||||
|
||||
**As a** DevOps Professional, **I want** the GitHub mirror to show the description and topics of the Gitea repository, **so that** visitors of the mirror see the same repository metadata as on the primary repository.
|
||||
|
||||
**Acceptance Criteria**
|
||||
|
||||
- Given a repository with one GitHub push mirror, when the workflow runs, then the GitHub description and topics equal the Gitea ones.
|
||||
- Given the description or the topics changed on Gitea, when the next run completes, then the GitHub mirror shows the new values.
|
||||
|
||||
| Traces to | Size | INVEST exceptions |
|
||||
| --- | --- | --- |
|
||||
| [UC-001], [MIL-002] | fits one iteration | none |
|
||||
|
||||
### US-001.02 — Repository without a mirror is skipped
|
||||
|
||||
**As a** DevOps Professional, **I want** a repository without a GitHub mirror to be skipped successfully, **so that** repositories that have no mirror do not show failed runs.
|
||||
|
||||
**Acceptance Criteria**
|
||||
|
||||
- Given a repository with no GitHub push mirror, when the workflow runs, then the run succeeds and the log says that there is nothing to sync.
|
||||
- Given a repository with several GitHub push mirrors, when the workflow runs, then the run fails with a configuration message and changes nothing.
|
||||
|
||||
| Traces to | Size | INVEST exceptions |
|
||||
| --- | --- | --- |
|
||||
| [UC-001], [MIL-002] | fits one iteration | none |
|
||||
|
||||
### US-001.03 — Check the tokens before changing anything
|
||||
|
||||
**As a** DevOps Professional, **I want** both tokens to be checked before the workflow changes anything, **so that** a wrong or too weak token is found without any side effect.
|
||||
|
||||
**Acceptance Criteria**
|
||||
|
||||
- Given a token that GitHub rejects, when the workflow runs, then nothing is changed and the log names the credentials category.
|
||||
- Given a GitHub token without administration access, when the workflow runs, then it stops with a permissions message before the first change.
|
||||
|
||||
| Traces to | Size | INVEST exceptions |
|
||||
| --- | --- | --- |
|
||||
| [UC-002], [MIL-002] | fits one iteration | none |
|
||||
|
||||
### US-001.04 — Store the secrets once per organization
|
||||
|
||||
**As a** Platform Operator, **I want** to store a workflow's secrets once for an organization, **so that** every repository of the organization can use the workflow without its own copy of the secrets.
|
||||
|
||||
**Acceptance Criteria**
|
||||
|
||||
- Given the secrets are stored for an organization, when a repository of that organization runs the workflow, then it passes the credential check.
|
||||
- Given a repository of another organization, when it runs the workflow, then it does not see these secrets and the log names the missing secret.
|
||||
|
||||
| Traces to | Size | INVEST exceptions |
|
||||
| --- | --- | --- |
|
||||
| [UC-002], [MIL-002] | fits one iteration | none |
|
||||
|
||||
### US-001.05 — Use the workflow without a copy
|
||||
|
||||
**As a** DevOps Professional, **I want** a repository to use the shared workflow without copying it, **so that** a fix made once reaches every repository.
|
||||
|
||||
**Acceptance Criteria**
|
||||
|
||||
- Given a repository without its own workflow files, when a push is made to `main`, then the shared workflow runs in it.
|
||||
- Given the shared workflow changes, when the next run starts in another repository, then it runs the changed version.
|
||||
|
||||
| Traces to | Size | INVEST exceptions |
|
||||
| --- | --- | --- |
|
||||
| [UC-003], [MIL-002] | fits one iteration | none |
|
||||
|
||||
### US-001.06 — Onboard from one guide
|
||||
|
||||
**As a** DevOps Professional, **I want** to onboard a repository by following one guide, **so that** the first run passes without undocumented steps.
|
||||
|
||||
**Acceptance Criteria**
|
||||
|
||||
- Given a repository with Actions enabled and a runner, when its owner follows only the onboarding guide, then the first run succeeds.
|
||||
- Given a step of the guide is wrong or missing, when it is found during onboarding, then it is raised as a defect of the guide.
|
||||
|
||||
| Traces to | Size | INVEST exceptions |
|
||||
| --- | --- | --- |
|
||||
| [UC-003], [MIL-002] | fits one iteration | none |
|
||||
|
||||
### US-001.07 — Every failure names its category
|
||||
|
||||
**As a** DevOps Professional, **I want** every failure message to name its category, **so that** I know at once whether to look at configuration, credentials, permissions, the service or the runner.
|
||||
|
||||
**Acceptance Criteria**
|
||||
|
||||
- Given any failure of the workflow, when its log is read, then the message starts with one of the categories configuration, credentials, permissions or api.
|
||||
- Given a message that has no category, when it is found, then it is raised as a defect.
|
||||
|
||||
| Traces to | Size | INVEST exceptions |
|
||||
| --- | --- | --- |
|
||||
| [UC-004], [MIL-002] | fits one iteration | none |
|
||||
|
||||
### US-001.08 — Recognise a runner problem
|
||||
|
||||
**As a** Platform Operator, **I want** to recognise a runner problem from its symptom, **so that** I fix the runner and not the workflow.
|
||||
|
||||
**Acceptance Criteria**
|
||||
|
||||
- Given a run that stays waiting, when the troubleshooting guide is read, then it names the missing runner label as the cause.
|
||||
- Given a job that fails before the script, when the guide is read, then it names the tool missing from the runner image.
|
||||
|
||||
| Traces to | Size | INVEST exceptions |
|
||||
| --- | --- | --- |
|
||||
| [UC-004], [MIL-002] | fits one iteration | none |
|
||||
|
||||
### US-001.09 — Same checks on every change
|
||||
|
||||
**As a** Software Engineer, **I want** every pull request to run the same quality checks for the languages of my repository, **so that** a defect is found before review without me writing a pipeline.
|
||||
|
||||
**Acceptance Criteria**
|
||||
|
||||
- Given a repository that calls the shared workflow and has Python files, when a pull request is opened, then lint, format and type checks run and the status is pass or fail.
|
||||
- Given a repository that has shell scripts, when a pull request is opened, then lint and format checks run for them and the status is pass or fail.
|
||||
|
||||
| Traces to | Size | INVEST exceptions |
|
||||
| --- | --- | --- |
|
||||
| [UC-005], [MIL-003] | fits one iteration | none |
|
||||
|
||||
### US-001.10 — A failure says what to fix
|
||||
|
||||
**As a** Software Engineer, **I want** a failed check to show the tool, the file, the line and the message, **so that** I can fix it without reading the workflow.
|
||||
|
||||
**Acceptance Criteria**
|
||||
|
||||
- Given a file with a finding, when the check runs, then the job fails and the log shows the tool name with `path:line` and the tool's message.
|
||||
- Given a language that has no files in the repository, when the check runs, then it passes and the log says that nothing was checked.
|
||||
|
||||
| Traces to | Size | INVEST exceptions |
|
||||
| --- | --- | --- |
|
||||
| [UC-005], [MIL-003] | fits one iteration | none |
|
||||
|
||||
### US-001.11 — Only validated commits are released
|
||||
|
||||
**As a** DevOps Professional, **I want** a release to be created only from a commit whose validation run is green, **so that** consumers never receive an unchecked version.
|
||||
|
||||
**Acceptance Criteria**
|
||||
|
||||
- Given a commit whose validation run failed, when a release is attempted, then no version tag is created.
|
||||
- Given a green commit and a changelog entry for the version, when the release is created, then the version tag, the major tag and the release page exist.
|
||||
|
||||
| Traces to | Size | INVEST exceptions |
|
||||
| --- | --- | --- |
|
||||
| [UC-006], [MIL-004] | fits one iteration | none |
|
||||
|
||||
### US-001.12 — A release says whether it is breaking
|
||||
|
||||
**As a** DevOps Professional, **I want** every release to say whether it is breaking, **so that** consumers know whether they must act.
|
||||
|
||||
**Acceptance Criteria**
|
||||
|
||||
- Given a change that renames a workflow, an input or a secret, or can turn a passing consumer red, when it is released, then the changelog marks it as breaking and a new major version is created.
|
||||
- Given a compatible change, when it is released, then the major tag moves to it and consumers pinned to that major version receive it.
|
||||
|
||||
| Traces to | Size | INVEST exceptions |
|
||||
| --- | --- | --- |
|
||||
| [UC-006], [MIL-004] | fits one iteration | none |
|
||||
|
||||
### US-001.13 — A pin that does not move
|
||||
|
||||
**As a** Software Engineer, **I want** to pin the shared workflows to a version that does not change under me, **so that** a release cannot break my pipeline by surprise.
|
||||
|
||||
**Acceptance Criteria**
|
||||
|
||||
- Given a repository that calls a shared workflow at an exact version tag, when a new release is made, then its runs use the same code as before.
|
||||
- Given a repository that calls a shared workflow at a major tag, when a compatible release is made, then it receives the release and a breaking release is not delivered to it.
|
||||
|
||||
| Traces to | Size | INVEST exceptions |
|
||||
| --- | --- | --- |
|
||||
| [UC-007], [MIL-004] | fits one iteration | none |
|
||||
|
||||
### US-001.14 — A changelog says whether to act
|
||||
|
||||
**As a** Software Engineer, **I want** to see in a changelog entry whether a release is breaking, **so that** I know whether I must change my pipeline.
|
||||
|
||||
**Acceptance Criteria**
|
||||
|
||||
- Given a release page or a changelog entry, when it is read, then the groups Breaking, Added, Changed and Fixed are visible and a breaking change is the first group.
|
||||
- Given a breaking release, when the entry is read, then it names what changed and what to do.
|
||||
|
||||
| Traces to | Size | INVEST exceptions |
|
||||
| --- | --- | --- |
|
||||
| [UC-007], [MIL-004] | fits one iteration | none |
|
||||
|
||||
### US-001.15 — Try an update in one place and go back
|
||||
|
||||
**As a** Software Engineer, **I want** to try a new version in one repository and return to the previous one, **so that** an update cannot harm all my pipelines at once.
|
||||
|
||||
**Acceptance Criteria**
|
||||
|
||||
- Given a branch that changes the pinned version in one repository, when its pull request runs, then the result of the new version is visible before any other repository changes.
|
||||
- Given a failing update, when the pin is set back to the previous exact tag, then the pipeline runs the previous code unchanged.
|
||||
|
||||
| Traces to | Size | INVEST exceptions |
|
||||
| --- | --- | --- |
|
||||
| [UC-007], [MIL-004] | fits one iteration | none |
|
||||
|
||||
## INVEST Check
|
||||
|
||||
All fifteen stories are independent of each other except that US-001.05 and
|
||||
US-001.06 build on US-001.04 (the secrets must exist before a repository can
|
||||
run the workflow). Each states one goal and can be negotiated, delivers value
|
||||
to the named role, is small enough for one iteration, and has acceptance
|
||||
criteria that are checked with a run or a read of the guide. Exception:
|
||||
US-001.01 and US-001.02 are already implemented and are written so that their
|
||||
behaviour is tested rather than built.
|
||||
|
||||
---
|
||||
|
||||
[UCD-001]: ./use-case-diagram.md
|
||||
[BC-001]: ./business-case.md
|
||||
[MIL-001]: ./milestones/mil-001-stabilise-metadata-sync.md
|
||||
[MIL-002]: ./milestones/mil-002-onboarding-and-operations.md
|
||||
[MIL-003]: ./milestones/mil-003-quality-checks.md
|
||||
[MIL-004]: ./milestones/mil-004-versioned-release.md
|
||||
[UC-001]: ./uc-001/uc.md
|
||||
[UC-002]: ./uc-002/uc.md
|
||||
[UC-003]: ./uc-003/uc.md
|
||||
[UC-004]: ./uc-004/uc.md
|
||||
[UC-005]: ./uc-005/uc.md
|
||||
[UC-006]: ./uc-006/uc.md
|
||||
[044d8ba]: https://git.tirsystem.com/TirSystem/github-action/commit/044d8ba21f96f4aceb807d62addc35cdcbb56051
|
||||
[UC-007]: ./uc-007/uc.md
|
||||
[4cf52af]: https://git.tirsystem.com/TirSystem/github-action/commit/4cf52afe00f546c6b20424fb8dfc12796ffd9296
|
||||
@@ -0,0 +1,51 @@
|
||||
# Wiki term list
|
||||
|
||||
Terms used in the Danish (`da`) and Bahasa Malaysia (`ms`) wiki pages, so the
|
||||
same English word is always translated the same way (ADR-0001, MIL-005 task 4).
|
||||
English is authoritative. A term in parentheses is shown once beside the
|
||||
translation when a reader may only know the English word.
|
||||
|
||||
This is a working list for translators and reviewers, not a project artifact.
|
||||
Add a row when a translation needs a term that is not here, in the same pull
|
||||
request.
|
||||
|
||||
## Kept in English
|
||||
|
||||
These stay as they are in every language: `workflow_dispatch`, `runs-on`, the
|
||||
names of secrets and workflows (`TOKEN_FOR_GITEA`, **Sync GitHub mirror
|
||||
metadata**, **Publish wiki**), command lines, file names, JSON keys, scope
|
||||
names, status labels such as `online` and `waiting`, and the workflow's
|
||||
messages, including the category names (`configuration`, `credentials`,
|
||||
`permissions`, `api`).
|
||||
|
||||
| English | Danish (`da`) | Bahasa Malaysia (`ms`) | Note |
|
||||
| --- | --- | --- | --- |
|
||||
| runner | runner | runner | Not translated in either language. |
|
||||
| label (of a runner) | label | label | |
|
||||
| token | token | token | |
|
||||
| repository | repository | repositori | Danish IT language keeps the English word. |
|
||||
| mirror, push mirror | spejl, push-spejl | cermin, push mirror | Malay keeps `push mirror` where it is the Gitea feature name. |
|
||||
| secret | secret | rahsia (secret) | Gitea's own term is `secret`. |
|
||||
| description | beskrivelse | penerangan | |
|
||||
| topics (of a repository) | emner (topics) | topik | |
|
||||
| workflow | workflow | aliran kerja (workflow) | |
|
||||
| least privilege | mindste rettigheder | keistimewaan paling minimum | |
|
||||
| permission | tilladelse | kebenaran | |
|
||||
| scope (of a token) | scope | skop | `scope` is the Gitea term in the UI. |
|
||||
| preflight check | forhåndskontrol (preflight) | semakan awal (preflight) | The log line `Preflight passed` stays in English. |
|
||||
| credentials | credentials | kelayakan (credentials) | |
|
||||
| rotate a token | udskifte et token | menukar token | |
|
||||
| revoke | tilbagekalde | membatalkan | |
|
||||
| onboard a repository | tilslutte et repository | menyertakan repositori | |
|
||||
| DevOps professional | DevOps-professionel | profesional DevOps | |
|
||||
| software engineer | softwareudvikler | jurutera perisian | |
|
||||
| capability | funktionalitet | keupayaan | |
|
||||
| implemented | implementeret | dilaksanakan | |
|
||||
| planned | planlagt | dirancang | |
|
||||
| verified, not verified | verificeret, ikke verificeret | disahkan, belum disahkan | |
|
||||
| schedule (cron) | tidsplan | jadual | |
|
||||
| manual run | manuel kørsel | pencetusan manual | |
|
||||
| pull request | pull request | pull request | Not translated. |
|
||||
| use case | use case | kes guna (use case) | |
|
||||
| Project Plan | projektplan | Pelan Projek | |
|
||||
| wiki | wiki | wiki | |
|
||||
@@ -0,0 +1,87 @@
|
||||
# Wiki translation review checklist
|
||||
|
||||
For MIL-005 task 5 (issue #36): a native reader of Danish and of Bahasa
|
||||
Malaysia checks the translated wiki pages before they are treated as final.
|
||||
English is authoritative; the translations follow it (ADR-0001). The drafts
|
||||
were written without a native review, so please read them as a reader, not as
|
||||
a proofreader of the English.
|
||||
|
||||
This is a working document for reviewers, like [the term list](wiki-terms.md).
|
||||
It is not a project artifact.
|
||||
|
||||
## What to review
|
||||
|
||||
Fifteen pages exist on the wiki. You review the five pages of your language.
|
||||
|
||||
| Page | Danish (`da`) | Bahasa Malaysia (`ms`) | What it is |
|
||||
| --- | --- | --- | --- |
|
||||
| Home | [Home.da](https://git.tirsystem.com/TirSystem/github-action/wiki/Home.da) | [Home.ms](https://git.tirsystem.com/TirSystem/github-action/wiki/Home.ms) | Overview, requirements, setup, run, tests |
|
||||
| Onboarding | [Onboarding.da](https://git.tirsystem.com/TirSystem/github-action/wiki/Onboarding.da) | [Onboarding.ms](https://git.tirsystem.com/TirSystem/github-action/wiki/Onboarding.ms) | Steps to use the workflow, runners |
|
||||
| Credentials | [Credentials.da](https://git.tirsystem.com/TirSystem/github-action/wiki/Credentials.da) | [Credentials.ms](https://git.tirsystem.com/TirSystem/github-action/wiki/Credentials.ms) | Secrets, token permissions, rotation |
|
||||
| Troubleshooting | [Troubleshooting.da](https://git.tirsystem.com/TirSystem/github-action/wiki/Troubleshooting.da) | [Troubleshooting.ms](https://git.tirsystem.com/TirSystem/github-action/wiki/Troubleshooting.ms) | Error messages and fixes |
|
||||
| Capabilities | [Capabilities.da](https://git.tirsystem.com/TirSystem/github-action/wiki/Capabilities.da) | [Capabilities.ms](https://git.tirsystem.com/TirSystem/github-action/wiki/Capabilities.ms) | What exists and what is planned, with a diagram |
|
||||
|
||||
Read each page next to its English page (`Home`, `Onboarding`, and so on). The
|
||||
files are in `wiki/` in the repository (`Home.da.md`, `Home.ms.md`, ...).
|
||||
|
||||
## Checklist (per page)
|
||||
|
||||
Mark each item Pass, Fix or N/A. A "Fix" needs a row in the findings table
|
||||
below.
|
||||
|
||||
| # | Check | Notes |
|
||||
| --- | --- | --- |
|
||||
| 1 | **Meaning:** every sentence says what the English says; nothing added, nothing dropped | Pay most attention to warnings (secrets, permissions, "not verified") |
|
||||
| 2 | **Natural language:** reads as written by a native speaker, not as a word-for-word translation | Flag stiff or confusing phrasing, not only errors |
|
||||
| 3 | **Terms:** the term list ([wiki-terms.md](wiki-terms.md)) is followed, and the same English term is always translated the same way | If a term in the list is a poor choice, say so with a better one |
|
||||
| 4 | **Kept in English:** commands, file names, JSON keys, secret names, scope names, and the workflow's messages in backticks are unchanged | A translated message would no longer match what the workflow prints |
|
||||
| 5 | **Register:** a clear, professional tone for DevOps and software engineers; consistent use of "you" form | Danish: du; Bahasa Malaysia: neutral, no slang |
|
||||
| 6 | **Spelling, grammar, punctuation:** including compounds (Danish) and affixes (Bahasa Malaysia) | |
|
||||
| 7 | **Headings and links:** headings are understandable; links go to the page in the same language | A link to an English page from a translated page is a defect |
|
||||
| 8 | **Tables:** headers and cells are translated; the number of rows equals the English table | An automatic test already checks the row count |
|
||||
| 9 | **Numbers, dates, units:** unchanged where they are technical (for example `03:17 UTC`, `HTTP 401`) | |
|
||||
| 10 | **Not misleading:** nothing would make a reader take a wrong action (wrong secret, wrong scope, skipping a check) | A finding here is a blocker |
|
||||
|
||||
## Judgement calls to look at first
|
||||
|
||||
These are the choices where the draft is least certain.
|
||||
|
||||
| Topic | Danish draft | Bahasa Malaysia draft | Question |
|
||||
| --- | --- | --- | --- |
|
||||
| secret (a stored credential) | `secret` | `rahsia (secret)` | Is the English word clearer to your readers, or the local word? |
|
||||
| mirror, push mirror | `spejl`, `push-spejl` | `cermin`, `push mirror` | Does the term read as the Gitea feature? |
|
||||
| workflow | `workflow` | `aliran kerja (workflow)` | Keep the English word, or the local term only? |
|
||||
| repository | `repository` | `repositori` | Which one do engineers actually use? |
|
||||
| use case | `use case` | `kes guna (use case)` | Is `kes guna` understood, or is `use case` better? |
|
||||
| preflight check | `forhåndskontrol (preflight)` | `semakan awal (preflight)` | Does the explanation help, or is it noise? |
|
||||
| least privilege | `mindste rettigheder` | `keistimewaan paling minimum` | Is this the term security staff use? |
|
||||
| rotate a token | `Udskiftning af et token` | `Menukar token` | Does it say "replace with a new one"? |
|
||||
|
||||
Bahasa Malaysia is the weaker draft; please read it more critically.
|
||||
|
||||
## Findings
|
||||
|
||||
One row per finding. Quote the current text and give your proposed text.
|
||||
|
||||
| # | Page | Section or line | Current text | Proposed text | Why | Severity |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| 1 | | | | | | Blocker / Fix / Suggestion |
|
||||
|
||||
Severity: **Blocker** changes the meaning or could mislead; **Fix** is a
|
||||
mistake that should be corrected; **Suggestion** is a style preference.
|
||||
|
||||
## Outcome
|
||||
|
||||
| Language | Reviewer (name) | Date | Result |
|
||||
| --- | --- | --- | --- |
|
||||
| Danish | | | Go / Go with fixes / No-Go |
|
||||
| Bahasa Malaysia | | | Go / Go with fixes / No-Go |
|
||||
|
||||
## After the review
|
||||
|
||||
1. Send the filled findings table and the outcome to S01.
|
||||
2. Fixes are made in the `wiki/*.da.md` and `wiki/*.ms.md` files through a
|
||||
pull request; the first line of each translation (the source hash) stays
|
||||
as it is unless the English page changed.
|
||||
3. The pull request lists the wiki pages it changes (rule 8 of `AGENTS.md`).
|
||||
4. When both languages are Go, issue #36 is closed and MIL-005 can be closed.
|
||||
Submodule
+1
Submodule framework added at 14d221ec1c
@@ -0,0 +1,114 @@
|
||||
# Workflow credentials
|
||||
|
||||
The sync workflow uses two secrets. Give each the least privilege that works,
|
||||
store it only as a Gitea secret, and rotate it when a person with access
|
||||
leaves.
|
||||
|
||||
| Secret | Content | Used for |
|
||||
| --- | --- | --- |
|
||||
| `TOKEN_FOR_GITEA` | The Gitea token, nothing else | Reading the repository (description, topics) and its push mirrors |
|
||||
| `PAT_FOR_GITHUB` | The GitHub token, nothing else | Changing the description and topics of the GitHub mirror |
|
||||
|
||||
## Minimum permissions
|
||||
|
||||
These were checked on 2026-10-10 against the Gitea source (the route
|
||||
definitions in `routers/api/v1/api.go`, `main` branch) and the GitHub page
|
||||
"Permissions required for fine-grained personal access tokens", for every API
|
||||
call the workflows make. S01, standing in for S05 (ADR-0002), approved them on
|
||||
2026-10-10. They have **not been tested on this instance with a token that
|
||||
holds only these permissions**; the checks at the end of this section are the
|
||||
way to do that.
|
||||
|
||||
**Gitea token** (a personal access token of a user, not a deploy key; deploy
|
||||
keys do not work for the REST API):
|
||||
|
||||
- scope `read:repository`: every `/repos/...` route needs the repository
|
||||
scope, and the calls below only read
|
||||
- the user must be an administrator of the repository: the `push_mirrors`
|
||||
routes require repository administration in addition to the token scope
|
||||
|
||||
Calls made: `GET /repos/{owner}/{repo}` and `GET /repos/{owner}/{repo}/push_mirrors`.
|
||||
|
||||
**GitHub token** (fine-grained personal access token):
|
||||
|
||||
- Resource owner: the owner of the mirror repository
|
||||
- Repository access: only the mirror repository
|
||||
- Repository permission: **Administration: Read and write** (no other
|
||||
permission); it is needed for `PATCH /repos/{owner}/{repo}` and
|
||||
`PUT /repos/{owner}/{repo}/topics`. `Metadata: Read` is added automatically
|
||||
and covers `GET /repos/{owner}/{repo}`.
|
||||
- Set an expiry date
|
||||
|
||||
Calls made: `GET /repos/{owner}/{repo}`, `PATCH /repos/{owner}/{repo}` (description)
|
||||
and `PUT /repos/{owner}/{repo}/topics`.
|
||||
|
||||
**Gitea token for the wiki** (see "Wiki publishing secret" below): scope
|
||||
`write:repository`, because writing a page (`POST`, `PATCH`, `DELETE` under
|
||||
`/repos/{owner}/{repo}/wiki`) needs the repository scope with write access, and
|
||||
the user needs write access to the repository's wiki. Listing and reading
|
||||
pages needs only the read scope.
|
||||
|
||||
**Testing the permissions on the instance (optional)**
|
||||
|
||||
1. In the Gitea settings of the user, the token stored as `TOKEN_FOR_GITEA`
|
||||
lists only `read:repository`, the user is an administrator of the
|
||||
repository, and a run still ends with `Preflight passed`.
|
||||
2. The GitHub token lists only the mirror repository and
|
||||
`Administration: Read and write` (plus the automatic `Metadata: Read`), and
|
||||
a run ends with `Preflight passed` and `Synced description and topics`.
|
||||
3. A throwaway token that lacks one of these permissions makes the run fail
|
||||
with `[permissions]` (or HTTP 403 for Gitea) and names the category,
|
||||
without printing the token.
|
||||
|
||||
Format of `PAT_FOR_GITHUB`: only the token string (for example
|
||||
`github_pat_...`), as clear text. The workflow only checks that it is not empty;
|
||||
GitHub rejects a wrong value (HTTP 401).
|
||||
|
||||
## What the workflow checks before it changes anything
|
||||
|
||||
The workflow runs a preflight and writes nothing to GitHub unless it passes:
|
||||
|
||||
1. Both secrets exist and have the expected shape.
|
||||
2. Gitea accepts the token and the repository is visible with it.
|
||||
3. At most one GitHub push mirror is configured. With none, the run ends
|
||||
successfully without syncing and the GitHub secret is not read.
|
||||
4. GitHub accepts the token for the mirror repository **and** the token
|
||||
reports administration access to it.
|
||||
|
||||
On success the log says `Preflight passed: Gitea and GitHub accepted the
|
||||
credentials.` Failures start with a category such as `[credentials]` or
|
||||
`[permissions]`; see [troubleshooting.md](troubleshooting.md). No secret value
|
||||
is ever printed.
|
||||
|
||||
## Wiki publishing secret
|
||||
|
||||
The workflow **Publish wiki** copies `wiki/` to the Gitea wiki of a repository
|
||||
that has opted in with `wiki/.publish` (see [onboarding.md](onboarding.md)). It
|
||||
uses its own secret, so the metadata sync token stays read-only.
|
||||
|
||||
| Secret | Content | Used for |
|
||||
| --- | --- | --- |
|
||||
| `TOKEN_FOR_GITEA_WIKI` | The Gitea token, nothing else | Writing the wiki pages of the repositories of an organization that opt in |
|
||||
|
||||
- Store it as a secret of the organization of each repository that publishes.
|
||||
There is no fallback to `TOKEN_FOR_GITEA`: a repository that opted in and has
|
||||
no such secret fails with a configuration error, and a repository that did
|
||||
not opt in does not need it.
|
||||
- The token needs scope `write:repository`, and its user needs write access to
|
||||
the repositories. Gitea has no wiki-only scope, so create the token for a
|
||||
dedicated user. S05 approves the scope and S03 stores the secret.
|
||||
- Calls made: `GET /repos/{owner}/{repo}`, `GET /repos/{owner}/{repo}/wiki/pages`,
|
||||
`GET`, `POST` and `PATCH /repos/{owner}/{repo}/wiki/...` and, for a page that
|
||||
no longer exists in `wiki/`, `DELETE /repos/{owner}/{repo}/wiki/page/{name}`.
|
||||
- The wiki must be enabled in the repository settings. The workflow refuses to
|
||||
run when it is not.
|
||||
- Pages that are in `wiki/` are always overwritten from it, so a change made
|
||||
in the Gitea web UI is lost on the next publish. Pages that are only in the
|
||||
wiki are removed only when `wiki/.publish` contains the word `prune`.
|
||||
|
||||
## Rotating a token
|
||||
|
||||
1. Create the new token with the permissions above.
|
||||
2. Replace the secret value in the repository or organization settings.
|
||||
3. Run the workflow manually and wait for `Preflight passed`.
|
||||
4. Revoke the old token.
|
||||
@@ -0,0 +1,94 @@
|
||||
# Onboarding a repository
|
||||
|
||||
How a DevOps professional makes a TirSystem repository use the shared
|
||||
**Sync GitHub mirror metadata** workflow, and which runners it needs. Only
|
||||
this workflow exists today; the quality-check and release workflows are
|
||||
planned (see the [Project Plan](../docs/project-plan.md)).
|
||||
|
||||
## What has been verified
|
||||
|
||||
| Item | Status |
|
||||
| --- | --- |
|
||||
| Gitea version | 1.27.3 |
|
||||
| `.gitea/scoped_workflows/sync-github-metadata.yml` runs in this repository | Verified: run 16, `workflow_dispatch`, succeeded |
|
||||
| The same workflow applies to other repositories automatically | Verified on 2026-10-10: it ran, with no copy in the repository, in repositories of `TirSystem`, `TirSystem-BashScript`, `vl-staal` and `Tirsvad-Udemy-100-days-of-code` (for example `TirSystem/sqa-qc-checklists` and `TirSystem-BashScript/RepoFoundry`). The script it ran changed when this repository's changed. |
|
||||
|
||||
Delivery is automatic, so a repository needs no copy of the workflow. Secrets are not shared between organisations: each organisation needs its own (step 3).
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Check the prerequisites** in the repository: Actions are enabled, and a
|
||||
runner with the label `ubuntu-latest` and `python3` is online (see
|
||||
[Runners](#runners)).
|
||||
2. **Configure one GitHub push mirror** in the repository settings
|
||||
(Settings, Repository, Mirror settings, Push mirror). The workflow fails
|
||||
when there are several GitHub mirrors. With none, it succeeds without
|
||||
syncing anything.
|
||||
3. **Add the two secrets** in the repository (or organization) settings,
|
||||
using the scopes in [credentials.md](credentials.md). The workflow runs in
|
||||
every repository of an organization, so store the secrets once per
|
||||
organization; a repository in another organization does not see them:
|
||||
- `TOKEN_FOR_GITEA`
|
||||
- `PAT_FOR_GITHUB` (the GitHub token only)
|
||||
4. **Deliver the workflow:** scoped workflows apply to every repository on
|
||||
this instance, so there is nothing to copy. Only where scoped delivery is
|
||||
not set up, copy `.gitea/scoped_workflows/sync-github-metadata.yml` from
|
||||
this repository to `.gitea/workflows/` in the target repository, pin the
|
||||
copy to a reviewed version and re-copy when it changes.
|
||||
5. **Set a description and topics** on the Gitea repository, so there is
|
||||
something to sync.
|
||||
6. **Run it once manually:** Actions, **Sync GitHub mirror metadata**,
|
||||
Run workflow. The log must end with `Synced description and topics to
|
||||
<owner>/<repo>.` and the GitHub repository must show the same description
|
||||
and topics.
|
||||
7. If it fails, use [troubleshooting.md](troubleshooting.md).
|
||||
|
||||
## Publish a wiki (optional)
|
||||
|
||||
The **Publish wiki** workflow copies the Markdown pages in `wiki/` to the
|
||||
repository wiki when a change to `wiki/` is merged to `main`. It is delivered
|
||||
like the sync workflow, but it writes only where a repository opts in.
|
||||
|
||||
1. Enable the wiki in the repository settings.
|
||||
2. Add Markdown pages to `wiki/`. The file name is the page name: `Home.md` is
|
||||
the home page.
|
||||
3. Add the marker `wiki/.publish`. Leave it empty to create and update pages
|
||||
only. Put the single word `prune` in it to also delete wiki pages that are
|
||||
not in `wiki/`, so the wiki always equals the folder.
|
||||
4. Store `TOKEN_FOR_GITEA_WIKI` as a secret of the repository's organization,
|
||||
using the scope in [credentials.md](credentials.md).
|
||||
5. Merge the change to `main`. The log must end with `Published <n> page(s) to
|
||||
the wiki of <owner>/<repo>`.
|
||||
|
||||
A repository without `wiki/.publish` is skipped with the line `No
|
||||
wiki/.publish marker in <owner>/<repo>`: nothing is written and no secret is
|
||||
needed.
|
||||
|
||||
## Runners
|
||||
|
||||
| Item | Value |
|
||||
| --- | --- |
|
||||
| Label the workflow uses | `ubuntu-latest` |
|
||||
| Labels offered by the runner on this instance | `ubuntu-latest`, `ubuntu-24.04`, `ubuntu-22.04` |
|
||||
| Tools the workflow needs | `python3` (standard library only), outbound HTTPS to the Gitea API and `api.github.com` |
|
||||
| Needed for `actions/checkout` (used by the validation workflow) | `git` and Node.js, normally in the runner image |
|
||||
|
||||
**Check that a suitable runner is online** (needs permission to view runners):
|
||||
|
||||
```bash
|
||||
curl -s -H "Authorization: token $GITEA_TOKEN" \
|
||||
https://git.tirsystem.com/api/v1/repos/<owner>/<repo>/actions/runners
|
||||
```
|
||||
|
||||
For runners shared by the whole instance, an administrator uses
|
||||
`/api/v1/admin/actions/runners`. At the time of writing the repository and
|
||||
organization lists are empty and one instance-level runner (`36cd20104923`)
|
||||
is `online`.
|
||||
|
||||
**Offline or incompatible runner**
|
||||
|
||||
| Symptom | Likely cause | Action |
|
||||
| --- | --- | --- |
|
||||
| Run stays `waiting` | No online runner has the label in `runs-on` | Start the runner, or register one with the label |
|
||||
| Job fails at the start with a missing command | Runner image lacks `python3`, `git` or Node.js | Use an image that has them |
|
||||
| Job cannot reach the API | Runner has no outbound HTTPS | Fix runner network or proxy settings |
|
||||
@@ -0,0 +1,105 @@
|
||||
# Reading quality-check results
|
||||
|
||||
How a software engineer calls the shared quality checks, reads a failed run and
|
||||
makes it pass. The workflow lints and format-checks the Python and shell files
|
||||
of a repository with pinned tools, changes no file and needs no secret. Its
|
||||
contract is ADR-0005 in this repository.
|
||||
|
||||
## Calling the workflow
|
||||
|
||||
```yaml
|
||||
name: Quality
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
quality:
|
||||
permissions:
|
||||
contents: read
|
||||
uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@main
|
||||
with:
|
||||
languages: python,shell
|
||||
```
|
||||
|
||||
| Input | Default | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `languages` | `python,shell` | Comma list of the languages to check |
|
||||
| `working-directory` | `.` | Directory, relative to the repository root, whose files are checked |
|
||||
| `ruff-version` | `0.6.9` | Version of ruff |
|
||||
| `mypy-version` | `1.11.2` | Version of mypy |
|
||||
| `shellcheck-py-version` | `0.10.0.1` | Version of the shellcheck-py package (ShellCheck 0.10.0) |
|
||||
| `shfmt-py-version` | `3.11.0.2` | Version of the shfmt-py package (shfmt 3.11.0) |
|
||||
|
||||
Reference the workflow at `main` or at a tag, never at the branch of a pull
|
||||
request: that branch is deleted when the pull request is merged and the
|
||||
reference stops working.
|
||||
|
||||
## What is checked
|
||||
|
||||
| Language | Files | Tools |
|
||||
| --- | --- | --- |
|
||||
| Python | tracked `*.py` under the working directory | `ruff check`, `ruff format --check`, `mypy --strict` |
|
||||
| Shell | tracked `*.sh` under the working directory | `shellcheck`, `shfmt -d` |
|
||||
|
||||
Untracked files are not checked. A language without files is skipped with a
|
||||
notice and counts as a pass. Project tests are not run.
|
||||
|
||||
## Reading a run
|
||||
|
||||
1. Open the status check on the pull request, then the job `quality-checks`.
|
||||
2. Each tool has its own log group named after it. Every tool runs even when an
|
||||
earlier one failed, so one run shows all findings.
|
||||
3. A tool ends with `PASS <tool>` or `FAIL <tool>`. The last line of a failed
|
||||
run names the tools that failed:
|
||||
`Quality checks failed: ruff check shellcheck`.
|
||||
4. A finding is written by the tool itself as `path:line:column: CODE message`.
|
||||
Paths are relative to `working-directory`.
|
||||
|
||||
## Typical failures and fixes
|
||||
|
||||
| Tool | What the log shows | Fix |
|
||||
| --- | --- | --- |
|
||||
| `ruff check` | `F401 ... imported but unused` | Remove the import, or use it |
|
||||
| `ruff format --check` | `Would reformat: <file>` | Run `ruff format <file>` and commit |
|
||||
| `mypy --strict` | `Function is missing a type annotation` | Add parameter and return types |
|
||||
| `shellcheck` | `SC2086 ... Double quote to prevent globbing` | Quote the expansion: `"$1"` |
|
||||
| `shfmt -d` | a diff of `<file>.orig` and `<file>` | Run `shfmt -w <file>` with the project's options and commit |
|
||||
|
||||
To reproduce a run on your machine, install the same versions and run the
|
||||
commands of the table:
|
||||
|
||||
```bash
|
||||
python3 -m venv .qc
|
||||
.qc/bin/pip install ruff==0.6.9 mypy==1.11.2 shellcheck-py==0.10.0.1 shfmt-py==3.11.0.2
|
||||
.qc/bin/ruff check . && .qc/bin/ruff format --check .
|
||||
```
|
||||
|
||||
## Configuring the tools
|
||||
|
||||
The workflow adds no configuration; it runs from the repository root, so the
|
||||
files of the project apply:
|
||||
|
||||
| Tool | File | Example |
|
||||
| --- | --- | --- |
|
||||
| ruff | `pyproject.toml` | `[tool.ruff]` with `line-length = 100` |
|
||||
| mypy | `pyproject.toml` | `[tool.mypy]` with per-module `ignore_missing_imports` |
|
||||
| shellcheck | `.shellcheckrc` | `external-sources=true` and `source-path=SCRIPTDIR` |
|
||||
| shfmt | `.editorconfig` | `[*.sh]` with `indent_size = 2` and `switch_case_indent = true` |
|
||||
|
||||
shfmt follows a project's style only through `.editorconfig`. A shell project
|
||||
that formats with its own flags (for example `shfmt -i 2 -ci`) should expect a
|
||||
first formatting failure and express the flags there; in the first adoption
|
||||
(RepoFoundry) one line, `switch_case_indent = true`, was enough and no script
|
||||
changed.
|
||||
|
||||
## When the workflow itself fails
|
||||
|
||||
| Message | Cause | Fix |
|
||||
| --- | --- | --- |
|
||||
| `[configuration] Unknown language '<x>'` | `languages` has a value other than `python` or `shell` | Correct the input |
|
||||
| `[configuration] working-directory must be a relative path inside the repository.` | An absolute path or `..` | Use a path inside the repository |
|
||||
| `[configuration] working-directory '<x>' does not exist.` | The directory is not in the repository | Correct the input |
|
||||
| The install step fails | PyPI or the runner network is unreachable | Re-run the job; see [troubleshooting.md](troubleshooting.md) |
|
||||
@@ -0,0 +1,79 @@
|
||||
# Release process
|
||||
|
||||
For the maintainers of this repository: how a change to the shared workflows
|
||||
is validated, versioned and announced, and how consumers pin a version. The
|
||||
decisions are in ADR-0006; this guide is the checklist. It is not published
|
||||
on the wiki.
|
||||
|
||||
Steps 5 and 6 are done by the **Release** workflow (`.gitea/workflows/release.yml`,
|
||||
`tools/release.py`); the manual commands below are the fallback.
|
||||
|
||||
## What a version is
|
||||
|
||||
| Item | Rule |
|
||||
| --- | --- |
|
||||
| Unit | The whole repository: the workflows, their scripts and the guides |
|
||||
| Version tag | `vMAJOR.MINOR.PATCH`, for example `v1.2.0`; never deleted or moved |
|
||||
| Major tag | `vMAJOR`, for example `v1`; points to the latest compatible release |
|
||||
| First release | `v1.0.0` |
|
||||
| Breaking (new major) | A renamed or removed workflow, input, secret name or output; a raised default tool version or a changed default that can turn a green consumer red; a changed meaning of pass or fail |
|
||||
| Minor | A new optional input, workflow or capability; nothing changes for existing callers |
|
||||
| Patch | A fix, or documentation and tests, with no visible change for consumers |
|
||||
|
||||
## Checklist for a release
|
||||
|
||||
1. **Decide the version** from the table above, looking at every merged change
|
||||
since the last tag.
|
||||
2. **Check the commit.** The validation run (`validate-workflows`) on the exact
|
||||
commit of `main` to be released is green; do not release from a red or
|
||||
unchecked commit.
|
||||
3. **Write the changelog entry** in `CHANGELOG.md`: move the items of
|
||||
`[Unreleased]` under `## [x.y.z] - date` in the groups Breaking, Added,
|
||||
Changed and Fixed. A change that touches credentials, tokens or permissions
|
||||
says so. Check it with
|
||||
`python tools/changelog.py check --version x.y.z`; a Breaking entry needs a
|
||||
new major version, and a new major version needs a Breaking entry.
|
||||
4. **Get the approval** of S01 for the release, in the pull request that adds
|
||||
the changelog entry.
|
||||
5. **Run the Release workflow in dry-run mode.** In the Actions tab of this
|
||||
repository start **Release** on `main` with the version and `dry_run`
|
||||
`true`. It checks that the commit is the tip of `main`, that its validation
|
||||
run is green, that the changelog has an entry for the version and that the
|
||||
tag does not exist, and writes nothing.
|
||||
6. **Release.** Start **Release** again with `dry_run` `false`. It creates the
|
||||
tag `vMAJOR.MINOR.PATCH`, the release page with the text of
|
||||
`python tools/changelog.py notes x.y.z`, and moves `vMAJOR` to the commit
|
||||
when this is the highest version of its major. The page on Gitea is the
|
||||
only destination (ADR-0007); nothing is attached to it. The workflow uses
|
||||
the token of its own run; if Gitea refuses it, store `TOKEN_FOR_GITEA_RELEASE`
|
||||
as a secret with write access to this repository only.
|
||||
|
||||
By hand, the same steps are:
|
||||
```bash
|
||||
git tag -a v1.2.0 -m "v1.2.0" <commit>
|
||||
git push origin v1.2.0
|
||||
git tag -f v1 <commit> && git push -f origin v1
|
||||
```
|
||||
and create the release page with the notes of the changelog entry.
|
||||
7. **Verify.** One repository pinned to the previous exact tag still runs the
|
||||
same code; one repository on the major tag receives the release.
|
||||
|
||||
## How consumers pin
|
||||
|
||||
| Pin | Receives | Use when |
|
||||
| --- | --- | --- |
|
||||
| `@v1.2.0` | nothing new, ever | a pipeline must not change |
|
||||
| `@v1` | compatible releases only | the default for a project |
|
||||
| `@main` | everything, unreleased | never; only this repository's own tests |
|
||||
|
||||
Reusable workflows are pinned in the `uses:` line of the caller. The scoped
|
||||
workflows (sync and publish wiki) are delivered from `main` by the instance
|
||||
and cannot be pinned by a consumer; they fetch their scripts at the major tag
|
||||
once `v1` exists.
|
||||
|
||||
## Undoing a faulty release
|
||||
|
||||
1. Move the major tag back to the previous exact tag:
|
||||
`git tag -f v1 v1.1.0 && git push -f origin v1`.
|
||||
2. Fix forward on `main` and release a patch version.
|
||||
3. Do not delete or move an exact tag; consumers may have pinned it.
|
||||
@@ -0,0 +1,73 @@
|
||||
# Diagnosing a failed run
|
||||
|
||||
Open the run in Gitea (Actions) and read the last lines of the failing step.
|
||||
Every failure from the sync script is written as
|
||||
|
||||
```
|
||||
ERROR: [<category>] <message>
|
||||
```
|
||||
|
||||
The category tells you where to look. A failure outside the script (the job
|
||||
never starts, or stops before the step) is a **runner** problem.
|
||||
|
||||
| Category | Meaning | First thing to check |
|
||||
| --- | --- | --- |
|
||||
| `configuration` | A secret or a repository setting is missing or malformed | Secret names and format, push mirror setup |
|
||||
| `credentials` | A service rejected the token (HTTP 401) | Token expired, revoked or mistyped |
|
||||
| `permissions` | The token is valid but not allowed (HTTP 403, or no GitHub administration access) | Token scopes and repository access |
|
||||
| `api` | Another HTTP error, or the service was unreachable | Service status, runner network |
|
||||
| runner | No `ERROR:` line; the run waits, or the job fails before the script | Runner online, label, tools |
|
||||
|
||||
## Messages and fixes
|
||||
|
||||
| Message (start) | Category | Cause and fix |
|
||||
| --- | --- | --- |
|
||||
| `PAT_FOR_GITHUB is missing or empty.` | configuration | Add the secret |
|
||||
| `TOKEN_FOR_GITEA is missing or empty.` | configuration | Add the secret |
|
||||
| `Could not determine the Gitea source repository.` | configuration | The run has no repository name; report as a defect |
|
||||
| `Expected at most one GitHub push mirror ... found N` | configuration | Keep one GitHub push mirror |
|
||||
| `TOKEN_FOR_GITEA_WIKI is missing or empty.` | configuration | Wiki publishing only: the repository opted in with `wiki/.publish` but its organization has no such secret; store it (see [credentials.md](credentials.md)) |
|
||||
| `wiki/.publish may only be empty or contain the word 'prune'.` | configuration | Wiki publishing only: leave the marker empty, or put only the word `prune` in it |
|
||||
| `... HTTP 403 ...` while publishing the wiki | permissions | Wiki publishing only: the token needs `write:repository` and write access to this repository |
|
||||
| `The wiki is not enabled on <repo>` | configuration | Wiki publishing only: enable the wiki in the repository settings |
|
||||
| `The wiki source directory ... has no Markdown pages` | configuration | Wiki publishing only: `wiki/` is empty or missing; nothing was changed |
|
||||
| `Could not determine the GitHub owner and repository ...` | configuration | The mirror address must look like `https://github.com/<owner>/<repo>.git` |
|
||||
| `Gitea API request failed with HTTP 401` | credentials | Create a new Gitea token and update `TOKEN_FOR_GITEA` |
|
||||
| `GitHub API request failed with HTTP 401` | credentials | Create a new GitHub token and update `PAT_FOR_GITHUB`; the value must be the token only (no name, quotes or JSON) |
|
||||
| `... HTTP 403 ...` (Gitea) | permissions | Token needs `read:repository`, and its user needs administrator access to the repository |
|
||||
| `... HTTP 403 ...` (GitHub) | permissions | Token needs Administration read and write on the mirror repository |
|
||||
| `The GitHub token cannot administer <repo>` | permissions | Same as above; the token can read the repository but not edit it |
|
||||
| `... HTTP 404 ...` | configuration | Repository not found, or the token cannot see it; check the mirror address and token repository access |
|
||||
| `... HTTP 5xx ...` | api | Service problem; re-run later |
|
||||
| `... API is unreachable ...` | api | Network, DNS or proxy problem on the runner |
|
||||
|
||||
## Not an error
|
||||
|
||||
`No GitHub push mirror configured for <repo>; nothing to sync.` The run
|
||||
succeeds. Not every Gitea repository has a GitHub mirror, so this is expected
|
||||
for those. If the repository should have one, add it in the repository
|
||||
settings.
|
||||
|
||||
`WARNING: Gitea returned an invalid push mirror list; GitHub metadata was not
|
||||
synced.` The run succeeds but nothing was synced. Check that the Gitea
|
||||
version supports the push mirror API and re-run.
|
||||
|
||||
`No wiki/.publish marker in <owner>/<repo>; wiki publishing is not enabled for
|
||||
this repository.` The Publish wiki run succeeds and writes nothing. The
|
||||
repository has not opted in; add `wiki/.publish` if it should publish.
|
||||
|
||||
`<n> page(s) are in the wiki but not in wiki/ and were kept; put the word
|
||||
'prune' in wiki/.publish to delete them.` The run succeeds. Pages that exist
|
||||
only in the wiki are left alone unless the marker contains `prune`.
|
||||
|
||||
## Runner problems
|
||||
|
||||
See the [Runners](onboarding.md#runners) section. In short: if the run stays
|
||||
`waiting`, no online runner has the label; if the job fails before the
|
||||
script, the runner image is missing a tool.
|
||||
|
||||
## Re-running
|
||||
|
||||
Use **Run workflow** (`workflow_dispatch`) after fixing the cause. The sync is
|
||||
safe to repeat: it overwrites the GitHub description and topics with the
|
||||
Gitea values.
|
||||
@@ -0,0 +1,66 @@
|
||||
# Upgrading to a new version of the shared workflows
|
||||
|
||||
How a software engineer adopts a new release of the shared workflows safely:
|
||||
read the changelog, try the update in one place, and go back if it fails. The
|
||||
version rules are those of the release process: one version for the whole
|
||||
repository, tags `vMAJOR.MINOR.PATCH` and a moving major tag `vMAJOR`.
|
||||
|
||||
## Which version you follow
|
||||
|
||||
| In your `uses:` line | You receive | When to use it |
|
||||
| --- | --- | --- |
|
||||
| `@v1.2.0` | nothing new, ever | a pipeline that must not change |
|
||||
| `@v1` | compatible releases only (minor and patch) | the default for a project |
|
||||
| `@main` | everything, unreleased | never; only for this repository's own tests |
|
||||
|
||||
A breaking release gets a new major version (`v2`), so a pipeline on `@v1`
|
||||
never receives it until you change the line yourself.
|
||||
|
||||
The two scoped workflows (**Sync GitHub mirror metadata** and **Publish
|
||||
wiki**) are delivered by the instance and are not in your `uses:` lines; you
|
||||
cannot pin them, but they fetch their scripts at the major tag.
|
||||
|
||||
## Reading a changelog entry
|
||||
|
||||
Open `CHANGELOG.md` of `TirSystem/github-action`, or the release page of the tag.
|
||||
An entry has up to four groups:
|
||||
|
||||
| Group | What it means for you |
|
||||
| --- | --- |
|
||||
| Breaking | You must act: a name, an input, a secret or a default changed. A release with this group has a new major version |
|
||||
| Added | Nothing to do; a new optional input, workflow or capability |
|
||||
| Changed | Nothing to do; no visible effect for existing callers |
|
||||
| Fixed | Nothing to do; a fix you receive on `@v1` |
|
||||
|
||||
An entry that changes credentials, tokens or permissions says so; check your
|
||||
secrets before you upgrade.
|
||||
|
||||
## Trying an update
|
||||
|
||||
1. Change the version in **one** repository, on a branch:
|
||||
```yaml
|
||||
jobs:
|
||||
quality:
|
||||
uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@v2
|
||||
```
|
||||
2. Open a pull request and read the run. A failing check shows the tool, the
|
||||
file and the message (see the guide for reading quality-check results).
|
||||
3. For a breaking release, follow the upgrade notes of the changelog entry,
|
||||
then repeat.
|
||||
4. When the pull request is green, make the same change in the other
|
||||
repositories.
|
||||
|
||||
## Going back
|
||||
|
||||
1. Change the line back to the previous exact tag, for example `@v1.2.0`, and
|
||||
merge it. Exact tags are never deleted or moved, so this always works.
|
||||
2. Tell the maintainers which release failed and what you saw, so that the
|
||||
major tag can be moved back and a fix released.
|
||||
|
||||
## When something is unclear
|
||||
|
||||
| Symptom | Likely cause | Fix |
|
||||
| --- | --- | --- |
|
||||
| The run says the workflow cannot be found | The tag does not exist, or the path is wrong | Check the tag on the release page and the path `.gitea/workflows/quality-checks.yml` |
|
||||
| A green pipeline turned red after a release on `@v1` | A compatible release should not do this | Pin the previous exact tag and report it as a defect |
|
||||
| An input is no longer accepted | A breaking release renamed it | Read the Breaking group of the entry |
|
||||
@@ -0,0 +1,2 @@
|
||||
pytest>=8,<10
|
||||
PyYAML>=6,<7
|
||||
@@ -0,0 +1,269 @@
|
||||
"""Offline tests for tools/build_wiki.py."""
|
||||
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||
_SPEC = importlib.util.spec_from_file_location(
|
||||
"build_wiki", REPO_ROOT / "tools" / "build_wiki.py"
|
||||
)
|
||||
assert _SPEC is not None and _SPEC.loader is not None
|
||||
build_wiki = importlib.util.module_from_spec(_SPEC)
|
||||
_SPEC.loader.exec_module(build_wiki)
|
||||
|
||||
BASE = build_wiki.SOURCE_BASE_URL
|
||||
|
||||
|
||||
class TestStripHeadingSymbols:
|
||||
@pytest.mark.parametrize(
|
||||
("line", "expected"),
|
||||
[
|
||||
("## 🧭 Overview", "## Overview"),
|
||||
("## 🛠️ Setup", "## Setup"),
|
||||
("## ▶️ Run", "## Run"),
|
||||
("#### 🕒 Cron", "#### Cron"),
|
||||
("## Plain", "## Plain"),
|
||||
("## `code` heading", "## `code` heading"),
|
||||
],
|
||||
)
|
||||
def test_removes_leading_emoji_only(self, line, expected):
|
||||
assert build_wiki.strip_heading_symbols(line) == expected
|
||||
|
||||
|
||||
class TestRewriteLink:
|
||||
@pytest.mark.parametrize(
|
||||
("target", "source", "expected"),
|
||||
[
|
||||
("guides/credentials.md", "README.md", "Credentials"),
|
||||
("guides/onboarding.md#runners", "README.md", "Onboarding#runners"),
|
||||
("troubleshooting.md", "guides/credentials.md", "Troubleshooting"),
|
||||
("onboarding.md#runners", "guides/troubleshooting.md", "Onboarding#runners"),
|
||||
("#-requirements", "README.md", "#requirements"),
|
||||
("#runners", "guides/onboarding.md", "#runners"),
|
||||
("https://example.test/a", "README.md", "https://example.test/a"),
|
||||
("mailto:a@example.test", "README.md", "mailto:a@example.test"),
|
||||
("docs/project-plan.md", "README.md", f"{BASE}/docs/project-plan.md"),
|
||||
("../docs/project-plan.md", "guides/onboarding.md", f"{BASE}/docs/project-plan.md"),
|
||||
(
|
||||
".gitea/scoped_workflows/sync-github-metadata.yml",
|
||||
"README.md",
|
||||
f"{BASE}/.gitea/scoped_workflows/sync-github-metadata.yml",
|
||||
),
|
||||
("../README.md", "guides/onboarding.md", "Home"),
|
||||
],
|
||||
)
|
||||
def test_rewrites_by_target_kind(self, target, source, expected):
|
||||
assert build_wiki.rewrite_link(target, source) == expected
|
||||
|
||||
|
||||
class TestConvertMarkdown:
|
||||
def test_leaves_fenced_code_untouched(self):
|
||||
text = "## 🧭 Title\n```bash\n## 🧭 not a heading\n[x](guides/a.md)\n```\n"
|
||||
converted = build_wiki.convert_markdown(text, "README.md")
|
||||
assert converted.splitlines()[0] == "## Title"
|
||||
assert "## 🧭 not a heading" in converted
|
||||
assert "[x](guides/a.md)" in converted
|
||||
|
||||
def test_rewrites_links_outside_code(self):
|
||||
text = "See [guide](guides/credentials.md) and [plan](docs/project-plan.md)."
|
||||
converted = build_wiki.convert_markdown(text, "README.md")
|
||||
assert f"[guide](Credentials) and [plan]({BASE}/docs/project-plan.md)" in converted
|
||||
|
||||
|
||||
class TestSplitH2Sections:
|
||||
def test_keeps_subsections_and_ignores_h2_in_code(self):
|
||||
text = (
|
||||
"# Title\nintro\n"
|
||||
"## 🧭 One\na\n### Sub\nb\n"
|
||||
"## Two\n```\n## not a section\n```\n"
|
||||
)
|
||||
preamble, sections = build_wiki.split_h2_sections(text)
|
||||
assert preamble == ["# Title", "intro"]
|
||||
assert list(sections) == ["One", "Two"]
|
||||
assert "### Sub" in sections["One"]
|
||||
assert "## not a section" in sections["Two"]
|
||||
|
||||
|
||||
def _write_sources(root: Path) -> None:
|
||||
(root / "guides").mkdir()
|
||||
(root / "README.md").write_text(
|
||||
"# 🚀 Name\nIntro.\n\n## 📚 Table of Contents\n- [x](#-overview)\n\n"
|
||||
"## 🧭 Overview\nSee [credentials](guides/credentials.md).\n\n"
|
||||
"## 📋 Requirements\nNeeds a runner.\n\n## 🛠️ Setup\nRun [it](#-requirements).\n\n"
|
||||
"## ▶️ Run\nGo.\n\n## 🧪 Tests\nPytest.\n\n## 🟢 Capabilities\nA table.\n\n"
|
||||
"### 🔄 Sync\nDetails.\n\n## 📄 License\nMIT.\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
for name in ("onboarding", "credentials", "troubleshooting", "quality-checks", "upgrading"):
|
||||
(root / "guides" / f"{name}.md").write_text(
|
||||
f"# {name.title()}\nBody.\n", encoding="utf-8"
|
||||
)
|
||||
|
||||
|
||||
class TestRenderPage:
|
||||
@pytest.fixture()
|
||||
def repo(self, tmp_path):
|
||||
_write_sources(tmp_path)
|
||||
return tmp_path
|
||||
|
||||
def test_home_keeps_overview_to_tests_and_drops_the_rest(self, repo):
|
||||
home = build_wiki.render_page(build_wiki.PAGES[0], repo)
|
||||
assert "# Name" in home
|
||||
assert "## Overview" in home
|
||||
assert "[credentials](Credentials)" in home
|
||||
assert "Run [it](#requirements)." in home
|
||||
assert "Table of Contents" not in home
|
||||
assert "Capabilities" not in home
|
||||
assert "License" not in home
|
||||
|
||||
def test_capabilities_page_keeps_its_subsections(self, repo):
|
||||
page = next(p for p in build_wiki.PAGES if p.name == "Capabilities")
|
||||
text = build_wiki.render_page(page, repo)
|
||||
assert "## Capabilities" in text
|
||||
assert "### Sync" in text
|
||||
assert "## Overview" not in text
|
||||
|
||||
def test_every_page_names_its_source_and_warns(self, repo):
|
||||
for page in build_wiki.PAGES:
|
||||
text = build_wiki.render_page(page, repo)
|
||||
assert f"Generated from {page.source}" in text
|
||||
assert "overwritten" in text
|
||||
|
||||
def test_missing_section_is_an_error(self, repo):
|
||||
(repo / "README.md").write_text("# Name\n", encoding="utf-8")
|
||||
with pytest.raises(build_wiki.WikiBuildError, match="section 'Overview'"):
|
||||
build_wiki.render_page(build_wiki.PAGES[0], repo)
|
||||
|
||||
def test_missing_source_is_an_error(self, repo):
|
||||
(repo / "guides" / "onboarding.md").unlink()
|
||||
page = next(p for p in build_wiki.PAGES if p.name == "Onboarding")
|
||||
with pytest.raises(build_wiki.WikiBuildError, match="is missing"):
|
||||
build_wiki.render_page(page, repo)
|
||||
|
||||
|
||||
class TestWriteAndCheck:
|
||||
@pytest.fixture()
|
||||
def repo(self, tmp_path):
|
||||
root = tmp_path / "repo"
|
||||
root.mkdir()
|
||||
_write_sources(root)
|
||||
return root
|
||||
|
||||
def test_write_then_check_passes(self, repo, tmp_path):
|
||||
wiki = tmp_path / "wiki"
|
||||
changed = build_wiki.write_pages(wiki, repo)
|
||||
assert sorted(changed) == sorted(f"{p.name}.md" for p in build_wiki.PAGES)
|
||||
assert build_wiki.check_pages(wiki, repo) == []
|
||||
assert build_wiki.write_pages(wiki, repo) == []
|
||||
|
||||
def test_check_reports_missing_and_changed_pages(self, repo, tmp_path):
|
||||
wiki = tmp_path / "wiki"
|
||||
build_wiki.write_pages(wiki, repo)
|
||||
(wiki / "Home.md").write_text("edited by hand\n", encoding="utf-8")
|
||||
(wiki / "Credentials.md").unlink()
|
||||
problems = build_wiki.check_pages(wiki, repo)
|
||||
assert "Home.md: differs from its source" in problems
|
||||
assert "Credentials.md: missing" in problems
|
||||
|
||||
def test_check_detects_a_changed_source(self, repo, tmp_path):
|
||||
wiki = tmp_path / "wiki"
|
||||
build_wiki.write_pages(wiki, repo)
|
||||
(repo / "guides" / "onboarding.md").write_text("# Changed\n", encoding="utf-8")
|
||||
assert build_wiki.check_pages(wiki, repo) == [
|
||||
"Onboarding.md: differs from its source"
|
||||
]
|
||||
|
||||
|
||||
def test_committed_wiki_pages_are_current():
|
||||
"""The pages in wiki/ match what README.md and guides/ produce."""
|
||||
assert build_wiki.check_pages() == []
|
||||
|
||||
|
||||
class TestLanguageSwitcher:
|
||||
def test_english_page_links_to_the_translations(self):
|
||||
assert build_wiki.language_switcher("Home") == (
|
||||
"English | [Dansk](Home.da) | [Bahasa Melayu](Home.ms)"
|
||||
)
|
||||
|
||||
def test_translation_does_not_link_to_itself(self):
|
||||
assert build_wiki.language_switcher("Home", "da") == (
|
||||
"[English](Home) | Dansk | [Bahasa Melayu](Home.ms)"
|
||||
)
|
||||
|
||||
|
||||
class TestCheckTranslations:
|
||||
@pytest.fixture()
|
||||
def repo(self, tmp_path):
|
||||
root = tmp_path / "repo"
|
||||
root.mkdir()
|
||||
_write_sources(root)
|
||||
return root
|
||||
|
||||
@staticmethod
|
||||
def write_translations(wiki, repo, only_hash=None):
|
||||
english = build_wiki.build_all(repo)
|
||||
wiki.mkdir(exist_ok=True)
|
||||
for page in build_wiki.PAGES:
|
||||
digest = only_hash or build_wiki.source_hash(
|
||||
english[f"{page.name}.md"].encode("utf-8")
|
||||
)
|
||||
for code, _label in build_wiki.LANGUAGES:
|
||||
(wiki / f"{page.name}.{code}.md").write_text(
|
||||
f"<!-- translation of {page.name}.md, source sha256 {digest} -->\n\nText\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
def test_current_translations_pass(self, repo, tmp_path):
|
||||
wiki = tmp_path / "wiki"
|
||||
self.write_translations(wiki, repo)
|
||||
assert build_wiki.check_translations(wiki, repo) == []
|
||||
|
||||
def test_reports_missing_translations(self, repo, tmp_path):
|
||||
wiki = tmp_path / "wiki"
|
||||
self.write_translations(wiki, repo)
|
||||
(wiki / "Home.ms.md").unlink()
|
||||
assert build_wiki.check_translations(wiki, repo) == ["Home.ms.md: missing"]
|
||||
|
||||
def test_reports_a_stale_translation(self, repo, tmp_path):
|
||||
wiki = tmp_path / "wiki"
|
||||
self.write_translations(wiki, repo)
|
||||
(repo / "guides" / "onboarding.md").write_text("# Changed\n", encoding="utf-8")
|
||||
problems = build_wiki.check_translations(wiki, repo)
|
||||
assert [p.split(":")[0] for p in problems] == ["Onboarding.da.md", "Onboarding.ms.md"]
|
||||
assert all("stale" in problem for problem in problems)
|
||||
|
||||
def test_reports_a_missing_or_wrong_header(self, repo, tmp_path):
|
||||
wiki = tmp_path / "wiki"
|
||||
self.write_translations(wiki, repo)
|
||||
(wiki / "Home.da.md").write_text("no header\n", encoding="utf-8")
|
||||
assert build_wiki.check_translations(wiki, repo) == [
|
||||
"Home.da.md: first line is not the translation header"
|
||||
]
|
||||
|
||||
|
||||
def _shape(text: str) -> dict:
|
||||
lines = text.splitlines()
|
||||
return {
|
||||
"fences": sum(line.startswith("```") for line in lines),
|
||||
"table_rows": sum(line.startswith("|") for line in lines),
|
||||
"heading_levels": [
|
||||
len(line) - len(line.lstrip("#")) for line in lines if line.startswith("#")
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("page", [page.name for page in build_wiki.PAGES])
|
||||
@pytest.mark.parametrize("code", [code for code, _label in build_wiki.LANGUAGES])
|
||||
def test_committed_translations_follow_the_english_structure(page, code):
|
||||
"""A translation has the same code blocks, table rows and heading levels."""
|
||||
wiki = REPO_ROOT / "wiki"
|
||||
english = _shape((wiki / f"{page}.md").read_text(encoding="utf-8"))
|
||||
translated = _shape((wiki / f"{page}.{code}.md").read_text(encoding="utf-8"))
|
||||
assert translated == english
|
||||
|
||||
|
||||
def test_committed_translations_are_current():
|
||||
"""No translation follows an older version of its English page."""
|
||||
assert build_wiki.check_translations() == []
|
||||
@@ -0,0 +1,140 @@
|
||||
"""Offline tests for tools/changelog.py and the CHANGELOG.md of this repository."""
|
||||
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||
_SPEC = importlib.util.spec_from_file_location("changelog", REPO_ROOT / "tools" / "changelog.py")
|
||||
assert _SPEC is not None and _SPEC.loader is not None
|
||||
changelog = importlib.util.module_from_spec(_SPEC)
|
||||
_SPEC.loader.exec_module(changelog)
|
||||
|
||||
GOOD = """# Changelog
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- A new optional input.
|
||||
|
||||
## [2.0.0] - 2026-12-01
|
||||
|
||||
### Breaking
|
||||
|
||||
- The input `languages` was renamed.
|
||||
|
||||
### Fixed
|
||||
|
||||
- A message.
|
||||
|
||||
## [1.1.0] - 2026-11-01
|
||||
|
||||
### Added
|
||||
|
||||
- A workflow.
|
||||
|
||||
## [1.0.0] - 2026-10-20
|
||||
|
||||
### Added
|
||||
|
||||
- The first release.
|
||||
"""
|
||||
|
||||
|
||||
class TestParse:
|
||||
def test_reads_releases_groups_and_items(self):
|
||||
releases = changelog.parse(GOOD)
|
||||
assert [r.name for r in releases] == ["Unreleased", "2.0.0", "1.1.0", "1.0.0"]
|
||||
assert releases[1].version == (2, 0, 0)
|
||||
assert releases[1].date == "2026-12-01"
|
||||
assert releases[1].groups["Breaking"] == ["The input `languages` was renamed."]
|
||||
assert releases[0].is_unreleased and releases[0].version is None
|
||||
|
||||
|
||||
class TestValidate:
|
||||
def test_a_correct_changelog_has_no_problem(self):
|
||||
assert changelog.validate(GOOD) == []
|
||||
|
||||
def test_requires_unreleased_first(self):
|
||||
text = GOOD.replace("## [Unreleased]\n\n### Added\n\n- A new optional input.\n\n", "")
|
||||
assert any("first section must be `## [Unreleased]`" in p for p in changelog.validate(text))
|
||||
|
||||
def test_rejects_an_unknown_group(self):
|
||||
text = GOOD.replace("### Fixed", "### Misc")
|
||||
assert any("group 'Misc'" in p for p in changelog.validate(text))
|
||||
|
||||
def test_rejects_an_empty_group(self):
|
||||
text = GOOD.replace("- A message.\n", "")
|
||||
assert any("has no item" in p for p in changelog.validate(text))
|
||||
|
||||
def test_rejects_a_release_without_a_date(self):
|
||||
text = GOOD.replace("## [1.1.0] - 2026-11-01", "## [1.1.0]")
|
||||
assert any("needs a date" in p for p in changelog.validate(text))
|
||||
|
||||
def test_rejects_a_name_that_is_not_a_version(self):
|
||||
text = GOOD.replace("## [1.1.0] - 2026-11-01", "## [v1.1] - 2026-11-01")
|
||||
assert any("not a version" in p for p in changelog.validate(text))
|
||||
|
||||
def test_versions_must_descend(self):
|
||||
text = GOOD.replace("## [1.1.0]", "## [2.0.0]")
|
||||
assert any("must be lower than the version above" in p for p in changelog.validate(text))
|
||||
|
||||
def test_breaking_needs_a_new_major(self):
|
||||
text = GOOD.replace("## [1.1.0] - 2026-11-01\n\n### Added\n\n- A workflow.",
|
||||
"## [1.1.0] - 2026-11-01\n\n### Breaking\n\n- A rename.")
|
||||
assert any("lists Breaking changes but the major version does not increase" in p
|
||||
for p in changelog.validate(text))
|
||||
|
||||
def test_a_new_major_needs_a_breaking_change(self):
|
||||
text = GOOD.replace("### Breaking\n\n- The input `languages` was renamed.\n\n### Fixed",
|
||||
"### Fixed")
|
||||
assert any("raises the major version but lists no Breaking change" in p
|
||||
for p in changelog.validate(text))
|
||||
|
||||
def test_an_empty_file_is_a_problem(self):
|
||||
assert changelog.validate("# Changelog\n")
|
||||
|
||||
|
||||
class TestNotes:
|
||||
def test_prints_the_groups_in_the_fixed_order(self):
|
||||
text = changelog.notes(GOOD, "2.0.0")
|
||||
assert text.startswith("## 2.0.0 - 2026-12-01")
|
||||
assert text.index("### Breaking") < text.index("### Fixed")
|
||||
assert "The input `languages` was renamed." in text
|
||||
|
||||
def test_an_unknown_version_is_an_error(self):
|
||||
with pytest.raises(LookupError):
|
||||
changelog.notes(GOOD, "3.0.0")
|
||||
|
||||
|
||||
class TestCommandLine:
|
||||
def test_check_passes_for_a_good_file(self, tmp_path, capsys):
|
||||
path = tmp_path / "CHANGELOG.md"
|
||||
path.write_text(GOOD, encoding="utf-8")
|
||||
assert changelog.main(["check", "--file", str(path)]) == 0
|
||||
|
||||
def test_check_version_fails_without_an_entry(self, tmp_path, capsys):
|
||||
path = tmp_path / "CHANGELOG.md"
|
||||
path.write_text(GOOD, encoding="utf-8")
|
||||
assert changelog.main(["check", "--file", str(path), "--version", "3.0.0"]) == 1
|
||||
assert "no changelog entry" in capsys.readouterr().err
|
||||
|
||||
def test_notes_prints_the_entry(self, tmp_path, capsys):
|
||||
path = tmp_path / "CHANGELOG.md"
|
||||
path.write_text(GOOD, encoding="utf-8")
|
||||
assert changelog.main(["notes", "1.1.0", "--file", str(path)]) == 0
|
||||
assert "A workflow." in capsys.readouterr().out
|
||||
|
||||
|
||||
def test_the_changelog_of_this_repository_follows_the_convention():
|
||||
text = (REPO_ROOT / "CHANGELOG.md").read_text(encoding="utf-8")
|
||||
assert changelog.validate(text) == []
|
||||
assert changelog.parse(text)[0].is_unreleased
|
||||
|
||||
|
||||
def test_wrapped_item_is_one_item_in_the_notes():
|
||||
text = "## [Unreleased]\n\n## [1.0.0] - 2026-10-10\n\n### Added\n\n- A long item that\n continues here.\n- Next.\n"
|
||||
assert changelog.parse(text)[1].groups["Added"] == ["A long item that continues here.", "Next."]
|
||||
assert "- A long item that continues here.\n" in changelog.notes(text, "1.0.0")
|
||||
@@ -0,0 +1,481 @@
|
||||
"""Offline tests for tools/publish_wiki.py and the scoped publish-wiki workflow."""
|
||||
|
||||
import base64
|
||||
import io
|
||||
import urllib.error
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
|
||||
from workflow_source import PUBLISH_WORKFLOW, REPO_ROOT, load_publish_module
|
||||
|
||||
API = "https://git.example.test/api/v1"
|
||||
REPO_URL = f"{API}/repos/TirSystem/repo"
|
||||
WIKI_URL = f"{REPO_URL}/wiki"
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def publish_wiki():
|
||||
return load_publish_module()
|
||||
|
||||
|
||||
def b64(text: str) -> str:
|
||||
return base64.b64encode(text.encode()).decode()
|
||||
|
||||
|
||||
class TestParseMarker:
|
||||
@pytest.mark.parametrize(
|
||||
("text", "expected"),
|
||||
[("", False), (" \n", False), (None, False), ("prune", True), (" prune\n", True)],
|
||||
)
|
||||
def test_reads_the_empty_marker_and_the_prune_word(self, publish_wiki, text, expected):
|
||||
assert publish_wiki.parse_marker(text) is expected
|
||||
|
||||
@pytest.mark.parametrize("text", ["Prune", "prune: true", "delete", "prune\nmore"])
|
||||
def test_rejects_anything_else(self, publish_wiki, text):
|
||||
with pytest.raises(publish_wiki.WorkflowError) as caught:
|
||||
publish_wiki.parse_marker(text)
|
||||
assert caught.value.category == "configuration"
|
||||
assert "prune" in str(caught.value)
|
||||
|
||||
|
||||
class TestParseGiteaToken:
|
||||
def test_returns_the_stripped_token(self, publish_wiki):
|
||||
assert publish_wiki.parse_gitea_token(" abc \n") == "abc"
|
||||
|
||||
@pytest.mark.parametrize("raw", [None, "", " "])
|
||||
def test_rejects_missing_or_empty_token(self, publish_wiki, raw):
|
||||
with pytest.raises(publish_wiki.WorkflowError) as caught:
|
||||
publish_wiki.parse_gitea_token(raw)
|
||||
assert caught.value.category == "configuration"
|
||||
assert "TOKEN_FOR_GITEA_WIKI is missing or empty" in str(caught.value)
|
||||
|
||||
|
||||
class TestReadPages:
|
||||
def test_reads_markdown_files_by_stem_and_ignores_the_marker(self, publish_wiki, tmp_path):
|
||||
(tmp_path / "Home.md").write_bytes(b"home")
|
||||
(tmp_path / "Home.da.md").write_bytes(b"hjem")
|
||||
(tmp_path / ".publish").write_bytes(b"prune")
|
||||
(tmp_path / "Notes.txt").write_bytes(b"ignored")
|
||||
assert publish_wiki.read_pages(tmp_path) == {"Home": b"home", "Home.da": b"hjem"}
|
||||
|
||||
def test_rejects_a_directory_without_pages_so_the_wiki_is_never_wiped(
|
||||
self, publish_wiki, tmp_path
|
||||
):
|
||||
(tmp_path / ".publish").write_text("prune", encoding="utf-8")
|
||||
with pytest.raises(publish_wiki.WorkflowError, match="no Markdown pages"):
|
||||
publish_wiki.read_pages(tmp_path)
|
||||
|
||||
|
||||
class TestPageKey:
|
||||
@pytest.mark.parametrize(
|
||||
("name", "key"),
|
||||
[("Home", "Home"), ("Home da", "Home-da"), ("Home-da", "Home-da"), ("Home.da", "Home.da"),
|
||||
("AI Prompt Template ms", "AI-Prompt-Template-ms"), ("_Sidebar", "_Sidebar")],
|
||||
)
|
||||
def test_a_space_and_a_hyphen_are_the_same_page(self, publish_wiki, name, key):
|
||||
assert publish_wiki.page_key(name) == key
|
||||
|
||||
def test_file_names_with_spaces_and_hyphens_are_keyed_the_same(self, publish_wiki, tmp_path):
|
||||
(tmp_path / "Home da.md").write_bytes(b"hjem")
|
||||
(tmp_path / "_Sidebar.md").write_bytes(b"menu")
|
||||
assert publish_wiki.read_pages(tmp_path) == {"Home-da": b"hjem", "_Sidebar": b"menu"}
|
||||
|
||||
def test_two_files_for_one_page_are_refused(self, publish_wiki, tmp_path):
|
||||
(tmp_path / "Home da.md").write_bytes(b"one")
|
||||
(tmp_path / "Home-da.md").write_bytes(b"two")
|
||||
with pytest.raises(publish_wiki.WorkflowError, match="name the wiki page Home-da"):
|
||||
publish_wiki.read_pages(tmp_path)
|
||||
|
||||
|
||||
class FakeGitea:
|
||||
"""Answers like the Gitea repository and wiki endpoints."""
|
||||
|
||||
def __init__(self, publish_wiki, wiki=None, has_wiki=True, wiki_initialised=True):
|
||||
self.error = publish_wiki.WorkflowError
|
||||
self.wiki = dict(wiki or {})
|
||||
self.has_wiki = has_wiki
|
||||
self.wiki_initialised = wiki_initialised
|
||||
self.calls = []
|
||||
|
||||
def __call__(self, url, method="GET", headers=None, body=None):
|
||||
self.calls.append((method, url, body, headers))
|
||||
if url == REPO_URL:
|
||||
return {"has_wiki": self.has_wiki}
|
||||
if url.startswith(f"{WIKI_URL}/pages"):
|
||||
if not self.wiki_initialised:
|
||||
raise self.error("configuration", "404")
|
||||
return [{"title": key.replace("-", " "), "sub_url": key} for key in self.wiki]
|
||||
if method == "POST" and url == f"{WIKI_URL}/new":
|
||||
self.wiki[body["title"]] = body["content_base64"]
|
||||
return None
|
||||
title = url.rsplit("/", 1)[-1]
|
||||
if method == "GET":
|
||||
return {"title": title, "content_base64": self.wiki[title]}
|
||||
if method == "PATCH":
|
||||
self.wiki[title] = body["content_base64"]
|
||||
return None
|
||||
if method == "DELETE":
|
||||
del self.wiki[title]
|
||||
return None
|
||||
raise AssertionError(f"unexpected request {method} {url}")
|
||||
|
||||
@property
|
||||
def writes(self):
|
||||
return [call for call in self.calls if call[0] != "GET"]
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def environment(monkeypatch, tmp_path):
|
||||
wiki_dir = tmp_path / "wiki"
|
||||
wiki_dir.mkdir()
|
||||
(wiki_dir / "Home.md").write_text("home v2", encoding="utf-8")
|
||||
(wiki_dir / "Credentials.md").write_text("credentials", encoding="utf-8")
|
||||
(wiki_dir / ".publish").write_text("prune\n", encoding="utf-8")
|
||||
monkeypatch.setenv("WIKI_DIR", str(wiki_dir))
|
||||
monkeypatch.setenv("GITEA_API_URL", f"{API}/")
|
||||
monkeypatch.setenv("SOURCE_REPOSITORY", "TirSystem/repo")
|
||||
monkeypatch.setenv("WIKI_CREDENTIALS", "wiki-token")
|
||||
return wiki_dir
|
||||
|
||||
|
||||
def run_main(publish_wiki, gitea):
|
||||
publish_wiki.request_json = gitea
|
||||
return publish_wiki.main()
|
||||
|
||||
|
||||
class TestOptIn:
|
||||
def test_a_repository_without_the_marker_is_never_written_to(
|
||||
self, publish_wiki, environment, capsys
|
||||
):
|
||||
(environment / ".publish").unlink()
|
||||
gitea = FakeGitea(publish_wiki, wiki={"Old": b64("hand written")})
|
||||
|
||||
assert run_main(publish_wiki, gitea) == 0
|
||||
|
||||
assert gitea.calls == []
|
||||
assert "wiki publishing is not enabled" in capsys.readouterr().out
|
||||
assert gitea.wiki == {"Old": b64("hand written")}
|
||||
|
||||
def test_a_repository_without_the_marker_does_not_need_the_secret(
|
||||
self, publish_wiki, environment, monkeypatch
|
||||
):
|
||||
(environment / ".publish").unlink()
|
||||
monkeypatch.setenv("WIKI_CREDENTIALS", "")
|
||||
assert run_main(publish_wiki, FakeGitea(publish_wiki)) == 0
|
||||
|
||||
def test_a_repository_without_a_wiki_directory_is_skipped(
|
||||
self, publish_wiki, monkeypatch, tmp_path
|
||||
):
|
||||
monkeypatch.setenv("WIKI_DIR", str(tmp_path / "missing"))
|
||||
monkeypatch.setenv("SOURCE_REPOSITORY", "TirSystem/repo")
|
||||
gitea = FakeGitea(publish_wiki)
|
||||
assert run_main(publish_wiki, gitea) == 0
|
||||
assert gitea.calls == []
|
||||
|
||||
def test_an_opted_in_repository_without_the_secret_fails_before_any_request(
|
||||
self, publish_wiki, environment, monkeypatch
|
||||
):
|
||||
monkeypatch.setenv("WIKI_CREDENTIALS", "")
|
||||
gitea = FakeGitea(publish_wiki)
|
||||
|
||||
with pytest.raises(publish_wiki.WorkflowError, match="TOKEN_FOR_GITEA_WIKI"):
|
||||
run_main(publish_wiki, gitea)
|
||||
|
||||
assert gitea.calls == []
|
||||
|
||||
def test_an_unknown_marker_content_is_refused_before_any_request(
|
||||
self, publish_wiki, environment
|
||||
):
|
||||
(environment / ".publish").write_text("mirror everything", encoding="utf-8")
|
||||
gitea = FakeGitea(publish_wiki)
|
||||
|
||||
with pytest.raises(publish_wiki.WorkflowError, match="prune"):
|
||||
run_main(publish_wiki, gitea)
|
||||
|
||||
assert gitea.calls == []
|
||||
|
||||
|
||||
class TestPublish:
|
||||
def test_prune_creates_updates_and_deletes_to_match_the_source(
|
||||
self, publish_wiki, environment, capsys
|
||||
):
|
||||
gitea = FakeGitea(
|
||||
publish_wiki,
|
||||
wiki={"Home": b64("home v1"), "Credentials": b64("credentials"), "Old": b64("x")},
|
||||
)
|
||||
|
||||
assert run_main(publish_wiki, gitea) == 0
|
||||
|
||||
assert gitea.wiki == {"Home": b64("home v2"), "Credentials": b64("credentials")}
|
||||
methods = [(call[0], call[1].rsplit("/", 1)[-1]) for call in gitea.calls]
|
||||
assert ("PATCH", "Home") in methods
|
||||
assert ("DELETE", "Old") in methods
|
||||
assert ("PATCH", "Credentials") not in methods
|
||||
assert "0 created, 1 updated, 1 deleted" in capsys.readouterr().out
|
||||
|
||||
def test_without_prune_pages_outside_the_source_are_kept(
|
||||
self, publish_wiki, environment, capsys
|
||||
):
|
||||
(environment / ".publish").write_text("", encoding="utf-8")
|
||||
gitea = FakeGitea(
|
||||
publish_wiki, wiki={"Home": b64("home v1"), "Old": b64("hand written")}
|
||||
)
|
||||
|
||||
assert run_main(publish_wiki, gitea) == 0
|
||||
|
||||
assert gitea.wiki["Old"] == b64("hand written")
|
||||
assert gitea.wiki["Home"] == b64("home v2")
|
||||
assert "Credentials" in gitea.wiki
|
||||
assert not [call for call in gitea.calls if call[0] == "DELETE"]
|
||||
out = capsys.readouterr().out
|
||||
assert "1 created, 1 updated, 0 deleted" in out
|
||||
assert "1 page(s) are in the wiki but not in" in out
|
||||
assert "prune" in out
|
||||
|
||||
def test_creates_every_page_when_the_wiki_was_never_written(
|
||||
self, publish_wiki, environment
|
||||
):
|
||||
gitea = FakeGitea(publish_wiki, wiki_initialised=False)
|
||||
|
||||
assert run_main(publish_wiki, gitea) == 0
|
||||
|
||||
assert set(gitea.wiki) == {"Home", "Credentials"}
|
||||
assert [call[0] for call in gitea.calls].count("POST") == 2
|
||||
|
||||
def test_does_nothing_when_the_wiki_is_already_current(self, publish_wiki, environment):
|
||||
gitea = FakeGitea(
|
||||
publish_wiki, wiki={"Home": b64("home v2"), "Credentials": b64("credentials")}
|
||||
)
|
||||
|
||||
assert run_main(publish_wiki, gitea) == 0
|
||||
|
||||
assert gitea.writes == []
|
||||
|
||||
def test_sends_the_token_and_never_prints_it(self, publish_wiki, environment, capsys):
|
||||
gitea = FakeGitea(publish_wiki)
|
||||
|
||||
assert run_main(publish_wiki, gitea) == 0
|
||||
|
||||
assert {call[3]["Authorization"] for call in gitea.calls} == {"token wiki-token"}
|
||||
output = capsys.readouterr()
|
||||
assert "wiki-token" not in output.out + output.err
|
||||
|
||||
def test_fails_when_the_wiki_is_not_enabled_and_writes_nothing(
|
||||
self, publish_wiki, environment
|
||||
):
|
||||
gitea = FakeGitea(publish_wiki, has_wiki=False)
|
||||
|
||||
with pytest.raises(publish_wiki.WorkflowError) as caught:
|
||||
run_main(publish_wiki, gitea)
|
||||
|
||||
assert caught.value.category == "configuration"
|
||||
assert gitea.writes == []
|
||||
|
||||
def test_an_empty_source_never_deletes_pages_even_with_prune(
|
||||
self, publish_wiki, environment
|
||||
):
|
||||
for path in environment.glob("*.md"):
|
||||
path.unlink()
|
||||
gitea = FakeGitea(publish_wiki, wiki={"Home": b64("keep me")})
|
||||
|
||||
with pytest.raises(publish_wiki.WorkflowError, match="no Markdown pages"):
|
||||
run_main(publish_wiki, gitea)
|
||||
|
||||
assert gitea.calls == []
|
||||
assert gitea.wiki == {"Home": b64("keep me")}
|
||||
|
||||
|
||||
class TestPageIdentity:
|
||||
"""A wiki that already has pages named with spaces, as Gitea stores them."""
|
||||
|
||||
def test_a_file_named_with_a_space_updates_the_existing_page(
|
||||
self, publish_wiki, environment
|
||||
):
|
||||
(environment / "Home.md").unlink()
|
||||
(environment / "Credentials.md").unlink()
|
||||
(environment / ".publish").write_text("", encoding="utf-8")
|
||||
(environment / "Home da.md").write_text("hjem v2", encoding="utf-8")
|
||||
gitea = FakeGitea(publish_wiki, wiki={"Home-da": b64("hjem v1")})
|
||||
|
||||
assert run_main(publish_wiki, gitea) == 0
|
||||
|
||||
assert gitea.wiki == {"Home-da": b64("hjem v2")}
|
||||
assert [call[0] for call in gitea.calls].count("POST") == 0
|
||||
assert ("PATCH", f"{WIKI_URL}/page/Home-da") in [(c[0], c[1]) for c in gitea.calls]
|
||||
|
||||
def test_identical_pages_with_spaces_are_a_no_op(self, publish_wiki, environment):
|
||||
(environment / "Home.md").unlink()
|
||||
(environment / "Credentials.md").unlink()
|
||||
(environment / "Home da.md").write_text("hjem", encoding="utf-8")
|
||||
(environment / "_Sidebar.md").write_text("menu", encoding="utf-8")
|
||||
gitea = FakeGitea(
|
||||
publish_wiki, wiki={"Home-da": b64("hjem"), "_Sidebar": b64("menu")}
|
||||
)
|
||||
|
||||
assert run_main(publish_wiki, gitea) == 0
|
||||
|
||||
assert gitea.writes == []
|
||||
|
||||
def test_prune_does_not_delete_a_page_that_is_in_the_folder_under_another_spelling(
|
||||
self, publish_wiki, environment
|
||||
):
|
||||
(environment / "Home.md").unlink()
|
||||
(environment / "Credentials.md").unlink()
|
||||
(environment / "Install ms.md").write_text("pasang", encoding="utf-8")
|
||||
gitea = FakeGitea(
|
||||
publish_wiki, wiki={"Install-ms": b64("pasang"), "Old-page": b64("x")}
|
||||
)
|
||||
|
||||
assert run_main(publish_wiki, gitea) == 0
|
||||
|
||||
assert gitea.wiki == {"Install-ms": b64("pasang")}
|
||||
|
||||
def test_the_address_wins_over_the_title_and_is_decoded(self, publish_wiki):
|
||||
def listing(url, headers=None, **kwargs):
|
||||
return [
|
||||
{"title": "Whatever", "sub_url": "Real-Address"},
|
||||
{"title": "Only title"},
|
||||
{"title": "Encoded", "sub_url": "Caf%C3%A9"},
|
||||
]
|
||||
|
||||
keys = publish_wiki.list_wiki_titles(WIKI_URL, {}, listing)
|
||||
|
||||
assert keys == {"Real-Address", "Only-title", "Café"}
|
||||
|
||||
|
||||
class TestDescribeToken:
|
||||
def test_recognises_a_gitea_token_shape(self, publish_wiki):
|
||||
description = publish_wiki.describe_token("a1b2c3d4e5" * 4)
|
||||
assert "40 characters" in description
|
||||
assert "looks like a Gitea token" in description
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("token", "expected"),
|
||||
[
|
||||
("*******", "only mask characters"),
|
||||
("TOKEN_FOR_GITEA_WIKI=" + "a" * 40, "contains '='"),
|
||||
('"' + "a" * 40 + '"', "quote character"),
|
||||
("abc def", "whitespace"),
|
||||
],
|
||||
)
|
||||
def test_names_the_likely_mistake_without_echoing_the_token(
|
||||
self, publish_wiki, token, expected
|
||||
):
|
||||
description = publish_wiki.describe_token(token)
|
||||
assert expected in description
|
||||
assert token not in description
|
||||
|
||||
|
||||
class TestRejectedToken:
|
||||
def test_rejection_adds_the_token_shape_but_not_the_token(
|
||||
self, publish_wiki, environment, monkeypatch
|
||||
):
|
||||
monkeypatch.setenv("WIKI_CREDENTIALS", "*******")
|
||||
|
||||
def reject(url, method="GET", headers=None, body=None):
|
||||
raise publish_wiki.WorkflowError("credentials", "Gitea rejected the token.")
|
||||
|
||||
publish_wiki.request_json = reject
|
||||
|
||||
with pytest.raises(publish_wiki.WorkflowError) as caught:
|
||||
publish_wiki.main()
|
||||
|
||||
message = str(caught.value)
|
||||
assert caught.value.category == "credentials"
|
||||
assert "Token shape: 7 characters" in message
|
||||
assert "only mask characters" in message
|
||||
assert "*******" not in message.split("Token shape:")[0]
|
||||
|
||||
def test_other_categories_are_not_changed(self, publish_wiki, environment):
|
||||
def forbid(url, method="GET", headers=None, body=None):
|
||||
raise publish_wiki.WorkflowError("permissions", "Forbidden.")
|
||||
|
||||
publish_wiki.request_json = forbid
|
||||
|
||||
with pytest.raises(publish_wiki.WorkflowError) as caught:
|
||||
publish_wiki.main()
|
||||
|
||||
assert str(caught.value) == "[permissions] Forbidden."
|
||||
|
||||
|
||||
class TestRequestJson:
|
||||
@staticmethod
|
||||
def raise_http_error(publish_wiki, monkeypatch, code, reason):
|
||||
def fake_urlopen(request, timeout):
|
||||
raise urllib.error.HTTPError(
|
||||
request.full_url, code, reason, {}, io.BytesIO(b"secret detail")
|
||||
)
|
||||
|
||||
monkeypatch.setattr(publish_wiki.urllib.request, "urlopen", fake_urlopen)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("code", "reason", "category"),
|
||||
[
|
||||
(401, "Unauthorized", "credentials"),
|
||||
(403, "Forbidden", "permissions"),
|
||||
(404, "Not Found", "configuration"),
|
||||
(500, "Server Error", "api"),
|
||||
],
|
||||
)
|
||||
def test_categorizes_http_errors(self, publish_wiki, monkeypatch, code, reason, category):
|
||||
self.raise_http_error(publish_wiki, monkeypatch, code, reason)
|
||||
|
||||
with pytest.raises(publish_wiki.WorkflowError) as caught:
|
||||
publish_wiki.request_json(REPO_URL)
|
||||
|
||||
assert caught.value.category == category
|
||||
assert f"HTTP {code}" in str(caught.value)
|
||||
assert "secret detail" not in str(caught.value)
|
||||
|
||||
def test_reports_unreachable_service_as_api_failure(self, publish_wiki, monkeypatch):
|
||||
def fake_urlopen(request, timeout):
|
||||
raise urllib.error.URLError("no route")
|
||||
|
||||
monkeypatch.setattr(publish_wiki.urllib.request, "urlopen", fake_urlopen)
|
||||
|
||||
with pytest.raises(publish_wiki.WorkflowError) as caught:
|
||||
publish_wiki.request_json(REPO_URL)
|
||||
|
||||
assert caught.value.category == "api"
|
||||
|
||||
|
||||
class TestWorkflow:
|
||||
@pytest.fixture()
|
||||
def document(self):
|
||||
return yaml.safe_load(PUBLISH_WORKFLOW.read_text(encoding="utf-8"))
|
||||
|
||||
def test_runs_only_on_main_when_wiki_changes_or_by_hand(self, document):
|
||||
triggers = document[True] # PyYAML reads the key `on` as True
|
||||
assert triggers["push"]["branches"] == ["main"]
|
||||
assert triggers["push"]["paths"] == ["wiki/**"]
|
||||
assert "workflow_dispatch" in triggers
|
||||
|
||||
def test_job_has_read_only_permissions(self, document):
|
||||
assert document["jobs"]["publish-wiki"]["permissions"] == {"contents": "read"}
|
||||
|
||||
def test_secret_is_passed_only_through_the_environment_and_has_no_fallback(self, document):
|
||||
text = PUBLISH_WORKFLOW.read_text(encoding="utf-8")
|
||||
assert "secrets.TOKEN_FOR_GITEA }}" not in text
|
||||
publish_step = document["jobs"]["publish-wiki"]["steps"][-1]
|
||||
assert publish_step["env"]["WIKI_CREDENTIALS"] == "${{ secrets.TOKEN_FOR_GITEA_WIKI }}"
|
||||
assert "secrets" not in publish_step["run"]
|
||||
|
||||
def test_the_workflow_has_one_source_and_runs_the_script_file(self, document):
|
||||
assert not (REPO_ROOT / ".gitea" / "workflows" / "publish-wiki.yml").exists()
|
||||
assert (REPO_ROOT / "tools" / "publish_wiki.py").is_file()
|
||||
steps = document["jobs"]["publish-wiki"]["steps"]
|
||||
assert "python3 - <<" not in PUBLISH_WORKFLOW.read_text(encoding="utf-8")
|
||||
assert steps[0]["uses"].startswith("actions/checkout@")
|
||||
assert steps[1]["with"] == {
|
||||
"repository": "TirSystem/github-action",
|
||||
"ref": "main",
|
||||
"path": "shared-scripts",
|
||||
}
|
||||
assert steps[-1]["run"] == "python3 shared-scripts/tools/publish_wiki.py"
|
||||
|
||||
|
||||
def test_this_repository_opts_in_and_prunes():
|
||||
"""The wiki of this repository must equal wiki/ (ADR-0001, ADR-0004)."""
|
||||
marker = REPO_ROOT / "wiki" / ".publish"
|
||||
assert marker.read_text(encoding="utf-8").strip() == "prune"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user