Merge branch 'master' of https://git.b4l.co.th/B4L/C64PSU
All checks were successful
KiBot PCB Generation / generate (push) Successful in 5m55s
KiBot PCB Generation / deploy (push) Successful in 36s

This commit is contained in:
janik
2025-10-07 17:11:08 +07:00
3 changed files with 1163 additions and 90 deletions

541
.gitea/workflows/kibot.yml Normal file
View File

@@ -0,0 +1,541 @@
name: "KiBot PCB Generation"
# Controls when the action will run
on:
push:
paths:
- '**/*.kicad_sch'
- '**/*.kicad_pcb'
- '**/*.kicad_pro'
- 'kibot.yaml'
- '.gitea/workflows/*.yml'
pull_request:
paths:
- '**/*.kicad_sch'
- '**/*.kicad_pcb'
- '**/*.kicad_pro'
- 'kibot.yaml'
- '.gitea/workflows/*.yml'
repository_dispatch:
types: [run_qs]
workflow_dispatch:
inputs:
board_layers:
description: 'Number of PCB layers'
required: false
default: '4'
type: choice
options:
- '2'
- '4'
- '6'
diff_old:
description: 'Old revision for diff (e.g., HEAD~1, commit hash, tag)'
required: false
default: 'HEAD~1'
type: string
diff_new:
description: 'New revision for diff (e.g., HEAD, commit hash, tag)'
required: false
default: 'HEAD'
type: string
enable_interactive_diff:
description: 'Generate interactive HTML diff'
required: false
default: false
type: boolean
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
generate:
runs-on: kicad-kibot-runner
steps:
- uses: actions/checkout@v3
with:
# Fetch full history for diff generation
fetch-depth: '0'
- name: Find KiCad project
id: find_project
run: |
# Find all .kicad_pcb files in the repository
PCB_FILES=$(find . -name "*.kicad_pcb" -type f | grep -v -E '/(backups?|backup|old|archive|deprecated)/' | head -5)
if [ -z "$PCB_FILES" ]; then
echo "Error: No KiCad PCB files found"
exit 1
fi
# Use the first PCB file found
PCB_FILE=$(echo "$PCB_FILES" | head -1)
PROJECT_DIR=$(dirname "$PCB_FILE")
PROJECT_NAME=$(basename "$PCB_FILE" .kicad_pcb)
echo "Found KiCad project: $PROJECT_NAME"
echo "Project directory: $PROJECT_DIR"
echo "PCB file: $PCB_FILE"
# Find schematic file
SCH_FILE=$(find "$PROJECT_DIR" -name "*.kicad_sch" -o -name "*.sch" | head -1)
echo "pcb_file=$PCB_FILE" >> $GITHUB_OUTPUT
echo "project_dir=$PROJECT_DIR" >> $GITHUB_OUTPUT
echo "project_name=$PROJECT_NAME" >> $GITHUB_OUTPUT
echo "sch_file=$SCH_FILE" >> $GITHUB_OUTPUT
# List all found projects for debugging
echo "All PCB files found:"
echo "$PCB_FILES"
- name: Set layer count
id: layers
run: |
# Use workflow input or default to 4 layers
LAYERS="${{ github.event.inputs.board_layers }}"
if [ -z "$LAYERS" ]; then
LAYERS="4"
fi
echo "layers=$LAYERS" >> $GITHUB_OUTPUT
echo "Using $LAYERS layer configuration"
- name: Check for KiBot config
id: config_check
run: |
# Check if kibot.yaml exists in repository root
if [ -f "kibot.yaml" ]; then
echo "found=true" >> $GITHUB_OUTPUT
echo "Using kibot.yaml configuration from repository root"
else
echo "found=false" >> $GITHUB_OUTPUT
echo "No kibot.yaml found in repository root - will use --quick-start mode"
fi
- name: Generate schematic diff
id: generate_diff
if: github.event_name == 'push' || github.event_name == 'pull_request'
run: |
PROJECT_DIR="${{ steps.find_project.outputs.project_dir }}"
PROJECT_NAME="${{ steps.find_project.outputs.project_name }}"
# Create DIFF output directory
mkdir -p "${GITHUB_WORKSPACE}/Generated/DIFF"
cd "$PROJECT_DIR"
# Get the previous commit hash
if [ "${{ github.event_name }}" = "pull_request" ]; then
BASE_SHA="${{ github.event.pull_request.base.sha }}"
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
else
# For push events, compare with previous commit
HEAD_SHA="${{ github.sha }}"
BASE_SHA=$(git rev-parse HEAD~1 2>/dev/null || echo "")
fi
if [ -z "$BASE_SHA" ]; then
echo "No previous commit found for comparison"
echo "has_diff=false" >> $GITHUB_OUTPUT
exit 0
fi
echo "Comparing commits: $BASE_SHA...$HEAD_SHA"
# Find all schematic files
SCH_FILES=$(find . -name "*.kicad_sch" -o -name "*.sch" | head -10)
if [ -z "$SCH_FILES" ]; then
echo "No schematic files found"
echo "has_diff=false" >> $GITHUB_OUTPUT
exit 0
fi
# Generate diff for each schematic
DIFF_GENERATED=false
for SCH_FILE in $SCH_FILES; do
SCH_NAME=$(basename "$SCH_FILE" | sed 's/\.[^.]*$//')
# Check if file changed between commits
if git diff --name-only "$BASE_SHA" "$HEAD_SHA" | grep -q "$SCH_FILE"; then
echo "Generating diff for $SCH_FILE"
# Create temp directory for processing
TEMP_DIR=$(mktemp -d)
# Export old version
git show "$BASE_SHA:$SCH_FILE" > "$TEMP_DIR/${SCH_NAME}_old.kicad_sch" 2>/dev/null || continue
# Copy current version
cp "$SCH_FILE" "$TEMP_DIR/${SCH_NAME}_new.kicad_sch"
# Try to use kidiff if available (better visual diff tool for KiCad)
if command -v kidiff &> /dev/null; then
kidiff -o "${GITHUB_WORKSPACE}/Generated/DIFF/${SCH_NAME}_diff.pdf" \
"$TEMP_DIR/${SCH_NAME}_old.kicad_sch" \
"$TEMP_DIR/${SCH_NAME}_new.kicad_sch" || true
fi
# Also generate text diff
git diff "$BASE_SHA" "$HEAD_SHA" -- "$SCH_FILE" > "${GITHUB_WORKSPACE}/Generated/DIFF/${SCH_NAME}_changes.txt"
# Generate a simple HTML diff for easy viewing
cat > "${GITHUB_WORKSPACE}/Generated/DIFF/${SCH_NAME}_diff.html" << EOF
<!DOCTYPE html>
<html>
<head>
<title>Schematic Diff: ${SCH_NAME}</title>
<style>
body { font-family: monospace; margin: 20px; }
.added { background-color: #90EE90; }
.removed { background-color: #FFB6C1; }
.header { font-weight: bold; margin: 20px 0; }
pre { background: #f4f4f4; padding: 10px; overflow-x: auto; }
</style>
</head>
<body>
<h1>Schematic Changes: ${SCH_NAME}</h1>
<div class="header">Commit: ${BASE_SHA:0:8} → ${HEAD_SHA:0:8}</div>
<pre>
EOF
# Add the diff content with HTML escaping
git diff "$BASE_SHA" "$HEAD_SHA" -- "$SCH_FILE" | \
sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g' | \
sed 's/^+[^+].*/<span class="added">&<\/span>/g' | \
sed 's/^-[^-].*/<span class="removed">&<\/span>/g' >> "${GITHUB_WORKSPACE}/Generated/DIFF/${SCH_NAME}_diff.html"
echo "</pre></body></html>" >> "${GITHUB_WORKSPACE}/Generated/DIFF/${SCH_NAME}_diff.html"
rm -rf "$TEMP_DIR"
DIFF_GENERATED=true
fi
done
# Generate PCB diff if PCB file changed
PCB_FILE="${{ steps.find_project.outputs.pcb_file }}"
if git diff --name-only "$BASE_SHA" "$HEAD_SHA" | grep -q "$PCB_FILE"; then
echo "Generating PCB diff"
PCB_NAME=$(basename "$PCB_FILE" | sed 's/\.[^.]*$//')
# Generate text diff for PCB
git diff "$BASE_SHA" "$HEAD_SHA" -- "$PCB_FILE" > "${GITHUB_WORKSPACE}/Generated/DIFF/${PCB_NAME}_pcb_changes.txt"
# Summary of changes
git diff --stat "$BASE_SHA" "$HEAD_SHA" -- "$PCB_FILE" > "${GITHUB_WORKSPACE}/Generated/DIFF/${PCB_NAME}_pcb_summary.txt"
DIFF_GENERATED=true
fi
# Create a summary file
cat > "${GITHUB_WORKSPACE}/Generated/DIFF/README.md" << EOF
# KiCad Project Diff Report
**Base Commit:** ${BASE_SHA:0:8}
**Head Commit:** ${HEAD_SHA:0:8}
**Date:** $(date)
## Changed Files:
$(git diff --name-status "$BASE_SHA" "$HEAD_SHA" -- "*.kicad_sch" "*.sch" "*.kicad_pcb" "*.pcb")
## Summary:
$(git diff --stat "$BASE_SHA" "$HEAD_SHA" -- "*.kicad_sch" "*.sch" "*.kicad_pcb" "*.pcb")
## Commit Messages:
$(git log --oneline "$BASE_SHA".."$HEAD_SHA")
EOF
if [ "$DIFF_GENERATED" = true ]; then
echo "has_diff=true" >> $GITHUB_OUTPUT
else
echo "No schematic or PCB changes detected"
echo "has_diff=false" >> $GITHUB_OUTPUT
fi
- name: Run ERC
if: steps.config_check.outputs.found == 'true'
run: |
cd "${{ steps.find_project.outputs.project_dir }}"
# Clean up any existing output directories
rm -rf Fabrication Generated Output
if [ -n "${{ steps.find_project.outputs.sch_file }}" ]; then
echo "Running ERC on schematic files..."
# Use absolute path to config file in repo root
# Skip ERC step in preflight to avoid stopping on errors
kibot -c "${GITHUB_WORKSPACE}/kibot.yaml" -s run_erc,run_drc -v || true
else
echo "No schematic files found, skipping ERC"
fi
continue-on-error: true
- name: Run DRC
if: steps.config_check.outputs.found == 'true'
run: |
cd "${{ steps.find_project.outputs.project_dir }}"
echo "Running DRC on PCB..."
# Use absolute path to config file in repo root
# Skip both ERC and DRC in preflight to avoid stopping on errors
kibot -c "${GITHUB_WORKSPACE}/kibot.yaml" -s run_erc,run_drc -v || true
continue-on-error: true
- name: Generate outputs with custom config
if: steps.config_check.outputs.found == 'true'
run: |
cd "${{ steps.find_project.outputs.project_dir }}"
echo "Generating outputs for ${{ steps.layers.outputs.layers }} layer board"
echo "Project: ${{ steps.find_project.outputs.project_name }}"
echo "Using config: ${GITHUB_WORKSPACE}/kibot.yaml"
# First, let's check what's in the current directory
echo "Current directory contents:"
ls -la
# Check if Fabrication exists and what it is
if [ -e "Fabrication" ]; then
echo "Fabrication exists as:"
file Fabrication
echo "Removing it..."
rm -rf Fabrication
fi
# Create a temporary modified config without the global output setting
cp "${GITHUB_WORKSPACE}/kibot.yaml" /tmp/kibot_temp.yaml
# Remove or comment out the global output line if it exists
sed -i 's/^ output:.*$/ # output: commented out for workflow/' /tmp/kibot_temp.yaml
# Update diff revisions if specified
if [ -n "${{ github.event.inputs.diff_old }}" ]; then
sed -i "s/old: 'HEAD~1'/old: '${{ github.event.inputs.diff_old }}'/" /tmp/kibot_temp.yaml
fi
if [ -n "${{ github.event.inputs.diff_new }}" ]; then
sed -i "s/new: 'HEAD'/new: '${{ github.event.inputs.diff_new }}'/" /tmp/kibot_temp.yaml
fi
# Use a timestamp-based directory to ensure uniqueness
OUTPUT_DIR="kibot_output_$(date +%s)"
# Determine which outputs to run
EXTRA_OUTPUTS=""
if [ "${{ github.event.inputs.enable_interactive_diff }}" = "true" ]; then
EXTRA_OUTPUTS="interactive_diff svg_diff"
fi
# Run KiBot with the modified configuration
# Skip ERC/DRC preflight checks to avoid stopping on errors
echo "Running KiBot with output directory: $OUTPUT_DIR"
# Run all outputs (KiBot will run all by default when no specific outputs are listed)
# Only add extra outputs if interactive diff is enabled
if [ "${{ github.event.inputs.enable_interactive_diff }}" = "true" ]; then
# Run with interactive diff outputs explicitly enabled
kibot -c /tmp/kibot_temp.yaml -s run_erc,run_drc -d "$OUTPUT_DIR" -v interactive_diff svg_diff
else
# Run all default outputs (everything with run_by_default: true)
kibot -c /tmp/kibot_temp.yaml -s run_erc,run_drc -d "$OUTPUT_DIR" -v
fi
# Move outputs to root Generated folder
mkdir -p "${GITHUB_WORKSPACE}/Generated"
if [ -d "$OUTPUT_DIR" ]; then
echo "Copying outputs from $OUTPUT_DIR to Generated/"
cp -r "$OUTPUT_DIR"/* "${GITHUB_WORKSPACE}/Generated/"
rm -rf "$OUTPUT_DIR"
elif [ -d "Fabrication" ]; then
echo "KiBot used default Fabrication directory, copying from there"
cp -r Fabrication/* "${GITHUB_WORKSPACE}/Generated/"
rm -rf Fabrication
else
echo "Warning: No output directory was created"
fi
- name: Check downloaded datasheets
if: steps.config_check.outputs.found == 'true'
continue-on-error: true
run: |
echo "Checking for downloaded datasheets..."
# KiBot should download datasheets to the configured directory
# Check if datasheets were downloaded
if [ -d "${GITHUB_WORKSPACE}/Generated/Datasheets" ]; then
echo "Datasheets folder found in Generated/"
# Create README
cat > "${GITHUB_WORKSPACE}/Generated/Datasheets/README.md" << EOF
# Component Datasheets
This folder contains downloaded datasheets for all components in the project.
Organized by component type:
- **ICs/** - Integrated circuits (U references)
- **Capacitors/** - Capacitors (C references)
- **Resistors/** - Resistors (R references)
- **Transistors/** - Transistors (Q references)
- **Diodes/** - Diodes (D references)
- **Connectors/** - Connectors (J, P references)
- **Inductors/** - Inductors (L references)
- And more...
Files are named: REFERENCE_VALUE.pdf (e.g., U1_LM7805.pdf)
Generated on: $(date)
Project: ${{ steps.find_project.outputs.project_name }}
EOF
echo "Datasheet folder structure:"
find "${GITHUB_WORKSPACE}/Generated/Datasheets" -type f -name "*.pdf" | head -20
# Count PDFs
PDF_COUNT=$(find "${GITHUB_WORKSPACE}/Generated/Datasheets" -type f -name "*.pdf" | wc -l)
echo "Total PDFs downloaded: $PDF_COUNT"
else
echo "No Datasheets folder found - KiBot may not have downloaded any datasheets"
echo "Check that components have valid Datasheet URLs in the schematic"
fi
- name: Quick Start fallback
if: steps.config_check.outputs.found == 'false'
run: |
cd "${{ steps.find_project.outputs.project_dir }}"
echo "Running KiBot in quick-start mode"
kibot --quick-start
# Move outputs to root Generated folder
mkdir -p "${GITHUB_WORKSPACE}/Generated"
if [ -d "Generated" ]; then
cp -r Generated/* "${GITHUB_WORKSPACE}/Generated/"
fi
- name: Add board information to outputs
run: |
echo "Board configuration: ${{ steps.layers.outputs.layers }} layers" > Generated/board_info.txt
echo "Project: ${{ steps.find_project.outputs.project_name }}" >> Generated/board_info.txt
echo "Project path: ${{ steps.find_project.outputs.project_dir }}" >> Generated/board_info.txt
echo "Generated on: $(date)" >> Generated/board_info.txt
echo "Commit: ${{ github.sha }}" >> Generated/board_info.txt
- name: Fix file permissions
run: |
chmod -R a+rw Generated || true
- name: Retrieve results - All outputs
uses: actions/upload-artifact@v3
with:
name: Automatic_outputs
path: Generated
- name: Retrieve results - Gerbers
if: steps.config_check.outputs.found == 'true'
uses: actions/upload-artifact@v3
with:
name: Gerbers-${{ steps.layers.outputs.layers }}layer
path: Generated/Gerbers
- name: Retrieve results - Assembly
if: steps.config_check.outputs.found == 'true'
uses: actions/upload-artifact@v3
with:
name: Assembly-${{ steps.layers.outputs.layers }}layer
path: Generated/Assembly
- name: Retrieve results - BOM
if: steps.config_check.outputs.found == 'true'
uses: actions/upload-artifact@v3
with:
name: BOM-${{ steps.layers.outputs.layers }}layer
path: Generated/BoM
- name: Retrieve results - Datasheets
if: steps.config_check.outputs.found == 'true'
uses: actions/upload-artifact@v3
with:
name: Datasheets
path: Generated/Datasheets
- name: Retrieve results - 3D Model
if: steps.config_check.outputs.found == 'true'
uses: actions/upload-artifact@v3
with:
name: 3D-Model
path: Generated/3D
- name: Retrieve results - Fabrication Package
if: steps.config_check.outputs.found == 'true'
uses: actions/upload-artifact@v3
with:
name: Fabrication-Package-${{ steps.layers.outputs.layers }}layer
path: Generated/*.zip
- name: Retrieve results - JLCPCB Package
if: steps.config_check.outputs.found == 'true'
uses: actions/upload-artifact@v3
with:
name: JLCPCB-${{ steps.layers.outputs.layers }}layer
path: Generated/*_JLCPCB_compress.zip
- name: Retrieve results - Interactive Viewers
if: steps.config_check.outputs.found == 'true'
uses: actions/upload-artifact@v3
with:
name: Interactive-Viewers
path: Generated/Interactive
- name: Retrieve results - Diff Report
if: steps.generate_diff.outputs.has_diff == 'true'
uses: actions/upload-artifact@v3
with:
name: Schematic-PCB-Diff
path: Generated/DIFF
# Deploy to documentation branch
deploy:
runs-on: kicad-kibot-runner
needs: generate
steps:
- uses: actions/checkout@v4
- name: Retrieve results
uses: actions/download-artifact@v3
with:
name: Automatic_outputs
path: Generated
- name: Disable Jekyll
# Jekyll will filter the KiRi folders
run: |
touch Generated/.nojekyll
- name: Push to docu branch
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
run: |
# Set up git identity
git config --global user.email "${{ gitea.actor }}@noreply.localhost"
git config --global user.name "${{ gitea.actor }}"
# Get the repository URL and add authentication
REPO_URL=$(git config --get remote.origin.url)
AUTHED_URL=${REPO_URL/https:\/\//https:\/\/${GITEA_TOKEN}@}
# Clone the docu branch into a separate folder
git clone --depth 1 --branch docu "$AUTHED_URL" docu-branch || \
git clone --depth 1 "$AUTHED_URL" docu-branch
cd docu-branch
git checkout -B docu
# Clean old contents and copy new files
rm -rf ./*
cp -r ../Generated/* ./
# Commit and push if there are changes
git add .
if ! git diff --cached --quiet; then
git commit -m "chore: update deployed documentation"
git push --force "$AUTHED_URL" docu
else
echo "No changes to deploy"
fi

View File

@@ -1,90 +0,0 @@
name: "Variants demo using --quick-start"
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
push:
paths:
- 'kicad/c64psu/*.kicad_sch'
- 'kicad/c64psu/*.kicad_pcb'
- '.gitea/workflows/kibot_quick_start.yml'
pull_request:
paths:
- 'kicad/c64psu/*.kicad_sch'
- 'kicad/c64psu/*.kicad_pcb'
- '.gitea/workflows/kibot_quick_start.yml'
repository_dispatch:
types: [run_qs]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
quick-start:
runs-on: kicad-kibot-runner
steps:
- uses: actions/checkout@v3
with:
# So we can run a diff between last 2 changes
fetch-depth: '0'
- name: Quick Start
run: |
kibot --quick-start
- name: Retrieve results
uses: actions/upload-artifact@v3
with:
name: Automatic_outputs
path: Generated
# This step is to upload the results to another repo (web pages)
deploy:
runs-on: kicad-kibot-runner
needs: quick-start
steps:
- uses: actions/checkout@v4
- name: Retrieve results
uses: actions/download-artifact@v3
with:
name: Automatic_outputs
path: Generated
- name: Disable Jekyll
# Jekyll will filter the KiRi folders
run: |
touch Generated/.nojekyll
- name: Push to docu branch
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
run: |
# Set up git identity
git config --global user.email "${{ gitea.actor }}@noreply.localhost"
git config --global user.name "${{ gitea.actor }}"
# Get the repository URL and add authentication
REPO_URL=$(git config --get remote.origin.url)
AUTHED_URL=${REPO_URL/https:\/\//https:\/\/${GITEA_TOKEN}@}
# Clone the docu branch into a separate folder
git clone --depth 1 --branch docu "$AUTHED_URL" docu-branch || \
git clone --depth 1 "$AUTHED_URL" docu-branch
cd docu-branch
git checkout -B docu
# Clean old contents and copy new files
rm -rf ./*
cp -r ../Generated/* ./
# Commit and push if there are changes
git add .
if ! git diff --cached --quiet; then
git commit -m "chore: update deployed documentation"
git push --force "$AUTHED_URL" docu
else
echo "No changes to deploy"
fi

622
kibot.yaml Normal file
View File

@@ -0,0 +1,622 @@
# KiBot configuration for 2/4/6 layer boards
# Works with Gitea CI/CD pipeline
kibot:
version: 1
global:
# Filters for ERC/DRC warnings
filters:
- number: 1007
- number: 1015
- number: 58
- number: 61
# Default output directory - will be overridden by command line
# output: 'Fabrication' # Commented out to use command line option
# Variant for assembly if needed
variant: ''
# Date format for filenames
date_format: '%Y-%m-%d_%H-%M-%S'
preflight:
run_erc: true
run_drc: true
check_zone_fills: true
ignore_unconnected: false
update_xml: true
erc:
warnings_as_errors: false
# Continue even if ERC fails
dont_stop: true
drc:
warnings_as_errors: false
# Continue even if DRC fails
dont_stop: true
outputs:
# Schematic outputs
- name: 'print_sch'
comment: "Schematic PDF"
type: pdf_sch_print
dir: Schematic
options:
output: '%f-schematic.%x'
- name: 'print_sch_svg'
comment: "Schematic SVG"
type: svg_sch_print
dir: Schematic
options:
output: '%f-schematic.%x'
# PCB 2D renders
- name: 'pcb_top'
comment: "PCB render top"
type: pcbdraw
dir: PCB/2D_render
options:
output: '%f-top.%x'
format: svg
show_components: all
dpi: 300
- name: 'pcb_bottom'
comment: "PCB render bottom"
type: pcbdraw
dir: PCB/2D_render
options:
output: '%f-bottom.%x'
format: svg
bottom: true
show_components: all
dpi: 300
# PCB PDF documentation
- name: 'print_pcb'
comment: "PCB PDF"
type: pdf_pcb_print
dir: PCB/PDF
options:
output: '%f-pcb.%x'
plot_sheet_reference: true
monochrome: false
pages:
- layers:
- F.Cu
- F.Paste
- F.Silkscreen
- Edge.Cuts
sheet: 'Front copper'
- layers:
- B.Cu
- B.Paste
- B.Silkscreen
- Edge.Cuts
mirror: true
sheet: 'Bottom copper'
- layers:
- In1.Cu
- Edge.Cuts
sheet: 'Inner layer 1'
skip_if_no_layer: true
- layers:
- In2.Cu
- Edge.Cuts
sheet: 'Inner layer 2'
skip_if_no_layer: true
- layers:
- In3.Cu
- Edge.Cuts
sheet: 'Inner layer 3'
skip_if_no_layer: true
- layers:
- In4.Cu
- Edge.Cuts
sheet: 'Inner layer 4'
skip_if_no_layer: true
# Gerber files - automatically handles 2/4/6 layers
- name: 'gerbers'
comment: "Gerber files"
type: gerber
dir: Gerbers
options:
output: '%f%i.%x'
exclude_edge_layer: true
exclude_pads_from_silkscreen: true
plot_sheet_reference: false
plot_footprint_refs: true
plot_footprint_values: false
force_plot_invisible_refs_vals: false
tent_vias: true
use_protel_extensions: false
create_gerber_job_file: true
disable_aperture_macros: true
gerber_precision: 4.6
use_gerber_x2_attributes: false
use_gerber_net_attributes: false
line_width: 0.1
subtract_mask_from_silk: true
layers:
# Copper layers - automatically included if present
- F.Cu
- B.Cu
- In1.Cu
- In2.Cu
- In3.Cu
- In4.Cu
# Technical layers
- F.Paste
- B.Paste
- F.Silkscreen
- B.Silkscreen
- F.Mask
- B.Mask
- Edge.Cuts
- User.Comments
- F.Fab
- B.Fab
# Excellon drill files
- name: 'drill'
comment: "Drill files"
type: excellon
dir: Gerbers
options:
output: '%f%i.%x'
metric_units: true
minimal_header: false
mirror_y_axis: false
report:
filename: '%f-drill_report.txt'
pth_and_npth_single_file: false
# Drill map
- name: 'drill_map'
comment: "Drill map"
type: gerb_drill
dir: Gerbers
options:
output: '%f-drill_map.%x'
# Pick and place files
- name: 'position'
comment: "Pick and place file"
type: position
dir: Assembly
options:
output: '%f-position-%i.%x' # Added %i to differentiate front/back files
format: CSV
units: millimeters
separate_files_for_front_and_back: true
only_smd: false
# Interactive BOM
- name: 'ibom'
comment: "Interactive BOM"
type: ibom
dir: Assembly
options:
output: '%f-ibom.%x'
dark_mode: false
hide_pads: false
show_fabrication: false
hide_silkscreen: false
highlight_pin1: true
no_redraw_on_drag: false
board_rotation: 0
check_extra_fields: false
include_tracks: false
include_nets: false
# Generic BOM in CSV format
- name: 'bom_csv'
comment: "Bill of Materials in CSV format"
type: bom
dir: BoM/Generic
options:
output: '%f_bom.%x'
format: CSV
separator: ','
ref_separator: ','
group_fields: ['Value', 'Footprint', 'Tolerance', 'Voltage']
columns:
- field: 'References'
name: 'Reference'
- field: 'Value'
name: 'Value'
- field: 'Quantity Per PCB'
name: 'Qty'
- field: 'Footprint'
name: 'Package'
- field: 'Description'
name: 'Description'
- field: 'Manufacturer'
name: 'Manufacturer'
- field: 'MPN'
name: 'Part Number'
- field: 'LCSC'
name: 'LCSC Part'
- field: 'Digikey'
name: 'Digikey Part'
- field: 'Mouser'
name: 'Mouser Part'
# Generic BOM in HTML format
- name: 'bom_html'
comment: "Bill of Materials in HTML format"
type: bom
dir: BoM/Generic
options:
output: '%f_bom.%x'
format: HTML
html:
style: 'modern-blue' # Style for HTML output
datasheet_as_link: 'Datasheet' # Column name for datasheet links
generate_dnf: true
logo: false
title: 'Bill of Materials - %f'
group_fields: ['Value', 'Footprint', 'Tolerance', 'Voltage']
columns:
- field: 'References'
name: 'Reference'
- field: 'Value'
name: 'Value'
- field: 'Quantity Per PCB'
name: 'Qty'
- field: 'Footprint'
name: 'Package'
- field: 'Description'
name: 'Description'
- field: 'Manufacturer'
name: 'Manufacturer'
- field: 'MPN'
name: 'Part Number'
- field: 'LCSC'
name: 'LCSC Part'
- field: 'Digikey'
name: 'Digikey Part'
- field: 'Mouser'
name: 'Mouser Part'
# Generic BOM in XLSX format
- name: 'bom_xlsx'
comment: "Bill of Materials in Excel format"
type: bom
dir: BoM/Generic
options:
output: '%f_bom.%x'
format: XLSX
xlsx:
datasheet_as_link: 'Datasheet' # Column name for datasheet links
generate_dnf: true
logo: false
title: 'Bill of Materials'
max_col_width: 50
highlight_empty: true
group_fields: ['Value', 'Footprint', 'Tolerance', 'Voltage']
columns:
- field: 'References'
name: 'Reference'
- field: 'Value'
name: 'Value'
- field: 'Quantity Per PCB'
name: 'Qty'
- field: 'Footprint'
name: 'Package'
- field: 'Description'
name: 'Description'
- field: 'Manufacturer'
name: 'Manufacturer'
- field: 'MPN'
name: 'Part Number'
- field: 'LCSC'
name: 'LCSC Part'
- field: 'Digikey'
name: 'Digikey Part'
- field: 'Mouser'
name: 'Mouser Part'
- field: 'Datasheet'
name: 'Datasheet'
# Download datasheets
- name: 'download_datasheets'
comment: "Download component datasheets as PDFs"
type: download_datasheets
dir: Datasheets # Put in root Datasheets folder
run_by_default: true
priority: 60
category: 'Schematic/docs'
options:
field: 'Datasheet' # Field containing the datasheet URLs
output: '${REFERENCE}_${VALUE}.pdf' # Name pattern for downloaded files
dnf: false # Don't include DNF components
dnf_filter: '_none' # No DNF filtering
link_repeated: true # Use symlinks for repeated datasheets
repeated: false # Don't re-download same URL
classify: true # Organize by component type (Capacitors/, Resistors/, etc.)
classify_extra: # Additional classification rules
'U': 'ICs'
'Q': 'Transistors'
'D': 'Diodes'
'L': 'Inductors'
'F': 'Fuses'
'J': 'Connectors'
'P': 'Connectors'
'SW': 'Switches'
'Y': 'Crystals'
'T': 'Transformers'
'RV': 'Varistors'
'FB': 'Ferrite_Beads'
# 3D model
- name: 'step'
comment: "3D STEP model"
type: step
dir: 3D
options:
output: '%f-3D.%x'
metric_units: true
origin: grid
no_virtual: true
# Board characteristics report
- name: 'report'
comment: "Board report"
type: report
dir: .
options:
output: '%f-report.%x'
do_convert: true
# Schematic diff
- name: 'sch_diff'
comment: "Schematic diff PDF"
type: diff
dir: DIFF
category: 'Schematic/docs'
run_by_default: true
priority: 50
layers: [] # Empty for schematic (not PCB)
options:
output: '%f-schematic-diff.%x'
format: 'pdf' # Output format: pdf, svg, ps, or png
pcb: false # This is for schematic
old: 'HEAD~1' # Old version to compare (previous commit)
new: 'HEAD' # New version (current)
cache_dir: '.cache'
add_link_id: true # Add link IDs to the generated diff
only_different: true # Only include pages that changed
threshold: 0 # Difference threshold (0 = any difference)
fuzz: 5 # Fuzzy matching tolerance in pixels
diff_mode: 'red_green' # How to show differences
old_color: '#FF0000' # Color for old/removed items
new_color: '#00FF00' # Color for new/added items
# PCB diff
- name: 'pcb_diff'
comment: "PCB diff PDF"
type: diff
dir: DIFF
category: 'PCB/docs'
run_by_default: true
priority: 50
layers: 'selected' # Use selected layers below
options:
output: '%f-pcb-diff.%x'
format: 'pdf' # Output format
pcb: true # This is for PCB
old: 'HEAD~1' # Old version to compare
new: 'HEAD' # New version
cache_dir: '.cache'
add_link_id: false # Not used for PCB
only_different: true # Only include layers that changed
threshold: 0 # Difference threshold
fuzz: 5 # Fuzzy matching tolerance
diff_mode: 'red_green' # Visual diff mode
old_color: '#FF0000' # Color for removed items
new_color: '#00FF00' # Color for added items
layers: # Which PCB layers to include in diff
- 'F.Cu'
- 'B.Cu'
- 'In1.Cu'
- 'In2.Cu'
- 'In3.Cu'
- 'In4.Cu'
- 'F.Silkscreen'
- 'B.Silkscreen'
- 'F.Mask'
- 'B.Mask'
- 'Edge.Cuts'
- 'F.Courtyard'
- 'B.Courtyard'
- 'F.Fab'
- 'B.Fab'
# Interactive diff using KiRi (HTML output)
- name: 'interactive_diff'
comment: "Interactive HTML diff"
type: diff
dir: DIFF
category: 'PCB/docs'
run_by_default: false # Optional - can be slow
priority: 40
layers: 'all' # Include all layers for interactive view
options:
output: '%f-interactive-diff.%x'
format: 'html' # HTML format for interactive viewing
pcb: true
old: 'HEAD~1'
new: 'HEAD'
cache_dir: '.cache'
only_different: true
diff_mode: 'stats' # Show statistics in HTML
# SVG diff for web viewing
- name: 'svg_diff'
comment: "SVG diff for web"
type: diff
dir: DIFF
category: 'PCB/docs'
run_by_default: false
priority: 40
layers: 'copper' # Only copper layers for web view
options:
output: '%f-diff.%x'
format: 'svg' # SVG format for web embedding
pcb: true
old: 'HEAD~1'
new: 'HEAD'
cache_dir: '.cache'
only_different: true
diff_mode: 'red_green'
old_color: '#FF0000'
new_color: '#00FF00'
zones: 'fill' # How to handle zones: fill, outline, or none
# JLCPCB fabrication package
- name: 'jlcpcb_gerbers'
comment: "Gerbers for JLCPCB"
type: gerber
dir: JLCPCB
options:
output: '%f%i.%x'
exclude_edge_layer: false
exclude_pads_from_silkscreen: true
plot_sheet_reference: false
plot_footprint_refs: true
plot_footprint_values: false
force_plot_invisible_refs_vals: false
tent_vias: true
use_protel_extensions: true # JLCPCB prefers Protel extensions
create_gerber_job_file: false # JLCPCB doesn't need this
disable_aperture_macros: true
gerber_precision: 4.6
use_gerber_x2_attributes: false
use_gerber_net_attributes: false
line_width: 0.1
subtract_mask_from_silk: true
layers:
- F.Cu
- B.Cu
- In1.Cu
- In2.Cu
- In3.Cu
- In4.Cu
- F.Paste
- B.Paste
- F.Silkscreen
- B.Silkscreen
- F.Mask
- B.Mask
- Edge.Cuts
# JLCPCB drill files
- name: 'jlcpcb_drill'
comment: "Drill files for JLCPCB"
type: excellon
dir: JLCPCB
options:
output: '%f%i.%x'
metric_units: true
minimal_header: false
mirror_y_axis: false
pth_and_npth_single_file: false # JLCPCB prefers separate files
# JLCPCB ZIP file
- name: 'jlcpcb_zip'
comment: "JLCPCB fabrication ZIP"
type: compress
dir: .
options:
output: '%f_JLCPCB_compress.%x'
format: ZIP
files:
- source: JLCPCB/*
dest: /
# Fabrication package (ZIP)
- name: 'fabrication'
comment: "Fabrication package"
type: compress
dir: .
options:
output: '%f-fabrication.%x'
format: ZIP
files:
- source: Gerbers/*
dest: /
- source: PCB/PDF/*
dest: /Documentation
- source: Assembly/*
dest: /Assembly
- source: 3D/*
dest: /3D
# KiCanvas interactive viewer - Schematic
- name: 'kicanvas_schematic'
comment: "Interactive schematic viewer"
type: kicanvas
dir: Interactive
output: '%f-schematic-viewer.%x'
category: 'Schematic/docs'
run_by_default: true
priority: 45
options:
source: 'schematic'
local_script: true # Download and use local copy of script
controls: 'full' # Full controls for navigation
download: true # Show download button
overlay: true # Show click overlay
title: '%f Schematic - Interactive Viewer'
# KiCanvas interactive viewer - PCB
- name: 'kicanvas_pcb'
comment: "Interactive PCB viewer"
type: kicanvas
dir: Interactive
output: '%f-pcb-viewer.%x'
category: 'PCB/docs'
run_by_default: true
priority: 45
options:
source: 'pcb'
local_script: true # Download and use local copy of script
controls: 'full' # Full controls for navigation
download: true # Show download button
overlay: true # Show click overlay
title: '%f PCB - Interactive Viewer'
# KiCanvas interactive viewer - Full Project
- name: 'kicanvas_project'
comment: "Interactive project viewer (both schematic and PCB)"
type: kicanvas
dir: Interactive
output: '%f-project-viewer.%x'
category: ['Schematic/docs', 'PCB/docs']
run_by_default: true
priority: 45
options:
source: 'project' # Show both schematic and PCB
local_script: true # Download and use local copy of script
controls: 'full' # Full controls for navigation
download: true # Show download button
overlay: true # Show click overlay
title: '%f Project - Interactive Viewer'
# Variants for different layer counts (optional)
variants:
- name: 2layer
comment: "2 layer board variant"
type: kibom
- name: 4layer
comment: "4 layer board variant"
type: kibom
- name: 6layer
comment: "6 layer board variant"
type: kibom