diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..bd73865 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,16 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + # Workflow files stored in the + # default location of `.github/workflows` + directory: "/" + schedule: + interval: "daily" + commit-message: + # Prefix all commit messages with "[gha] " + prefix: "[gha] " + + - package-ecosystem: "gitsubmodule" + directory: "/" + schedule: + interval: "daily" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a35cf7a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,233 @@ +name: "Build manufacturing files" + +# Controls when the action will run. Triggers the workflow on push or pull request +# events but only for the master branch +on: + push: + branches: + - "**" + paths: + - '**.kicad_sch' + - '**.kicad_pcb' + - 'footprints.pretty/*' + - 'footprints_project_specific.pretty/*' + - 'libraries/*' + - '.github/workflows/ci.yml' + - 'config.kibot.yaml' + - 'bom.ini' + # Ignore the push event when creating tags + tags-ignore: + - 'v?[0-9]+.[0-9]+.[0-9]+' + release: + types: + - published + +env: + SCHEMATIC_FILE: 6632B_binding_posts.kicad_sch + PCB_FILE: 6632B_binding_posts.kicad_pcb + KIBOT_CONFIG: config.kibot.yaml + +jobs: + tests: + name: Run tests + runs-on: ubuntu-latest + outputs: + revision: ${{ steps.extract_sch_revision.outputs.value }} + basename: ${{ steps.repo-basename.outputs.value }} + + steps: + - name: Download repository + uses: actions/checkout@v4 + + - name: Parse repository name + id: repo-basename + run: | + echo "value=$(basename ${{ github.repository }})" >> $GITHUB_OUTPUT + shell: bash + + - name: Extract schematic revision + id: extract_sch_revision + run: | + echo "value=$(perl -0777 -ne "print /\(title_block.+\(rev \"(.+?)\"\)/sg" ${{ env.SCHEMATIC_FILE }})" >>${GITHUB_OUTPUT} + shell: bash + + - name: Extract PCB revision + id: extract_pcb_revision + run: | + echo "value=$(perl -0777 -ne "print /\(title_block.+\(rev \"(.+?)\"\)/sg" ${{ env.PCB_FILE }})" >>${GITHUB_OUTPUT} + shell: bash + + - name: Test if the revision number was extracted + if: steps.extract_sch_revision.outputs.value == '' + run: | + echo "::error::Failed to extract revision number from schematic file: ${{ env.SCHEMATIC_FILE }}" + exit 1 + shell: bash + + - name: Test schematic revision == pcb revision + if: steps.extract_sch_revision.outputs.value != steps.extract_pcb_revision.outputs.value + run: | + echo "::error::Revision number of the schematic (${{ steps.extract_sch_revision.outputs.value }}) does not match PCB (${{ steps.extract_pcb_revision.outputs.value }}) revision." + exit 1 + shell: bash + + - name: Test for correct git tag + if: github.ref_type == 'tag' && github.ref_name != steps.extract_sch_revision.outputs.value + run: | + echo "::error::Revision number of the schematic/PCB (${{ steps.extract_sch_revision.outputs.value }}) does not match the Github tag (${{ github.ref_name }})." + exit 1 + shell: bash + + ERC: + name: Run ERC + runs-on: ubuntu-latest + needs: tests + + steps: + - name: Download repository + uses: actions/checkout@v4 + with: + submodules: true + + - name: Run ERC + uses: INTI-CMNB/KiBot@v2_dk8 + with: + config: ${{ env.KIBOT_CONFIG }} + schema: ${{ env.SCHEMATIC_FILE }} + dir: generated + skip: run_drc + targets: __NONE__ # Only run preflights + + - name: Upload results + uses: actions/upload-artifact@v4 + with: + name: ERC_Output + path: generated + retention-days: 7 + + DRC: + name: Run DRC + runs-on: ubuntu-latest + needs: ERC + + steps: + - name: Download repository + uses: actions/checkout@v4 + with: + submodules: true + + - name: Run DRC + uses: INTI-CMNB/KiBot@v2_dk8 + with: + config: ${{ env.KIBOT_CONFIG }} + board: ${{ env.PCB_FILE }} + dir: generated + skip: run_erc + targets: __NONE__ # Only run preflights + + - name: Upload results + uses: actions/upload-artifact@v4 + with: + name: DRC_Output + path: generated + retention-days: 7 + + fabrication_output: + name: 'Produce fabrication outputs' + runs-on: ubuntu-latest + needs: [ERC, DRC] + strategy: + matrix: + variant: [ 'default', ] + steps: + - name: Download repository + uses: actions/checkout@v4 + with: + submodules: true + + - uses: INTI-CMNB/KiBot@v2_dk8 + with: + config: ${{ env.KIBOT_CONFIG }} + schema: ${{ env.SCHEMATIC_FILE }} + board: ${{ env.PCB_FILE }} + skip: run_erc,run_drc + variant: ${{ matrix.variant }} + verbose: 0 # use 3 for debugging + + - name: Upload bill of materials files as artifact + uses: actions/upload-artifact@v4 + with: + name: manufacturing_files-bom-${{ matrix.variant }} + path: bom_files_compressed + retention-days: 7 + + - name: Upload schematic files as artifact + uses: actions/upload-artifact@v4 + with: + name: manufacturing_files-schematics-${{ matrix.variant }} + path: schematics + retention-days: 7 + + - name: Upload Gerber files as artifact + uses: actions/upload-artifact@v4 + with: + name: manufacturing_files-gerber-${{ matrix.variant }} + path: gerber_files_compressed + retention-days: 7 + + release: + name: 'Upload manufacturing files to release' + runs-on: ubuntu-latest + needs: [tests, fabrication_output] + if: github.event.action == 'published' + strategy: + matrix: + variant: [ 'default', ] + steps: + - name: Download manufacturing files artifact + uses: actions/download-artifact@v4 + with: + path: manufacturing_files + pattern: manufacturing_files-* + merge-multiple: true + + - name: Display structure of downloaded files + run: ls -R + working-directory: ./manufacturing_files + shell: bash + + - name: Append BOM (bill of materials) as asset + if: github.event.action == 'published' + run: | + mv "./manufacturing_files/bom_(${{ matrix.variant }}).zip" ${{ needs.tests.outputs.basename }}_bom_${{ needs.tests.outputs.revision }}_${{ matrix.variant }}.zip + gh release upload ${{ github.ref_name }} ${{ needs.tests.outputs.basename }}_bom_${{ needs.tests.outputs.revision }}_${{ matrix.variant }}.zip#"Bill of materials for the ${{ matrix.variant }} variant (zip)" --repo ${{ github.repository }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + + - name: Append schematics as asset + if: github.event.action == 'published' + run: | + mv "./manufacturing_files/$(basename ${{ env.SCHEMATIC_FILE }} .kicad_sch)_schematics_${{ needs.tests.outputs.revision }}_(${{ matrix.variant }}).pdf" ${{ needs.tests.outputs.basename }}_schematics_${{ needs.tests.outputs.revision }}_${{ matrix.variant }}.pdf + gh release upload ${{ github.ref_name }} ${{ needs.tests.outputs.basename }}_schematics_${{ needs.tests.outputs.revision }}_${{ matrix.variant }}.pdf#"Schematics for the ${{ matrix.variant }} variant (pdf)" --repo ${{ github.repository }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + + - name: Append position files as asset + if: github.event.action == 'published' + run: | + mv "./manufacturing_files/pos_(${{ matrix.variant }}).zip" ${{ needs.tests.outputs.basename }}_position_${{ needs.tests.outputs.revision }}_${{ matrix.variant }}.zip + gh release upload ${{ github.ref_name }} ${{ needs.tests.outputs.basename }}_position_${{ needs.tests.outputs.revision }}_${{ matrix.variant }}.zip#"Pick & Place position files for the ${{ matrix.variant }} variant (zip)" --repo ${{ github.repository }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + + - name: Append Gerber files as asset + if: github.event.action == 'published' + run: | + mv "./manufacturing_files/gerbers_(${{ matrix.variant }}).zip" ${{ needs.tests.outputs.basename }}_gerber_${{ needs.tests.outputs.revision }}_${{ matrix.variant }}.zip + gh release upload ${{ github.ref_name }} ${{ needs.tests.outputs.basename }}_gerber_${{ needs.tests.outputs.revision }}_${{ matrix.variant }}.zip#"Gerber files for the ${{ matrix.variant }} variant (zip)" --repo ${{ github.repository }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash diff --git a/config.kibot.yaml b/config.kibot.yaml new file mode 100644 index 0000000..474f582 --- /dev/null +++ b/config.kibot.yaml @@ -0,0 +1,168 @@ +kibot: + version: 1 + +globals: + # Filters for KiBot warnings + filters: + - filter: Ignore missing KiCad config, not in docker images + number: 8 + - filter: Ignore missing KiCad 3D models, not in docker images + number: 10 + - filter: Ignore missing KiCad config from KiAuto, not in docker images + number: 58 + regex: kicad_common.json + # This will undo the `set_text_variables` when we run it locally + restore_project: true + +preflight: + update_xml: true + drc: + ignore_unconnected: false + +variants: + - name: 'default' + comment: 'The normal PCB layout.' + type: kibom + file_id: _(default) + +outputs: + - name: 'gerbers' + comment: 'Create the Gerber files for the board house' + type: gerber + dir: gerber_files + options: + # generic layer options + exclude_edge_layer: false + exclude_pads_from_silkscreen: false + plot_sheet_reference: false + plot_footprint_refs: true + plot_footprint_values: true + force_plot_invisible_refs_vals: false + tent_vias: true + + # gerber options + use_aux_axis_as_origin: false + subtract_mask_from_silk: false + use_protel_extensions: false + gerber_precision: 4.6 + create_gerber_job_file: false + use_gerber_x2_attributes: false + use_gerber_net_attributes: false + output: '%f-%i%I_%r.%x' + + layers: + - 'F.Cu' + - 'B.Cu' + - 'F.Paste' + - 'B.Paste' + - 'F.Silkscreen' + - 'B.Silkscreen' + - 'F.Mask' + - 'B.Mask' + - 'User.Comments' + - 'User.Drawings' + - 'Edge.Cuts' + - 'F.Fab' + - 'B.Fab' + + - name: 'excellon_drill' + comment: 'Create the Excellon drill files to go with the Gerber files' + type: excellon + dir: gerber_files + options: + metric_units: true + map: + type: ps + output: '%f-%i%I_%r.%x' # %i is defined by npth_id and pth_id + use_aux_axis_as_origin: false + pth_and_npth_single_file: false + zeros_format: 'DECIMAL_FORMAT' + npth_id: 'NPTH' + pth_id: 'PTH' + output: '%f-%i%I_%r.%x' # %i is defined by npth_id and pth_id + + - name: 'position' + comment: 'Pick and place file' + type: position + dir: positiondir + options: + format: CSV # CSV or ASCII format + units: millimeters # millimeters or inches + separate_files_for_front_and_back: true + use_aux_axis_as_origin: true + output: '%f-%i%I_%r%v.%x' + + - name: 'BOM' + comment: 'Generate bill of materials (BOM)' + type: kibom + dir: bom + options: + format: CSV + conf: 'bom.ini' + output: '%f_%I_%sr_(%V).%x' # Note: The %v replacement is broken, so use _(%V) for now + output_id: 'bom' # Used for the %I expansion int the output file name + + - name: 'iBOM' + comment: 'Generate Interactive HTML BOM' + type: ibom + dir: bom + options: + dark_mode: false + blacklist: 'LOGO*,TP*,H*' + extra_fields: 'PN' + output: '%f_%I_%sr%v.%x' + highlight_pin1: true + output_id: 'ibom' # Used for the %I expansion int the output file name + + - name: 'pdfs' + comment: "Create PDFs of the schematics" + type: pdf_sch_print + dir: schematics + options: + title: "+ (%V variant)" + output: '%f_%I_%sr%v.%x' + output_id: 'schematics' # Used for the %I expansion int the output file name + + - name: 'compress_bom' + comment: 'Compress the BOM output' + type: compress + dir: bom_files_compressed + options: + files: + - from_output: BOM + - from_output: iBOM + output: '%I%v.%x' + output_id: 'bom' # Used for the %I expansion int the output file name + + - name: 'compress_fab' + comment: 'Compress the fabrication output' + type: compress + dir: gerber_files_compressed + options: + files: + - from_output: gerbers + - from_output: excellon_drill + output: '%I%v.%x' + output_id: 'gerbers' # Used for the %I expansion int the output file name + + - name: 'compress_position' + comment: "Compress the position files for assembly orders" + type: compress + dir: gerber_files_compressed + options: + files: + - from_output: position + output: '%I%v.%x' + output_id: 'pos' # Used for the %I expansion int the output file name + +groups: + - name: fab + outputs: + - gerbers + - excellon_drill + - position + + - name: bom + outputs: + - BOM + - iBOM