diff --git a/.gitea/workflows/kibot.yml b/.gitea/workflows/kibot.yml new file mode 100644 index 0000000..84ddadc --- /dev/null +++ b/.gitea/workflows/kibot.yml @@ -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 + + +
+
+ EOF
+
+ # Add the diff content with HTML escaping
+ git diff "$BASE_SHA" "$HEAD_SHA" -- "$SCH_FILE" | \
+ sed 's/&/\&/g; s/\</g; s/>/\>/g' | \
+ sed 's/^+[^+].*/&<\/span>/g' | \
+ sed 's/^-[^-].*/&<\/span>/g' >> "${GITHUB_WORKSPACE}/Generated/DIFF/${SCH_NAME}_diff.html"
+
+ echo "" >> "${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
\ No newline at end of file
diff --git a/.gitea/workflows/kibot_quick_start.yml b/.gitea/workflows/kibot_quick_start.yml
deleted file mode 100644
index 0e3a562..0000000
--- a/.gitea/workflows/kibot_quick_start.yml
+++ /dev/null
@@ -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
\ No newline at end of file
diff --git a/kibot.yaml b/kibot.yaml
new file mode 100644
index 0000000..3997525
--- /dev/null
+++ b/kibot.yaml
@@ -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
\ No newline at end of file