From 48b12293a9d0ff06769d46a5b4b2429278233dc9 Mon Sep 17 00:00:00 2001 From: Daniel Lindmark Date: Sun, 28 Jul 2024 18:38:35 -0500 Subject: [PATCH 1/2] Add Actions --- .allspice/columns.yml | 21 +++++ .allspice/utils/generate_netlist.py | 110 +++++++++++++++++++++++ .allspice/utils/hello-world.py | 1 + .allspice/utils/py-allspice-BIST.py | 57 ++++++++++++ .allspice/utils/requirements.txt | 2 + .allspice/workflows/generate-bom.yml | 47 ++++++++++ .allspice/workflows/generate-netlist.yml | 54 +++++++++++ 7 files changed, 292 insertions(+) create mode 100644 .allspice/columns.yml create mode 100644 .allspice/utils/generate_netlist.py create mode 100644 .allspice/utils/hello-world.py create mode 100644 .allspice/utils/py-allspice-BIST.py create mode 100644 .allspice/utils/requirements.txt create mode 100644 .allspice/workflows/generate-bom.yml create mode 100644 .allspice/workflows/generate-netlist.yml diff --git a/.allspice/columns.yml b/.allspice/columns.yml new file mode 100644 index 0000000..cde5c77 --- /dev/null +++ b/.allspice/columns.yml @@ -0,0 +1,21 @@ +columns: + - name: "Manufacturer" + part_attributes: + - "Manufacturer" + - "MANUFACTURER" + sort: "asc" + - name: "Part Number" + part_attributes: + - "PART" + - "MANUFACTURER #" + - "_part_id" + remove_rows_matching: "TP|MTG|FID" + - name: "Designator" + part_attributes: "Designator" + grouped_values_separator: ", " + grouped_values_sort: "asc" + - name: "Description" + part_attributes: + - "PART DESCRIPTION" + - "_description" + diff --git a/.allspice/utils/generate_netlist.py b/.allspice/utils/generate_netlist.py new file mode 100644 index 0000000..e0ab5b0 --- /dev/null +++ b/.allspice/utils/generate_netlist.py @@ -0,0 +1,110 @@ +#! /usr/bin/env python3 + +# Generate a Netlist from a PcbDoc file. +# For more information, read the README file in this directory. + +import argparse +import os +import sys +from contextlib import ExitStack + +from allspice import AllSpice +from allspice.utils.netlist_generation import generate_netlist + + +if __name__ == "__main__": + print("Hello World") + # Parse command line arguments. If you're writing a special purpose script, + # you can hardcode these values instead of using command line arguments. + parser = argparse.ArgumentParser( + prog="generate_pcb_netlist", description="Generate a netlist from a PCB file." + ) + parser.add_argument("repository", help="The repo containing the project") + parser.add_argument( + "pcb_file", + help="The path to the PCB file in the source repo.", + ) + parser.add_argument( + "--source_ref", + help="The git reference the netlist should be generated for (eg. branch name, tag name, commit SHA). Defaults to main.", + default="main", + ) + parser.add_argument( + "--allspice_hub_url", + help="The URL of your AllSpice Hub instance. Defaults to https://hub.allspice.io.", + ) + parser.add_argument( + "--output_file", + help="The path to the output file. If absent, the output will direct to the command line.", + ) + + args = parser.parse_args() + + # Use Environment Variables to store your auth token. This keeps your token + # secure when sharing code. + auth_token = os.environ.get("ALLSPICE_AUTH_TOKEN") + if auth_token is None: + print("Please set the environment variable ALLSPICE_AUTH_TOKEN") + exit(1) + + if args.allspice_hub_url is None: + allspice = AllSpice(token_text=auth_token) + else: + allspice = AllSpice( + token_text=auth_token, allspice_hub_url=args.allspice_hub_url + ) + + try: + # Test connection and key + print("AllSpice Version: " + allspice.get_version()) + + # Test private API call + print("API-Token belongs to user: " + allspice.get_user().username) + + except Exception as e: + print(f"Could not connect to AllSpice Hub: {e}") + exit(1) + + repo_owner, repo_name = args.repository.split("/") + try: + print(f"repo_owner={repo_owner}, repo_name={repo_name}") + repository = allspice.get_repository(repo_owner, repo_name) + except Exception as e: + print(f"Could not find repository {args.repository}: {e}") + exit(1) + pcb_file = args.pcb_file + + print("Generating PCB Netlist...πŸƒ", file=sys.stderr) + + netlist_rows = generate_netlist( + allspice, + repository, + pcb_file, + args.source_ref, + ) + + with ExitStack() as stack: + if args.output_file is not None: + writer = stack.enter_context(open(args.output_file, "w")) + else: + writer = sys.stdout + + nets = list(netlist_rows.keys()) + + # It's helpful to sort here to generate repeatable netlist files + nets.sort() + + # You can change formatting here + for net in nets: + writer.write(net + "\n") + pins_on_net = netlist_rows[net] + try: + # Convert to list if it's not already, and then sort + if not isinstance(pins_on_net, list): + pins_on_net = list(pins_on_net) + pins_on_net.sort() + except Exception as e: + print(f"Error sorting pins on net {net}: {e}", file=sys.stderr) + writer.write(" " + " ".join(pins_on_net) + "\n") + + print("Generated PCB netlist.", file=sys.stderr) \ No newline at end of file diff --git a/.allspice/utils/hello-world.py b/.allspice/utils/hello-world.py new file mode 100644 index 0000000..1dc45ac --- /dev/null +++ b/.allspice/utils/hello-world.py @@ -0,0 +1 @@ +print("Hello World!") \ No newline at end of file diff --git a/.allspice/utils/py-allspice-BIST.py b/.allspice/utils/py-allspice-BIST.py new file mode 100644 index 0000000..b431803 --- /dev/null +++ b/.allspice/utils/py-allspice-BIST.py @@ -0,0 +1,57 @@ +# HelloWorld.py + +# If you're new to scripting, this is a great place to start. + +# Hello World starts you out easy with some simple server requests. +# This will help you troubleshoot your connection and show you the basics of making an api request +# +# For more information read our README.md +from allspice import AllSpice +import argparse, sys + + + + +print("Starting Test") + +parser = argparse.ArgumentParser( + prog="Allspice_API_BIST", description="Test connection and execution of API actions" + ) + +parser.add_argument( + "--allspice_hub_url", + help="The URL of your AllSpice Hub instance. Defaults to https://hub.allspice.io.", +) +parser.add_argument( + "--allspice_token", + help="Your AllSpice application token. Generate a token: https://hub.allspice.io/user/settings/applications", +) + +print("Parsing args") +args = parser.parse_args() + +auth_token = args.allspice_token +if auth_token is None: + print("Please supply a token with --allspice_token Generate a token: https://hub.allspice.io/user/settings/applications") + sys.exit(1) +print(f"Auth token {auth_token}") + +if args.allspice_hub_url is None: + allspice = AllSpice(token_text="https://hub.allspice.io") +else: + try: + allspice = AllSpice( + token_text=auth_token, allspice_hub_url=args.allspice_hub_url + ) + except Exception as e: + print("Error") + sys.exit(1) + +print("Finish making connection") +# Test connection and key +print("AllSpice Version: " + allspice.get_version()) + +# Test private API call +print("API-Token belongs to user: " + allspice.get_user().username) + +print("End test") \ No newline at end of file diff --git a/.allspice/utils/requirements.txt b/.allspice/utils/requirements.txt new file mode 100644 index 0000000..c7124bd --- /dev/null +++ b/.allspice/utils/requirements.txt @@ -0,0 +1,2 @@ +py-allspice~=3.0 +rich~=13.0 diff --git a/.allspice/workflows/generate-bom.yml b/.allspice/workflows/generate-bom.yml new file mode 100644 index 0000000..27cd7e5 --- /dev/null +++ b/.allspice/workflows/generate-bom.yml @@ -0,0 +1,47 @@ +# AllSpice Running common Actions workflow +# Action triggers on push and issues +# Action runs "generate-bom-altium" action +# .allspice/workflows/generate_bom.yml +name: Generate BOM +on: + push: + issues: + types: [opened, closed, reopened] + +jobs: + Generate_BOM: + runs-on: ubuntu-latest + steps: + # Checkout is only needed if columns.json is committed in your Altium project repo. + - name: Checkout + uses: actions/checkout@v3 + + - name: Generate BOM + uses: https://hub.allspice.io/Actions/generate-bom@v0.5 + with: + # The path to the project file in your repo (.PrjPcb for Altium, .DSN for OrCad). + source_path: Archimajor.PrjPcb + # [optional] A path to a YAML file mapping columns to the component attributes + # This file must be provided. + # Default: 'columns.json' + columns: .allspice/columns.yml + # [optional] The path to the output file that will be generated. + # Default: 'bom.csv' + output_file_name: bom.csv + # [optional] A comma-separated list of columns to group the BOM by. If empty + # or not present, the BOM will be flat. + # Default: '' + group_by: 'Part Number' + # [optional] The variant of the project to generate the BOM for. If empty + # or not present, the BOM will be generated for the default variant. + # Default: '' + variant: '' + # Print bom.csv to terminal + - name: Show BOM + run: cat bom.csv + + - name: Upload file as artifact + uses: actions/upload-artifact@v3 + with: + name: BOM.csv + path: bom.csv \ No newline at end of file diff --git a/.allspice/workflows/generate-netlist.yml b/.allspice/workflows/generate-netlist.yml new file mode 100644 index 0000000..cafbc4a --- /dev/null +++ b/.allspice/workflows/generate-netlist.yml @@ -0,0 +1,54 @@ + +# Python-py-allspice demo repository +# This workflow demonstrates how to use Python and py-allspice to interact with the AllSpice API +# AllSpice Actions documentation: https://learn.allspice.io/docs/actions-cicd +name: Python-py-allspice +on: + push: + issues: + types: [opened, closed, reopened] + +jobs: + py-allspice test: + runs-on: ubuntu-latest + steps: + # Check out repository code + - name: "[πŸ“š->πŸ–₯️] Check out repository code" + uses: actions/checkout@v3 + + - name: "[πŸ”Ž->πŸ“‚] List files in repo πŸ”Ž" + run: | + ls -la ${{ allspice.workspace }} + + # Installs python requirements from the requirements.txt file + - name: "[🀼->πŸ–₯️] Install python requirements" + run: pip install -r .allspice/utils/requirements.txt + + # Call a python script from the .allspice/utils directory + - name: "[πŸƒ->🐍] Run .allspice/utils/hello-world.py πŸ”Ž" + run: python .allspice/utils/hello-world.py + + # Run the py-allspice self-test script, this will ping the server and verify the API is working + # Parameters: ${allspice.server_url} and ${allspice.token} are automatic Workflow variables and are used to authenticate the AllSpice API + - name: "[πŸ”‘->πŸ•ΈοΈ] Test AllSpice API with py-allspice πŸ”Ž" + run: python .allspice/utils/py-allspice-BIST.py --allspice_hub_url ${{ allspice.server_url }} --allspice_token ${{ allspice.token }} + + # Generate a netlist from Altium .PcbDoc file + # Run the generate_netlist.py script from the .allspice/utils directory + - name: Generate Netlist + run: | + echo -e "repo ${{ allspice.repository }}" + ALLSPICE_AUTH_TOKEN=${{ allspice.token }} python .allspice/utils/generate_netlist.py "${{ allspice.repository }}" "Archimajor.PcbDoc" --allspice_hub_url "${{ allspice.server_url }}" --output_file Archimajor.pcbdoc.netlist.txt + + + # Print the netlist file to the terminal + - name: Show Netlist πŸ”Ž + run: cat Archimajor.pcbdoc.netlist.txt + + # Archive the netlist file as an artifact file + - name: Archive code coverage results + uses: actions/upload-artifact@v3 + with: + name: Archimajor.PcbDoc.netlist.txt + path: Archimajor.pcbdoc.netlist.txt + From 43f519191ee34583b547174bda9126106b1bb4fe Mon Sep 17 00:00:00 2001 From: Gautam Peri Date: Tue, 13 May 2025 00:47:56 +0000 Subject: [PATCH 2/2] Update generate-bom to 0.8 --- .allspice/workflows/generate-bom.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.allspice/workflows/generate-bom.yml b/.allspice/workflows/generate-bom.yml index 27cd7e5..4d710d6 100644 --- a/.allspice/workflows/generate-bom.yml +++ b/.allspice/workflows/generate-bom.yml @@ -17,7 +17,7 @@ jobs: uses: actions/checkout@v3 - name: Generate BOM - uses: https://hub.allspice.io/Actions/generate-bom@v0.5 + uses: https://hub.allspice.io/Actions/generate-bom@v0.8 with: # The path to the project file in your repo (.PrjPcb for Altium, .DSN for OrCad). source_path: Archimajor.PrjPcb