Create boilerplate template from example #1
1
.allspice/examples/config.yml
Normal file
1
.allspice/examples/config.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Mock config yaml file
|
1
.allspice/examples/input.txt
Normal file
1
.allspice/examples/input.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
Mock input file
|
22
.allspice/workflows/add-on-workflow-example.yml
Normal file
22
.allspice/workflows/add-on-workflow-example.yml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
name: Hardware DevOps Workflow
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
hardware-devops:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Run Hardware DevOps Action
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
source_path: "path/to/source_file"
|
||||||
|
output_file_name: "output.txt"
|
||||||
|
config_file: "path/to/config_file"
|
||||||
|
task_type: "Schematic-Review"
|
||||||
|
additional_params: '{"SCH_VER":"3"}'
|
||||||
|
env:
|
||||||
|
ALLSPICE_TOKEN: ${{ secrets.ALLSPICE_TOKEN }}
|
139
Add-on-script.py
139
Add-on-script.py
@ -1,123 +1,90 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
# Generate a BOM from a PrjPcb file.
|
|
||||||
# For more information, read the README file in this directory.
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import csv
|
|
||||||
import os
|
import os
|
||||||
import yaml
|
|
||||||
import sys
|
import sys
|
||||||
from contextlib import ExitStack
|
import json
|
||||||
|
|
||||||
from allspice import AllSpice
|
from allspice import AllSpice
|
||||||
from allspice.utils.bom_generation import generate_bom
|
|
||||||
|
|
||||||
|
def hello_world(task_type, source_file, output_file, additional_params):
|
||||||
|
print(f"Hello, World! Performing task: {task_type}")
|
||||||
|
print(f"Source file: {source_file}")
|
||||||
|
print(f"Output file: {output_file}")
|
||||||
|
print(f"Additional parameters: {additional_params}")
|
||||||
|
|
||||||
|
# Parse additional_params
|
||||||
|
params = json.loads(additional_params)
|
||||||
|
sch_ver = params.get("SCH_VER", "3")
|
||||||
|
print(f"Schematic version: {sch_ver}")
|
||||||
|
|
||||||
|
def test_allspice_connection(allspice_hub_url, auth_token):
|
||||||
|
try:
|
||||||
|
allspice = AllSpice(token_text=auth_token, allspice_hub_url=allspice_hub_url)
|
||||||
|
print("AllSpice Version: " + allspice.get_version())
|
||||||
|
print("API-Token belongs to user: " + allspice.get_user().username)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error connecting to AllSpice API: {e}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
prog="generate_bom", description="Generate a BOM from a project repository."
|
prog="hardware_devops_action",
|
||||||
|
description="Perform hardware development tasks such as Schematic-Review, PCB-Review, ECO-Review, and Release."
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"repository", help="The repo containing the project in the form 'owner/repo'"
|
"repository", help="The repo containing the project in the form 'owner/repo'"
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"source_file",
|
"source_file",
|
||||||
help=(
|
help="The path to the source file used for the task. Example: 'Archimajor.PrjPcb', 'Schematics/Beagleplay.dsn'."
|
||||||
"The path to the source file used to generate the BOM. If this is an Altium project, "
|
|
||||||
"this should be the .PrjPcb file. For an OrCAD project, this should be the .dsn file. "
|
|
||||||
"Example: 'Archimajor.PrjPcb', 'Schematics/Beagleplay.dsn'."
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--columns",
|
"--task_type",
|
||||||
help=(
|
help="The type of hardware task to perform. Options include 'Schematic-Review', 'PCB-Review', 'ECO-Review', 'Release'.",
|
||||||
"A path to a YAML file mapping columns to the attributes they are from. See the README "
|
default="Schematic-Review",
|
||||||
"for more details. Defaults to 'columns.yml'."
|
|
||||||
),
|
|
||||||
default="columns.yml",
|
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--source_ref",
|
"--source_ref",
|
||||||
help=(
|
help="The git reference the task should be performed for (eg. branch name, tag name, commit SHA).",
|
||||||
"The git reference the BOM should be generated for (eg. branch name, tag name, commit "
|
|
||||||
"SHA). Defaults to the main branch."
|
|
||||||
),
|
|
||||||
default="main",
|
default="main",
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--server_url",
|
||||||
|
help="The URL of your GitHub server instance.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--output_file",
|
||||||
|
help="The path to the output file. If absent, the output will be printed to the command line.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--additional_params",
|
||||||
|
help="Any additional parameters required for the task, provided as a JSON string.",
|
||||||
|
default="{}",
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--allspice_hub_url",
|
"--allspice_hub_url",
|
||||||
help="The URL of your AllSpice Hub instance. Defaults to https://hub.allspice.io.",
|
help="The URL of your AllSpice Hub instance. Defaults to https://hub.allspice.io.",
|
||||||
|
default="https://hub.allspice.io",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--output_file",
|
"--allspice_token",
|
||||||
help="The path to the output file. If absent, the CSV will be output to the command line.",
|
help="Your AllSpice application token. Generate a token: https://hub.allspice.io/user/settings/applications",
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--group_by",
|
|
||||||
help=(
|
|
||||||
"A comma-separated list of columns to group the BOM by. If not present, the BOM will "
|
|
||||||
"be flat."
|
|
||||||
),
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--variant",
|
|
||||||
help=(
|
|
||||||
"The variant of the project to generate the BOM for. If not present, the BOM will be "
|
|
||||||
"generated for the default variant. This is not used for OrCAD projects."
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
columns_file = args.columns
|
auth_token = os.environ.get("GITHUB_TOKEN") or args.allspice_token
|
||||||
columns = {}
|
|
||||||
try:
|
|
||||||
with open(columns_file, "r") as f:
|
|
||||||
columns_data = yaml.safe_load(f.read())
|
|
||||||
for column_value in columns_data["columns"]:
|
|
||||||
columns[column_value["name"]] = column_value["part_attributes"]
|
|
||||||
except KeyError as e:
|
|
||||||
print(f"Error: columns file {columns_file} does not seem to be in the right format.")
|
|
||||||
print("Please refer to the README for more information.")
|
|
||||||
print(f"Caused by: {e}")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
auth_token = os.environ.get("ALLSPICE_AUTH_TOKEN")
|
|
||||||
if auth_token is None:
|
if auth_token is None:
|
||||||
print("Please set the environment variable ALLSPICE_AUTH_TOKEN")
|
print("Please set the environment variable GITHUB_TOKEN or supply a token with --allspice_token <your_token>. Generate a token: https://hub.allspice.io/user/settings/applications")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
if args.allspice_hub_url is None:
|
# Test connection to AllSpice API
|
||||||
allspice = AllSpice(token_text=auth_token)
|
test_allspice_connection(args.allspice_hub_url, auth_token)
|
||||||
else:
|
|
||||||
allspice = AllSpice(token_text=auth_token, allspice_hub_url=args.allspice_hub_url)
|
|
||||||
|
|
||||||
repo_owner, repo_name = args.repository.split("/")
|
# Perform the Hello World task
|
||||||
repository = allspice.get_repository(repo_owner, repo_name)
|
hello_world(
|
||||||
group_by = args.group_by.split(",") if args.group_by else None
|
task_type=args.task_type,
|
||||||
|
source_file=args.source_file,
|
||||||
print("Generating BOM...", file=sys.stderr)
|
output_file=args.output_file,
|
||||||
|
additional_params=args.additional_params,
|
||||||
bom_rows = generate_bom(
|
|
||||||
allspice,
|
|
||||||
repository,
|
|
||||||
args.source_file,
|
|
||||||
columns,
|
|
||||||
group_by=group_by,
|
|
||||||
ref=args.source_ref if args.source_ref else "main",
|
|
||||||
variant=args.variant if args.variant else None,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
with ExitStack() as stack:
|
|
||||||
keys = bom_rows[0].keys()
|
|
||||||
if args.output_file is not None:
|
|
||||||
f = stack.enter_context(open(args.output_file, "w"))
|
|
||||||
writer = csv.DictWriter(f, fieldnames=keys)
|
|
||||||
else:
|
|
||||||
writer = csv.DictWriter(sys.stdout, fieldnames=keys)
|
|
||||||
|
|
||||||
writer.writeheader()
|
|
||||||
writer.writerows(bom_rows)
|
|
||||||
|
|
||||||
print("Generated bom.", file=sys.stderr)
|
|
||||||
|
Loading…
Reference in New Issue
Block a user