Add complete KiCad CI pipeline with hfsntree integration

Pipeline stages:
- preflight: extract_version, run_erc, run_drc
- fabrication: schematic, BOM, 3D, gerbers, position, panel
- inventree: dry-run on dev, full upload on main
- release: package upload and GitLab release

Features:
- Version extraction from MR title (V1.0, V1.1, etc.)
- Version injection into KiBot outputs
- Samsung P&P file generation
- Panel gerber generation

Usage: Include this file in project CI and set PROJECT_NAME variable.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
timmyhadwen
2026-01-17 10:23:05 +10:00
parent 1cae44ffdc
commit 614b566d31

View File

@@ -1,3 +1,12 @@
# 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"
@@ -9,19 +18,20 @@ variables:
GIT_STRATEGY: clone
GIT_SUBMODULE_STRATEGY: recursive
GIT_SUBMODULE_FORCE_HTTPS: "true"
# GIT_SUBMODULE_UPDATE_FLAGS: --remote --merge
PACKAGE_REGISTRY_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/kicad"
stages:
- gen_mech
- gen_fab
- preflight
- fabrication
- inventree
- upload
- 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"'
@@ -32,387 +42,401 @@ image:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "dev"'
- if: $CI_COMMIT_BRANCH == "dev"
- if: $GITLAB_CI == 'false'
.commands:
get_files:
- FILES=$(find . -name *$SEARCH -not -path "./.gitlab/*")
get_dirs:
- !reference [.commands, get_files]
# =============================================================================
# Stage: Preflight
# =============================================================================
extract_version:
stage: preflight
script:
- |
if [[ $FILES == "" ]]; then
DIRS=""
else
DIRS=$(dirname $FILES)
# Extract version from MR title (pattern: V followed by numbers and dots)
if [[ -n "$CI_MERGE_REQUEST_TITLE" ]]; then
VERSION=$(echo "$CI_MERGE_REQUEST_TITLE" | grep -oE 'V[0-9]+(\.[0-9]+)*' | head -1)
fi
sch_from_pro:
- 'SCHEMS=$(for f in $FILES ; do echo "${f%.*}.kicad_sch"; done)'
- 'SCHEMS=$(for f in $SCHEMS ; do echo "${f##**/}"; done)'
get_dirs_filt:
- !reference [.commands, get_files]
- |
FILT_FILES=""
FILT_DIRS=""
for f in $FILES
do
dir=$(dirname $f)
echo $dir
if [[ "$dir" =~ ^.?\/?[a-z]?[0-9]{6}-.*$ || "$dir" =~ .+_panel ]]
then
FILT_FILES=$(echo "$FILT_FILES $f")
FILT_DIRS=$(echo "$FILT_DIRS $dir")
# Fallback to git tag or commit SHA
if [[ -z "$VERSION" ]]; then
VERSION=$(git describe --tags 2>/dev/null || echo "$CI_COMMIT_SHORT_SHA")
fi
done
FILES=$FILT_FILES
DIRS=$FILT_DIRS
dir_arr:
- !reference [.commands, get_dirs_filt]
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:
- |
END=$(echo $DIRS | wc -w)
dir_arr=($DIRS)
if [ -f "${PROJECT_NAME}/${PROJECT_NAME}.kicad_sch" ]; then
echo "Running ERC..."
cat > /tmp/erc.kibot.yaml << 'EOF'
kibot:
- 'SEARCH=".kicad_pro"'
- !reference [.commands, dir_arr]
- !reference [.commands, sch_from_pro]
- sch_arr=($SCHEMS)
- |
for i in $(seq 1 $END)
do
if [[ ${dir_arr[i-1]} == "./Frame" ]]; then
continue
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
echo ${dir_arr[i-1]}
echo ${sch_arr[i-1]}
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 for KiBot text variable injection
export KIBOT_VAR_rev="${VERSION}"
export KIBOT_VAR_rev_pcb="${VERSION}"
echo "KiBot version variables set to: $VERSION"
# Setup user config
USER_FILE="$CI_PROJECT_DIR/.gitlab/configs/blank.kibot.yaml"
if [ -f "${dir_arr[i-1]}/kibot.yaml" ]; then
USER_FILE="${dir_arr[i-1]}/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
python3 $CI_PROJECT_DIR/.gitlab/.scripts/orig.py ${dir_arr[i-1]}
for CONF in $KIBOT_CONF
do
kibot -e ${dir_arr[i-1]}/${sch_arr[i-1]} -c $CI_PROJECT_DIR/.gitlab/configs/$CONF.kibot.yaml -d $CI_PROJECT_DIR/Fabrication/${dir_arr[i-1]} $VARIANTS
done
mv $CI_PROJECT_DIR/Fabrication/${dir_arr[i-1]}/*.zip Fabrication/ 2> /dev/null || true
done
- cd $CI_PROJECT_DIR
pre_panel:
- cd $CI_PROJECT_DIR
- mkdir panels
- 'SEARCH="_panel.json"'
- !reference [.commands, get_dirs]
- |
for d in $DIRS
do
echo "found panel: $d"
JSON=$(find $d/*_panel.json)
FILE=$(basename "${JSON}")
NAME=$(echo "${FILE%.json}")
PCB=$(find $d/*.kicad_pcb)
mkdir -p panels/$NAME
echo "panelising"
python3 .gitlab/.scripts/pre_panel.py $PCB $JSON
kikit panelize -p $JSON $PCB panels/$NAME/$NAME.kicad_pcb
cp .gitlab/templates/micromelon_default/micromelon_default.kicad_sch panels/$NAME/$NAME.kicad_sch
cp $d/fp-lib-table panels/$NAME/
python3 .gitlab/.scripts/post_panel.py panels/$NAME/$NAME.kicad_pro $PCB
done
- cd panels
post_panel:
- mv panels/* . || true
neo:
- 'SEARCH=".kicad_pro"'
- !reference [.commands, get_dirs_filt]
- |
for d in $DIRS
do
if [[ $d == "./Frame" ]]; then
continue
fi
echo $d
python3 $CI_PROJECT_DIR/.gitlab/.scripts/neo.py $d
done
boms:
- client=$(echo $CI_PROJECT_PATH | cut -d'/' -f3 | sed -r 's/\<./\U&/g')
- proj=$(echo $CI_PROJECT_NAME | tr -d '0123456789' | tr '-' ' ' | cut -d ' ' -f 2)
- desc_suffix=$(echo $client $proj)
- url="https://gitlab.com/api/v4/projects/${DIGI_API_PRJ_ID}/packages/generic/digikey_api/0/token_storage.json"
- |
if [[ -z "$KINTREE_DIGI_TOKEN" ]]; then
curl --header "JOB-TOKEN: $CI_JOB_TOKEN" $url >> token_storage.json
else
cp $KINTREE_DIGI_TOKEN token_storage.json
fi
- cat token_storage.json
- cd $CI_PROJECT_DIR/Fabrication
- 'SEARCH="bom.csv"'
- !reference [.commands, parse_commit]
- !reference [.commands, get_files]
- cd $CI_PROJECT_DIR
- FAIL=0
- |
for f in $FILES
do
echo $f
fab_path=$CI_PROJECT_DIR/Fabrication/$(dirname $f | cut -c3-)
full_name=$(echo $f | cut -c3- | rev | cut -d'/' -f1 | cut -c9- | rev)
echo "name: $full_name"
name_n_rev=$(echo $full_name | cut -d'_' -f1,2)
assembly_rev=$(echo $full_name | cut -d'_' -f2)
name=$(echo $full_name | cut -d'-' -f1)A$(echo ${full_name//$assembly_rev/.} | cut -d'.' -f2)
pcb_rev=$(echo ${assembly_rev} | cut -d'_' -f1,2 | cut -d'.' -f1,2)
pcb_im=${fab_path}/PCB_${name_n_rev}.png
pcba_im=${fab_path}/PCBA_${name_n_rev}.png
pcb_attach=$(echo "['${fab_path}/${name_n_rev}_PCB.pdf', '$CI_PROJECT_DIR/Fabrication/${name_n_rev}_JLC.zip']")
pcba_attach=$(echo "['${fab_path}/${full_name}_schematic.pdf', '${fab_path}/${full_name}_bom.csv', '${fab_path}/${full_name}-neo-pos_top.csv', '${fab_path}/${full_name}-neo-pos_bot.csv', '${fab_path}/${full_name}_ibom.html']")
DRY="--dry assemblies"
if [[ $CI_COMMIT_BRANCH == "main" ]]; then
DRY=""
fi
echo "Revs: $pcb_rev, $assembly_rev"
python -m kintree.kintree_cli $DRY -b $CI_PROJECT_DIR/Fabrication/$f -a "{'ipn': '$name', 'rev': ['$pcb_rev', '$assembly_rev'], 'image': ['$pcb_im', '$pcba_im'], 'desc': '$desc_suffix', 'attachments': [$pcb_attach, $pcba_attach]}" --settings $KINTREE_SETT --digi_token token_storage.json || FAIL=1
done
# - cp token_storage.json /tmp
- |
cd $CI_PROJECT_DIR
cat token_storage.json
curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file token_storage.json $url
- exit $FAIL
# USE PRIVATE-TOKEN to upload from gitlab-ci
git_tag:
- !reference [.commands, parse_commit]
- |
if [[ $GITLAB_CI == 'true' && $CI_COMMIT_BRANCH == "main" ]]; then
echo "running git tag"
git tag $TAG
elif [[ $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main" && "$CI_MERGE_REQUEST_TITLE" =~ [^a-zA-Z0-9.-_] ]]; then
exit 1
fi
merge_libs:
- |
if [[ $GITLAB_CI == 'true' && $CI_COMMIT_BRANCH == "main" ]]; then
git config --global user.name "KicadCi"
git config --global user.email "andrew@micromelon.com.au"
cd $CI_PROJECT_DIR
for d in "libs/melonlib" "libs/melon3d"
do
cd $d
if [ $d == "libs/melonlib" ]
then
TOKEN=$KI_LIB_TOKEN
else
TOKEN=$KI_LIB_3D_TOKEN
fi
REPO=$(basename $(git remote get-url origin))
cd $CI_PROJECT_DIR
rm -rf $d
rm -rf .git/modules/$d
git submodule set-url $d https://ci_push:$TOKEN@gitlab.com/Micromelon/education/hardware/$REPO
git submodule update --init --remote --merge $d
cd $d
git remote set-url origin https://ci_push:$TOKEN@gitlab.com/Micromelon/education/hardware/$REPO
cd $CI_PROJECT_DIR
done
git submodule status
for d in "libs/melonlib" "libs/melon3d"
do
cd $d
if [ $(git rev-parse HEAD) != $(git rev-parse main) ]
then
CURR_B=$(git config -f $CI_PROJECT_DIR/.gitmodules submodule.$d.branch)
echo CURR_B
echo $CURR_B
git checkout $CURR_B
git commit --allow-empty -m "Merge"
git remote get-url origin
git push -u origin HEAD:$CURR_B -o ci.skip -o merge_request.create -o merge_request.remove_source_branch=false -o merge_request.merge_when_pipeline_succeeds -o merge_request.target=main
fi
cd $CI_PROJECT_DIR
done
fi
parse_commit:
- |
initials () {
echo "$(echo $1 | cut -d' ' -f1 | cut -c1-1)$(echo $1 | cut -d' ' -f2 | cut -c1-1)"
}
str=$CI_COMMIT_MESSAGE
REV=$(echo "$str" | sed -n '1 p')
DWN=$(initials "$(echo "$str" | sed -n '3 p' | cut -d' ' -f1,2)")
CHK=''
APP=''
while IFS= read -r line; do
if [[ $line == Rev* ]]; then
CHK=$(initials "$(echo $line | cut -d' ' -f2,3)")
fi
if [[ $line == App* ]]; then
APP=$(initials "$(echo $line | cut -d' ' -f2,3)")
fi
done <<<"$str"
export DWN
export CHK
export APP
- !reference [.commands, parse_tag]
parse_tag:
- TAG=$(echo "$CI_COMMIT_MESSAGE" | sed -n '1 p')
- echo $TAG
outputs_mech:
stage: gen_mech
when: always
artifacts:
when: always
paths:
- Fabrication/**/*
- Fabrication/
expire_in: 1 week
generate_schematic:
extends: .fabrication_base
script:
- |
export KIBOT_VAR_rev="${VERSION}"
export KIBOT_VAR_rev_pcb="${VERSION}"
echo "Using version: $VERSION"
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}"
echo "Using version: $VERSION"
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}"
echo "Using version: $VERSION"
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
rules:
- !reference [.main_rules, rules]
script:
- |
export KIBOT_VAR_rev="${VERSION}"
export KIBOT_VAR_rev_pcb="${VERSION}"
echo "Using version: $VERSION"
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
rules:
- !reference [.main_rules, rules]
script:
- |
export KIBOT_VAR_rev="${VERSION}"
export KIBOT_VAR_rev_pcb="${VERSION}"
echo "Using version: $VERSION"
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
rules:
- !reference [.main_rules, rules]
script:
- |
export KIBOT_VAR_rev="${VERSION}"
export KIBOT_VAR_rev_pcb="${VERSION}"
echo "Using version: $VERSION"
# 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: InvenTree
# =============================================================================
.inventree_base:
stage: inventree
image: python:3.11-slim
before_script:
- !reference [.commands, git_tag]
script:
- VARIANTS="$VARIANTS_MECH"
- KIBOT_CONF="mech"
- !reference [.commands, kibot]
- |
cd hfsntree
pip install -e . --quiet
cd $CI_PROJECT_DIR
outputs_dev:
extends: outputs_mech
rules:
- !reference [.dev_rules, rules]
stage: gen_fab
script:
# SCH
- VARIANTS="$VARIANTS_SCH"
- KIBOT_CONF="sch"
- !reference [.commands, kibot]
# PCB
- VARIANTS="$VARIANTS_PCB"
- KIBOT_CONF="pcb_dev"
- !reference [.commands, kibot]
outputs_main:
extends: outputs_dev
rules:
- !reference [.main_rules, rules]
script:
# SCH
- VARIANTS="$VARIANTS_SCH"
- KIBOT_CONF="sch"
- !reference [.commands, kibot]
# PCB
- VARIANTS="$VARIANTS_PCB"
- KIBOT_CONF="pcb_main"
- !reference [.commands, kibot]
# Panels
- !reference [.commands, pre_panel]
- KIBOT_CONF="panel"
- !reference [.commands, kibot]
- !reference [.commands, post_panel]
# Pos
- VARIANTS="$VARIANTS_SCH"
- KIBOT_CONF="pos"
- !reference [.commands, kibot]
- !reference [.commands, neo]
inventree_job_dev:
image:
name: ghcr.io/andrew-collins/ki-ntree:cli
entrypoint: [""]
stage: inventree
inventree_dev:
extends: .inventree_base
rules:
- !reference [.dev_rules, rules]
needs:
- job: outputs_mech
- job: extract_version
artifacts: true
- job: outputs_dev
- job: generate_schematic
artifacts: true
- job: generate_bom
artifacts: true
- job: generate_3d
artifacts: true
script:
- !reference [.commands, boms]
- |
echo "Running InvenTree upload in dry-run mode for dev branch"
cd hfsntree
python main.py batch $CI_PROJECT_DIR/Fabrication --dry-run -y
inventree_job_main:
image:
name: ghcr.io/andrew-collins/ki-ntree:cli
entrypoint: [""]
stage: inventree
inventree_main:
extends: .inventree_base
rules:
- !reference [.main_rules, rules]
needs:
- job: outputs_mech
- job: extract_version
artifacts: true
- job: outputs_main
- 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:
- !reference [.commands, boms]
- |
echo "Running InvenTree upload for main branch"
cd hfsntree
python main.py batch $CI_PROJECT_DIR/Fabrication -y
upload_job:
stage: upload
needs:
- job: inventree_job_main
- job: outputs_main
artifacts: true
# Generate Samsung P&P files (requires parts to exist in InvenTree)
echo "Generating Samsung pick-and-place files..."
python main.py samsung $CI_PROJECT_DIR/Fabrication
cd $CI_PROJECT_DIR
# =============================================================================
# Stage: Release
# =============================================================================
upload_packages:
stage: release
rules:
- if: $CI_COMMIT_TAG
when: never # Do not run this job when a tag is created manually
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch
when: never
- if: $CI_COMMIT_BRANCH == "main"
needs:
- job: extract_version
artifacts: true
- job: inventree_main
artifacts: true
script:
- !reference [.commands, parse_commit]
- apt remove libcurl4 -y
- apt-get update && apt-get -y install zip curl
- |
apt-get update && apt-get -y install zip curl
# Create combined zip
zip -r Fabrication/All.zip Fabrication/
for d in $(find Fabrication/* -maxdepth 0 -type d)
do
zip=$d.zip
zip -r $zip $d
done
for d in $(find Fabrication/ -maxdepth 1 -name '*.zip')
do
b=$(basename $d)
f=$(echo "${b%.*}")
url=${PACKAGE_REGISTRY_URL}/$TAG/$f-$TAG.zip
echo "uploading: $d to $url"
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file $d $url
# Upload each zip to package registry
for zipfile in $(find Fabrication/ -maxdepth 1 -name '*.zip'); do
basename=$(basename "$zipfile" .zip)
url="${PACKAGE_REGISTRY_URL}/${VERSION}/${basename}-${VERSION}.zip"
echo "Uploading: $zipfile to $url"
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file "$zipfile" "$url"
done
artifacts:
when: always
paths:
- Fabrication/**/*
- Fabrication/
expire_in: 1 week
release_job:
create_release:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
needs:
- job: upload_job
artifacts: true
rules:
- if: $CI_COMMIT_TAG
when: never # Do not run this job when a tag is created manually
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch
when: never
- if: $CI_COMMIT_BRANCH == "main"
needs:
- job: extract_version
artifacts: true
- job: upload_packages
artifacts: true
script:
- !reference [.commands, parse_tag]
- apk add jq curl
- |
echo "running release_job for $TAG"
echo "#!/bin/sh" >> fab.sh
packid=$(curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages | jq .[-1].id)
echo "release-cli create --name \"Release $TAG\" --tag-name \"$TAG\" \\" >> fab.sh
cnt=$(curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/$packid/package_files | jq length)
ids=$(curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/$packid/package_files | jq .[].id)
names=$(curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/$packid/package_files | jq .[].file_name)
i=1
while [ "$i" -le $cnt ]
do
id=$(echo $ids | cut -d' ' -f $i)
name=$(echo $names | cut -d' ' -f $i)
echo " --assets-link \"{\\\"name\\\":\\\"$name\\\",\\\"url\\\":\\\"${CI_PROJECT_URL}/-/package_files/$id/download\\\"}\" \\" >> fab.sh
i=$(( i + 1 ))
apk add jq curl
echo "Creating release for version: $VERSION"
# Get package ID
packid=$(curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" \
"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages" | jq '.[-1].id')
# Build release command with asset links
echo "#!/bin/sh" > release.sh
echo "release-cli create --name \"Release $VERSION\" --tag-name \"$VERSION\" \\" >> release.sh
# Get package files
files_json=$(curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" \
"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/$packid/package_files")
cnt=$(echo "$files_json" | jq 'length')
for i in $(seq 0 $((cnt - 1))); do
id=$(echo "$files_json" | jq -r ".[$i].id")
name=$(echo "$files_json" | jq -r ".[$i].file_name")
echo " --assets-link \"{\\\"name\\\":\\\"$name\\\",\\\"url\\\":\\\"${CI_PROJECT_URL}/-/package_files/$id/download\\\"}\" \\" >> release.sh
done
chmod +x fab.sh
./fab.sh
chmod +x release.sh
./release.sh