Initial commit

This commit is contained in:
2025-10-22 00:50:46 -07:00
commit c378b6a813
34 changed files with 5938 additions and 0 deletions

41
.github/rename.py vendored Normal file
View File

@@ -0,0 +1,41 @@
from pathlib import Path
import os
import sys
from ruamel.yaml import YAML
# renames the main project in the template dir and in the project settings
def rename_project(project_name, new_name = "template"):
"""renames the kicad project"""
project_path = str(Path(f"Hardware/{project_name}_PROJECT"))
files = os.listdir(project_path)
for index, file in enumerate(files):
print(file)
os.rename(os.path.join(project_path, file), os.path.join(project_path, file.replace(project_name, new_name)))
os.rename(project_path, project_path.replace(project_name, new_name))
pcb_path = str(Path(f"Hardware/{project_name}_PCB"))
os.rename(pcb_path, pcb_path.replace(project_name, new_name))
doc_path = str(Path(f"Hardware/{project_name}_DOCS"))
os.rename(doc_path, doc_path.replace(project_name, new_name))
def main():
yaml : YAML = YAML()
with open(Path("project_settings.yaml"), "r") as yaml_file:
settings = yaml.load(yaml_file)
print(f"{settings['project_name']=}")
print(f"{settings=}")
rename_project(settings["project_name"], sys.argv[1])
settings["project_name"] = sys.argv[1]
settings["needs_setup"] = False
# have to just print it out a rewrite over .project_settings because this guy
# is dumb and doesnt just let you write these out to string
with open(Path("project_settings.yaml"), "w", encoding=("utf-8")) as file:
yaml.dump(settings, file)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,46 @@
# look it would be piss easy to just keep it as a CSV but we can post process to add cool things like cost to each of the parts
import csv
import sys
import chevron
import datetime
from pprint import pprint
file_path_delimter = "\\" if sys.platform == "win32" else "/"
def load_bom(filename : str) -> dict:
out_dict = {
"parts" : [],
"time" : str(datetime.datetime.now().time()),
"date" : str(datetime.datetime.now().date().strftime("%d-%m-%Y")),
"total_cost" : 0,
"total_parts" : 0,
"project_name" : filename.strip(".csv").strip("bom").split(file_path_delimter)[-1]
}
with open(filename, "r") as csv_file:
for row in csv.DictReader(csv_file):
part_cost = 0
out_dict["total_parts"] += 1
out_dict["parts"].append(
{
"Reference" : row["Refs"],
"Value" : row["Value"],
"Quantity" : row["Qty"],
"part_number" : row["Footprint"],
"cost" : part_cost, # add some API call somewhere here
}
)
return out_dict
def main():
report_hash = load_bom(sys.argv[1])
# pprint(report_hash)
with open(sys.argv[2], "r") as txt:
out = chevron.render(txt.read(), report_hash)
with open(sys.argv[3], "w") as md:
md.write(out)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,57 @@
from violation import Violation
import datetime
import json
from pprint import pprint
def process_violation_list(drc_json : dict, list_name : str) -> None:
if list_name in drc_json.keys():
unconnected_items_errors = []
unconnected_items_warns = []
number_of_errors = 0
number_of_warns = 0
for violation in drc_json[list_name]:
v = Violation(violation, "drc")
if (v.violation_type == "error"):
unconnected_items_errors.append(v)
number_of_errors += 1
if (v.violation_type == "warn"):
unconnected_items_warns.append(v)
number_of_warns += 1
drc_json[list_name] = {
"errors" : unconnected_items_errors,
"warns" : unconnected_items_warns,
"number_of_errors" : number_of_errors,
"number_of_warns" : number_of_warns,
}
else:
drc_json.setdefault(list_name, {})
drc_json[list_name].setdefault("number_of_errors", 0)
drc_json[list_name].setdefault("number_of_warns", 0)
def process_report(report : str) -> dict:
out_dict : dict = json.loads(report)
number_of_errors = 0;
number_of_errors = 0;
process_violation_list(out_dict, "unconnected_items")
process_violation_list(out_dict, "violations")
process_violation_list(out_dict, "schematic_parity")
out_dict.setdefault(
"total_errors",
out_dict["unconnected_items"]["number_of_errors"] +
out_dict["violations"]["number_of_errors"] +
out_dict["schematic_parity"]["number_of_errors"]
)
out_dict.setdefault(
"total_warns",
out_dict["unconnected_items"]["number_of_warns"] +
out_dict["violations"]["number_of_warns"] +
out_dict["schematic_parity"]["number_of_warns"]
)
return out_dict

View File

@@ -0,0 +1,53 @@
from violation import Violation
import datetime
import json
class Sheet:
def __init__(self, json_obj : dict) -> None:
self.name : str = json_obj["path"]
self.name_md : str = self.name.replace(" ", "-")
self.number_of_errors : int = 0
self.number_of_warns : int = 0
self.errors : list[Violation] = list()
self.warns : list[Violation] = list()
for violation in json_obj["violations"]:
v = Violation(violation, "erc")
if (v.violation_type == "error"):
self.errors.append(v)
self.number_of_errors += 1
if (v.violation_type == "warn"):
self.warns.append(v)
self.number_of_warns += 1
def to_dict(self) -> dict:
out_dict = self.__dict__
errors_strings = []
warns_strings = []
for error in out_dict["errors"]:
errors_strings.append(error.__dict__)
out_dict["errors"] = errors_strings
for warn in out_dict["warns"]:
warns_strings.append(warn.__dict__)
out_dict["warns"] = warns_strings
return out_dict
def process_report(report : str) -> dict:
out_dict : dict = json.loads(report)
sheets = [Sheet(sheet) for sheet in out_dict["sheets"]]
out_dict["sheets"] = [sheet.to_dict() for sheet in sheets]
out_dict.setdefault(
"total_errors",
sum(sheet.number_of_errors for sheet in sheets)
)
out_dict.setdefault(
"total_warns",
sum(sheet.number_of_warns for sheet in sheets)
)
return out_dict

View File

@@ -0,0 +1,50 @@
# usage: python process_json_reports.py report.json template.mustache outfile.md project_name
import chevron
import sys
import datetime
import json
import process_erc_json
import process_drc_json
from pprint import pprint
def load_report(filename : str, project_name : str) -> dict:
out_dict : dict = {}
with open(filename, "r") as js:
if ("erc" in filename.lower()):
out_dict = process_erc_json.process_report(js.read())
if ("drc" in filename.lower()):
out_dict = process_drc_json.process_report(js.read())
out_dict.setdefault(
"time",
str(datetime.datetime.now().time())
)
out_dict.setdefault(
"date",
str(datetime.datetime.now().date().strftime("%d-%m-%Y"))
)
out_dict.setdefault(
"project_name",
project_name
)
out_dict.setdefault(
"has_violations",
True if out_dict["total_warns"] + out_dict["total_errors"] else None
)
return out_dict
def main():
report_hash = load_report(sys.argv[1], sys.argv[4])
# pprint(report_hash)
with open(sys.argv[2], "r") as txt:
out = chevron.render(txt.read(), report_hash)
with open(sys.argv[3], "w") as md:
md.write(out)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,94 @@
import chevron
import sys
import datetime
import json
import glob
from pathlib import Path
from pprint import pprint
# erc
# {
# "project_name" : "string",
# "passing_erc" : "bool",
# "erc_summary_link" : "link",
# }
# drc
# {
# "project_name" : "string",
# "passing_drc" : "bool",
# "drc_summary_link" : "link",
# }
# project
# {
# "project_name" : "string",
# "project_link" : "link",
# "schematic_link" : "link",
# "gerber_link" : "link",
# "bom_report_link" : "link",
# "bom_csv_link" : "link"
# }
EXTRAS_FILENAME = "readme_extras.json"
def load_json_file(filename : str) -> dict:
with open(Path(f"{filename}/{filename}"), "r") as js:
return json.loads(js.read())
def create_hash(filenames : list[str]) -> dict:
report_outs = filenames
report_outs.remove("readme_extras.json")
extras = {}
with open("readme_extras.json", "r") as js:
extras = json.loads(js.read())
reports_dicts : list[dict] = []
for report_name in report_outs:
reports_dicts.append(load_json_file(report_name))
readme_hash = {
**extras,
"projects" : [],
"did_error" : False,
"multiple_projects" : None
}
for report in reports_dicts:
for project in readme_hash["projects"]:
if project["project_name"] == report["project_name"]:
for key in report.keys():
project.setdefault(key, report[key])
break
else:
readme_hash["projects"].append(report)
pprint(readme_hash)
for project in readme_hash["projects"]:
readme_hash["did_error"] |= not project["passing_erc"]
readme_hash["did_error"] |= not project["passing_drc"]
project.setdefault("passing_erc_emoji", "" if project["passing_erc"] == "true" else "")
project.setdefault("passing_drc_emoji", "" if project["passing_drc"] == "true" else "")
readme_hash["multiple_projects"] = True if len(readme_hash["projects"]) > 1 else None
pprint(readme_hash)
return readme_hash
def main():
print(sys.argv)
readme_template, *args = sys.argv[1:]
report_hash = create_hash(args)
with open(readme_template, "r") as txt:
out = chevron.render(txt.read(), report_hash)
with open("README.md", "w") as md:
md.write(out)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,3 @@
chevron
pathlib
ruamel.yaml

18
.github/report_processing/violation.py vendored Normal file
View File

@@ -0,0 +1,18 @@
class Violation:
def __init__(self, violation : dict, violation_report_type : str = ["erc", "drc"]) -> None:
self.violation_type : str = \
"warn" if violation["severity"] == "warning" else "error"
self.name : str = violation["description"]
self.content : str = ""
# this violation_report_type purely exists because of a bug
# in kicads json output format where json output on erc reports
# the position in decimeters
for item in violation["items"]:
item_string = item["description"]
x : float = float(item["pos"]["x"]) * (100.0 if (violation_report_type == "erc") else 1.0)
y : float = float(item["pos"]["y"]) * (100.0 if (violation_report_type == "erc") else 1.0)
# print(f"{x=}")
item_string += f" at [x = {x:.4}mm, y = {y:.4}mm]\n"
self.content += item_string

View File

@@ -0,0 +1,29 @@
{{! hash schema }}
{{! {
"project_name" : "the name of the project",
"time" : "the name of the project",
"date" : "the name of the project",
"total_parts" : "number",
"total_cost" : "number",
"parts" : [
{
"Reference" : "part_reference" ,
"Value" : "the value of the part" ,
"Quantity" : "number" ,
"part_number" : "the part number" ,
"cost" : "number"
}
]
} }}
# 📄 BOM for {{project_name}} 📄
report created at {{time}} on {{date}}.
{{project_name}} has a total of {{total_parts}} parts with a cost of ${{total_cost}}.
| Reference | Value | Quantity | part number | cost |
| --------- | ----- | -------- | ----------- | ---- |
{{#parts}}
| {{Reference}} | {{Value}} | {{Quantity}} | {{part_number}} | ${{cost}} |
{{/parts}}
| | total | {{total_parts}} | total | ${{total_cost}} |

View File

@@ -0,0 +1,133 @@
{{! hash schema }}
{{! {
"date" : "the date of creation",
"time" : "the time of creation",
"total_warns" : "number",
"total_errors" : "number",
"has_violations" : "flag to say if the project has a violation",
"violations" : {
"number_of_errors" : "number",
"number_of_warns" : "number",
"warns" : [
{
"name" : "string",
"content" : "string"
}
],
"errors" : [
{
"name" : "string",
"content" : "string"
}
]
},
"unconnected_items" : {
"number_of_errors" : "number",
"number_of_warns" : "number",
"warns" : [
{
"name" : "string",
"content" : "string"
}
],
"errors" : [
{
"name" : "string",
"content" : "string"
}
]
},
"schematic_parity" :{
"number_of_errors" : "number",
"number_of_warns" : "number",
"warns" : [
{
"name" : "string",
"content" : "string"
}
],
"errors" : [
{
"name" : "string",
"content" : "string"
}
]
}
} }}
# 📟 {{project_name}} DRC report 📟
report created at {{time}} 🕧 on {{date}} 🗓️.
the design rule check found:
- {{total_errors}} errors in your design 😱
- {{total_warns}} warns in your design 🫨
{{#has_violations}}
number of errors and warns breakdown per sheet:
| error type | number of errors 🔴 | number of warns 🟠 |
| ----------------------------------------- | -------------------------------------- | ------------------------------------- |
| [violations](#violations) ❌ | {{violations.number_of_errors}} | {{violations.number_of_warns}} |
| [unconnected items](#unconnected-items) ⛓️‍💥| {{unconnected_items.number_of_errors}} | {{unconnected_items.number_of_warns}} |
| [schematic parity](#schematic-parity) 🔗 | {{schematic_parity.number_of_errors}} | {{schematic_parity.number_of_warns}} |
| total | {{total_errors}} | {{total_warns}} |
below is a more in-depth breakdown of the errors and warns per error type.
note you should only use this for quickly checking that the project
you uploaded has no error or warn. YOU SHOULD *NOT* use this to actually
run the drc in kicad so you can see where is erroring.
# violations
## errors : {{violations.number_of_errors}}
{{#violations.errors}}
### {{name}}
{{content}}
{{loction}}
{{/violations.errors}}
## warns : {{violations.number_of_warns}}
{{#violations.warns}}
### {{name}}
{{content}}
{{loction}}
{{/violations.warns}}
# unconnected items
## errors : {{unconnected_items.number_of_errors}}
{{#unconnected_items.errors}}
### {{name}}
{{content}}
{{loction}}
{{/unconnected_items.errors}}
## warns : {{unconnected_items.number_of_warns}}
{{#unconnected_items.warns}}
### {{name}}
{{content}}
{{loction}}
{{/unconnected_items.warns}}
# schematic parity
## errors : {{schematic_parity.number_of_errors}}
{{#schematic_parity.errors}}
### {{name}}
{{content}}
{{loction}}
{{/schematic_parity.errors}}
## warns : {{schematic_parity.number_of_warns}}
{{#schematic_parity.warns}}
### {{name}}
{{content}}
{{loction}}
{{/schematic_parity.warns}}
{{/has_violations}}
{{^has_violations}}
the design had no errors or warns, good job. ✅✅
{{/has_violations}}

View File

@@ -0,0 +1,73 @@
{{! hash schema }}
{{! {
"date" : "the date of creation",
"time" : "the time of creation",
"total_warns" : "number",
"total_errors" : "number",
"has_violations" : "flag to say if the project has a violation",
"sheets" : [
{
"name" : "string",
"name_md" : "just name but i replaced the spaces with hyphens",
"number_of_errors" : "number",
"number_of_warns" : "number",
"warns" : [
{
"name" : "string",
"content" : "string"
}
],
"errors" : [
{
"name" : "string",
"content" : "string"
}
]
}
]
} }}
# ⚡{{project_name}} ERC report ⚡
report created at {{time}} 🕧 on {{date}} 🗓️.
the electronic rules check found:
- {{total_errors}} errors in your design 😱
- {{total_warns}} warns in your design 🫨
{{#has_violations}}
number of errors and warns breakdown per sheet:
| sheet name 📄| number of errors 🔴 | number of warns 🟠 |
| ---------- | ---------------- | --------------- |
{{#sheets}}
| [{{name}}](#{{name_md}}) | {{number_of_errors}} | {{number_of_warns}} |
{{/sheets}}
| total | {{total_errors}}| {{total_warns}}|
below is a more in-depth breakdown of the errors and warn per sheets.
note you should only use this for quickly checking that the project
you uploaded has no error or warn. YOU SHOULD *NOT* use this to actually
run your ERC in kicad so you can see where is erroring.
{{#sheets}}
# {{name}}
## errors : {{number_of_errors}}
{{#errors}}
### {{name}}
{{content}}
{{/errors}}
## warns : {{number_of_warns}}
{{#warns}}
### {{name}}
{{content}}
{{/warns}}
{{/sheets}}
{{/has_violations}}
{{^has_violations}}
the design had no errors or warns, good job. ✅✅
{{/has_violations}}

View File

@@ -0,0 +1,5 @@
# how the templates work
templates work by using a json file to fill in the templating spots. for more information on the templates checkout [mustache templates](https://mustache.github.io/). these templates use a json file format as what they call a "hash" to fill out the templates. the hashs for each of these templates are layout at the top of each of the `.mustache` files in a comment. These are also the hashes outputted by the processing scripts. usages for these scripts are at the top of the file.
if any schema says bool this actually means the value is either something or either doesnt exist/null.

153
.github/report_templates/readme.mustache vendored Normal file
View File

@@ -0,0 +1,153 @@
{{! hash schema }}
{{! {
"badge" : "the ci badge",
"lastest_action_run_link" : "link to the lastest action",
"did_error" : "to check if errors occured in the pipeline",
"title" : "the tiltle of the project, can be set in project_settings or it will use the repo name",
"multiple_projects" : "bool",
"projects" : [
{
"project_name" : "string",
"project_link" : "link",
"passing_erc" : "bool",
"passing_erc_emoji" : "string",
"erc_summary_link" : "link",
"passing_drc" : "bool",
"passing_drc_emoji" : "string",
"drc_summary_link" : "link",
"gerber_link" : "link",
"schematic_link" : "link",
"bom_report_link" : "link",
"bom_csv_link" : "link"
}
]
} }}
# kicad project {{title}}
{{badge}}
{{! [![.github/workflows/main.yaml](https://github.com/sirlilpanda/kicad-project-template/actions/workflows/main.yaml/badge.svg)](https://github.com/sirlilpanda/kicad-project-template/actions/workflows/main.yaml) }}
a cool table showing the workflow of all the kicad projects.
| project_name | DRC | ERC |
| ------------ | --- | --- |
{{#projects}}
| {{project_name}} | [{{passing_erc_emoji}}]({{erc_summary_link}})| [{{passing_drc_emoji}}]({{drc_summary_link}}) |
{{/projects}}
for a quick guide check [project setup](#project-setup)
This is a simple project template for new kicad projects. This template has some basic setup already completed such as workflows for auto creating all the things you forget when creating a kicad project such as:
{{^multiple_projects}}
{{#projects}}
- [gerbers]({{gerber_link}})
- [bom]({{bom_report_link}})
- [schematic pdf]({{schematic_link}})
{{/projects}}
{{/multiple_projects}}
{{#multiple_projects}}
| project_name | schematic | bom | bom report | gerbers |
| ------------ | --------- | --- | ---------- | ------- |
{{#projects}}
| [{{project_name}}]({{project_link}}) | [{{project_name}}_schematic.pdf]({{schematic_link}}) | [{{project_name}}_bill_of_materials.csv]({{bom_csv_link}}) | [{{project_name}}_bom_report.md]({{bom_report_link}}) | [{{project_name}}_grbr.zip]({{gerber_link}}) |
{{/projects}}
{{/multiple_projects}}
This workflow will also run the design rules check on the PCB and schematic to ensure that you upload a working PCB. These reports are uploaded as summaries within the github [actions tab]({{lastest_action_run_link}}). This template has a simple schematic PCB in it (because DRC fails on an empty PCB). Shown below is the example PCB.
![example pcb with battery diode and resistor](res/image.png)
besides from that the project also has:
- common predefined trace widths
- smallest vias size [JLCPBC allows](https://jlcpcb.com/capabilities/Capabilities#Drilling)
- custom net colours in the schematic editor
- `red` for +V
- `blue` for -V
- `grey` for ground
to create a repo from this template follow this [guide](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template)
contained in this template are:
---
- `.github/` : all files relating to github actions and other admin see [here](https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions) for more example of what can be placed in it
- `report_processing` : where the python scripts are stored for processing the json report data from kicad
- `report_templates` : where the template for said reports are stored
- `workflows/` : this is where the github actions are kept
- `main.yaml` : the main github action that will auto generate all files required and run DRC and ERC
- `rename.py` : the script for renaming the project
- `hardware/` : this is where the kicad projects live note this can be changed
- `docs/` : this is where the generate docs are placed by default
- `BOM/` : where the bill of materials and price breakdown are kept
- `bill_of_materials.csv`: the auto generated bom for the kicad project
- `bom_report.md` : a report for the bill of materials
- `template_schematic.pdf` : the schematic for the kicad project, auto generated by the github action
- `pcbs/` : this is where the auto generated gerbers for the kicad project are stored
- `res/` : where resources are stored for the README
- `.gitignore`: a slightly modified gitignore from the [standard one](https://github.com/github/gitignore/blob/main/KiCad.gitignore)
- `project_settings.yaml` : where the settings for this project is stored
- `README.md` : this file, suggest you change this one creating your project
## project settings
there are currently very few project settings that can be changed (will will be change in the future) these are:
| setting | description |
| --------------------------- | ----------------------------------------------------------------- |
| has_been_set_up | a flag to tell the setup action if the project has been set up |
| project_name | the name of the project, this will be set to the name of the repo |
| production_formats | the output production format for the PCBs |
| dynamic_read_me | allow the readme to be updated using the given template |
| bom_template_path | the template used to write the bom report files |
| erc_report_template_path | the template used to write the erc report files |
| drc_report_template_path | the template used to write the drc report files |
| readme_template_path | the template used to write projects readme |
| schematic_output_name | the name suffix of the generated schematics |
| bom_csv_output_name | the name suffix of the generated bom csv file |
| bom_report_output_name | the name suffix of the generated bom report |
| production_file_output_name | the name suffix of the generated production file |
| schematic_output_path | the output path of the generated schematics files |
| bom_csv_output_path | the output path of the generated bom csv file |
| bom_report_output_path | the output path of the generated bom report |
| production_file_output_path | the output path of the generated production file |
## project setup
### creating a new repo with the template
creating a new template from a repo is simple:
1. click on the button in the top right hand corner called `use this template`
![alt text](res/image-5.png)
2. when the drop down menu appears click on `create a new repository`
![alt text](res/image-6.png)
3. once you click you will be brought to this page, note that the repo name you choose here will be the name that you kicad project is called.
![alt text](res/image-7.png)
after these steps you then need to configure the repo settings to do their magic see [configuring repo settings](#configuring-repo-settings) for what to do next.
### configuring repo settings
once you have created a new repo with the template, you ill have to configure the github action settings. this is because you will get an error that looks something along these lines:
![alt text](res/image-4.png)
where the action can not commit the changes due to not having permissions follow these steps:
1. open the repo setting
![alt text](res/image-1.png)
2. then head in to actions : General
![alt text](res/image-2.png)
3. then scroll down to workflow permissions and ensure that both
`Read and write permissions` and `Allow GitHub Actions to create and approve pull requests` are ticked as seen below
![alt text](res/image-3.png)
this should fix the problem if not, go harass stack overflow they need it
Once all of these steps have been followed the workflow should be passing, however the `README.md` will only update on the next push request.
## editing the readme
As this repo can and will automatically update the repo corresponding to the given readme template. If you dont want to use this you can always disable this by setting the `dynamic_read_me` to `false`. but if you want some very cool features like auto updating tables to show what projects are passing the rules check or simple links to parts of your directory. then have a look at the template readme and learn [mustache](https://mustache.github.io/)
## improvements

539
.github/workflows/main.yaml vendored Normal file
View File

@@ -0,0 +1,539 @@
on:
push:
branches: [main, master, workflow_testing]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
ERC_JOB_NAME : "⚡ERC report⚡"
DRC_JOB_NAME : "📟 DRC report 📟"
jobs:
setup_new_project: # this job only exists for project creation
runs-on: ubuntu-latest
name: set up project
steps:
- name: Checkout
uses: actions/checkout@v4
# reads the project_setting.yaml file allowing you to access it with steps.id.outputs.[key]
- name: read yaml file
uses: juliojimenez/yamler@v1.1.0
id: yaml
with:
yaml-file: ${{ github.workspace }}/project_settings.yaml
- name: check setup
run: |
echo ${{steps.yaml.outputs.needs_setup}}
- name: Setting up Python and chevron to processes failed reports
# workflows really need some more work done on them
if: ${{ !cancelled() && steps.yaml.outputs.needs_setup == 'true' && github.repository != 'sirlilpanda/kicad-project-template'}}
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
- name: installing requirements
if: ${{ !cancelled() && steps.yaml.outputs.needs_setup == 'true' && github.repository != 'sirlilpanda/kicad-project-template'}}
run: pip install -r ${{ github.workspace }}/.github/report_processing/requirements.txt
- name: rename project if setup has not been completed
if: ${{ !cancelled() && steps.yaml.outputs.needs_setup == 'true' && github.repository != 'sirlilpanda/kicad-project-template'}}
run: python ${{ github.workspace }}/.github/rename.py ${{github.event.repository.name}}
- name: commit production files
if: ${{ !cancelled() && steps.yaml.outputs.needs_setup == 'true' && github.repository != 'sirlilpanda/kicad-project-template'}}
uses: EndBug/add-and-commit@v9
with:
default_author: github_actions
message: 'setup project'
push: true
add: "."
setup_matrixs:
outputs:
projects: ${{ steps.projects.outputs.projects }}
runs-on: ubuntu-latest
name: matrix setup 🗓️
needs: setup_new_project
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setting up Python
# workflows really need some more work done on them
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
- name: installing requirements
run: pip install pyyaml
- name: creating list start
run:
echo -n "projects=[" >> temp.txt
# this find commad outputs path1,path2,path3 with out the .kicad_pro ext
# .kicad_pro ext is removed because the erc and drc steps want either a
# .kicad_sch or .kicad_pcb file it also makes it easier to name files
# with the project name
# this output will look like
# projects=["path/projet_name", "path/projet_name2", ...]
- name: get kicad project names
run:
find . -type f -name "*.kicad_pro" -exec sh -c 'echo -n "\"${0%.kicad_pro}\","' {} \; | sed 's/.\{1\}$//' >> temp.txt
- name: creating list end
run:
echo "]" >> temp.txt
- name: list output
run:
cat temp.txt
- name: creating list end
id: projects
run:
cat temp.txt >> "$GITHUB_OUTPUT"
# basename is used here to remove the rest of the path from the find
#
DRC:
runs-on: ubuntu-latest
name: "📟 DRC report 📟"
needs: setup_matrixs
strategy:
matrix:
project_path: ${{ fromJSON(needs.setup_matrixs.outputs.projects) }}
steps:
- name: check matrix
run: basename ${{ matrix.project_path }}
- name: setting env
run:
echo "PROJECT_NAME=$(basename ${{ matrix.project_path }})" >> $GITHUB_ENV
- name: Checkout
uses: actions/checkout@v4
- name: read-yaml-file
uses: juliojimenez/yamler@v1.1.0
id: yaml
with:
yaml-file: ${{ github.workspace }}/project_settings.yaml
- name: Setting up Python and chevron to processes reports
# workflows really need some more work done on them
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
- name: installing requirements
run: pip install -r ${{ github.workspace }}/.github/report_processing/requirements.txt
- name: Run KiCad DRC
id: drc
uses: sparkengineering/kicad-action@v4
with:
kicad_pcb: ${{ matrix.project_path }}.kicad_pcb
pcb_drc: true
report_format: json
pcb_drc_file: drc.json
- name: checking files were created
run:
ls -R
- name: creating DRC report in markdown
if: ${{ always() }}
run: python
${{ github.workspace }}/.github/report_processing/process_json_reports.py
${{ github.workspace }}/$(dirname ${{matrix.project_path}})/drc.json
${{ github.workspace }}/${{steps.yaml.outputs.drc_report_template_path}}
${{ github.workspace }}/${{ env.PROJECT_NAME }}_drc.md
${{ env.PROJECT_NAME }}
- name: upload report summary
if: ${{ always() }}
run: cat ${{ github.workspace }}/${{ env.PROJECT_NAME }}_drc.md >> $GITHUB_STEP_SUMMARY
- name: get summary url
if: ${{always()}}
id: exp
uses: pl-strflt/job-summary-url-action@v1
with:
job: "${{env.DRC_JOB_NAME}} (${{matrix.project_path}})"
- name: create files to upload
if: ${{always()}}
run: |
echo "{\"passing_drc\":\"${{steps.drc.conclusion != 'failure'}}\",\"project_name\":\"${{env.PROJECT_NAME}}\", \"drc_summary_link\":\"${{ steps.exp.outputs.job_summary_url }}\"}" >> ${{env.PROJECT_NAME}}_drc.json
- name: upload data for readme updating
if: ${{always()}}
uses: actions/upload-artifact@v4
with:
name: ${{env.PROJECT_NAME}}_drc.json
path: ${{env.PROJECT_NAME}}_drc.json
ERC:
runs-on: ubuntu-latest
name: "⚡ERC report⚡"
needs: setup_matrixs
strategy:
matrix:
project_path: ${{ fromJSON(needs.setup_matrixs.outputs.projects) }}
steps:
- name: check matrix
run: basename ${{ matrix.project_path }}
- name: setting env
run:
echo "PROJECT_NAME=$(basename ${{ matrix.project_path }})" >> $GITHUB_ENV
- name: setting env
run:
echo "PROJECT_NAME=$(basename ${{ matrix.project_path }})" >> $GITHUB_ENV
- name: Checkout
uses: actions/checkout@v4
- name: read-yaml-file
uses: juliojimenez/yamler@v1.1.0
id: yaml
with:
yaml-file: ${{ github.workspace }}/project_settings.yaml
- name: Setting up Python and chevron to processes reports
# workflows really need some more work done on them
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
- name: installing requirements
run: pip install -r ${{ github.workspace }}/.github/report_processing/requirements.txt
- name: Run KiCad ERC
id: erc
uses: sparkengineering/kicad-action@v4
with:
kicad_sch: ${{ matrix.project_path }}.kicad_sch
sch_erc: true
report_format: json
sch_erc_file: erc.json
- name: checking files were created
run:
ls -R
- name: creating ERC report in markdown
if: ${{ always() }}
run: python
${{ github.workspace }}/.github/report_processing/process_json_reports.py
${{ github.workspace }}/$(dirname ${{matrix.project_path}})/erc.json
${{ github.workspace }}/${{steps.yaml.outputs.erc_report_template_path}}
${{ github.workspace }}/${{ env.PROJECT_NAME }}_erc.md
${{ env.PROJECT_NAME }}
- name: upload report summary
if: ${{ always() }}
run: cat ${{ github.workspace }}/${{ env.PROJECT_NAME }}_erc.md >> $GITHUB_STEP_SUMMARY
- name: get summary url
if: ${{always()}}
id: exp
uses: pl-strflt/job-summary-url-action@v1
with:
job: "${{env.ERC_JOB_NAME}} (${{matrix.project_path}})"
- name: print summary url
if: ${{always()}}
run: echo '${{ steps.exp.outputs.job_summary_url }}'
shell: bash
- name: create files to upload
if: ${{always()}}
run: |
echo "{\"passing_erc\":\"${{steps.erc.conclusion != 'failure'}}\",\"project_name\":\"${{env.PROJECT_NAME}}\", \"erc_summary_link\":\"${{ steps.exp.outputs.job_summary_url }}\"}" >> ${{env.PROJECT_NAME}}_erc.json
- name: upload data for readme updating
if: ${{always()}}
uses: actions/upload-artifact@v4
with:
name: ${{env.PROJECT_NAME}}_erc.json
path: ${{env.PROJECT_NAME}}_erc.json
production_job:
runs-on: ubuntu-latest
name: creating production files bom sch gerbers 📂
needs: setup_matrixs
strategy:
matrix:
project_path: ${{ fromJSON(needs.setup_matrixs.outputs.projects) }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: read-yaml-file
uses: juliojimenez/yamler@v1.1.0
id: yaml
with:
yaml-file: ${{ github.workspace }}/project_settings.yaml
- name: setting env
run:
echo "PROJECT_NAME=$(basename ${{ matrix.project_path }})" >> $GITHUB_ENV
- name: setting env
run: | # | the / here is defined in the project settings
echo "schematic_file=${{env.PROJECT_NAME}}${{steps.yaml.outputs.schematic_output_name}}.pdf" >> $GITHUB_ENV
echo "bill_of_materials_file=${{env.PROJECT_NAME}}${{steps.yaml.outputs.bom_csv_output_name}}.csv" >> $GITHUB_ENV
echo "production_format_file=${{env.PROJECT_NAME}}${{steps.yaml.outputs.production_file_output_name}}.zip" >> $GITHUB_ENV
echo "bom_report_file=${{env.PROJECT_NAME}}${{steps.yaml.outputs.bom_report_output_name}}.md" >> $GITHUB_ENV
- name: checking envs
run:
echo "${{env.schematic_file}}"
echo "${{env.bill_of_materials_file}}"
echo "${{env.production_format_file}}"
echo "${{env.bom_report_file}}"
- name: setting env
run:
echo "PROJECT_NAME=$(basename ${{ matrix.project_path }})" >> $GITHUB_ENV
- name: setting env
run: | # | the / here is defined in the project settings
echo "schematic_file=${{env.PROJECT_NAME}}${{steps.yaml.outputs.schematic_output_name}}.pdf" >> $GITHUB_ENV
echo "bill_of_materials_file=${{env.PROJECT_NAME}}${{steps.yaml.outputs.bom_csv_output_name}}.csv" >> $GITHUB_ENV
echo "production_format_file=${{env.PROJECT_NAME}}${{steps.yaml.outputs.production_file_output_name}}.zip" >> $GITHUB_ENV
echo "bom_report_file=${{env.PROJECT_NAME}}${{steps.yaml.outputs.bom_report_output_name}}.md" >> $GITHUB_ENV
- name: checking envs
run:
echo "${{env.schematic_file}}"
echo "${{env.bill_of_materials_file}}"
echo "${{env.production_format_file}}"
echo "${{env.bom_report_file}}"
- name: Setting up Python and chevron to processes reports
# workflows really need some more work done on them
if: ${{ !cancelled() }}
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
- name: installing requirements
if: ${{ !cancelled() }}
run: pip install -r ${{ github.workspace }}/.github/report_processing/requirements.txt
- name: Export production files
id: production
uses: sparkengineering/kicad-action@v4
if: '!cancelled()'
with:
kicad_sch: ${{ matrix.project_path }}.kicad_sch
sch_pdf: true # Generate PDF
sch_bom: true # Generate BOM
kicad_pcb: ${{ matrix.project_path }}.kicad_pcb
pcb_gerbers: true # Generate Gerbers
- name: Moving production files to correct location
if: ${{ !cancelled() && steps.production.conclusion == 'success' }}
run: |
mv ${{ github.workspace }}/$(dirname ${{matrix.project_path}})/sch.pdf ${{ github.workspace }}/${{env.schematic_file}}
mv ${{ github.workspace }}/$(dirname ${{matrix.project_path}})/bom.csv ${{ github.workspace }}/${{env.bill_of_materials_file}}
mv ${{ github.workspace }}/$(dirname ${{matrix.project_path}})/gbr.zip ${{ github.workspace }}/${{env.production_format_file}}
- name: creating BOM report in markdown
if: ${{ !cancelled() }}
run: python
${{ github.workspace }}/.github/report_processing/process_bom_files.py
${{ github.workspace }}/${{env.bill_of_materials_file}}
${{ github.workspace }}/${{steps.yaml.outputs.bom_template_path}}
${{ github.workspace }}/${{env.bom_report_file}}
- name: upload report'
uses: actions/upload-artifact@v4
with:
name: production-files-${{env.PROJECT_NAME}}.zip
path: |
${{ github.workspace }}/${{env.schematic_file}}
${{ github.workspace }}/${{env.bill_of_materials_file}}
${{ github.workspace }}/${{env.production_format_file}}
${{ github.workspace }}/${{env.bom_report_file}}
- name: data for readme updating
if: ${{always()}}
run: |
echo "{" >> ${{env.PROJECT_NAME}}_project.json
echo "\"schematic_link\":\"https://github.com/${{ github.repository }}/tree/${{ github.ref_name }}/${{env.schematic_file}}\"," >> ${{env.PROJECT_NAME}}_project.json
echo "\"bom_csv_link\":\"https://github.com/${{ github.repository }}/tree/${{ github.ref_name }}/${{env.bill_of_materials_file}}\"," >> ${{env.PROJECT_NAME}}_project.json
echo "\"bom_report_link\":\"https://github.com/${{ github.repository }}/tree/${{ github.ref_name }}/${{env.bom_report_file}}\"," >> ${{env.PROJECT_NAME}}_project.json
echo "\"gerber_link\":\"https://github.com/${{ github.repository }}/tree/${{ github.ref_name }}/${{env.production_format_file}}\"," >> ${{env.PROJECT_NAME}}_project.json
echo "\"project_link\":\"https://github.com/${{ github.repository }}/tree/${{ github.ref_name }}/$(dirname ${{matrix.project_path}})\"," >> ${{env.PROJECT_NAME}}_project.json
echo "\"project_name\":\"${{env.PROJECT_NAME}}\"" >> ${{env.PROJECT_NAME}}_project.json
echo "}" >> ${{env.PROJECT_NAME}}_project.json
- name: upload report
if: ${{always()}}
uses: actions/upload-artifact@v4
with:
name: ${{env.PROJECT_NAME}}_project.json
path: ${{env.PROJECT_NAME}}_project.json
readme_job:
runs-on: ubuntu-latest
name: update readme
if: ${{ always() }}
needs: [DRC, ERC, production_job]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: read-yaml-file
uses: juliojimenez/yamler@v1.1.0
id: yaml
with:
yaml-file: ${{ github.workspace }}/project_settings.yaml
- name: download ercs files
if: ${{ steps.yaml.outputs.dynamic_read_me == 'true' }}
uses: actions/download-artifact@v4
with:
pattern: "*_erc.json"
path: ${{ github.workspace }}
- name: download drcs files
if: ${{ steps.yaml.outputs.dynamic_read_me == 'true' }}
uses: actions/download-artifact@v4
with:
pattern: "*_drc.json"
path: ${{ github.workspace }}
- name: download production json files
if: ${{ steps.yaml.outputs.dynamic_read_me == 'true' }}
uses: actions/download-artifact@v4
with:
pattern: "*_project.json"
path: ${{ github.workspace }}
- name: Setting up Python
if: ${{ steps.yaml.outputs.dynamic_read_me == 'true' }}
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
- name: installing requirements
if: ${{ !cancelled() && steps.yaml.outputs.dynamic_read_me == 'true' }}
run: pip install -r ${{ github.workspace }}/.github/report_processing/requirements.txt
- name: create extra info for readme hash
if: ${{ steps.yaml.outputs.dynamic_read_me == 'true' }}
run: |
echo "{" >> readme_extras.json
echo "\"badge\" : \"[![.github/workflows/main.yaml](https://github.com/${{github.repository}}/actions/workflows/main.yaml/badge.svg?branch=${{github.ref_name}})](https://github.com/${{github.repository}}/actions/workflows/main.yaml)\"," >> readme_extras.json
echo "\"lastest_action_run_link\" : \"https://github.com/${{github.repository}}/actions/runs/${{ github.run_id }}\"," >> readme_extras.json
echo "\"title\" : \"${{steps.yaml.outputs.project_name}}\"" >> readme_extras.json
echo "}" >> readme_extras.json
- name: show extras
run:
cat readme_extras.json
- name: create new readme
if: ${{ steps.yaml.outputs.dynamic_read_me == 'true' }}
run:
python
${{ github.workspace }}/.github/report_processing/process_output_files.py
${{ github.workspace }}/${{steps.yaml.outputs.readme_template_path}} *.json
- name: upload data for readme updating
if: ${{ steps.yaml.outputs.dynamic_read_me == 'true' }}
uses: actions/upload-artifact@v4
with:
name: README.md
path: README.md
- name: list everything
if: ${{always()}}
run: ls -R
upload_job:
runs-on: ubuntu-latest
name: commit production files
if: ${{ always() }}
needs: [readme_job]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: read-yaml-file
uses: juliojimenez/yamler@v1.1.0
id: yaml
with:
yaml-file: ${{ github.workspace }}/project_settings.yaml
- name: download production files
uses: actions/download-artifact@v4
with:
pattern: production-files-*
path: ${{ github.workspace }}
- name: download readme
uses: actions/download-artifact@v4
with:
name: README.md
path: ${{ github.workspace }}
- name: check downloads
run: ls -R
- name: Moving files to correct location
run: |
mv ${{ github.workspace }}/production-files-*/*${{steps.yaml.outputs.schematic_output_name}}.pdf ${{ github.workspace }}/${{steps.yaml.outputs.schematic_output_path}}
mv ${{ github.workspace }}/production-files-*/*${{steps.yaml.outputs.bom_csv_output_name}}.csv ${{ github.workspace }}/${{steps.yaml.outputs.bom_csv_output_path}}
mv ${{ github.workspace }}/production-files-*/*${{steps.yaml.outputs.bom_report_output_name}}.md ${{ github.workspace }}/${{steps.yaml.outputs.bom_report_output_path}}
mv ${{ github.workspace }}/production-files-*/*${{steps.yaml.outputs.production_file_output_name}}.zip ${{ github.workspace }}/${{steps.yaml.outputs.production_file_output_path}}
- name: commit production files
uses: EndBug/add-and-commit@v9
with:
default_author: github_actions
message: 'production files'
push: true
pull: '--rebase --autostash'
tag_push: '--force' # just makes life easier
tag: 'v1.0.0 --force'
add: |
${{ github.workspace }}/*${{steps.yaml.outputs.schematic_output_name}}.pdf
${{ github.workspace }}/*${{steps.yaml.outputs.bom_csv_output_name}}.csv
${{ github.workspace }}/*${{steps.yaml.outputs.bom_report_output_name}}.md
${{ github.workspace }}/*${{steps.yaml.outputs.production_file_output_name}}.zip
${{ github.workspace }}/README.md
- name: list everything
if: ${{always()}}
run: ls -R

31
.gitignore vendored Normal file
View File

@@ -0,0 +1,31 @@
# For PCBs designed using KiCad: https://www.kicad.org/
# Format documentation: https://kicad.org/help/file-formats/
# Temporary files
Hardware/*/*.000
Hardware/*/*.bak
Hardware/*/*.bck
Hardware/*/*.kicad_pcb-bak
Hardware/*/*.kicad_sch-bak
Hardware/*/*-backups
Hardware/*/*.kicad_prl
Hardware/*/*.sch-bak
Hardware/*/*~
Hardware/*/_autosave-*
Hardware/*/*.tmp
Hardware/*/*-save.pro
Hardware/*/*-save.kicad_pcb
Hardware/*/fp-info-cache
# Netlist files (exported from Eeschema)
Hardware/*/*.net
# Autorouter files (exported from Pcbnew)
Hardware/*/*.dsn
Hardware/*/*.ses
# Exported BOM files
Hardware/*/*.xml
Hardware/*/*.csv
__pycache__/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,669 @@
{
"board": {
"3dviewports": [],
"design_settings": {
"defaults": {
"apply_defaults_to_fp_fields": false,
"apply_defaults_to_fp_shapes": false,
"apply_defaults_to_fp_text": false,
"board_outline_line_width": 0.049999999999999996,
"copper_line_width": 0.19999999999999998,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.049999999999999996,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.09999999999999999,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.09999999999999999,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.09999999999999999,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.09999999999999999,
"silk_text_upright": false,
"zones": {
"min_clearance": 0.5
}
},
"diff_pair_dimensions": [
{
"gap": 0.0,
"via_gap": 0.0,
"width": 0.0
}
],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"connection_width": "warning",
"copper_edge_clearance": "error",
"copper_sliver": "warning",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint": "error",
"footprint_symbol_mismatch": "warning",
"footprint_type_mismatch": "ignore",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"isolated_copper": "warning",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"lib_footprint_issues": "warning",
"lib_footprint_mismatch": "warning",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "warning",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_edge_clearance": "warning",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"solder_mask_bridge": "error",
"starved_thermal": "error",
"text_height": "warning",
"text_thickness": "warning",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zones_intersect": "error"
},
"rules": {
"max_error": 0.005,
"min_clearance": 0.0,
"min_connection": 0.0,
"min_copper_edge_clearance": 0.5,
"min_hole_clearance": 0.25,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.19999999999999998,
"min_microvia_drill": 0.09999999999999999,
"min_resolved_spokes": 2,
"min_silk_clearance": 0.0,
"min_text_height": 0.7999999999999999,
"min_text_thickness": 0.08,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.0,
"min_via_annular_width": 0.09999999999999999,
"min_via_diameter": 0.5,
"solder_mask_to_copper_clearance": 0.0,
"use_height_for_length_calcs": true
},
"teardrop_options": [
{
"td_onpadsmd": true,
"td_onroundshapesonly": false,
"td_ontrackend": false,
"td_onviapad": true
}
],
"teardrop_parameters": [
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_round_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_rect_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_track_end",
"td_width_to_size_filter_ratio": 0.9
}
],
"track_widths": [
0.0,
0.2,
0.3,
0.4,
0.5,
0.8,
1.0
],
"tuning_pattern_settings": {
"diff_pair_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 1.0
},
"diff_pair_skew_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
},
"single_track_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
}
},
"via_dimensions": [
{
"diameter": 0.0,
"drill": 0.0
},
{
"diameter": 0.25,
"drill": 0.15
}
],
"zones_allow_external_fillets": false
},
"ipc2581": {
"dist": "",
"distpn": "",
"internal_id": "",
"mfg": "",
"mpn": ""
},
"layer_presets": [],
"viewports": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"conflicting_netclasses": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"endpoint_off_grid": "ignore",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"missing_bidi_pin": "warning",
"missing_input_pin": "warning",
"missing_power_pin": "error",
"missing_unit": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "error",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"simulation_model_issue": "ignore",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "template.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.2,
"via_diameter": 0.6,
"via_drill": 0.3,
"wire_width": 6
},
{
"bus_width": 12,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "+POWER",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgb(255, 8, 21)",
"track_width": 0.2,
"via_diameter": 0.6,
"via_drill": 0.3,
"wire_width": 6
},
{
"bus_width": 12,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "-POWER",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgb(15, 0, 255)",
"track_width": 0.2,
"via_diameter": 0.6,
"via_drill": 0.3,
"wire_width": 6
},
{
"bus_width": 12,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "GND",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgb(134, 129, 126)",
"track_width": 0.2,
"via_diameter": 0.6,
"via_drill": 0.3,
"wire_width": 6
}
],
"meta": {
"version": 3
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": [
{
"netclass": "+POWER",
"pattern": "*+*V*"
},
{
"netclass": "-POWER",
"pattern": "*-*V*"
},
{
"netclass": "GND",
"pattern": "*GND*"
}
]
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"plot": "",
"pos_files": "",
"specctra_dsn": "",
"step": "",
"svg": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"bom_fmt_presets": [],
"bom_fmt_settings": {
"field_delimiter": ",",
"keep_line_breaks": false,
"keep_tabs": false,
"name": "CSV",
"ref_delimiter": ",",
"ref_range_delimiter": "",
"string_delimiter": "\""
},
"bom_presets": [],
"bom_settings": {
"exclude_dnp": false,
"fields_ordered": [
{
"group_by": false,
"label": "Reference",
"name": "Reference",
"show": true
},
{
"group_by": true,
"label": "Value",
"name": "Value",
"show": true
},
{
"group_by": false,
"label": "Datasheet",
"name": "Datasheet",
"show": true
},
{
"group_by": false,
"label": "Footprint",
"name": "Footprint",
"show": true
},
{
"group_by": false,
"label": "Qty",
"name": "${QUANTITY}",
"show": true
},
{
"group_by": true,
"label": "DNP",
"name": "${DNP}",
"show": true
}
],
"filter_string": "",
"group_symbols": true,
"name": "Grouped By Value",
"sort_asc": true,
"sort_field": "Reference"
},
"connection_grid_size": 50.0,
"drawing": {
"dashed_lines_dash_length_ratio": 12.0,
"dashed_lines_gap_length_ratio": 3.0,
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.375,
"operating_point_overlay_i_precision": 3,
"operating_point_overlay_i_range": "~A",
"operating_point_overlay_v_precision": 3,
"operating_point_overlay_v_range": "~V",
"overbar_offset_ratio": 1.23,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"page_layout_descr_file": "",
"plot_directory": "",
"spice_current_sheet_as_root": false,
"spice_external_command": "spice \"%I\"",
"spice_model_current_sheet_as_root": true,
"spice_save_all_currents": false,
"spice_save_all_dissipations": false,
"spice_save_all_voltages": false,
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"92a86815-0425-4ac3-80bb-037195814139",
"Root"
]
],
"text_variables": {}
}

File diff suppressed because it is too large Load Diff

115
README.md Normal file
View File

@@ -0,0 +1,115 @@
# kicad project template
[![.github/workflows/main.yaml](https://github.com/sirlilpanda/kicad-project-template/actions/workflows/main.yaml/badge.svg?branch=main)](https://github.com/sirlilpanda/kicad-project-template/actions/workflows/main.yaml)
a cool table showing the workflow of all the kicad projects.
| project_name | DRC | ERC |
| ------------ | --- | --- |
| template | [](https://github.com/sirlilpanda/kicad-project-template/actions/runs/14507154830/attempts/1#summary-40698563204)| [](https://github.com/sirlilpanda/kicad-project-template/actions/runs/14507154830/attempts/1#summary-40698563199) |
for a quick guide check [project setup](#project-setup)
This is a simple project template for new kicad projects. This template has some basic setup already completed such as workflows for auto creating all the things you forget when creating a kicad project such as:
- [gerbers](https://github.com/sirlilpanda/kicad-project-template/tree/main/template_gerber.zip)
- [bom](https://github.com/sirlilpanda/kicad-project-template/tree/main/template_bom_report.md)
- [schematic pdf](https://github.com/sirlilpanda/kicad-project-template/tree/main/template_schematic.pdf)
This workflow will also run the design rules check on the PCB and schematic to ensure that you upload a working PCB. These reports are uploaded as summaries within the github [actions tab](https://github.com/sirlilpanda/kicad-project-template/actions/runs/14507154830). This template has a simple schematic PCB in it (because DRC fails on an empty PCB). Shown below is the example PCB.
![example pcb with battery diode and resistor](res/image.png)
besides from that the project also has:
- common predefined trace widths
- smallest vias size [JLCPBC allows](https://jlcpcb.com/capabilities/Capabilities#Drilling)
- custom net colours in the schematic editor
- `red` for +V
- `blue` for -V
- `grey` for ground
to create a repo from this template follow this [guide](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template)
contained in this template are:
---
- `.github/` : all files relating to github actions and other admin see [here](https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions) for more example of what can be placed in it
- `report_processing` : where the python scripts are stored for processing the json report data from kicad
- `report_templates` : where the template for said reports are stored
- `workflows/` : this is where the github actions are kept
- `main.yaml` : the main github action that will auto generate all files required and run DRC and ERC
- `rename.py` : the script for renaming the project
- `hardware/` : this is where the kicad projects live note this can be changed
- `docs/` : this is where the generate docs are placed by default
- `BOM/` : where the bill of materials and price breakdown are kept
- `bill_of_materials.csv`: the auto generated bom for the kicad project
- `bom_report.md` : a report for the bill of materials
- `template_schematic.pdf` : the schematic for the kicad project, auto generated by the github action
- `pcbs/` : this is where the auto generated gerbers for the kicad project are stored
- `res/` : where resources are stored for the README
- `.gitignore`: a slightly modified gitignore from the [standard one](https://github.com/github/gitignore/blob/main/KiCad.gitignore)
- `project_settings.yaml` : where the settings for this project is stored
- `README.md` : this file, suggest you change this one creating your project
## project settings
there are currently very few project settings that can be changed (will will be change in the future) these are:
| setting | description |
| --------------------------- | ----------------------------------------------------------------- |
| has_been_set_up | a flag to tell the setup action if the project has been set up |
| project_name | the name of the project, this will be set to the name of the repo |
| production_formats | the output production format for the PCBs |
| dynamic_read_me | allow the readme to be updated using the given template |
| bom_template_path | the template used to write the bom report files |
| erc_report_template_path | the template used to write the erc report files |
| drc_report_template_path | the template used to write the drc report files |
| readme_template_path | the template used to write projects readme |
| schematic_output_name | the name suffix of the generated schematics |
| bom_csv_output_name | the name suffix of the generated bom csv file |
| bom_report_output_name | the name suffix of the generated bom report |
| production_file_output_name | the name suffix of the generated production file |
| schematic_output_path | the output path of the generated schematics files |
| bom_csv_output_path | the output path of the generated bom csv file |
| bom_report_output_path | the output path of the generated bom report |
| production_file_output_path | the output path of the generated production file |
## project setup
### creating a new repo with the template
creating a new template from a repo is simple:
1. click on the button in the top right hand corner called `use this template`
![alt text](res/image-5.png)
2. when the drop down menu appears click on `create a new repository`
![alt text](res/image-6.png)
3. once you click you will be brought to this page, note that the repo name you choose here will be the name that you kicad project is called.
![alt text](res/image-7.png)
after these steps you then need to configure the repo settings to do their magic see [configuring repo settings](#configuring-repo-settings) for what to do next.
### configuring repo settings
once you have created a new repo with the template, you ill have to configure the github action settings. this is because you will get an error that looks something along these lines:
![alt text](res/image-4.png)
where the action can not commit the changes due to not having permissions follow these steps:
1. open the repo setting
![alt text](res/image-1.png)
2. then head in to actions : General
![alt text](res/image-2.png)
3. then scroll down to workflow permissions and ensure that both
`Read and write permissions` and `Allow GitHub Actions to create and approve pull requests` are ticked as seen below
![alt text](res/image-3.png)
this should fix the problem if not, go harass stack overflow they need it
Once all of these steps have been followed the workflow should be passing, however the `README.md` will only update on the next push request.
## editing the readme
As this repo can and will automatically update the repo corresponding to the given readme template. If you dont want to use this you can always disable this by setting the `dynamic_read_me` to `false`. but if you want some very cool features like auto updating tables to show what projects are passing the rules check or simple links to parts of your directory. then have a look at the template readme and learn [mustache](https://mustache.github.io/)
## improvements

0
docs/BOM/.gitkeep Normal file
View File

View File

@@ -0,0 +1,4 @@
"Refs","Value","Footprint","Qty","DNP"
"BT1","Battery","Battery:BatteryHolder_LINX_BAT-HLD-012-SMT","1",""
"D1","LED","LED_SMD:LED_0805_2012Metric","1",""
"R1","R","Resistor_SMD:R_0805_2012Metric","1",""
1 Refs Value Footprint Qty DNP
2 BT1 Battery Battery:BatteryHolder_LINX_BAT-HLD-012-SMT 1
3 D1 LED LED_SMD:LED_0805_2012Metric 1
4 R1 R Resistor_SMD:R_0805_2012Metric 1

View File

@@ -0,0 +1,12 @@
# 📄 BOM for template_bill_of_material 📄
report created at 03:09:02.038853 on 17-04-2025.
template_bill_of_material has a total of 3 parts with a cost of $0.
| Reference | Value | Quantity | part number | cost |
| --------- | ----- | -------- | ----------- | ---- |
| BT1 | Battery | 1 | Battery:BatteryHolder_LINX_BAT-HLD-012-SMT | $0 |
| D1 | LED | 1 | LED_SMD:LED_0805_2012Metric | $0 |
| R1 | R | 1 | Resistor_SMD:R_0805_2012Metric | $0 |
| | total | 3 | total | $0 |

BIN
docs/template_schematic.pdf Normal file

Binary file not shown.

0
pcbs/.gitkeep Normal file
View File

BIN
pcbs/template_gerber.zip Normal file

Binary file not shown.

45
project_settings.yaml Normal file
View File

@@ -0,0 +1,45 @@
needs_setup: true
# this is set to the name of your repo during setup, you can change it later on using the rename tool
project_name: template
# this is a list of the production formats that you would like
# honestly only use gerbers, i doubt i will add anything else
# but if you want something custom, implement it and throw in
# a pull request
#not support
production_format: gerber
schematic_output_path: docs/
bom_csv_output_path: docs/BOM/
bom_report_output_path: docs/BOM/
production_file_output_path: pcbs/
# all names will follow the pattern [project_name]name.*
# these settings just define that name suffix
# the underscore here are purely for readablity of the
# output files so the schematic output file name will be
# project_name_schematic.pdf
schematic_output_name: _schematic
bom_csv_output_name: _bill_of_materials
bom_report_output_name: _bom_report
production_file_output_name: _gerber
# these templates use mustache (https://mustache.github.io/mustache.5.html)
# a logic less templating langauge for templating just about anything
bom_template_path: .github/report_templates/bom_report_template.mustache
erc_report_template_path: .github/report_templates/erc_report_template.mustache
drc_report_template_path: .github/report_templates/drc_report_template.mustache
readme_template_path: .github/report_templates/readme.mustache
# allow the readme to be auto updated using the readme template
dynamic_read_me: true

BIN
res/image-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

BIN
res/image-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
res/image-3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
res/image-4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
res/image-5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

BIN
res/image-6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
res/image-7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

BIN
res/image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB