Skip to content

Commit 037b575

Browse files
committed
KiCad Automation
1 parent 7c93f71 commit 037b575

File tree

2 files changed

+221
-0
lines changed

2 files changed

+221
-0
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
name: KiCad docs via KiBot (auto-discover)
2+
3+
on:
4+
push:
5+
paths:
6+
- "**/*.kicad_pro"
7+
- "**/*.kicad_sch"
8+
- "**/*.kicad_pcb"
9+
- "config.kibot.yaml"
10+
- ".github/workflows/kibot-autodiscover.yml"
11+
pull_request:
12+
paths:
13+
- "**/*.kicad_pro"
14+
- "**/*.kicad_sch"
15+
- "**/*.kicad_pcb"
16+
- "config.kibot.yaml"
17+
workflow_dispatch:
18+
19+
concurrency:
20+
group: kibot-${{ github.ref }}
21+
cancel-in-progress: true
22+
23+
# needed for the final commit job
24+
permissions:
25+
contents: write
26+
27+
jobs:
28+
discover:
29+
runs-on: ubuntu-latest
30+
outputs:
31+
matrix: ${{ steps.mk.outputs.matrix }}
32+
steps:
33+
- uses: actions/checkout@v4
34+
with: { lfs: true }
35+
36+
- id: mk
37+
shell: bash
38+
run: |
39+
set -euo pipefail
40+
shopt -s nullglob
41+
42+
# Find all .kicad_pro (prefer git to respect .gitignore)
43+
if git ls-files '*.kicad_pro' >/dev/null 2>&1; then
44+
mapfile -t PROJ < <(git ls-files '*.kicad_pro' | sort)
45+
else
46+
mapfile -d '' -t PROJ < <(find . -type f -name '*.kicad_pro' -print0 | sed -z 's|^\./||' | sort -z)
47+
fi
48+
49+
echo "Found ${#PROJ[@]} KiCad projects:" >> "$GITHUB_STEP_SUMMARY"
50+
for p in "${PROJ[@]}"; do echo "- $p" >> "$GITHUB_STEP_SUMMARY"; done
51+
52+
: > rows.jsonl
53+
for p in "${PROJ[@]}"; do
54+
dir="$(dirname "$p")"
55+
base="$(basename "$p" .kicad_pro)"
56+
sch="${dir}/${base}.kicad_sch"
57+
pcb="${dir}/${base}.kicad_pcb"
58+
[[ -f "$sch" ]] || sch="$(find "$dir" -maxdepth 1 -name '*.kicad_sch' | sort | head -n1 || true)"
59+
[[ -f "$pcb" ]] || pcb="$(find "$dir" -maxdepth 1 -name '*.kicad_pcb' | sort | head -n1 || true)"
60+
if [[ -f "${sch:-}" && -f "${pcb:-}" ]]; then
61+
jq -n --arg project "$p" --arg schema "$sch" --arg board "$pcb" \
62+
'{project:$project, schema:$schema, board:$board}' >> rows.jsonl
63+
else
64+
echo "⚠️ Skipping '$p' (missing SCH or PCB). sch='${sch:-none}', pcb='${pcb:-none}'" >> "$GITHUB_STEP_SUMMARY"
65+
fi
66+
done
67+
68+
matrix_json="$(jq -c -s '.' rows.jsonl)"
69+
printf 'matrix=%s\n' "$matrix_json" >> "$GITHUB_OUTPUT"
70+
71+
build:
72+
needs: discover
73+
if: ${{ needs.discover.outputs.matrix != '[]' && needs.discover.outputs.matrix != '' }}
74+
runs-on: ubuntu-latest
75+
strategy:
76+
fail-fast: false
77+
matrix:
78+
include: ${{ fromJson(needs.discover.outputs.matrix) }}
79+
steps:
80+
- uses: actions/checkout@v4
81+
with: { lfs: true }
82+
83+
- name: Run KiBot (KiCad 8)
84+
uses: INTI-CMNB/KiBot@v2_k8
85+
with:
86+
config: config.kibot.yaml
87+
dir: build/${{ matrix.project }}
88+
schema: ${{ matrix.schema }}
89+
board: ${{ matrix.board }}
90+
91+
# Compute names/paths once for artifact
92+
- name: Compute artifact paths
93+
id: paths
94+
shell: bash
95+
run: |
96+
set -euo pipefail
97+
pname="$(basename '${{ matrix.project }}' .kicad_pro)"
98+
# We upload the docs directory (so the <ProjectName>/ subfolder is preserved)
99+
src_dir="build/${{ matrix.project }}/docs"
100+
aname="kicad-exports-${pname}"
101+
aname="${aname//\//_}"; aname="${aname// /_}"; aname="${aname//:/_}"
102+
echo "pname=$pname" >> "$GITHUB_OUTPUT"
103+
echo "src_dir=$src_dir" >> "$GITHUB_OUTPUT"
104+
echo "artifact=$aname" >> "$GITHUB_OUTPUT"
105+
106+
# Safety net: upload each project's docs as an artifact
107+
- name: Upload per-project artifact (always)
108+
if: always()
109+
uses: actions/upload-artifact@v4
110+
with:
111+
name: ${{ steps.paths.outputs.artifact }}
112+
path: ${{ steps.paths.outputs.src_dir }}
113+
if-no-files-found: warn
114+
retention-days: 14
115+
116+
publish:
117+
needs: build
118+
if: ${{ github.event_name == 'push' }}
119+
runs-on: ubuntu-latest
120+
steps:
121+
- uses: actions/checkout@v4
122+
123+
- name: Download all project artifacts
124+
uses: actions/download-artifact@v4
125+
with:
126+
pattern: kicad-exports-*
127+
path: collected
128+
merge-multiple: true
129+
130+
- name: Merge into repo docs/
131+
shell: bash
132+
run: |
133+
set -euo pipefail
134+
mkdir -p docs
135+
if [ -d "collected/docs" ]; then
136+
# case A: artifacts contained a docs/ root
137+
rsync -a collected/docs/ docs/
138+
elif [ -d "collected" ]; then
139+
# case B (your current case): artifacts are <ProjectName>/...
140+
rsync -a collected/ docs/
141+
else
142+
echo "Nothing to merge."
143+
fi
144+
echo "Merged into docs/. Contents:"
145+
find docs -maxdepth 2 -type f | sort
146+
147+
- name: Commit updated docs (single commit)
148+
shell: bash
149+
run: |
150+
set -euo pipefail
151+
git config user.name "github-actions[bot]"
152+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
153+
git add -A -f docs
154+
if git diff --cached --quiet; then
155+
echo "No changes to commit."
156+
else
157+
git commit -m "docs: update KiCad exports [skip ci]"
158+
git push
159+
fi

config.kibot.yaml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
kibot:
2+
version: 1
3+
4+
preflight:
5+
check_zone_fills: false
6+
7+
variants: []
8+
9+
outputs:
10+
# 1) Schematic PDF
11+
- name: pdf_schematic
12+
type: pdf_sch_print
13+
dir: docs/%f
14+
options:
15+
monochrome: false
16+
output: "%f_schematic.pdf"
17+
18+
# 2) CSV BoM (only the columns you want)
19+
- name: bom_csv
20+
type: bom
21+
dir: docs/%f
22+
options:
23+
format: CSV
24+
csv:
25+
hide_pcb_info: true
26+
hide_stats_info: true
27+
separator: ","
28+
string_delimiter: '"'
29+
columns:
30+
- { field: "References", name: "Reference" }
31+
- { field: "Value" }
32+
- { field: "Quantity Per PCB", name: "Qty" }
33+
- { field: "Note" }
34+
- { field: "Description" }
35+
# IMPORTANT: stop KiBot “fixing” your Value text
36+
parse_value: false # <- don’t canonicalize 1k/1000 or strip 1%, 5%, etc.
37+
normalize_values: false # <- keep your exact units/prefixes
38+
merge_blank_fields: false # <- avoid merging groups just because a field is blank
39+
# Optional: grouping rules (keep or adjust as you like)
40+
group_fields: ["Value"]
41+
ref_separator: " "
42+
output: "%f_bom.csv"
43+
44+
# 4) PCB render - top
45+
- name: pcbdraw_top
46+
type: pcbdraw
47+
dir: docs/%f
48+
options:
49+
format: png
50+
dpi: 300
51+
bottom: false
52+
output: "%f_board_top.png"
53+
54+
# 5) PCB render - bottom
55+
- name: pcbdraw_bottom
56+
type: pcbdraw
57+
dir: docs/%f
58+
options:
59+
format: png
60+
dpi: 300
61+
bottom: true
62+
output: "%f_board_bottom.png"

0 commit comments

Comments
 (0)