23 Commits
Author SHA1 Message Date
Tirsvad 2817ecdef5 Merge pull request 'Run the quality checks from a script file' (#90) from quality-checks-script-file into main
Validate workflows / validate (push) Successful in 15s
TirSystem/github-action: Publish wiki / publish-wiki (push) Successful in 11s
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 5s
2026-10-11 05:15:53 +02:00
Tirsvad 0025c58e7b Add the changelog entry of release 1.1.0
TirSystem/github-action: Publish wiki / publish-wiki (push) Skipped
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Skipped
Validate workflows / validate (pull_request) Successful in 14s
Task: MIL-004#5
2026-10-11 11:15:13 +08:00
Tirsvad ae0360350a Resolve pending commit links in the quality-checks script documents
TirSystem/github-action: Publish wiki / publish-wiki (push) Skipped
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Skipped
Task: MIL-003#3
2026-10-11 11:14:04 +08:00
Tirsvad 670f0ac469 Run the quality checks from a script file of this repository
Task: MIL-003#3
2026-10-11 11:14:03 +08:00
Tirsvad 6f01fd6828 Merge pull request 'Add the changelog entry of release 1.0.1' (#89) from release-1-0-1 into main
TirSystem/github-action: Publish wiki / publish-wiki (push) Skipped
Validate workflows / validate (push) Successful in 14s
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Skipped
2026-10-11 04:49:18 +02:00
Tirsvad b8d08f7d90 Add the changelog entry of release 1.0.1
TirSystem/github-action: Publish wiki / publish-wiki (push) Skipped
Validate workflows / validate (pull_request) Successful in 16s
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Skipped
Task: MIL-004#5
2026-10-11 10:48:46 +08:00
Tirsvad 893890497a Merge pull request 'End the sync log with Skipped when there is no GitHub mirror' (#88) from sync-skipped-without-mirror into main
TirSystem/github-action: Publish wiki / publish-wiki (push) Successful in 9s
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 5s
Validate workflows / validate (push) Successful in 14s
2026-10-11 04:43:01 +02:00
Tirsvad aa88ea6f8b End the sync log with Skipped when there is no GitHub mirror
TirSystem/github-action: Publish wiki / publish-wiki (push) Skipped
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Skipped
Validate workflows / validate (pull_request) Successful in 14s
Task: MIL-001#1
2026-10-11 10:42:18 +08:00
Tirsvad 532e9663cb Merge pull request 'List all workflows with purpose and diagram on the Home page' (#87) from home-workflow-list into main
Validate workflows / validate (push) Successful in 14s
TirSystem/github-action: Publish wiki / publish-wiki (push) Successful in 10s
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 5s
2026-10-11 04:39:22 +02:00
Tirsvad 4cb4689471 List all workflows with their purpose and a diagram on the Home page
TirSystem/github-action: Publish wiki / publish-wiki (push) Skipped
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Skipped
Validate workflows / validate (pull_request) Successful in 16s
Task: MIL-005#3
2026-10-11 10:38:54 +08:00
Tirsvad 4b8d659e02 Merge pull request 'Name the quality-check wiki page for what it covers' (#86) from rename-quality-checks-wiki-page into main
Validate workflows / validate (push) Successful in 13s
TirSystem/github-action: Publish wiki / publish-wiki (push) Successful in 15s
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 5s
2026-10-11 04:34:40 +02:00
Tirsvad d8dc35e88f Name the quality-check wiki page for what it covers
TirSystem/github-action: Publish wiki / publish-wiki (push) Skipped
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Skipped
Validate workflows / validate (pull_request) Successful in 16s
Task: MIL-005#3
2026-10-11 10:33:47 +08:00
Tirsvad 21b9b83e82 Merge pull request 'Generate a _Sidebar page so the wiki shows its subpages' (#85) from mil-005-wiki-sidebar into main
Validate workflows / validate (push) Successful in 14s
TirSystem/github-action: Publish wiki / publish-wiki (push) Successful in 8s
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 5s
2026-10-11 03:56:23 +02:00
Tirsvad e6c855554c Generate a _Sidebar page so the wiki shows its subpages
TirSystem/github-action: Publish wiki / publish-wiki (push) Skipped
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Skipped
Validate workflows / validate (pull_request) Successful in 15s
Task: MIL-005#3
2026-10-11 09:55:58 +08:00
Tirsvad e375900d2a Merge pull request 'Accept the translations of MIL-005 and record its results' (#84) from mil-005-accept-translations into main
TirSystem/github-action: Publish wiki / publish-wiki (push) Skipped
Validate workflows / validate (push) Successful in 15s
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 6s
2026-10-11 03:48:39 +02:00
Tirsvad 4210a7492e Resolve pending commit links in the MIL-005 results
TirSystem/github-action: Publish wiki / publish-wiki (push) Skipped
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Skipped
Validate workflows / validate (pull_request) Successful in 17s
Task: MIL-005#5
2026-10-11 09:48:08 +08:00
Tirsvad ead3d98d73 Accept the translations of MIL-005 and record its results
Task: MIL-005#5
2026-10-11 09:48:06 +08:00
Tirsvad 2f1aa4d26d Merge pull request 'Record the pilot results of MIL-006' (#83) from mil-006-pilot-results into main
TirSystem/github-action: Publish wiki / publish-wiki (push) Skipped
Validate workflows / validate (push) Successful in 16s
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 15s
2026-10-10 21:16:36 +02:00
Tirsvad b85947f076 Resolve pending commit links in the MIL-006 results
TirSystem/github-action: Publish wiki / publish-wiki (push) Skipped
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Skipped
Validate workflows / validate (pull_request) Successful in 22s
Task: MIL-006#4
2026-10-11 03:15:58 +08:00
Tirsvad d575f272fc Record the pilot results of MIL-006
Task: MIL-006#4
2026-10-11 03:15:57 +08:00
Tirsvad 81fd82a909 Merge pull request 'Pin the scoped workflows to v1 and record the MIL-004 results' (#82) from mil-004-pin-scripts-v1 into main
Validate workflows / validate (push) Successful in 14s
TirSystem/github-action: Publish wiki / publish-wiki (push) Successful in 8s
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 5s
2026-10-10 21:04:23 +02:00
Tirsvad 513ad69de2 Resolve pending commit links in the MIL-004 results
TirSystem/github-action: Publish wiki / publish-wiki (push) Skipped
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Skipped
Validate workflows / validate (pull_request) Successful in 17s
Task: MIL-004#1
2026-10-11 03:03:43 +08:00
Tirsvad 6933e91c83 Pin the scoped workflows to v1 and record the MIL-004 results
Task: MIL-004#1
2026-10-11 03:03:42 +08:00
42 changed files with 1649 additions and 443 deletions
+1 -1
View File
@@ -31,7 +31,7 @@ jobs:
uses: actions/checkout@v4
with:
repository: TirSystem/github-action
ref: main
ref: v1
path: shared-scripts
- name: Publish the pages to the wiki
@@ -21,7 +21,7 @@ jobs:
uses: actions/checkout@v4
with:
repository: TirSystem/github-action
ref: main
ref: v1
path: shared-scripts
- name: Sync description and topics
+17 -96
View File
@@ -4,7 +4,7 @@ name: Quality checks
#
# jobs:
# quality:
# uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@main
# uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@v1
#
# It checks the Python and shell files of the repository with pinned tools,
# changes no file and needs no secret.
@@ -35,6 +35,10 @@ on:
description: "Version of the shfmt-py package (shfmt 3.11.0)"
type: string
default: "3.11.0.2"
tools-ref:
description: "Tag or branch of TirSystem/github-action whose tools/quality-checks.sh is run; pin it to the exact tag together with the workflow"
type: string
default: "v1"
jobs:
quality-checks:
@@ -50,104 +54,21 @@ jobs:
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: Fetch the shared script
uses: actions/checkout@v4
with:
repository: TirSystem/github-action
ref: ${{ inputs.tools-ref }}
path: shared-scripts
- name: Validate the inputs
run: bash shared-scripts/tools/quality-checks.sh validate
- 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[@]}"
run: bash shared-scripts/tools/quality-checks.sh install
- 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."
run: bash shared-scripts/tools/quality-checks.sh run
+22
View File
@@ -20,6 +20,28 @@ Each release lists its changes in these groups, in this order:
## [Unreleased]
## [1.1.0] - 2026-10-11
### Added
- Input `tools-ref` of `quality-checks.yml` (default `v1`): the tag or branch from
which the workflow fetches its script `tools/quality-checks.sh`.
### Changed
- `quality-checks.yml` runs the script file `tools/quality-checks.sh` instead of
embedding about 100 lines of shell; the checks, messages and results are the
same.
## [1.0.1] - 2026-10-11
### Changed
- Sync GitHub mirror metadata: a repository without a GitHub push mirror still
succeeds, and the log now ends with the line `Skipped`.
- The scoped workflows fetch their scripts at the tag `v1` instead of `main`,
so a merge to `main` reaches consumers only when it is released.
## [1.0.0] - 2026-10-10
First release. The reusable workflow can be pinned at `v1` or `v1.0.0`. The
+232 -50
View File
@@ -5,6 +5,7 @@ A collection of reusable Gitea Actions workflows for DevOps professionals and so
## 📚 Table of Contents
- [Overview](#-overview)
- [Workflows](#-workflows)
- [Requirements](#-requirements)
- [Setup](#-setup)
- [Run](#-run)
@@ -16,59 +17,19 @@ A collection of reusable Gitea Actions workflows for DevOps professionals and so
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.
It contains five workflows: metadata sync to the GitHub mirror, wiki publishing, shared quality checks, a release workflow and the repository's own validation. They are listed with their purpose and a diagram under [Workflows](#-workflows).
## 📋 Requirements
## 🔧 Workflows
- 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`
Five workflows live in this repository. A **scoped** workflow is delivered by the instance to every repository of the TirSystem organizations and needs nothing in the repository; a **reusable** workflow is called by a repository with `uses:`; the others run only here. The diagrams are PlantUML source.
## 🛠️ 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)) |
| Workflow | File | Kind | Starts on | Purpose |
| --- | --- | --- | --- | --- |
| Sync GitHub mirror metadata | [`sync-github-metadata.yml`](.gitea/scoped_workflows/sync-github-metadata.yml) | Scoped | push to `main`, manual, daily 03:17 UTC | Copies the description and topics of a Gitea repository to its GitHub push mirror |
| Publish wiki | [`publish-wiki.yml`](.gitea/scoped_workflows/publish-wiki.yml) | Scoped, opt-in with `wiki/.publish` | push to `main` that changes `wiki/**`, manual | Publishes the pages in `wiki/` to the repository wiki |
| Quality checks | [`quality-checks.yml`](.gitea/workflows/quality-checks.yml) | Reusable (`workflow_call`) | a call from another repository | Runs ruff, mypy, shellcheck and shfmt on the tracked files and changes nothing |
| Release | [`release.yml`](.gitea/workflows/release.yml) | This repository only | manual | Creates the version tag, the release page and the major tag after the checks |
| Validate workflows | [`validate-workflows.yml`](.gitea/workflows/validate-workflows.yml) | This repository only | pull request, push to `main`, manual | Parses every workflow and runs the offline tests |
### 🔄 Sync GitHub metadata
@@ -136,6 +97,227 @@ deactivate Workflow
@enduml
```
### 📖 Publish wiki
Publishes `wiki/` to the repository wiki, only in a repository that has opted in with `wiki/.publish`. The word `prune` in that file also deletes pages that are not in `wiki/`.
#### 🔀 Workflow
```plantuml
@startuml
title Publish wiki/ to the repository wiki
autonumber
actor "Push to main that changes wiki/**,\nor manual trigger" as Trigger
participant "Gitea Actions\npublish-wiki" as Workflow
participant "shared-scripts\n(tools/publish_wiki.py at v1)" as Script
participant "Gitea wiki API" as Wiki
Trigger -> Workflow: Start workflow
activate Workflow
Workflow -> Script: Check out the repository and the script, run it
activate Script
alt wiki/.publish does not exist
Script --> Workflow: Log that publishing is not enabled and succeed\n(nothing is written)
else wiki/ has no Markdown pages
Script --> Workflow: Fail with [configuration]\n(an empty wiki/ never deletes pages)
else
Script -> Script: Read the marker (empty, or the word prune)\nand TOKEN_FOR_GITEA_WIKI
Script -> Wiki: GET repository (preflight)
Wiki --> Script: Wiki is enabled, token accepted
Script -> Wiki: GET pages
Wiki --> Script: Existing pages
Script -> Wiki: Create new pages, update changed pages
opt marker says prune
Script -> Wiki: Delete pages that are not in wiki/
end
Script --> Workflow: Log created, updated and deleted counts
end
deactivate Script
Workflow --> Trigger: Workflow result
deactivate Workflow
@enduml
```
### ✅ Quality checks
A reusable workflow for Python and shell, called with `uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@v1` (see the [guide](guides/quality-checks.md)).
#### 🔀 Workflow
```plantuml
@startuml
title Shared quality checks (reusable workflow)
autonumber
actor "Calling repository\nuses: ...quality-checks.yml@v1" as Caller
participant "Gitea Actions\nquality-checks" as Workflow
participant "PyPI" as PyPI
Caller -> Workflow: workflow_call with languages,\nworking-directory and tool versions
activate Workflow
Workflow -> Workflow: Validate the inputs
alt languages or working-directory is invalid
Workflow --> Caller: Fail with [configuration]
end
Workflow -> Workflow: Check out the calling repository
Workflow -> PyPI: Install the pinned tools in a virtual environment\n(ruff, mypy, shellcheck-py, shfmt-py as selected)
PyPI --> Workflow: Tools installed
loop for each selected language
Workflow -> Workflow: List tracked files
alt no files of that language
Workflow -> Workflow: Notice: nothing was checked
else
Workflow -> Workflow: Run every tool and record PASS or FAIL
end
end
alt any tool failed
Workflow --> Caller: Fail and list the failed tools
else
Workflow --> Caller: All selected checks passed
end
deactivate Workflow
@enduml
```
### 🏷️ Release
Started by hand by a maintainer; with `dry_run` `true` (the default) it only checks (see the [release process](guides/release-process.md)).
#### 🔀 Workflow
```plantuml
@startuml
title Release this repository
autonumber
actor "Maintainer\n(workflow_dispatch: version, dry_run)" as Trigger
participant "Gitea Actions\nrelease" as Workflow
participant "Gitea REST API" as Gitea
Trigger -> Workflow: Start with version and dry_run
activate Workflow
Workflow -> Workflow: Check the version and read CHANGELOG.md
alt version malformed or no changelog entry
Workflow --> Trigger: Fail with [validation] or [configuration]
end
Workflow -> Gitea: GET branch main and status of the commit
Gitea --> Workflow: Tip of main and the validation run
alt commit is not the tip of main,\nor the validation run is not green
Workflow --> Trigger: Fail with [validation]\n(no tag is created)
end
Workflow -> Gitea: GET tags
Gitea --> Workflow: Existing tags
alt tag vMAJOR.MINOR.PATCH exists
Workflow --> Trigger: Fail with [validation]\n(tags are never moved)
end
alt dry_run is true (default)
Workflow --> Trigger: Log what would be created and stop
else
Workflow -> Gitea: POST release (creates the version tag,\nbody is the changelog entry)
opt this is the highest version of its major
Workflow -> Gitea: Delete and recreate the major tag vMAJOR
end
Workflow --> Trigger: Released
end
deactivate Workflow
@enduml
```
### 🧪 Validate workflows
The repository's own validation: the offline tests that gate every pull request.
#### 🔀 Workflow
```plantuml
@startuml
title Validate workflows (this repository's own checks)
autonumber
actor "Pull request,\npush to main, or manual trigger" as Trigger
participant "Gitea Actions\nvalidate-workflows" as Workflow
Trigger -> Workflow: Start workflow
activate Workflow
Workflow -> Workflow: Check out the repository
Workflow -> Workflow: Create a virtual environment and\ninstall tests/requirements.txt
Workflow -> Workflow: Run pytest on tests/ (offline, no secrets):\nworkflows parse as YAML, no embedded Python,\nscripts compile, wiki pages and translations are current,\nsync, publish and release flows against a fake API
alt a test fails
Workflow --> Trigger: Workflow fails (the pull request is not ready)
else
Workflow --> Trigger: Workflow succeeds
end
deactivate Workflow
@enduml
```
## 📋 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 the repositories of all four organizations verified (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; a pilot in a second repository publishes its wiki (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; adopted in RepoFoundry ([guide](guides/quality-checks.md)) |
| Versioned release and publishing | Release process, changelog and upgrade guide defined; the release workflow exists and `v1.0.0` is released (MIL-004) ([guide](guides/upgrading.md)) |
## 📄 License
Licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See [LICENSE](LICENSE).
+9 -5
View File
@@ -9,8 +9,8 @@
## 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] |
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S01 | Reviewed (RC-038): the security impact of installing the tools from PyPI named | [385d2fb] |
| 2026-10-11 | Accepted | Jens Tirsvad Nielsen | S01 | Added the input tools-ref: the shell steps moved to a script file fetched at that ref (RC-051) | [670f0ac] |
Allowed Status values: `Proposed`, `Accepted`, `Rejected`, `Deprecated`, `Superseded by ADR-NNNN`.
@@ -55,9 +55,12 @@ Options for the shape of the workflow:
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
`working-directory` (default `.`), one version input per tool whose
defaults are the pinned versions above, and `tools-ref` (default `v1`, the
tag or branch from which the workflow fetches its script
`tools/quality-checks.sh`), and it installs the tools from PyPI into a virtual
environment. A call at an exact tag is pinned completely only when `tools-ref`
names the same tag; with the default the script follows the major tag. 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.
@@ -122,3 +125,4 @@ The rules that follow from it:
[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
[670f0ac]: https://git.tirsystem.com/TirSystem/github-action/commit/670f0ac469043bb166c84290c0dbf62b4908e3cc
+1 -1
View File
@@ -11,7 +11,7 @@ each document lives in *this* project and the next version to use.
| 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 |
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 052 |
| 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 |
+20 -4
View File
@@ -9,8 +9,8 @@
## 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] |
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S01 | Added task 6 (embedded scripts to files) and Go/No-Go criterion 5; traceability adds O2 (RC-034) | [616c5d2] |
| 2026-10-11 | Accepted | Jens Tirsvad Nielsen | S01 | Added the verification results of the first release (v1.0.0) | [6933e91] |
---
@@ -71,10 +71,26 @@ reference that a release can pin, instead of Python embedded in their YAML.
| 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 | |
## Verification results
The first release was cut on 2026-10-11 with the Release workflow (run 623 on
`97ffa49`, after a dry run, run 622): the tag `v1.0.0`, the moving tag `v1`
and the release page were created, and the job token was enough (ADR-0007).
| # | Criterion | Result |
| --- | --- | --- |
| 1 | A release is validated before a tag is created | Go: `tools/release.py` refuses unless the status `Validate workflows / validate (push)` of the tip of `main` is success; tested for failed and missing runs |
| 2 | Version tag and changelog entry that marks breaking changes | Go: `v1.0.0` and `CHANGELOG.md` `[1.0.0]`; `tools/changelog.py` checks the convention |
| 3 | A consumer pinned to the previous version keeps working | Go: tags are never moved or deleted; the upgrade guide describes the way back; the first release has no previous version, so this is by construction until `v1.0.1` |
| 4 | Publish destination decided, token scope documented | Go: ADR-0007 |
| 5 | No embedded Python in the scoped workflows | Go: both run files of this repository, with offline tests that exercise the files (MIL-004 task 6) |
After the release the two scoped workflows fetch their scripts at `ref: v1`
(RC-043 action item).
---
[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
[6933e91]: https://git.tirsystem.com/TirSystem/github-action/commit/6933e91c83075fb39b2dfbe41683cb2a0a0bce28
@@ -9,8 +9,8 @@
## 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] |
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S01 | Target date 2026-12-12 confirmed on 2026-10-10 by S01 (stand-in for S05) | [ea06eaa] |
| 2026-10-11 | Accepted | Jens Tirsvad Nielsen | S01 | Criterion 4 amended (accepted by S01 as stand-in when no native reader exists); added the verification results | [ead3d98] |
---
@@ -36,7 +36,7 @@ to `main`, and a pull request rule in `AGENTS.md` keeps the wiki current.
| 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 |
| 4 | The translations are reviewed and accepted: by a native reader of each language, or, when none is available, by S01 as the stand-in of ADR-0002, with the lack of a native reader stated | Acceptance recorded, and a native review where one exists | 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 |
@@ -76,9 +76,22 @@ to `main`, and a pull request rule in `AGENTS.md` keeps the wiki current.
| 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 | |
## Verification results
Checked on 2026-10-11 against `main` at the merge of PR 83.
| # | Criterion | Result |
| --- | --- | --- |
| 1 | The wiki is enabled and contains the pages in all three languages | Go: 21 pages (seven pages in English, Danish and Bahasa Malaysia), more than the 15 the criterion names |
| 2 | Each English page is generated from `README.md` or `guides/`, and a check reports a page that differs | Go: `python tools/build_wiki.py --check` passes and the tests fail on a stale page |
| 3 | Each translation names the English source version it follows | Go: every `.da` and `.ms` file starts with `translation of X.md, source sha256`, and the tests check it |
| 4 | The translations are reviewed and accepted | Go on the stand-in: no native reader of Danish or Bahasa Malaysia reviewed the pages. S01 accepted them on 2026-10-11 (RC-050) and the checklist `docs/wiki-translation-review.md` stays available for a native reader. The accuracy of the text rests on the author and S01, not on a native reader |
| 5 | `AGENTS.md` requires a wiki update and the PR lists the pages | Go: rule 8 of `AGENTS.md`; used by PR 78, PR 82 and others, each listing the wiki pages it changed |
| 6 | The wiki is published only by the workflow from `main` | Go: the last commit of all 21 pages has the message `Publish wiki from the repository`, which only the publisher writes |
---
[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
[ead3d98]: https://git.tirsystem.com/TirSystem/github-action/commit/ead3d98d73fcab95fd57b0eb005a02aff9983256
@@ -9,8 +9,8 @@
## 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] |
| 2026-10-10 | Deprecated | Jens Tirsvad Nielsen | S01 | Target date 2026-12-26 confirmed on 2026-10-10 by S01 (stand-in for S05) | [ea06eaa] |
| 2026-10-11 | Accepted | Jens Tirsvad Nielsen | S01 | Criterion 1 evidence amended; added the verification results of the pilot | [d575f27] |
---
@@ -31,7 +31,7 @@ repository other than this one that publishes its wiki through it.
| # | 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 |
| 1 | A repository without the opt-in marker is never written to, shown by offline tests and by the trigger rule (a run in such a repository cannot be started: a scoped workflow is not dispatchable through the API and runs only on a push that changes `wiki/**`) | 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 |
@@ -72,9 +72,26 @@ repository other than this one that publishes its wiki through it.
| 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 | |
## Verification results
The pilot was `TirSystem/sqa-qc-checklists` (its PR 10, merged 2026-10-11).
The scoped workflow ran as run 629 on `d4ddbb6`, fetched the scripts at `v1`,
passed the token preflight and reported `Published 13 page(s): 0 created,
0 updated, 0 deleted`. The 13 pages of the wiki were then read back through
the API and equal `wiki/*.md` on `main` (0 differences).
| # | Criterion | Result |
| --- | --- | --- |
| 1 | A repository without the marker is never written to | Go by the offline tests (`test_a_repository_without_the_marker_is_never_written_to`: no request, the existing page unchanged; `..._does_not_need_the_secret`; `..._without_a_wiki_directory_is_skipped`) and by the trigger rule. A live run was tried on 2026-10-11 in `TirSystem/IaC.server-setup-4-linux`: the API answered 404, the workflow is not listed for that repository and cannot be dispatched. S01 accepted the weaker evidence on 2026-10-11 (RC-049) |
| 2 | The workflow exists once | Go: only `.gitea/scoped_workflows/publish-wiki.yml`; no copy in `.gitea/workflows/` and nothing is needed from `tools/` in the target repository (the script is fetched from `TirSystem/github-action`, MIL-004 task 6) |
| 3 | One repository outside this one publishes its wiki | Go: `TirSystem/sqa-qc-checklists`, run 629, 13 pages equal |
| 4 | An empty or missing `wiki/` never deletes pages; a failure names its category | Go: `test_an_empty_source_never_deletes_pages_even_with_prune` and the category tests |
| 5 | `TOKEN_FOR_GITEA_WIKI` is documented and stored in the pilot's organisation | Go: `guides/credentials.md`; run 629 used the organisation secret |
| 6 | The onboarding and credentials guides and their wiki languages describe opting in | Go: `wiki/.publish` and `TOKEN_FOR_GITEA_WIKI` appear in the guides and the English, Danish and Bahasa Malaysia pages |
---
[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
[d575f27]: https://git.tirsystem.com/TirSystem/github-action/commit/d575f272fcb044e3165951013464177a6e659ea6
@@ -0,0 +1,46 @@
# Review Record: MIL-004 (verification results)
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-048 |
| CrossReference | [MIL-004], [QC-MIL-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-11 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [6933e91] |
---
## Artifact Under Review
- Instance reviewed: [MIL-004] after the first release, with its new Verification results section
- Checklist used: [QC-MIL-001]
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | The release process, the upgrade guide, the release workflow and the scripts at a pinned reference now exist; the release page of `v1.0.0` is the proof. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | All five criteria have a result in the Verification results table, each naming its evidence. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Unchanged (MIL-003). |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | O2 and O4, unchanged. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Owner S05, approving reviewer S01, unchanged. |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | 2026-11-28; the criteria are met on 2026-10-11. |
## Overall Verdict
Go - all six criteria pass, and the five Go/No-Go criteria of MIL-004 are met. One limit is stated, not hidden: criterion 3 (a consumer pinned to the previous version keeps working) is met by construction until a second release exists, because tags are never moved. S01 gave the Go in chat on 2026-10-11, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Verify criterion 3 with a real consumer when `v1.0.1` or `v1.1.0` is released | S05 | next release |
---
[MIL-004]: ../../milestones/mil-004-versioned-release.md
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
[6933e91]: https://git.tirsystem.com/TirSystem/github-action/commit/6933e91c83075fb39b2dfbe41683cb2a0a0bce28
@@ -0,0 +1,46 @@
# Review Record: MIL-006 (pilot results)
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-049 |
| CrossReference | [MIL-006], [QC-MIL-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-11 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [d575f27] |
---
## Artifact Under Review
- Instance reviewed: [MIL-006] with its amended criterion 1 and its new Verification results section
- Checklist used: [QC-MIL-001]
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | The scoped workflow, the opt-in rule, tests, guides and a pilot exist; run 629 is the proof. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Finding fixed during this review: criterion 1 demanded a live run in a repository without the marker, which the instance cannot produce (a scoped workflow is not dispatchable and runs only on a push that changes `wiki/**`). The criterion now names the offline tests and the trigger rule as its evidence. This is weaker than a live run, which the results state. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Unchanged (MIL-005, MIL-002). |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | O2 and O3, unchanged. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Owner S05, approving reviewer S01, unchanged. |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | 2026-12-26; the criteria are met on 2026-10-11. |
## Overall Verdict
Go - all six criteria pass; the one finding (criterion 2) was fixed during the review, and the milestone's six Go/No-Go criteria are met, criterion 1 on the weaker evidence stated. S01 gave the Go in chat on 2026-10-11, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Observe the first push that changes `wiki/**` in a repository without the marker, if one occurs, and record that the run only logs that publishing is not enabled | S05 | when it occurs |
---
[MIL-006]: ../../milestones/mil-006-shared-wiki-publishing.md
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
[d575f27]: https://git.tirsystem.com/TirSystem/github-action/commit/d575f272fcb044e3165951013464177a6e659ea6
@@ -0,0 +1,46 @@
# Review Record: MIL-005 (translations accepted)
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-050 |
| CrossReference | [MIL-005], [QC-MIL-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-11 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [ead3d98] |
---
## Artifact Under Review
- Instance reviewed: [MIL-005] with its amended criterion 4 and its new Verification results section
- Checklist used: [QC-MIL-001]
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | A concrete deliverable is defined for every gate | Pass | The wiki in three languages, generated and published from `wiki/`; 21 pages are published. |
| 2 | Explicit Go/No-Go criteria are stated for each gate | Pass | Finding fixed during this review: criterion 4 demanded a native reader, which the project does not have. It now allows acceptance by S01 as the stand-in of ADR-0002 and says that the lack of a native reader is stated. This is weaker than a native review, and the results say so. |
| 3 | Dependencies on other milestones are explicitly mapped | Pass | Unchanged (MIL-002). |
| 4 | Each milestone is traceable to a Business Case objective or KPI | Pass | Unchanged. |
| 5 | Milestone owner and approving reviewer are identified | Pass | Owner S05, approving reviewer S01, unchanged. |
| 6 | Milestone has a defined target date consistent with project constraints | Pass | 2026-12-12; the criteria are met on 2026-10-11. |
## Overall Verdict
Go - all six criteria pass; the one finding (criterion 2) was fixed during the review. The Danish and Bahasa Malaysia pages are accepted by S01 on 2026-10-11 without a native reader, standing in for the other reviewers as ADR-0002 records; there is no independent reader. Bahasa Malaysia is the weaker draft (`docs/wiki-translation-review.md`).
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Have a native reader of each language use `docs/wiki-translation-review.md` when one is available; fix the findings through a pull request | S05 | when a reader is available |
---
[MIL-005]: ../../milestones/mil-005-wiki-and-translations.md
[QC-MIL-001]: ../../../framework/qc/qc-milestones-gateways.md
[ead3d98]: https://git.tirsystem.com/TirSystem/github-action/commit/ead3d98d73fcab95fd57b0eb005a02aff9983256
@@ -0,0 +1,51 @@
# Review Record: ADR-0005 (tools-ref)
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-051 |
| CrossReference | [ADR-0005], [QC-ADR-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-11 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [670f0ac] |
---
## Artifact Under Review
- Instance reviewed: [ADR-0005] after the addition of the input `tools-ref`
- 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 | Unchanged. |
| 2 | Context states the problem, the forces (cost, risk, constraints) and the options evaluated | Pass | Unchanged; the move of the shell steps to a script file is an implementation of the decided contract, not a new option. |
| 3 | At least two options were considered, or the absence of alternatives is justified | Pass | Unchanged. |
| 4 | Decision is stated in one or two unhedged sentences and matches one of the evaluated options | Pass | The decision sentence names the new optional input. |
| 5 | Consequences list both Positive and Negative outcomes | Pass | Finding noted for the next revision, not a blocker: a reusable workflow cannot learn the ref it was called at (the context fields `workflow_ref`, `workflow_sha`, `job_workflow_sha` and `action_ref` are empty on this instance, verified on 2026-10-11), so the script ref is an input and a call at an exact tag is pinned completely only with `tools-ref` set to the same tag. |
| 6 | Quality-attribute impacts (performance, security, portability, etc.) are named where the decision affects them | Pass | Maintainability gains (a script of this repository, linted and tested as a file); the pin limitation above is the reliability cost. |
| 7 | Affected Artifacts are listed as links, and each is also in CrossReference | Pass | Unchanged. |
| 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 with status Deprecated and a new row added. |
| 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 | Unchanged. |
| 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. |
## Overall Verdict
Go - all applicable criteria pass. Adding an optional input is a minor change under ADR-0006. S01 gave the Go in chat on 2026-10-11, standing in for the other reviewers as ADR-0002 records; there is no independent reader.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Run a pinned consumer (`@v1.0.1` with `tools-ref: v1.0.1`) after the next release to confirm the complete pin | S05 | next release |
---
[ADR-0005]: ../../adr/adr-0005-quality-check-contract.md
[QC-ADR-001]: ../../../framework/qc/qc-adr.md
[670f0ac]: https://git.tirsystem.com/TirSystem/github-action/commit/670f0ac469043bb166c84290c0dbf62b4908e3cc
+17 -9
View File
@@ -4,13 +4,13 @@
| 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] |
| 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], [RC-048], [RC-049], [RC-050], [RC-051], [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] |
| 2026-10-11 | Deprecated | Jens Tirsvad Nielsen | S01 | Added RC-050 (MIL-005 translations accepted) | [ead3d98] |
| 2026-10-11 | Accepted | Jens Tirsvad Nielsen | S01 | Added RC-051 (ADR-0005 tools-ref) | [670f0ac] |
---
@@ -30,15 +30,15 @@ updated whenever an artifact instance is created or reviewed.
| [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] |
| [MIL-004] | MIL | [BC-001], [PP-001], [MIL-003] | - | [RC-007], [RC-029], [RC-034], [RC-048] |
| [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] |
| [MIL-005] | MIL | [BC-001], [PP-001], [MIL-002] | [MIL-006] | [RC-010], [RC-011], [RC-030], [RC-050] |
| [MIL-006] | MIL | [BC-001], [PP-001], [MIL-002], [MIL-005] | - | [RC-016], [RC-031], [RC-049] |
| [RC-007] | RC | [MIL-004] | - | - |
| [RC-008] | RC | [BC-001] | - | - |
| [RC-009] | RC | [PP-001] | - | - |
@@ -62,7 +62,7 @@ updated whenever an artifact instance is created or reviewed.
| [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] |
| [ADR-0005] | ADR | [MIL-003], [UC-005], [US-001], [ADR-0004] | - | [RC-038], [RC-051] |
| [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] |
@@ -96,6 +96,10 @@ updated whenever an artifact instance is created or reviewed.
| [RC-045] | RC | [UCD-001] | - | - |
| [RC-046] | RC | [US-001] | - | - |
| [RC-047] | RC | [ADR-0007] | - | - |
| [RC-048] | RC | [MIL-004] | - | - |
| [RC-049] | RC | [MIL-006] | - | - |
| [RC-050] | RC | [MIL-005] | - | - |
| [RC-051] | RC | [ADR-0005] | - | - |
## Coverage Notes
@@ -172,11 +176,15 @@ updated whenever an artifact instance is created or reviewed.
[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
[RC-048]: ./reviews/rc-048-mil-004-outcome.md
[RC-049]: ./reviews/rc-049-mil-006-outcome.md
[RC-050]: ./reviews/rc-050-mil-005-outcome.md
[RC-051]: ./reviews/rc-051-adr-0005-tools-ref.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
[ead3d98]: https://git.tirsystem.com/TirSystem/github-action/commit/ead3d98d73fcab95fd57b0eb005a02aff9983256
[670f0ac]: https://git.tirsystem.com/TirSystem/github-action/commit/670f0ac469043bb166c84290c0dbf62b4908e3cc
+4
View File
@@ -9,6 +9,10 @@ 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.
**Status (2026-10-11):** no native reader was available; S01 accepted the
translations as the stand-in of ADR-0002 (RC-050). This checklist stays for
a native reader who wants to review them; the findings go in a pull request.
## What to review
Fifteen pages exist on the wiki. You review the five pages of your language.
+11 -4
View File
@@ -19,7 +19,7 @@ jobs:
quality:
permissions:
contents: read
uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@main
uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@v1
with:
languages: python,shell
```
@@ -32,10 +32,17 @@ jobs:
| `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) |
| `tools-ref` | `v1` | Tag or branch of `TirSystem/github-action` from which the script `tools/quality-checks.sh` is fetched |
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.
Reference the workflow at the major tag (`@v1`) or at an exact tag
(`@v1.0.0`), never at `main` and never at the branch of a pull request: that
branch is deleted when the pull request is merged and the reference stops
working. See the upgrade guide for what each choice receives.
The workflow file calls a script of this repository, fetched at `tools-ref`. A
call at an exact tag is pinned completely only when `tools-ref` names the same
tag, for example `@v1.0.1` with `tools-ref: v1.0.1`; with the default the
script follows `v1`.
## What is checked
+3 -3
View File
@@ -43,9 +43,9 @@ never starts, or stops before the step) is a **runner** problem.
## 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
`No GitHub push mirror configured for <repo>; nothing to sync.` followed by
`Skipped`. 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
+4
View File
@@ -16,6 +16,10 @@ repository, tags `vMAJOR.MINOR.PATCH` and a moving major tag `vMAJOR`.
A breaking release gets a new major version (`v2`), so a pipeline on `@v1`
never receives it until you change the line yourself.
The quality-checks workflow fetches its script at its input `tools-ref`, which
defaults to `v1`. To pin it completely, call it at an exact tag and set
`tools-ref` to the same tag; otherwise the script follows the major tag.
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.
+44 -4
View File
@@ -1,6 +1,7 @@
"""Offline tests for tools/build_wiki.py."""
import importlib.util
import re
from pathlib import Path
import pytest
@@ -91,9 +92,10 @@ def _write_sources(root: Path) -> None:
(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"
"## 🔧 Workflows\nA table and diagrams.\n\n### 🔄 Sync\nDetails.\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",
"## ▶️ Run\nGo.\n\n## 🧪 Tests\nPytest.\n\n## 🟢 Capabilities\nA table.\n\n### 🔎 Detail\nMore.\n\n"
"## 📄 License\nMIT.\n",
encoding="utf-8",
)
for name in ("onboarding", "credentials", "troubleshooting", "quality-checks", "upgrading"):
@@ -122,7 +124,8 @@ class TestRenderPage:
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 "### Detail" in text
assert "### Sync" not in text
assert "## Overview" not in text
def test_every_page_names_its_source_and_warns(self, repo):
@@ -154,7 +157,8 @@ class TestWriteAndCheck:
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)
expected = [f"{p.name}.md" for p in build_wiki.PAGES] + [build_wiki.SIDEBAR_NAME]
assert sorted(changed) == sorted(expected)
assert build_wiki.check_pages(wiki, repo) == []
assert build_wiki.write_pages(wiki, repo) == []
@@ -267,3 +271,39 @@ def test_committed_translations_follow_the_english_structure(page, code):
def test_committed_translations_are_current():
"""No translation follows an older version of its English page."""
assert build_wiki.check_translations() == []
class TestSidebar:
"""Gitea shows subpages only through _Sidebar, so it must reach every page."""
def test_links_every_page_in_every_language(self):
sidebar = build_wiki.render_sidebar()
for page in build_wiki.PAGES:
assert f"]({page.name})" in sidebar
for code, _label in build_wiki.LANGUAGES:
assert f"]({page.name}.{code})" in sidebar
def test_every_link_names_a_committed_page(self):
sidebar = build_wiki.render_sidebar()
targets = re.findall(r"\]\(([^)]+)\)", sidebar)
assert targets
for target in targets:
assert (build_wiki.WIKI_DIR / f"{target}.md").is_file(), target
def test_has_one_label_per_page_and_language(self):
for code in ("en", *(c for c, _ in build_wiki.LANGUAGES)):
assert len(build_wiki.SIDEBAR_LABELS[code]) == len(build_wiki.PAGES)
def test_home_lists_every_workflow_file_with_a_diagram():
"""The Home page names each workflow file of the repository and draws it."""
home = (REPO_ROOT / "wiki" / "Home.md").read_text(encoding="utf-8")
files = sorted(
path.name
for folder in (".gitea/scoped_workflows", ".gitea/workflows")
for path in (REPO_ROOT / folder).glob("*.yml")
)
assert files
for name in files:
assert f"[`{name}`]" in home, f"{name} is not listed on the Home page"
assert home.count("@startuml") == len(files)
+1 -1
View File
@@ -469,7 +469,7 @@ class TestWorkflow:
assert steps[0]["uses"].startswith("actions/checkout@")
assert steps[1]["with"] == {
"repository": "TirSystem/github-action",
"ref": "main",
"ref": "v1",
"path": "shared-scripts",
}
assert steps[-1]["run"] == "python3 shared-scripts/tools/publish_wiki.py"
+31 -9
View File
@@ -15,6 +15,8 @@ import yaml
from workflow_source import REPO_ROOT
WORKFLOW = REPO_ROOT / ".gitea" / "workflows" / "quality-checks.yml"
SCRIPT = REPO_ROOT / "tools" / "quality-checks.sh"
COMMANDS = {"Validate the inputs": "validate", "Install the tools": "install", "Run the checks": "run"}
BASH = shutil.which("bash")
pytestmark = pytest.mark.skipif(BASH is None, reason="bash is needed to run the workflow steps")
@@ -25,7 +27,7 @@ def document() -> dict:
return yaml.safe_load(WORKFLOW.read_text(encoding="utf-8"))
def step_script(document: dict, name: str) -> str:
def step_command(document: dict, name: str) -> str:
steps = document["jobs"]["quality-checks"]["steps"]
return next(step["run"] for step in steps if step.get("name") == name)
@@ -40,9 +42,11 @@ class TestDefinition:
"mypy-version",
"shellcheck-py-version",
"shfmt-py-version",
"tools-ref",
}
assert inputs["languages"]["default"] == "python,shell"
assert inputs["working-directory"]["default"] == "."
assert inputs["tools-ref"]["default"] == "v1"
def test_tool_versions_are_pinned_to_the_adr(self, document):
inputs = document[True]["workflow_call"]["inputs"]
@@ -60,14 +64,32 @@ class TestDefinition:
for step in document["jobs"]["quality-checks"]["steps"]:
assert "${{" not in step.get("run", ""), f"{step.get('name')} interpolates an expression"
@pytest.mark.parametrize(
"name", ["Validate the inputs", "Install the tools", "Run the checks"]
)
def test_every_script_parses(self, document, name):
script = step_script(document, name)
result = subprocess.run([BASH, "-n"], input=script, text=True, capture_output=True)
def test_the_script_parses(self):
result = subprocess.run([BASH, "-n", str(SCRIPT)], text=True, capture_output=True)
assert result.returncode == 0, result.stderr
def test_the_workflow_embeds_no_script_and_runs_the_file(self, document):
steps = document["jobs"]["quality-checks"]["steps"]
commands = [step["run"] for step in steps if "run" in step]
assert commands == [
"bash shared-scripts/tools/quality-checks.sh validate",
"bash shared-scripts/tools/quality-checks.sh install",
"bash shared-scripts/tools/quality-checks.sh run",
]
def test_the_script_is_fetched_at_the_tools_ref_input(self, document):
steps = document["jobs"]["quality-checks"]["steps"]
fetch = next(step for step in steps if step.get("name") == "Fetch the shared script")
assert fetch["with"] == {
"repository": "TirSystem/github-action",
"ref": "${{ inputs.tools-ref }}",
"path": "shared-scripts",
}
def test_an_unknown_command_is_refused(self):
result = subprocess.run([BASH, str(SCRIPT), "bogus"], text=True, capture_output=True)
assert result.returncode == 2
STUB = """#!/usr/bin/env bash
name="$(basename "$0")"
@@ -111,7 +133,7 @@ def add_files(root: Path, *relative: str) -> None:
def run_step(document, name, repo, bin_dir, tmp_path, **env):
script = step_script(document, name)
command = COMMANDS[name]
log = tmp_path / "tools.log"
environment = dict(os.environ)
environment.update(
@@ -126,7 +148,7 @@ def run_step(document, name, repo, bin_dir, tmp_path, **env):
)
environment.update(env)
result = subprocess.run(
[BASH, "-c", script], cwd=repo, env=environment, text=True, capture_output=True
[BASH, str(SCRIPT), command], cwd=repo, env=environment, text=True, capture_output=True
)
calls = log.read_text(encoding="utf-8").splitlines() if log.exists() else []
return result, calls
+3 -1
View File
@@ -245,7 +245,9 @@ class TestMain:
assert all(call[0] == "GET" for call in api.calls)
assert not any(call[1].startswith("https://api.github.com") for call in api.calls)
assert "No GitHub push mirror configured" in capsys.readouterr().out
output = capsys.readouterr().out
assert "No GitHub push mirror configured" in output
assert output.rstrip().splitlines()[-1] == "Skipped"
def test_fails_before_any_change_when_github_credentials_are_missing(
self, sync, environment, monkeypatch
+37 -5
View File
@@ -39,11 +39,11 @@ class Page:
PAGES: tuple[Page, ...] = (
Page("Home", "README.md", ("Overview", "Requirements", "Setup", "Run", "Tests")),
Page("Home", "README.md", ("Overview", "Workflows", "Requirements", "Setup", "Run", "Tests")),
Page("Onboarding", "guides/onboarding.md"),
Page("Credentials", "guides/credentials.md"),
Page("Troubleshooting", "guides/troubleshooting.md"),
Page("QualityChecks", "guides/quality-checks.md"),
Page("QualityChecksPythonShell", "guides/quality-checks.md"),
Page("Upgrading", "guides/upgrading.md"),
Page("Capabilities", "README.md", ("Capabilities",)),
)
@@ -61,7 +61,7 @@ _PAGE_FOR_SOURCE = {
"guides/onboarding.md": "Onboarding",
"guides/credentials.md": "Credentials",
"guides/troubleshooting.md": "Troubleshooting",
"guides/quality-checks.md": "QualityChecks",
"guides/quality-checks.md": "QualityChecksPythonShell",
"guides/upgrading.md": "Upgrading",
}
@@ -184,9 +184,41 @@ def render_page(page: Page, repo_root: Path = REPO_ROOT) -> str:
return banner + body + "\n"
# Link text of the sidebar: English, then one list per translation code.
SIDEBAR_TITLE = "TirSystem GitHub Actions"
SIDEBAR_LABELS: dict[str, tuple[str, ...]] = {
"en": ("Home", "Onboarding", "Credentials", "Troubleshooting", "Quality checks (Python, shell)", "Upgrading", "Capabilities"),
"da": ("Hjem", "Tilslutning", "Credentials", "Fejlfinding", "Kvalitetskontrol (Python, shell)", "Opgradering", "Kapabiliteter"),
"ms": ("Utama", "Menyertakan", "Kelayakan", "Diagnosis", "Semakan kualiti (Python, shell)", "Menaik taraf", "Keupayaan"),
}
SIDEBAR_NAME = "_Sidebar.md"
def render_sidebar() -> str:
"""Return the navigation shown beside every wiki page.
Gitea lists subpages only through a ``_Sidebar`` page, so without it a
visitor sees the home page and no way to the others.
"""
languages = (("en", "English", ""), *((code, label, f".{code}") for code, label in LANGUAGES))
lines = [
f"<!-- Generated by {GENERATOR}. Edit the generator, not this page. -->",
"",
f"**{SIDEBAR_TITLE}**",
]
for code, label, suffix in languages:
labels = SIDEBAR_LABELS[code]
assert len(labels) == len(PAGES), "one sidebar label per page"
lines += ["", f"**{label}**", ""]
lines += [f"- [{text}]({page.name}{suffix})" for text, page in zip(labels, PAGES)]
return chr(10).join(lines) + chr(10)
def build_all(repo_root: Path = REPO_ROOT) -> dict[str, str]:
"""Return ``{file name: content}`` for every English page."""
return {f"{page.name}.md": render_page(page, repo_root) for page in PAGES}
"""Return ``{file name: content}`` for every English page and the sidebar."""
pages = {f"{page.name}.md": render_page(page, repo_root) for page in PAGES}
pages[SIDEBAR_NAME] = render_sidebar()
return pages
def write_pages(wiki_dir: Path = WIKI_DIR, repo_root: Path = REPO_ROOT) -> list[str]:
+122
View File
@@ -0,0 +1,122 @@
#!/usr/bin/env bash
# Steps of the reusable workflow .gitea/workflows/quality-checks.yml (ADR-0005).
# The workflow checks out the calling repository, fetches this file into
# shared-scripts/ and runs one command per step:
#
# quality-checks.sh validate check the inputs, before anything is installed
# quality-checks.sh install install the pinned tools into a virtual environment
# quality-checks.sh run run every selected tool on the tracked files
#
# Settings come from the environment, never from interpolated expressions:
# LANGUAGES, WORKING_DIRECTORY, RUFF_VERSION, MYPY_VERSION,
# SHELLCHECK_PY_VERSION, SHFMT_PY_VERSION, QC_VENV (and QC_BIN for tests).
# Every failure is printed as ::error::[category] message.
validate_inputs() {
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}"
}
install_tools() {
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[@]}"
}
run_checks() {
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."
}
case "${1:-}" in
validate) validate_inputs ;;
install) install_tools ;;
run) run_checks ;;
*)
echo "::error::[configuration] usage: quality-checks.sh validate|install|run" >&2
exit 2
;;
esac
+1
View File
@@ -170,6 +170,7 @@ def main():
"No GitHub push mirror configured for "
f"{source_owner}/{source_repo}; nothing to sync."
)
print("Skipped")
return 0
github_token = parse_github_token(os.environ.get("PAT_FOR_GITHUB"))
+5 -71
View File
@@ -1,4 +1,4 @@
<!-- translation of Capabilities.md, source sha256 94af1c3e6949 -->
<!-- translation of Capabilities.md, source sha256 a8c03a001880 -->
> Dette er en oversættelse af [`Capabilities`](Capabilities). Den engelske side er autoritativ, og ændringer her bliver overskrevet, næste gang wikien publiceres.
@@ -12,73 +12,7 @@ Rækker, der siger Implementeret eller Vejledninger er skrevet, findes i dag. Re
| --- | --- |
| Synkronisering af repositorymetadata (Gitea til GitHub-spejl) | Implementeret i `.gitea/scoped_workflows/`, med offline-tests og et valideringsworkflow |
| Konfiguration og validering af workflow-credentials | Implementeret for synkroniseringsworkflowet: en forhåndskontrol tjekker begge tokens før enhver ændring ([vejledning](Credentials.da)) |
| Tilslutning af et repository, administration af runners, fejlfinding | Vejledninger er skrevet ([tilslutning](Onboarding.da), [fejlfinding](Troubleshooting.da)); scoped levering til andre repositories er ikke verificeret endnu; korte use cases er åbne (MIL-002) |
| Publicering af et repositorys wiki fra `wiki/` (tilmelding, leveres til alle organisationer) | Implementeret i `.gitea/scoped_workflows/publish-wiki.yml`, med offline-tests; pilotforsøget i et andet repository afventer (MIL-006) |
| Fælles kvalitetskontrol (Python og shell) | Implementeret som det genbrugelige workflow `.gitea/workflows/quality-checks.yml`, med offline-tests og et forsøg i en anden organisation; tilslutningen i RepoFoundry er til gennemgang ([vejledning](QualityChecks.da)) |
| Versioneret udgivelse og publicering | Udgivelsesproces, changelog og opgraderingsvejledning er defineret; udgivelsesworkflowet findes; den første udgivelse `v1.0.0` mangler (MIL-004) ([vejledning](Upgrading.da)) |
### Synkronisering af GitHub-metadata
Synkroniserer Gitea-repositoryets beskrivelse og emner til GitHub push-spejlet.
#### Tidsplan (cron)
Dagligt kl. 03:17 UTC (`17 3 * * *`) samt ved hvert push til `main` og manuel `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
```
| Tilslutning af et repository, administration af runners, fejlfinding | Vejledninger er skrevet ([tilslutning](Onboarding.da), [fejlfinding](Troubleshooting.da)); scoped levering til alle fire organisationers repositories er verificeret (MIL-002) |
| Publicering af et repositorys wiki fra `wiki/` (tilmelding, leveres til alle organisationer) | Implementeret i `.gitea/scoped_workflows/publish-wiki.yml`, med offline-tests; et pilotforsøg i et andet repository publicerer sin wiki (MIL-006) |
| Fælles kvalitetskontrol (Python og shell) | Implementeret som det genbrugelige workflow `.gitea/workflows/quality-checks.yml`, med offline-tests og et forsøg i en anden organisation; taget i brug i RepoFoundry ([vejledning](QualityChecksPythonShell.da)) |
| Versioneret udgivelse og publicering | Udgivelsesproces, changelog og opgraderingsvejledning er defineret; udgivelsesworkflowet findes, og `v1.0.0` er udgivet (MIL-004) ([vejledning](Upgrading.da)) |
+4 -70
View File
@@ -12,73 +12,7 @@ Rows that say Implemented or Guides written exist today. The rest is planned and
| --- | --- |
| 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](Credentials)) |
| Onboard a repository, manage runners, diagnose failures | Guides written ([onboarding](Onboarding), [troubleshooting](Troubleshooting)); 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](QualityChecks)) |
| 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](Upgrading)) |
### 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
```
| Onboard a repository, manage runners, diagnose failures | Guides written ([onboarding](Onboarding), [troubleshooting](Troubleshooting)); scoped delivery to the repositories of all four organizations verified (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; a pilot in a second repository publishes its wiki (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; adopted in RepoFoundry ([guide](QualityChecksPythonShell)) |
| Versioned release and publishing | Release process, changelog and upgrade guide defined; the release workflow exists and `v1.0.0` is released (MIL-004) ([guide](Upgrading)) |
+5 -71
View File
@@ -1,4 +1,4 @@
<!-- translation of Capabilities.md, source sha256 94af1c3e6949 -->
<!-- translation of Capabilities.md, source sha256 a8c03a001880 -->
> Ini ialah terjemahan [`Capabilities`](Capabilities). Halaman bahasa Inggeris ialah teks yang sah, dan perubahan di sini akan ditimpa pada penerbitan wiki yang seterusnya.
@@ -12,73 +12,7 @@ Baris yang menyatakan Dilaksanakan atau Panduan telah ditulis wujud hari ini. Se
| --- | --- |
| Menyegerakkan metadata repositori (Gitea ke cermin GitHub) | Dilaksanakan dalam `.gitea/scoped_workflows/`, dengan ujian luar talian dan aliran kerja pengesahan |
| Mengkonfigur dan mengesahkan kelayakan (credentials) aliran kerja | Dilaksanakan untuk aliran kerja penyegerakan: semakan awal (preflight) memeriksa kedua-dua token sebelum sebarang perubahan ([panduan](Credentials.ms)) |
| Menyertakan repositori, mengurus runner, mendiagnosis kegagalan | Panduan telah ditulis ([menyertakan repositori](Onboarding.ms), [diagnosis](Troubleshooting.ms)); penghantaran scoped ke repositori lain belum disahkan; use case ringkas masih terbuka (MIL-002) |
| Menerbitkan wiki repositori daripada `wiki/` (pilih menyertai, dihantar ke setiap organisasi) | Dilaksanakan dalam `.gitea/scoped_workflows/publish-wiki.yml`, dengan ujian luar talian; juruterbang dalam repositori kedua belum dibuat (MIL-006) |
| Semakan kualiti bersama (Python dan shell) | Dilaksanakan sebagai aliran kerja boleh guna semula `.gitea/workflows/quality-checks.yml`, dengan ujian luar talian dan percubaan dalam organisasi kedua; penerimaan dalam RepoFoundry sedang disemak ([panduan](QualityChecks.ms)) |
| Keluaran berversi dan penerbitan | Proses keluaran, changelog dan panduan naik taraf telah ditakrifkan; aliran kerja keluaran sudah ada; keluaran pertama `v1.0.0` belum ada (MIL-004) ([panduan](Upgrading.ms)) |
### Menyegerakkan metadata GitHub
Menyegerakkan penerangan dan topik repositori Gitea ke push mirror GitHub.
#### Jadual (cron)
Setiap hari pada 03:17 UTC (`17 3 * * *`), serta pada setiap push ke `main` dan `workflow_dispatch` manual.
#### Aliran kerja
```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
```
| Menyertakan repositori, mengurus runner, mendiagnosis kegagalan | Panduan telah ditulis ([menyertakan repositori](Onboarding.ms), [diagnosis](Troubleshooting.ms)); penghantaran scoped ke repositori keempat-empat organisasi telah disahkan (MIL-002) |
| Menerbitkan wiki repositori daripada `wiki/` (pilih menyertai, dihantar ke setiap organisasi) | Dilaksanakan dalam `.gitea/scoped_workflows/publish-wiki.yml`, dengan ujian luar talian; satu juruterbang dalam repositori kedua menerbitkan wikinya (MIL-006) |
| Semakan kualiti bersama (Python dan shell) | Dilaksanakan sebagai aliran kerja boleh guna semula `.gitea/workflows/quality-checks.yml`, dengan ujian luar talian dan percubaan dalam organisasi kedua; digunakan dalam RepoFoundry ([panduan](QualityChecksPythonShell.ms)) |
| Keluaran berversi dan penerbitan | Proses keluaran, changelog dan panduan naik taraf telah ditakrifkan; aliran kerja keluaran sudah ada dan `v1.0.0` telah dikeluarkan (MIL-004) ([panduan](Upgrading.ms)) |
+250 -2
View File
@@ -1,4 +1,4 @@
<!-- translation of Home.md, source sha256 eedaeddbea3e -->
<!-- translation of Home.md, source sha256 8d1f5ed6df38 -->
> Dette er en oversættelse af [`Home`](Home). Den engelske side er autoritativ, og ændringer her bliver overskrevet, næste gang wikien publiceres.
@@ -13,7 +13,255 @@ En samling af genbrugelige Gitea Actions-workflows til DevOps-professionelle og
Dette repository er den centrale samling af genbrugelig automatisering til TirSystems repositories. Det primære repository ligger på `git.tirsystem.com` (Gitea) og spejles med push til GitHub.
Det indeholder i øjeblikket Gitea-workflowet [`sync-github-metadata.yml`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.gitea/scoped_workflows/sync-github-metadata.yml), som kopierer repositoryets beskrivelse og emner (topics) fra Gitea til GitHub-spejlet ved hvert push til `main`, ved manuel kørsel og dagligt kl. 03:17 UTC.
Det indeholder fem workflows: synkronisering af metadata til GitHub-spejlet, publicering af wiki, fælles kvalitetskontrol, et udgivelsesworkflow og repositoryets egen validering. De er listet med formål og diagram under [Workflows](#workflows).
## Workflows
Der er fem workflows i dette repository. Et **scoped** workflow leveres af instansen til alle repositories i TirSystem-organisationerne og kræver intet i repositoryet; et **genbrugeligt** workflow kaldes fra et repository med `uses:`; de øvrige kører kun her. Diagrammerne er PlantUML-kildekode og er på engelsk.
| Workflow | Fil | Type | Starter ved | Formål |
| --- | --- | --- | --- | --- |
| Sync GitHub mirror metadata | [`sync-github-metadata.yml`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.gitea/scoped_workflows/sync-github-metadata.yml) | Scoped | push til `main`, manuelt, dagligt kl. 03:17 UTC | Kopierer beskrivelsen og emnerne for et Gitea-repository til dets GitHub push-spejl |
| Publish wiki | [`publish-wiki.yml`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.gitea/scoped_workflows/publish-wiki.yml) | Scoped, tilmelding med `wiki/.publish` | push til `main`, der ændrer `wiki/**`, manuelt | Publicerer siderne i `wiki/` til repositoryets wiki |
| Quality checks | [`quality-checks.yml`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.gitea/workflows/quality-checks.yml) | Genbrugeligt (`workflow_call`) | et kald fra et andet repository | Kører ruff, mypy, shellcheck og shfmt på de sporede filer og ændrer intet |
| Release | [`release.yml`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.gitea/workflows/release.yml) | Kun dette repository | manuelt | Opretter versionstagget, udgivelsessiden og major-tagget efter kontrollerne |
| Validate workflows | [`validate-workflows.yml`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.gitea/workflows/validate-workflows.yml) | Kun dette repository | pull request, push til `main`, manuelt | Læser hvert workflow som YAML og kører offline-testene |
### Synkronisering af GitHub-metadata
Synkroniserer Gitea-repositoryets beskrivelse og emner til GitHub push-spejlet.
#### Tidsplan (cron)
Dagligt kl. 03:17 UTC (`17 3 * * *`) samt ved hvert push til `main` og manuel `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
```
### Publicering af wiki
Publicerer `wiki/` til repositoryets wiki, kun i et repository, der har tilmeldt sig med `wiki/.publish`. Ordet `prune` i den fil sletter også sider, som ikke findes i `wiki/`.
#### Workflow
```plantuml
@startuml
title Publish wiki/ to the repository wiki
autonumber
actor "Push to main that changes wiki/**,\nor manual trigger" as Trigger
participant "Gitea Actions\npublish-wiki" as Workflow
participant "shared-scripts\n(tools/publish_wiki.py at v1)" as Script
participant "Gitea wiki API" as Wiki
Trigger -> Workflow: Start workflow
activate Workflow
Workflow -> Script: Check out the repository and the script, run it
activate Script
alt wiki/.publish does not exist
Script --> Workflow: Log that publishing is not enabled and succeed\n(nothing is written)
else wiki/ has no Markdown pages
Script --> Workflow: Fail with [configuration]\n(an empty wiki/ never deletes pages)
else
Script -> Script: Read the marker (empty, or the word prune)\nand TOKEN_FOR_GITEA_WIKI
Script -> Wiki: GET repository (preflight)
Wiki --> Script: Wiki is enabled, token accepted
Script -> Wiki: GET pages
Wiki --> Script: Existing pages
Script -> Wiki: Create new pages, update changed pages
opt marker says prune
Script -> Wiki: Delete pages that are not in wiki/
end
Script --> Workflow: Log created, updated and deleted counts
end
deactivate Script
Workflow --> Trigger: Workflow result
deactivate Workflow
@enduml
```
### Kvalitetskontrol
Et genbrugeligt workflow til Python og shell, kaldt med `uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@v1` (se [vejledningen](QualityChecksPythonShell)).
#### Workflow
```plantuml
@startuml
title Shared quality checks (reusable workflow)
autonumber
actor "Calling repository\nuses: ...quality-checks.yml@v1" as Caller
participant "Gitea Actions\nquality-checks" as Workflow
participant "PyPI" as PyPI
Caller -> Workflow: workflow_call with languages,\nworking-directory and tool versions
activate Workflow
Workflow -> Workflow: Validate the inputs
alt languages or working-directory is invalid
Workflow --> Caller: Fail with [configuration]
end
Workflow -> Workflow: Check out the calling repository
Workflow -> PyPI: Install the pinned tools in a virtual environment\n(ruff, mypy, shellcheck-py, shfmt-py as selected)
PyPI --> Workflow: Tools installed
loop for each selected language
Workflow -> Workflow: List tracked files
alt no files of that language
Workflow -> Workflow: Notice: nothing was checked
else
Workflow -> Workflow: Run every tool and record PASS or FAIL
end
end
alt any tool failed
Workflow --> Caller: Fail and list the failed tools
else
Workflow --> Caller: All selected checks passed
end
deactivate Workflow
@enduml
```
### Udgivelse
Startes manuelt af en vedligeholder; med `dry_run` `true` (standard) kontrollerer det kun (se [udgivelsesprocessen](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/guides/release-process.md)).
#### Workflow
```plantuml
@startuml
title Release this repository
autonumber
actor "Maintainer\n(workflow_dispatch: version, dry_run)" as Trigger
participant "Gitea Actions\nrelease" as Workflow
participant "Gitea REST API" as Gitea
Trigger -> Workflow: Start with version and dry_run
activate Workflow
Workflow -> Workflow: Check the version and read CHANGELOG.md
alt version malformed or no changelog entry
Workflow --> Trigger: Fail with [validation] or [configuration]
end
Workflow -> Gitea: GET branch main and status of the commit
Gitea --> Workflow: Tip of main and the validation run
alt commit is not the tip of main,\nor the validation run is not green
Workflow --> Trigger: Fail with [validation]\n(no tag is created)
end
Workflow -> Gitea: GET tags
Gitea --> Workflow: Existing tags
alt tag vMAJOR.MINOR.PATCH exists
Workflow --> Trigger: Fail with [validation]\n(tags are never moved)
end
alt dry_run is true (default)
Workflow --> Trigger: Log what would be created and stop
else
Workflow -> Gitea: POST release (creates the version tag,\nbody is the changelog entry)
opt this is the highest version of its major
Workflow -> Gitea: Delete and recreate the major tag vMAJOR
end
Workflow --> Trigger: Released
end
deactivate Workflow
@enduml
```
### Validering af workflows
Repositoryets egen validering: de offline-tests, der er en betingelse for hver pull request.
#### Workflow
```plantuml
@startuml
title Validate workflows (this repository's own checks)
autonumber
actor "Pull request,\npush to main, or manual trigger" as Trigger
participant "Gitea Actions\nvalidate-workflows" as Workflow
Trigger -> Workflow: Start workflow
activate Workflow
Workflow -> Workflow: Check out the repository
Workflow -> Workflow: Create a virtual environment and\ninstall tests/requirements.txt
Workflow -> Workflow: Run pytest on tests/ (offline, no secrets):\nworkflows parse as YAML, no embedded Python,\nscripts compile, wiki pages and translations are current,\nsync, publish and release flows against a fake API
alt a test fails
Workflow --> Trigger: Workflow fails (the pull request is not ready)
else
Workflow --> Trigger: Workflow succeeds
end
deactivate Workflow
@enduml
```
## Krav
+249 -1
View File
@@ -13,7 +13,255 @@ A collection of reusable Gitea Actions workflows for DevOps professionals and so
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`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.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.
It contains five workflows: metadata sync to the GitHub mirror, wiki publishing, shared quality checks, a release workflow and the repository's own validation. They are listed with their purpose and a diagram under [Workflows](#workflows).
## Workflows
Five workflows live in this repository. A **scoped** workflow is delivered by the instance to every repository of the TirSystem organizations and needs nothing in the repository; a **reusable** workflow is called by a repository with `uses:`; the others run only here. The diagrams are PlantUML source.
| Workflow | File | Kind | Starts on | Purpose |
| --- | --- | --- | --- | --- |
| Sync GitHub mirror metadata | [`sync-github-metadata.yml`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.gitea/scoped_workflows/sync-github-metadata.yml) | Scoped | push to `main`, manual, daily 03:17 UTC | Copies the description and topics of a Gitea repository to its GitHub push mirror |
| Publish wiki | [`publish-wiki.yml`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.gitea/scoped_workflows/publish-wiki.yml) | Scoped, opt-in with `wiki/.publish` | push to `main` that changes `wiki/**`, manual | Publishes the pages in `wiki/` to the repository wiki |
| Quality checks | [`quality-checks.yml`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.gitea/workflows/quality-checks.yml) | Reusable (`workflow_call`) | a call from another repository | Runs ruff, mypy, shellcheck and shfmt on the tracked files and changes nothing |
| Release | [`release.yml`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.gitea/workflows/release.yml) | This repository only | manual | Creates the version tag, the release page and the major tag after the checks |
| Validate workflows | [`validate-workflows.yml`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.gitea/workflows/validate-workflows.yml) | This repository only | pull request, push to `main`, manual | Parses every workflow and runs the offline tests |
### 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
```
### Publish wiki
Publishes `wiki/` to the repository wiki, only in a repository that has opted in with `wiki/.publish`. The word `prune` in that file also deletes pages that are not in `wiki/`.
#### Workflow
```plantuml
@startuml
title Publish wiki/ to the repository wiki
autonumber
actor "Push to main that changes wiki/**,\nor manual trigger" as Trigger
participant "Gitea Actions\npublish-wiki" as Workflow
participant "shared-scripts\n(tools/publish_wiki.py at v1)" as Script
participant "Gitea wiki API" as Wiki
Trigger -> Workflow: Start workflow
activate Workflow
Workflow -> Script: Check out the repository and the script, run it
activate Script
alt wiki/.publish does not exist
Script --> Workflow: Log that publishing is not enabled and succeed\n(nothing is written)
else wiki/ has no Markdown pages
Script --> Workflow: Fail with [configuration]\n(an empty wiki/ never deletes pages)
else
Script -> Script: Read the marker (empty, or the word prune)\nand TOKEN_FOR_GITEA_WIKI
Script -> Wiki: GET repository (preflight)
Wiki --> Script: Wiki is enabled, token accepted
Script -> Wiki: GET pages
Wiki --> Script: Existing pages
Script -> Wiki: Create new pages, update changed pages
opt marker says prune
Script -> Wiki: Delete pages that are not in wiki/
end
Script --> Workflow: Log created, updated and deleted counts
end
deactivate Script
Workflow --> Trigger: Workflow result
deactivate Workflow
@enduml
```
### Quality checks
A reusable workflow for Python and shell, called with `uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@v1` (see the [guide](QualityChecksPythonShell)).
#### Workflow
```plantuml
@startuml
title Shared quality checks (reusable workflow)
autonumber
actor "Calling repository\nuses: ...quality-checks.yml@v1" as Caller
participant "Gitea Actions\nquality-checks" as Workflow
participant "PyPI" as PyPI
Caller -> Workflow: workflow_call with languages,\nworking-directory and tool versions
activate Workflow
Workflow -> Workflow: Validate the inputs
alt languages or working-directory is invalid
Workflow --> Caller: Fail with [configuration]
end
Workflow -> Workflow: Check out the calling repository
Workflow -> PyPI: Install the pinned tools in a virtual environment\n(ruff, mypy, shellcheck-py, shfmt-py as selected)
PyPI --> Workflow: Tools installed
loop for each selected language
Workflow -> Workflow: List tracked files
alt no files of that language
Workflow -> Workflow: Notice: nothing was checked
else
Workflow -> Workflow: Run every tool and record PASS or FAIL
end
end
alt any tool failed
Workflow --> Caller: Fail and list the failed tools
else
Workflow --> Caller: All selected checks passed
end
deactivate Workflow
@enduml
```
### Release
Started by hand by a maintainer; with `dry_run` `true` (the default) it only checks (see the [release process](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/guides/release-process.md)).
#### Workflow
```plantuml
@startuml
title Release this repository
autonumber
actor "Maintainer\n(workflow_dispatch: version, dry_run)" as Trigger
participant "Gitea Actions\nrelease" as Workflow
participant "Gitea REST API" as Gitea
Trigger -> Workflow: Start with version and dry_run
activate Workflow
Workflow -> Workflow: Check the version and read CHANGELOG.md
alt version malformed or no changelog entry
Workflow --> Trigger: Fail with [validation] or [configuration]
end
Workflow -> Gitea: GET branch main and status of the commit
Gitea --> Workflow: Tip of main and the validation run
alt commit is not the tip of main,\nor the validation run is not green
Workflow --> Trigger: Fail with [validation]\n(no tag is created)
end
Workflow -> Gitea: GET tags
Gitea --> Workflow: Existing tags
alt tag vMAJOR.MINOR.PATCH exists
Workflow --> Trigger: Fail with [validation]\n(tags are never moved)
end
alt dry_run is true (default)
Workflow --> Trigger: Log what would be created and stop
else
Workflow -> Gitea: POST release (creates the version tag,\nbody is the changelog entry)
opt this is the highest version of its major
Workflow -> Gitea: Delete and recreate the major tag vMAJOR
end
Workflow --> Trigger: Released
end
deactivate Workflow
@enduml
```
### Validate workflows
The repository's own validation: the offline tests that gate every pull request.
#### Workflow
```plantuml
@startuml
title Validate workflows (this repository's own checks)
autonumber
actor "Pull request,\npush to main, or manual trigger" as Trigger
participant "Gitea Actions\nvalidate-workflows" as Workflow
Trigger -> Workflow: Start workflow
activate Workflow
Workflow -> Workflow: Check out the repository
Workflow -> Workflow: Create a virtual environment and\ninstall tests/requirements.txt
Workflow -> Workflow: Run pytest on tests/ (offline, no secrets):\nworkflows parse as YAML, no embedded Python,\nscripts compile, wiki pages and translations are current,\nsync, publish and release flows against a fake API
alt a test fails
Workflow --> Trigger: Workflow fails (the pull request is not ready)
else
Workflow --> Trigger: Workflow succeeds
end
deactivate Workflow
@enduml
```
## Requirements
+250 -2
View File
@@ -1,4 +1,4 @@
<!-- translation of Home.md, source sha256 eedaeddbea3e -->
<!-- translation of Home.md, source sha256 8d1f5ed6df38 -->
> Ini ialah terjemahan [`Home`](Home). Halaman bahasa Inggeris ialah teks yang sah, dan perubahan di sini akan ditimpa pada penerbitan wiki yang seterusnya.
@@ -13,7 +13,255 @@ Koleksi aliran kerja (workflow) Gitea Actions yang boleh digunakan semula untuk
Repositori ini ialah koleksi pusat bagi automasi yang boleh digunakan semula untuk repositori TirSystem. Repositori utama berada di `git.tirsystem.com` (Gitea) dan dicerminkan dengan push ke GitHub.
Buat masa ini ia mengandungi aliran kerja Gitea [`sync-github-metadata.yml`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.gitea/scoped_workflows/sync-github-metadata.yml), yang menyalin penerangan dan topik repositori dari Gitea ke cermin GitHub pada setiap push ke `main`, pada pencetusan manual dan setiap hari pada 03:17 UTC.
Ia mengandungi lima aliran kerja: penyegerakan metadata ke cermin GitHub, penerbitan wiki, semakan kualiti bersama, aliran kerja keluaran dan pengesahan repositori sendiri. Ia disenaraikan dengan tujuan dan rajah di bawah [Aliran kerja](#aliran-kerja).
## Aliran kerja
Terdapat lima aliran kerja dalam repositori ini. Aliran kerja **scoped** dihantar oleh instans ke setiap repositori organisasi TirSystem dan tidak memerlukan apa-apa dalam repositori; aliran kerja **boleh guna semula** dipanggil oleh sebuah repositori dengan `uses:`; yang lain hanya berjalan di sini. Rajah ialah kod sumber PlantUML dan dalam bahasa Inggeris.
| Aliran kerja | Fail | Jenis | Bermula apabila | Tujuan |
| --- | --- | --- | --- | --- |
| Sync GitHub mirror metadata | [`sync-github-metadata.yml`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.gitea/scoped_workflows/sync-github-metadata.yml) | Scoped | push ke `main`, manual, setiap hari 03:17 UTC | Menyalin penerangan dan topik repositori Gitea ke push mirror GitHub-nya |
| Publish wiki | [`publish-wiki.yml`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.gitea/scoped_workflows/publish-wiki.yml) | Scoped, pilih menyertai dengan `wiki/.publish` | push ke `main` yang mengubah `wiki/**`, manual | Menerbitkan halaman dalam `wiki/` ke wiki repositori |
| Quality checks | [`quality-checks.yml`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.gitea/workflows/quality-checks.yml) | Boleh guna semula (`workflow_call`) | panggilan daripada repositori lain | Menjalankan ruff, mypy, shellcheck dan shfmt pada fail yang dijejaki dan tidak mengubah apa-apa |
| Release | [`release.yml`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.gitea/workflows/release.yml) | Repositori ini sahaja | manual | Mencipta tag versi, halaman keluaran dan tag major selepas semakan |
| Validate workflows | [`validate-workflows.yml`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/.gitea/workflows/validate-workflows.yml) | Repositori ini sahaja | pull request, push ke `main`, manual | Menghurai setiap aliran kerja sebagai YAML dan menjalankan ujian luar talian |
### Menyegerakkan metadata GitHub
Menyegerakkan penerangan dan topik repositori Gitea ke push mirror GitHub.
#### Jadual (cron)
Setiap hari pada 03:17 UTC (`17 3 * * *`), serta pada setiap push ke `main` dan `workflow_dispatch` manual.
#### Aliran kerja
```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
```
### Menerbitkan wiki
Menerbitkan `wiki/` ke wiki repositori, hanya dalam repositori yang telah menyertai dengan `wiki/.publish`. Perkataan `prune` dalam fail itu juga memadam halaman yang tiada dalam `wiki/`.
#### Aliran kerja
```plantuml
@startuml
title Publish wiki/ to the repository wiki
autonumber
actor "Push to main that changes wiki/**,\nor manual trigger" as Trigger
participant "Gitea Actions\npublish-wiki" as Workflow
participant "shared-scripts\n(tools/publish_wiki.py at v1)" as Script
participant "Gitea wiki API" as Wiki
Trigger -> Workflow: Start workflow
activate Workflow
Workflow -> Script: Check out the repository and the script, run it
activate Script
alt wiki/.publish does not exist
Script --> Workflow: Log that publishing is not enabled and succeed\n(nothing is written)
else wiki/ has no Markdown pages
Script --> Workflow: Fail with [configuration]\n(an empty wiki/ never deletes pages)
else
Script -> Script: Read the marker (empty, or the word prune)\nand TOKEN_FOR_GITEA_WIKI
Script -> Wiki: GET repository (preflight)
Wiki --> Script: Wiki is enabled, token accepted
Script -> Wiki: GET pages
Wiki --> Script: Existing pages
Script -> Wiki: Create new pages, update changed pages
opt marker says prune
Script -> Wiki: Delete pages that are not in wiki/
end
Script --> Workflow: Log created, updated and deleted counts
end
deactivate Script
Workflow --> Trigger: Workflow result
deactivate Workflow
@enduml
```
### Semakan kualiti
Aliran kerja boleh guna semula untuk Python dan shell, dipanggil dengan `uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@v1` (lihat [panduan](QualityChecksPythonShell)).
#### Aliran kerja
```plantuml
@startuml
title Shared quality checks (reusable workflow)
autonumber
actor "Calling repository\nuses: ...quality-checks.yml@v1" as Caller
participant "Gitea Actions\nquality-checks" as Workflow
participant "PyPI" as PyPI
Caller -> Workflow: workflow_call with languages,\nworking-directory and tool versions
activate Workflow
Workflow -> Workflow: Validate the inputs
alt languages or working-directory is invalid
Workflow --> Caller: Fail with [configuration]
end
Workflow -> Workflow: Check out the calling repository
Workflow -> PyPI: Install the pinned tools in a virtual environment\n(ruff, mypy, shellcheck-py, shfmt-py as selected)
PyPI --> Workflow: Tools installed
loop for each selected language
Workflow -> Workflow: List tracked files
alt no files of that language
Workflow -> Workflow: Notice: nothing was checked
else
Workflow -> Workflow: Run every tool and record PASS or FAIL
end
end
alt any tool failed
Workflow --> Caller: Fail and list the failed tools
else
Workflow --> Caller: All selected checks passed
end
deactivate Workflow
@enduml
```
### Keluaran
Dimulakan secara manual oleh penyelenggara; dengan `dry_run` `true` (lalai) ia hanya menyemak (lihat [proses keluaran](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/guides/release-process.md)).
#### Aliran kerja
```plantuml
@startuml
title Release this repository
autonumber
actor "Maintainer\n(workflow_dispatch: version, dry_run)" as Trigger
participant "Gitea Actions\nrelease" as Workflow
participant "Gitea REST API" as Gitea
Trigger -> Workflow: Start with version and dry_run
activate Workflow
Workflow -> Workflow: Check the version and read CHANGELOG.md
alt version malformed or no changelog entry
Workflow --> Trigger: Fail with [validation] or [configuration]
end
Workflow -> Gitea: GET branch main and status of the commit
Gitea --> Workflow: Tip of main and the validation run
alt commit is not the tip of main,\nor the validation run is not green
Workflow --> Trigger: Fail with [validation]\n(no tag is created)
end
Workflow -> Gitea: GET tags
Gitea --> Workflow: Existing tags
alt tag vMAJOR.MINOR.PATCH exists
Workflow --> Trigger: Fail with [validation]\n(tags are never moved)
end
alt dry_run is true (default)
Workflow --> Trigger: Log what would be created and stop
else
Workflow -> Gitea: POST release (creates the version tag,\nbody is the changelog entry)
opt this is the highest version of its major
Workflow -> Gitea: Delete and recreate the major tag vMAJOR
end
Workflow --> Trigger: Released
end
deactivate Workflow
@enduml
```
### Mengesahkan aliran kerja
Pengesahan repositori sendiri: ujian luar talian yang menjadi syarat bagi setiap pull request.
#### Aliran kerja
```plantuml
@startuml
title Validate workflows (this repository's own checks)
autonumber
actor "Pull request,\npush to main, or manual trigger" as Trigger
participant "Gitea Actions\nvalidate-workflows" as Workflow
Trigger -> Workflow: Start workflow
activate Workflow
Workflow -> Workflow: Check out the repository
Workflow -> Workflow: Create a virtual environment and\ninstall tests/requirements.txt
Workflow -> Workflow: Run pytest on tests/ (offline, no secrets):\nworkflows parse as YAML, no embedded Python,\nscripts compile, wiki pages and translations are current,\nsync, publish and release flows against a fake API
alt a test fails
Workflow --> Trigger: Workflow fails (the pull request is not ready)
else
Workflow --> Trigger: Workflow succeeds
end
deactivate Workflow
@enduml
```
## Keperluan
@@ -1,8 +1,8 @@
<!-- translation of QualityChecks.md, source sha256 84ed5e09689a -->
<!-- translation of QualityChecksPythonShell.md, source sha256 2a0c9d43c77d -->
> Dette er en oversættelse af [`QualityChecks`](QualityChecks). Den engelske side er autoritativ, og ændringer her bliver overskrevet, næste gang wikien publiceres.
> Dette er en oversættelse af [`QualityChecksPythonShell`](QualityChecksPythonShell). Den engelske side er autoritativ, og ændringer her bliver overskrevet, næste gang wikien publiceres.
[English](QualityChecks) | Dansk | [Bahasa Melayu](QualityChecks.ms)
[English](QualityChecksPythonShell) | Dansk | [Bahasa Melayu](QualityChecksPythonShell.ms)
# Aflæsning af resultater fra kvalitetskontrol
@@ -22,7 +22,7 @@ jobs:
quality:
permissions:
contents: read
uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@main
uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@v1
with:
languages: python,shell
```
@@ -35,8 +35,11 @@ jobs:
| `mypy-version` | `1.11.2` | Version af mypy |
| `shellcheck-py-version` | `0.10.0.1` | Version af pakken shellcheck-py (ShellCheck 0.10.0) |
| `shfmt-py-version` | `3.11.0.2` | Version af pakken shfmt-py (shfmt 3.11.0) |
| `tools-ref` | `v1` | Tag eller gren i `TirSystem/github-action`, hvorfra scriptet `tools/quality-checks.sh` hentes |
Henvis til workflowet ved `main` eller et tag, aldrig ved en pull requests gren: den gren slettes, når pull requesten flettes, og henvisningen holder op med at virke.
Henvis til workflowet ved major-tagget (`@v1`) eller et præcist tag (`@v1.0.0`), aldrig ved `main` og aldrig ved en pull requests gren: den gren slettes, når pull requesten flettes, og henvisningen holder op med at virke. Se opgraderingsvejledningen for, hvad hvert valg modtager.
Workflowfilen kalder et script i dette repository, hentet ved `tools-ref`. Et kald ved et præcist tag er kun fuldt fastlåst, når `tools-ref` angiver samme tag, for eksempel `@v1.0.1` med `tools-ref: v1.0.1`; med standardværdien følger scriptet `v1`.
## Hvad der kontrolleres
@@ -2,7 +2,7 @@
> This page is generated from [`guides/quality-checks.md`](https://git.tirsystem.com/TirSystem/github-action/src/branch/main/guides/quality-checks.md). Changes made here are overwritten the next time the wiki is published.
English | [Dansk](QualityChecks.da) | [Bahasa Melayu](QualityChecks.ms)
English | [Dansk](QualityChecksPythonShell.da) | [Bahasa Melayu](QualityChecksPythonShell.ms)
# Reading quality-check results
@@ -25,7 +25,7 @@ jobs:
quality:
permissions:
contents: read
uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@main
uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@v1
with:
languages: python,shell
```
@@ -38,10 +38,17 @@ jobs:
| `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) |
| `tools-ref` | `v1` | Tag or branch of `TirSystem/github-action` from which the script `tools/quality-checks.sh` is fetched |
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.
Reference the workflow at the major tag (`@v1`) or at an exact tag
(`@v1.0.0`), never at `main` and never at the branch of a pull request: that
branch is deleted when the pull request is merged and the reference stops
working. See the upgrade guide for what each choice receives.
The workflow file calls a script of this repository, fetched at `tools-ref`. A
call at an exact tag is pinned completely only when `tools-ref` names the same
tag, for example `@v1.0.1` with `tools-ref: v1.0.1`; with the default the
script follows `v1`.
## What is checked
@@ -1,8 +1,8 @@
<!-- translation of QualityChecks.md, source sha256 84ed5e09689a -->
<!-- translation of QualityChecksPythonShell.md, source sha256 2a0c9d43c77d -->
> Ini ialah terjemahan [`QualityChecks`](QualityChecks). Halaman bahasa Inggeris ialah teks yang sah, dan perubahan di sini akan ditimpa pada penerbitan wiki yang seterusnya.
> Ini ialah terjemahan [`QualityChecksPythonShell`](QualityChecksPythonShell). Halaman bahasa Inggeris ialah teks yang sah, dan perubahan di sini akan ditimpa pada penerbitan wiki yang seterusnya.
[English](QualityChecks) | [Dansk](QualityChecks.da) | Bahasa Melayu
[English](QualityChecksPythonShell) | [Dansk](QualityChecksPythonShell.da) | Bahasa Melayu
# Membaca keputusan semakan kualiti
@@ -22,7 +22,7 @@ jobs:
quality:
permissions:
contents: read
uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@main
uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@v1
with:
languages: python,shell
```
@@ -35,8 +35,11 @@ jobs:
| `mypy-version` | `1.11.2` | Versi mypy |
| `shellcheck-py-version` | `0.10.0.1` | Versi pakej shellcheck-py (ShellCheck 0.10.0) |
| `shfmt-py-version` | `3.11.0.2` | Versi pakej shfmt-py (shfmt 3.11.0) |
| `tools-ref` | `v1` | Tag atau cabang `TirSystem/github-action` tempat skrip `tools/quality-checks.sh` diambil |
Rujuk aliran kerja pada `main` atau pada tag, jangan sekali-kali pada cabang pull request: cabang itu dipadam apabila pull request digabungkan dan rujukan itu berhenti berfungsi.
Rujuk aliran kerja pada tag major (`@v1`) atau pada tag tepat (`@v1.0.0`), jangan sekali-kali pada `main` dan jangan pada cabang pull request: cabang itu dipadam apabila pull request digabungkan dan rujukan itu berhenti berfungsi. Lihat panduan naik taraf untuk apa yang diterima oleh setiap pilihan.
Fail aliran kerja memanggil skrip dalam repositori ini, yang diambil pada `tools-ref`. Panggilan pada tag tepat hanya disematkan sepenuhnya apabila `tools-ref` menamakan tag yang sama, contohnya `@v1.0.1` dengan `tools-ref: v1.0.1`; dengan nilai lalai skrip mengikuti `v1`.
## Perkara yang disemak
+2 -2
View File
@@ -1,4 +1,4 @@
<!-- translation of Troubleshooting.md, source sha256 e8a34cbe7e93 -->
<!-- translation of Troubleshooting.md, source sha256 eb63f4109a0d -->
> Dette er en oversættelse af [`Troubleshooting`](Troubleshooting). Den engelske side er autoritativ, og ændringer her bliver overskrevet, næste gang wikien publiceres.
@@ -47,7 +47,7 @@ Kategorien fortæller, hvor du skal kigge. En fejl uden for scriptet (jobbet sta
## Ikke en fejl
`No GitHub push mirror configured for <repo>; nothing to sync.` Kørslen lykkes. Ikke alle Gitea-repositories har et GitHub-spejl, så det er forventet for dem. Hvis repositoryet skal have et, så tilføj det i repositoryets indstillinger.
`No GitHub push mirror configured for <repo>; nothing to sync.` efterfulgt af `Skipped`. Kørslen lykkes. Ikke alle Gitea-repositories har et GitHub-spejl, så det er forventet for dem. Hvis repositoryet skal have et, så tilføj det i repositoryets indstillinger.
`WARNING: Gitea returned an invalid push mirror list; GitHub metadata was not synced.` Kørslen lykkes, men intet blev synkroniseret. Kontroller, at Gitea-versionen understøtter push mirror-API'et, og kør igen.
+3 -3
View File
@@ -49,9 +49,9 @@ never starts, or stops before the step) is a **runner** problem.
## 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
`No GitHub push mirror configured for <repo>; nothing to sync.` followed by
`Skipped`. 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
+2 -2
View File
@@ -1,4 +1,4 @@
<!-- translation of Troubleshooting.md, source sha256 e8a34cbe7e93 -->
<!-- translation of Troubleshooting.md, source sha256 eb63f4109a0d -->
> Ini ialah terjemahan [`Troubleshooting`](Troubleshooting). Halaman bahasa Inggeris ialah teks yang sah, dan perubahan di sini akan ditimpa pada penerbitan wiki yang seterusnya.
@@ -47,7 +47,7 @@ Kategori menunjukkan di mana perlu dilihat. Kegagalan di luar skrip (kerja tidak
## Bukan satu ralat
`No GitHub push mirror configured for <repo>; nothing to sync.` Larian berjaya. Tidak semua repositori Gitea mempunyai cermin GitHub, jadi ini dijangka bagi repositori tersebut. Jika repositori itu sepatutnya mempunyainya, tambahkannya dalam tetapan repositori.
`No GitHub push mirror configured for <repo>; nothing to sync.` diikuti oleh `Skipped`. Larian berjaya. Tidak semua repositori Gitea mempunyai cermin GitHub, jadi ini dijangka bagi repositori tersebut. Jika repositori itu sepatutnya mempunyainya, tambahkannya dalam tetapan repositori.
`WARNING: Gitea returned an invalid push mirror list; GitHub metadata was not synced.` Larian berjaya tetapi tiada apa-apa disegerakkan. Semak bahawa versi Gitea menyokong API push mirror dan jalankan semula.
+3 -1
View File
@@ -1,4 +1,4 @@
<!-- translation of Upgrading.md, source sha256 ff8a06c4a03f -->
<!-- translation of Upgrading.md, source sha256 3f119a1ab12d -->
> Dette er en oversættelse af [`Upgrading`](Upgrading). Den engelske side er autoritativ, og ændringer her bliver overskrevet, næste gang wikien publiceres.
@@ -18,6 +18,8 @@ Sådan tager en softwareudvikler en ny udgivelse af de fælles workflows i brug
En udgivelse, der bryder kompatibiliteten, får en ny major-version (`v2`), så en pipeline på `@v1` aldrig modtager den, før du selv ændrer linjen.
Kvalitetskontrol-workflowet henter sit script ved sit input `tools-ref`, som som standard er `v1`. For at fastlåse det helt skal du kalde det ved et præcist tag og sætte `tools-ref` til samme tag; ellers følger scriptet major-tagget.
De to scoped workflows (**Sync GitHub mirror metadata** og **Publish wiki**) leveres af instansen og står ikke i dine `uses:`-linjer; du kan ikke fastlåse dem, men de henter deres scripts ved major-tagget.
## Aflæsning af en changelog-post
+4
View File
@@ -22,6 +22,10 @@ repository, tags `vMAJOR.MINOR.PATCH` and a moving major tag `vMAJOR`.
A breaking release gets a new major version (`v2`), so a pipeline on `@v1`
never receives it until you change the line yourself.
The quality-checks workflow fetches its script at its input `tools-ref`, which
defaults to `v1`. To pin it completely, call it at an exact tag and set
`tools-ref` to the same tag; otherwise the script follows the major tag.
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.
+3 -1
View File
@@ -1,4 +1,4 @@
<!-- translation of Upgrading.md, source sha256 ff8a06c4a03f -->
<!-- translation of Upgrading.md, source sha256 3f119a1ab12d -->
> Ini ialah terjemahan [`Upgrading`](Upgrading). Halaman bahasa Inggeris ialah teks yang sah, dan perubahan di sini akan ditimpa pada penerbitan wiki yang seterusnya.
@@ -18,6 +18,8 @@ Cara seorang jurutera perisian menerima keluaran baharu aliran kerja bersama den
Keluaran yang memecahkan keserasian mendapat versi major baharu (`v2`), jadi saluran paip pada `@v1` tidak menerimanya sehingga anda sendiri menukar baris itu.
Aliran kerja semakan kualiti mengambil skripnya pada inputnya `tools-ref`, yang lalai ialah `v1`. Untuk menyematkannya sepenuhnya, panggil pada tag tepat dan tetapkan `tools-ref` kepada tag yang sama; jika tidak, skrip mengikuti tag major.
Dua aliran kerja scoped (**Sync GitHub mirror metadata** dan **Publish wiki**) dihantar oleh instans dan tidak terdapat dalam baris `uses:` anda; anda tidak boleh menyematkannya, tetapi ia mengambil skripnya pada tag major.
## Membaca satu catatan changelog
+33
View File
@@ -0,0 +1,33 @@
<!-- Generated by tools/build_wiki.py. Edit the generator, not this page. -->
**TirSystem GitHub Actions**
**English**
- [Home](Home)
- [Onboarding](Onboarding)
- [Credentials](Credentials)
- [Troubleshooting](Troubleshooting)
- [Quality checks (Python, shell)](QualityChecksPythonShell)
- [Upgrading](Upgrading)
- [Capabilities](Capabilities)
**Dansk**
- [Hjem](Home.da)
- [Tilslutning](Onboarding.da)
- [Credentials](Credentials.da)
- [Fejlfinding](Troubleshooting.da)
- [Kvalitetskontrol (Python, shell)](QualityChecksPythonShell.da)
- [Opgradering](Upgrading.da)
- [Kapabiliteter](Capabilities.da)
**Bahasa Melayu**
- [Utama](Home.ms)
- [Menyertakan](Onboarding.ms)
- [Kelayakan](Credentials.ms)
- [Diagnosis](Troubleshooting.ms)
- [Semakan kualiti (Python, shell)](QualityChecksPythonShell.ms)
- [Menaik taraf](Upgrading.ms)
- [Keupayaan](Capabilities.ms)