Product repository template

Layout, proplan.toml, README/CHANGELOG, placeholder product image, .gitignore, KiBot/release/docgen workflows and TEMPLATE.md. Source of truth: contrib/product-template in B4L/proplan (cargo test --test product_template checks it as Gitea 1.27 creates a repository from it).
This commit is contained in:
grabowski committed 2026-10-13 16:32:25 +07:00
commit 421b4202cc
24 files changed
+573

No files matched your search

+9
View File
@@ -0,0 +1,9 @@
# Files Gitea fills in when a repository is created from this template: the
# new repository's name and description go into their text and their path
# (the board folder under hardware/ is renamed to the repository's name).
# Gitea 1.27: plain globs only. Everything else (workflows, TEMPLATE.md) is
# copied as it is.
proplan.toml
README.md
CHANGELOG.md
hardware/*/README.md
+54
View File
@@ -0,0 +1,54 @@
name: Fabrication document
# With a docs/input.md (typecad-docgen front matter, as in PowerModule):
# builds the fabrication document of the first board and pushes it to the
# docu branch, so main stays free of generated files. Adapted from
# LVSolarBuck and PowerModule.
on:
push:
branches: [main]
paths:
- 'docs/input.md'
- 'hardware/**'
- '.gitea/workflows/docgen.yml'
jobs:
docgen:
runs-on: kicad10_auto
steps:
- uses: actions/checkout@v4
- name: Inputs
id: inputs
run: |
pcb=$(find hardware -mindepth 2 -maxdepth 2 -name '*.kicad_pcb' | sort | head -1)
if [ -f docs/input.md ] && [ -n "$pcb" ]; then
echo "pcb=$pcb" >> "$GITHUB_OUTPUT"
else
echo "No docs/input.md or no board yet: nothing to build."
fi
- name: Build
if: steps.inputs.outputs.pcb != ''
run: |
mkdir -p output-docs
typecad-docgen docs/input.md "${{ steps.inputs.outputs.pcb }}" -o output-docs/index.html
- name: Push to the docu branch
if: steps.inputs.outputs.pcb != ''
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
run: |
git config --global user.email "${{ gitea.actor }}@noreply.localhost"
git config --global user.name "${{ gitea.actor }}"
REPO_URL=$(git config --get remote.origin.url)
AUTHED_URL=${REPO_URL/https:\/\//https:\/\/${GITEA_TOKEN}@}
git clone --depth 1 --branch docu "$AUTHED_URL" docu || git clone --depth 1 "$AUTHED_URL" docu
cd docu
git checkout -B docu
git rm -rq . || true
cp -r ../output-docs/* .
git add -A
if git diff --cached --quiet; then echo "No changes"; exit 0; fi
git commit -m "chore: fabrication document"
git push --force "$AUTHED_URL" docu
+48
View File
@@ -0,0 +1,48 @@
name: KiBot
# Checks every board (hardware/*/*.kicad_pro): ERC, DRC, schematic PDF,
# gerbers, drill, pick and place, BOM; the outputs are kept as an artifact.
# Adapted from LVSolarBuck (runner label kicad10_auto). Without a board yet
# the job ends right away.
on:
push:
branches: [main]
paths:
- 'hardware/**'
- 'kibot.yaml'
- '.gitea/workflows/kibot.yml'
pull_request:
paths:
- 'hardware/**'
- 'kibot.yaml'
workflow_dispatch:
jobs:
boards:
runs-on: kicad10_auto
steps:
- uses: actions/checkout@v4
- name: Find boards
id: boards
run: |
found=$(find hardware -mindepth 2 -maxdepth 2 -name '*.kicad_pro' | sort | tr '\n' ' ')
echo "projects=$found" >> "$GITHUB_OUTPUT"
if [ -z "$found" ]; then echo "No KiCad project under hardware/ yet."; fi
- name: KiBot
if: steps.boards.outputs.projects != ''
run: |
for pro in ${{ steps.boards.outputs.projects }}; do
dir=$(dirname "$pro"); board=$(basename "$dir")
echo "== $board"
(cd "$dir" && kibot -c "$GITHUB_WORKSPACE/kibot.yaml" -d "$GITHUB_WORKSPACE/Generated/$board" -v) \
|| echo "::warning::KiBot reported problems for $board"
done
- name: Keep the outputs
if: steps.boards.outputs.projects != ''
uses: https://github.com/christopherHX/gitea-upload-artifact@v4
with:
name: kibot-outputs
path: Generated
+57
View File
@@ -0,0 +1,57 @@
name: Release outputs
# On a tag v* (a prototype stage): the KiBot outputs of every board, zipped per
# board, attached to the tag's release (created when missing). The job token
# must be allowed to write releases. Adapted from LVSolarBuck; runs for the
# first time at the first tag.
on:
push:
tags: ['v*']
jobs:
release:
runs-on: kicad10_auto
steps:
- uses: actions/checkout@v4
- name: KiBot outputs per board
run: |
mkdir -p dist
for pro in $(find hardware -mindepth 2 -maxdepth 2 -name '*.kicad_pro' | sort); do
dir=$(dirname "$pro"); board=$(basename "$dir")
(cd "$dir" && kibot -c "$GITHUB_WORKSPACE/kibot.yaml" -d "$GITHUB_WORKSPACE/out/$board") \
|| echo "::warning::KiBot reported problems for $board"
python3 -c 'import shutil, sys; shutil.make_archive(sys.argv[1], "zip", sys.argv[2])' \
"dist/$board-${GITHUB_REF_NAME}" "out/$board"
done
ls -la dist
- name: Attach to the release
env:
TOKEN: ${{ secrets.GITEA_TOKEN }}
run: |
python3 - <<'EOF'
import json, os, pathlib, urllib.error, urllib.request, uuid
api = f"{os.environ['GITHUB_SERVER_URL']}/api/v1/repos/{os.environ['GITHUB_REPOSITORY']}"
tag = os.environ["GITHUB_REF_NAME"]
auth = {"Authorization": f"token {os.environ['TOKEN']}"}
def call(method, url, body=None, ctype="application/json"):
req = urllib.request.Request(url, data=body, method=method, headers={**auth, "Content-Type": ctype})
with urllib.request.urlopen(req) as r:
return json.load(r)
try:
rel = call("GET", f"{api}/releases/tags/{tag}")
except urllib.error.HTTPError as e:
if e.code != 404:
raise
rel = call("POST", f"{api}/releases", json.dumps({"tag_name": tag, "name": tag}).encode())
for f in sorted(pathlib.Path("dist").glob("*.zip")):
b = uuid.uuid4().hex
head = (f"--{b}\r\nContent-Disposition: form-data; name=\"attachment\"; filename=\"{f.name}\"\r\n"
"Content-Type: application/zip\r\n\r\n").encode()
body = head + f.read_bytes() + f"\r\n--{b}--\r\n".encode()
call("POST", f"{api}/releases/{rel['id']}/assets?name={f.name}", body, f"multipart/form-data; boundary={b}")
print("attached", f.name)
EOF