Replaces the `inventree_dev` + `inventree_main` jobs with `astable_dev` + `astable_main` calling `POST /api/v1/bom/upload` on the Astable instance. The old hfsntree path is removed — Astable is now the source of truth for BOMs, and owns the supplier-API credentials (Digi-Key / Mouser / etc.) so the CI runner doesn't need them any more. Revision targeting matches the previous convention: - dev branch: uploads to the DRAFT "dev" rev - main branch: uploads to the rev named from commit message, promoted to ACTIVE - MR-to-main: uploads to dev (matches old hfsntree behaviour) Strict mode: any MPN that can't be resolved against an enabled supplier integration aborts the whole upload — no orphan parts get created when a CSV ships with typos. Files uploaded alongside the BOM CSV (each optional, skipped when absent so dev and main share the same template): gerbers, panel gerbers, STEP, schematic PDF, PCB layout PDF, iBOM HTML, BOM xlsx, PCBA + bare-PCB renders, DRC + ERC reports, CPL CSV. Astable attaches each file to the PCBA part, the bare PCB part, or both (per fab-file dispatch table). Files attached to both parts dedupe storage via content-addressed paths. Required CI variables (set group-level on Micromelon/education/hardware/, masked + protected): ASTABLE_URL e.g. https://astable.timhadwen.com ASTABLE_API_TOKEN minted at /manage/api-tokens (ast_…) scripts/upload-bom.sh vendored from the Astable repo (scripts/ci/upload-bom.sh) — the .astable_base before_script curls a copy from this repo's raw URL at job time so the include: project: pattern stays self-contained. Downstream `upload_packages` needs: updated from inventree_main → astable_main.
512 lines
19 KiB
YAML
512 lines
19 KiB
YAML
# KiCad CI Pipeline with hfsntree Integration
|
|
# Include this file in your project's .gitlab-ci.yml and set PROJECT_NAME variable
|
|
#
|
|
# Example project .gitlab-ci.yml:
|
|
# include:
|
|
# - local: '.gitlab/kibot-ci.yml'
|
|
# variables:
|
|
# PROJECT_NAME: "my_project_name"
|
|
|
|
workflow:
|
|
rules:
|
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
|
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
|
|
when: never
|
|
- if: $CI_COMMIT_BRANCH
|
|
|
|
variables:
|
|
GIT_STRATEGY: clone
|
|
GIT_SUBMODULE_STRATEGY: recursive
|
|
GIT_SUBMODULE_FORCE_HTTPS: "true"
|
|
PACKAGE_REGISTRY_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/kicad"
|
|
|
|
stages:
|
|
- preflight
|
|
- fabrication
|
|
- inventree
|
|
- release
|
|
|
|
image:
|
|
name: ghcr.io/inti-cmnb/kicad9_auto:1.8.4
|
|
|
|
# =============================================================================
|
|
# Rule Templates
|
|
# =============================================================================
|
|
.main_rules:
|
|
rules:
|
|
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"'
|
|
- if: $CI_COMMIT_BRANCH == "main"
|
|
- if: $GITLAB_CI == 'false'
|
|
|
|
.dev_rules:
|
|
rules:
|
|
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "dev"'
|
|
- if: $CI_COMMIT_BRANCH == "dev"
|
|
- if: $GITLAB_CI == 'false'
|
|
|
|
# =============================================================================
|
|
# Stage: Preflight
|
|
# =============================================================================
|
|
extract_version:
|
|
stage: preflight
|
|
script:
|
|
- |
|
|
# Version strategy:
|
|
# - dev branch: always "dev"
|
|
# - main branch: extract from commit message (e.g., "V1.2")
|
|
|
|
if [[ "$CI_COMMIT_BRANCH" == "main" ]]; then
|
|
# On main, extract version from commit message
|
|
VERSION=$(echo "$CI_COMMIT_MESSAGE" | grep -oE 'V[0-9]+(\.[0-9]+)*' | head -1)
|
|
if [[ -z "$VERSION" ]]; then
|
|
VERSION="$CI_COMMIT_SHORT_SHA"
|
|
echo "Warning: No version found in commit message, using SHA"
|
|
fi
|
|
echo "Main branch version: $VERSION"
|
|
else
|
|
# On dev or any other branch, use "dev"
|
|
VERSION="dev"
|
|
echo "Dev branch version: $VERSION"
|
|
fi
|
|
|
|
echo "VERSION=$VERSION" >> build.env
|
|
echo "Extracted version: $VERSION"
|
|
artifacts:
|
|
reports:
|
|
dotenv: build.env
|
|
|
|
run_erc:
|
|
stage: preflight
|
|
needs:
|
|
- job: extract_version
|
|
artifacts: true
|
|
script:
|
|
- |
|
|
if [ -f "${PROJECT_NAME}/${PROJECT_NAME}.kicad_sch" ]; then
|
|
echo "Running ERC..."
|
|
cat > /tmp/erc.kibot.yaml << 'EOF'
|
|
kibot:
|
|
version: 1
|
|
preflight:
|
|
erc:
|
|
enabled: true
|
|
warnings_as_errors: false
|
|
EOF
|
|
kibot -e ${PROJECT_NAME}/${PROJECT_NAME}.kicad_sch \
|
|
-c /tmp/erc.kibot.yaml \
|
|
-d Validation/
|
|
fi
|
|
artifacts:
|
|
when: always
|
|
paths:
|
|
- Validation/
|
|
expire_in: 1 week
|
|
|
|
run_drc:
|
|
stage: preflight
|
|
needs:
|
|
- job: extract_version
|
|
artifacts: true
|
|
script:
|
|
- |
|
|
if [ -f "${PROJECT_NAME}/${PROJECT_NAME}.kicad_pcb" ]; then
|
|
echo "Running DRC..."
|
|
# Extract part number from project name for text variables
|
|
PART_NUM=$(echo "${PROJECT_NAME}" | cut -d"-" -f1)
|
|
cat > /tmp/drc.kibot.yaml << EOF
|
|
kibot:
|
|
version: 1
|
|
preflight:
|
|
set_text_variables:
|
|
- name: 'name'
|
|
text: '${PART_NUM}'
|
|
- name: 'rev'
|
|
text: '${VERSION}'
|
|
- name: 'rev_pcb'
|
|
text: '${VERSION}'
|
|
drc:
|
|
enabled: true
|
|
warnings_as_errors: false
|
|
EOF
|
|
kibot -e ${PROJECT_NAME}/${PROJECT_NAME}.kicad_sch \
|
|
-b ${PROJECT_NAME}/${PROJECT_NAME}.kicad_pcb \
|
|
-c /tmp/drc.kibot.yaml \
|
|
-d Validation/
|
|
fi
|
|
artifacts:
|
|
when: always
|
|
paths:
|
|
- Validation/
|
|
expire_in: 1 week
|
|
|
|
# =============================================================================
|
|
# Stage: Fabrication
|
|
# =============================================================================
|
|
.fabrication_base:
|
|
stage: fabrication
|
|
needs:
|
|
- job: extract_version
|
|
artifacts: true
|
|
- job: run_erc
|
|
artifacts: false
|
|
- job: run_drc
|
|
artifacts: false
|
|
before_script:
|
|
- |
|
|
# Ensure submodules are initialized (needed for gitlab-ci-local)
|
|
git submodule update --init --recursive 2>/dev/null || true
|
|
|
|
# Export version and name for KiBot text variable injection
|
|
export KIBOT_VAR_rev="${VERSION}"
|
|
export KIBOT_VAR_rev_pcb="${VERSION}"
|
|
export KIBOT_VAR_name=$(echo "${PROJECT_NAME}" | cut -d"-" -f1)
|
|
echo "KiBot version variables set to: $VERSION"
|
|
echo "KiBot name variable set to: $KIBOT_VAR_name"
|
|
|
|
# Setup user config
|
|
USER_FILE="$CI_PROJECT_DIR/.gitlab/configs/blank.kibot.yaml"
|
|
if [ -f "${PROJECT_NAME}/kibot.yaml" ]; then
|
|
USER_FILE="${PROJECT_NAME}/kibot.yaml"
|
|
fi
|
|
cp $USER_FILE $CI_PROJECT_DIR/.gitlab/configs/user.kibot.yaml
|
|
artifacts:
|
|
when: always
|
|
paths:
|
|
- Fabrication/
|
|
expire_in: 1 week
|
|
|
|
generate_schematic:
|
|
extends: .fabrication_base
|
|
script:
|
|
- |
|
|
export KIBOT_VAR_rev="${VERSION}"
|
|
export KIBOT_VAR_rev_pcb="${VERSION}"
|
|
export KIBOT_VAR_name=$(echo "${PROJECT_NAME}" | cut -d"-" -f1)
|
|
echo "Using version: $VERSION, name: $KIBOT_VAR_name"
|
|
|
|
if [ -f "${PROJECT_NAME}/${PROJECT_NAME}.kicad_sch" ]; then
|
|
kibot -e ${PROJECT_NAME}/${PROJECT_NAME}.kicad_sch \
|
|
-c $CI_PROJECT_DIR/.gitlab/configs/sch.kibot.yaml \
|
|
-d $CI_PROJECT_DIR/Fabrication/${PROJECT_NAME}
|
|
mv Fabrication/${PROJECT_NAME}/*.pdf Fabrication/ 2>/dev/null || true
|
|
fi
|
|
|
|
generate_bom:
|
|
extends: .fabrication_base
|
|
script:
|
|
- |
|
|
export KIBOT_VAR_rev="${VERSION}"
|
|
export KIBOT_VAR_rev_pcb="${VERSION}"
|
|
export KIBOT_VAR_name=$(echo "${PROJECT_NAME}" | cut -d"-" -f1)
|
|
echo "Using version: $VERSION, name: $KIBOT_VAR_name"
|
|
|
|
if [ -f "${PROJECT_NAME}/${PROJECT_NAME}.kicad_sch" ]; then
|
|
kibot -e ${PROJECT_NAME}/${PROJECT_NAME}.kicad_sch \
|
|
-c $CI_PROJECT_DIR/.gitlab/configs/sch.kibot.yaml \
|
|
-d $CI_PROJECT_DIR/Fabrication/${PROJECT_NAME}
|
|
mv Fabrication/${PROJECT_NAME}/*.csv Fabrication/ 2>/dev/null || true
|
|
mv Fabrication/${PROJECT_NAME}/*.xlsx Fabrication/ 2>/dev/null || true
|
|
fi
|
|
|
|
generate_3d:
|
|
extends: .fabrication_base
|
|
script:
|
|
- |
|
|
export KIBOT_VAR_rev="${VERSION}"
|
|
export KIBOT_VAR_rev_pcb="${VERSION}"
|
|
export KIBOT_VAR_name=$(echo "${PROJECT_NAME}" | cut -d"-" -f1)
|
|
echo "Using version: $VERSION, name: $KIBOT_VAR_name"
|
|
|
|
if [ -f "${PROJECT_NAME}/${PROJECT_NAME}.kicad_pcb" ]; then
|
|
kibot -e ${PROJECT_NAME}/${PROJECT_NAME}.kicad_sch \
|
|
-c $CI_PROJECT_DIR/.gitlab/configs/mech.kibot.yaml \
|
|
-d $CI_PROJECT_DIR/Fabrication/${PROJECT_NAME}
|
|
mv Fabrication/${PROJECT_NAME}/*.step Fabrication/ 2>/dev/null || true
|
|
fi
|
|
|
|
generate_gerbers:
|
|
extends: .fabrication_base
|
|
script:
|
|
- |
|
|
export KIBOT_VAR_rev="${VERSION}"
|
|
export KIBOT_VAR_rev_pcb="${VERSION}"
|
|
export KIBOT_VAR_name=$(echo "${PROJECT_NAME}" | cut -d"-" -f1)
|
|
echo "Using version: $VERSION, name: $KIBOT_VAR_name"
|
|
|
|
if [ -f "${PROJECT_NAME}/${PROJECT_NAME}.kicad_pcb" ]; then
|
|
kibot -e ${PROJECT_NAME}/${PROJECT_NAME}.kicad_sch \
|
|
-c $CI_PROJECT_DIR/.gitlab/configs/pcb_main.kibot.yaml \
|
|
-d $CI_PROJECT_DIR/Fabrication/${PROJECT_NAME}
|
|
mv Fabrication/${PROJECT_NAME}/*.zip Fabrication/ 2>/dev/null || true
|
|
fi
|
|
|
|
generate_position:
|
|
extends: .fabrication_base
|
|
script:
|
|
- |
|
|
export KIBOT_VAR_rev="${VERSION}"
|
|
export KIBOT_VAR_rev_pcb="${VERSION}"
|
|
export KIBOT_VAR_name=$(echo "${PROJECT_NAME}" | cut -d"-" -f1)
|
|
echo "Using version: $VERSION, name: $KIBOT_VAR_name"
|
|
|
|
if [ -f "${PROJECT_NAME}/${PROJECT_NAME}.kicad_pcb" ]; then
|
|
kibot -e ${PROJECT_NAME}/${PROJECT_NAME}.kicad_sch \
|
|
-c $CI_PROJECT_DIR/.gitlab/configs/pos.kibot.yaml \
|
|
-d $CI_PROJECT_DIR/Fabrication/${PROJECT_NAME}
|
|
mv Fabrication/${PROJECT_NAME}/*cpl*.csv Fabrication/ 2>/dev/null || true
|
|
fi
|
|
|
|
generate_panel:
|
|
extends: .fabrication_base
|
|
script:
|
|
- |
|
|
export KIBOT_VAR_rev="${VERSION}"
|
|
export KIBOT_VAR_rev_pcb="${VERSION}"
|
|
export KIBOT_VAR_name=$(echo "${PROJECT_NAME}" | cut -d"-" -f1)
|
|
echo "Using version: $VERSION, name: $KIBOT_VAR_name"
|
|
|
|
# Find panel configuration
|
|
PANEL_JSON=$(find ${PROJECT_NAME} -name "*_panel.json" 2>/dev/null | head -1)
|
|
|
|
if [ -n "$PANEL_JSON" ] && [ -f "$PANEL_JSON" ]; then
|
|
echo "Found panel config: $PANEL_JSON"
|
|
|
|
# Create panel directory
|
|
PANEL_NAME=$(basename "${PANEL_JSON%.json}")
|
|
mkdir -p panels/${PANEL_NAME}
|
|
PCB_FILE="${PROJECT_NAME}/${PROJECT_NAME}.kicad_pcb"
|
|
|
|
# Run pre-panel script if exists
|
|
if [ -f ".gitlab/.scripts/pre_panel.py" ]; then
|
|
python3 .gitlab/.scripts/pre_panel.py $PCB_FILE $PANEL_JSON
|
|
fi
|
|
|
|
# Generate panel
|
|
kikit panelize -p $PANEL_JSON $PCB_FILE panels/${PANEL_NAME}/${PANEL_NAME}.kicad_pcb
|
|
|
|
# Copy required files for panel
|
|
cp .gitlab/templates/micromelon_default/micromelon_default.kicad_sch panels/${PANEL_NAME}/${PANEL_NAME}.kicad_sch 2>/dev/null || true
|
|
cp ${PROJECT_NAME}/fp-lib-table panels/${PANEL_NAME}/ 2>/dev/null || true
|
|
# Copy libs folder for 3D models
|
|
cp -r ${PROJECT_NAME}/libs panels/${PANEL_NAME}/ 2>/dev/null || true
|
|
|
|
# Run post-panel script if exists
|
|
if [ -f ".gitlab/.scripts/post_panel.py" ]; then
|
|
python3 .gitlab/.scripts/post_panel.py panels/${PANEL_NAME}/${PANEL_NAME}.kicad_pro $PCB_FILE
|
|
fi
|
|
|
|
# Generate panel gerbers
|
|
# Set name variable explicitly for panel (extract part number from project name)
|
|
export KIBOT_VAR_name=$(echo "${PROJECT_NAME}" | cut -d"-" -f1)
|
|
cd panels
|
|
kibot -e ${PANEL_NAME}/${PANEL_NAME}.kicad_sch \
|
|
-c $CI_PROJECT_DIR/.gitlab/configs/panel.kibot.yaml \
|
|
-d $CI_PROJECT_DIR/Fabrication/panels
|
|
cd $CI_PROJECT_DIR
|
|
|
|
mv Fabrication/panels/*.zip Fabrication/ 2>/dev/null || true
|
|
else
|
|
echo "No panel configuration found, skipping panel generation"
|
|
fi
|
|
|
|
# =============================================================================
|
|
# Stage: Astable (replaces the old InvenTree/hfsntree upload path)
|
|
# =============================================================================
|
|
#
|
|
# Uploads the BOM + every fabrication output to Astable via
|
|
# POST /api/v1/bom/upload. Astable owns the supplier-API
|
|
# credentials, so the CI runner doesn't need Digi-Key / Mouser
|
|
# tokens any more. The upload is strict: any MPN that can't be
|
|
# resolved against an enabled supplier integration aborts the
|
|
# upload and writes nothing.
|
|
#
|
|
# Revision-targeting follows the existing dev/main convention:
|
|
# - dev branch: uploads to the part's DRAFT "dev" revision.
|
|
# - main branch: uploads to the rev named from the commit
|
|
# message's "VX.Y" token, promoted to ACTIVE.
|
|
# - MR-to-main: uploads to "dev" (matches old behaviour).
|
|
#
|
|
# Required CI variables (set group-level on
|
|
# Micromelon/education/hardware/, masked + protected):
|
|
#
|
|
# ASTABLE_URL e.g. https://astable.timhadwen.com
|
|
# ASTABLE_API_TOKEN minted at /manage/api-tokens (ast_…)
|
|
#
|
|
# The script vendored at scripts/upload-bom.sh in this repo handles
|
|
# the POST + polling loop. PROJECT_NAME flows through as the
|
|
# part-ipn — Astable splits on the first hyphen to derive the
|
|
# PCBA IPN ("<base>A") + bare-PCB IPN ("<base>") + display name.
|
|
|
|
.astable_base:
|
|
stage: inventree # keep stage name so existing `needs:`
|
|
# downstream (upload_packages) still match
|
|
image: curlimages/curl:8.10.1
|
|
before_script:
|
|
- apk add --no-cache bash jq
|
|
# Fetch the upload script from the kicad-ci repo so the yml stays
|
|
# self-contained (GitLab's `include: project:` only ships the yml
|
|
# itself, not sibling files in the repo). The ref pins to kicad9
|
|
# — bump if you move the script.
|
|
- |
|
|
curl -fsSL -o /usr/local/bin/upload-bom.sh \
|
|
"https://gitlab.com/Micromelon/education/hardware/kicad-ci/-/raw/kicad9/scripts/upload-bom.sh"
|
|
chmod +x /usr/local/bin/upload-bom.sh
|
|
|
|
astable_dev:
|
|
extends: .astable_base
|
|
rules:
|
|
- !reference [.dev_rules, rules]
|
|
needs:
|
|
- job: extract_version
|
|
artifacts: true
|
|
- job: generate_schematic
|
|
artifacts: true
|
|
- job: generate_bom
|
|
artifacts: true
|
|
- job: generate_3d
|
|
artifacts: true
|
|
script:
|
|
- |
|
|
FAB="$CI_PROJECT_DIR/Fabrication"
|
|
SUB="$FAB/${PROJECT_NAME}"
|
|
VAL="$CI_PROJECT_DIR/Validation"
|
|
|
|
# Build args list — each --flag is optional; the script skips
|
|
# files that aren't present. Dev runs have fewer outputs than
|
|
# main (no gerbers/panel), so we just pass what exists.
|
|
ARGS=(
|
|
--file "$FAB/${PROJECT_NAME}_dev_bom.csv"
|
|
--part-ipn "$PROJECT_NAME"
|
|
--branch dev
|
|
--commit-sha "$CI_COMMIT_SHA"
|
|
--commit-message "$CI_COMMIT_MESSAGE"
|
|
)
|
|
[ -f "$FAB/${PROJECT_NAME}_dev_cpl.csv" ] && ARGS+=(--cpl "$FAB/${PROJECT_NAME}_dev_cpl.csv")
|
|
[ -f "$FAB/${PROJECT_NAME}_dev.step" ] && ARGS+=(--step "$FAB/${PROJECT_NAME}_dev.step")
|
|
[ -f "$FAB/${PROJECT_NAME}_dev_schematic.pdf" ] && ARGS+=(--schematic-pdf "$FAB/${PROJECT_NAME}_dev_schematic.pdf")
|
|
[ -f "$SUB/${PROJECT_NAME}_dev_ibom.html" ] && ARGS+=(--ibom-html "$SUB/${PROJECT_NAME}_dev_ibom.html")
|
|
[ -f "$SUB/${PROJECT_NAME}_dev_bom.xlsx" ] && ARGS+=(--bom-xlsx "$SUB/${PROJECT_NAME}_dev_bom.xlsx")
|
|
[ -f "$SUB/PCBA_${PROJECT_NAME}_dev.png" ] && ARGS+=(--pcba-image "$SUB/PCBA_${PROJECT_NAME}_dev.png")
|
|
[ -f "$SUB/PCB_${PROJECT_NAME}_dev.png" ] && ARGS+=(--pcb-image "$SUB/PCB_${PROJECT_NAME}_dev.png")
|
|
[ -f "$VAL/${PROJECT_NAME}-erc.html" ] && ARGS+=(--erc-report "$VAL/${PROJECT_NAME}-erc.html")
|
|
[ -f "$VAL/${PROJECT_NAME}-drc.html" ] && ARGS+=(--drc-report "$VAL/${PROJECT_NAME}-drc.html")
|
|
|
|
upload-bom.sh "${ARGS[@]}"
|
|
|
|
astable_main:
|
|
extends: .astable_base
|
|
rules:
|
|
- !reference [.main_rules, rules]
|
|
needs:
|
|
- job: extract_version
|
|
artifacts: true
|
|
- job: generate_schematic
|
|
artifacts: true
|
|
- job: generate_bom
|
|
artifacts: true
|
|
- job: generate_3d
|
|
artifacts: true
|
|
- job: generate_gerbers
|
|
artifacts: true
|
|
- job: generate_position
|
|
artifacts: true
|
|
- job: generate_panel
|
|
artifacts: true
|
|
optional: true
|
|
artifacts:
|
|
when: always
|
|
paths:
|
|
- Fabrication/
|
|
expire_in: 1 week
|
|
script:
|
|
- |
|
|
FAB="$CI_PROJECT_DIR/Fabrication"
|
|
SUB="$FAB/${PROJECT_NAME}"
|
|
VAL="$CI_PROJECT_DIR/Validation"
|
|
|
|
# MR-to-main → upload to the dev rev (pre-ordering window).
|
|
# Actual main pushes → released rev named from the commit
|
|
# message. The BOM CSV's filename always uses ${VERSION} —
|
|
# extract_version sets it to "dev" for MRs and the V-token
|
|
# for direct pushes, so we can read the same path either way.
|
|
if [[ "$CI_PIPELINE_SOURCE" == "merge_request_event" ]]; then
|
|
BRANCH=dev
|
|
else
|
|
BRANCH=main
|
|
fi
|
|
|
|
ARGS=(
|
|
--file "$FAB/${PROJECT_NAME}_${VERSION}_bom.csv"
|
|
--part-ipn "$PROJECT_NAME"
|
|
--branch "$BRANCH"
|
|
--commit-sha "$CI_COMMIT_SHA"
|
|
--commit-message "$CI_COMMIT_MESSAGE"
|
|
)
|
|
[ -f "$FAB/${PROJECT_NAME}_${VERSION}_cpl.csv" ] && ARGS+=(--cpl "$FAB/${PROJECT_NAME}_${VERSION}_cpl.csv")
|
|
[ -f "$FAB/${PROJECT_NAME}_${VERSION}_JLC.zip" ] && ARGS+=(--gerbers "$FAB/${PROJECT_NAME}_${VERSION}_JLC.zip")
|
|
[ -f "$FAB/${PROJECT_NAME}_panel_${VERSION}_JLC.zip" ] && ARGS+=(--panel-gerbers "$FAB/${PROJECT_NAME}_panel_${VERSION}_JLC.zip")
|
|
[ -f "$FAB/${PROJECT_NAME}_${VERSION}.step" ] && ARGS+=(--step "$FAB/${PROJECT_NAME}_${VERSION}.step")
|
|
[ -f "$FAB/${PROJECT_NAME}_${VERSION}_schematic.pdf" ] && ARGS+=(--schematic-pdf "$FAB/${PROJECT_NAME}_${VERSION}_schematic.pdf")
|
|
[ -f "$SUB/${PROJECT_NAME}_${VERSION}_PCB.pdf" ] && ARGS+=(--pcb-pdf "$SUB/${PROJECT_NAME}_${VERSION}_PCB.pdf")
|
|
[ -f "$SUB/${PROJECT_NAME}_${VERSION}_ibom.html" ] && ARGS+=(--ibom-html "$SUB/${PROJECT_NAME}_${VERSION}_ibom.html")
|
|
[ -f "$SUB/${PROJECT_NAME}_${VERSION}_bom.xlsx" ] && ARGS+=(--bom-xlsx "$SUB/${PROJECT_NAME}_${VERSION}_bom.xlsx")
|
|
[ -f "$SUB/PCBA_${PROJECT_NAME}_${VERSION}.png" ] && ARGS+=(--pcba-image "$SUB/PCBA_${PROJECT_NAME}_${VERSION}.png")
|
|
[ -f "$SUB/PCB_${PROJECT_NAME}_${VERSION}.png" ] && ARGS+=(--pcb-image "$SUB/PCB_${PROJECT_NAME}_${VERSION}.png")
|
|
[ -f "$VAL/${PROJECT_NAME}-erc.html" ] && ARGS+=(--erc-report "$VAL/${PROJECT_NAME}-erc.html")
|
|
[ -f "$VAL/${PROJECT_NAME}-drc.html" ] && ARGS+=(--drc-report "$VAL/${PROJECT_NAME}-drc.html")
|
|
|
|
upload-bom.sh "${ARGS[@]}"
|
|
|
|
# =============================================================================
|
|
# Stage: Release
|
|
# =============================================================================
|
|
upload_packages:
|
|
stage: release
|
|
rules:
|
|
- if: $CI_COMMIT_TAG
|
|
when: never
|
|
- if: $CI_COMMIT_BRANCH == "main"
|
|
needs:
|
|
- job: extract_version
|
|
artifacts: true
|
|
- job: astable_main
|
|
artifacts: true
|
|
script:
|
|
- apt-get update && apt-get -y install zip
|
|
- |
|
|
# Create single release zip with all fabrication outputs
|
|
RELEASE_ZIP="${PROJECT_NAME}_${VERSION}.zip"
|
|
zip -r "Fabrication/${RELEASE_ZIP}" Fabrication/
|
|
echo "Created release package: ${RELEASE_ZIP}"
|
|
- echo 'import urllib.request,sys,os;f=open(sys.argv[1],"rb");req=urllib.request.Request(sys.argv[2],data=f.read(),method="PUT");req.add_header("JOB-TOKEN",os.environ["CI_JOB_TOKEN"]);urllib.request.urlopen(req);print("Uploaded",sys.argv[1])' > /tmp/upload.py
|
|
- |
|
|
# Upload release package
|
|
RELEASE_ZIP="${PROJECT_NAME}_${VERSION}.zip"
|
|
url="${PACKAGE_REGISTRY_URL}/${VERSION}/${RELEASE_ZIP}"
|
|
echo "Uploading: Fabrication/${RELEASE_ZIP} to $url"
|
|
python3 /tmp/upload.py "Fabrication/${RELEASE_ZIP}" "$url"
|
|
artifacts:
|
|
when: always
|
|
paths:
|
|
- Fabrication/
|
|
expire_in: 1 week
|
|
|
|
create_release:
|
|
stage: release
|
|
image: registry.gitlab.com/gitlab-org/release-cli:latest
|
|
rules:
|
|
- if: $CI_COMMIT_TAG
|
|
when: never
|
|
- if: $CI_COMMIT_BRANCH == "main"
|
|
needs:
|
|
- job: extract_version
|
|
artifacts: true
|
|
- job: upload_packages
|
|
artifacts: true
|
|
script:
|
|
- echo "Creating release for version $VERSION"
|
|
release:
|
|
tag_name: '$VERSION'
|
|
name: 'Release $VERSION'
|
|
description: 'Automated release for $VERSION'
|