* ci: add status badges to README * chore: major overhaul - docs, commands & workflows * fix: general fixes and improvements * chore: various updates and fixes * chore: minor fixes
299 lines
10 KiB
YAML
299 lines
10 KiB
YAML
name: Macro Release (Reusable)
|
|
|
|
# Reusable workflow for releasing individual FreeCAD macros
|
|
# Called by component-specific workflows with appropriate inputs
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
tag_prefix:
|
|
description: 'Tag prefix to match (e.g., macro-cut-object-for-magnets-v)'
|
|
required: true
|
|
type: string
|
|
macro_dir:
|
|
description: 'Macro directory relative to macros/ (e.g., Cut_Object_for_Magnets)'
|
|
required: true
|
|
type: string
|
|
macro_file:
|
|
description: 'Main macro filename (e.g., CutObjectForMagnets.FCMacro)'
|
|
required: true
|
|
type: string
|
|
macro_name:
|
|
description: 'Human-readable macro name (e.g., Cut Object for Magnets)'
|
|
required: true
|
|
type: string
|
|
archive_name:
|
|
description: 'Archive base name (e.g., CutObjectForMagnets)'
|
|
required: true
|
|
type: string
|
|
readme_file:
|
|
description: 'README filename (e.g., README-CutObjectForMagnets.md)'
|
|
required: true
|
|
type: string
|
|
wiki_url:
|
|
description: 'FreeCAD Wiki URL for this macro'
|
|
required: false
|
|
type: string
|
|
default: ''
|
|
description:
|
|
description: 'Short description for release notes'
|
|
required: true
|
|
type: string
|
|
workflow_call:
|
|
inputs:
|
|
tag_prefix:
|
|
description: 'Tag prefix to match (e.g., macro-cut-object-for-magnets-v)'
|
|
required: true
|
|
type: string
|
|
macro_dir:
|
|
description: 'Macro directory relative to macros/ (e.g., Cut_Object_for_Magnets)'
|
|
required: true
|
|
type: string
|
|
macro_file:
|
|
description: 'Main macro filename (e.g., CutObjectForMagnets.FCMacro)'
|
|
required: true
|
|
type: string
|
|
macro_name:
|
|
description: 'Human-readable macro name (e.g., Cut Object for Magnets)'
|
|
required: true
|
|
type: string
|
|
archive_name:
|
|
description: 'Archive base name (e.g., CutObjectForMagnets)'
|
|
required: true
|
|
type: string
|
|
readme_file:
|
|
description: 'README filename (e.g., README-CutObjectForMagnets.md)'
|
|
required: true
|
|
type: string
|
|
wiki_url:
|
|
description: 'FreeCAD Wiki URL for this macro'
|
|
required: false
|
|
type: string
|
|
default: ''
|
|
description:
|
|
description: 'Short description for release notes'
|
|
required: true
|
|
type: string
|
|
|
|
jobs:
|
|
validate-and-release:
|
|
name: Validate Tag and Create Release
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: write
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Validate semantic version tag
|
|
id: version
|
|
env:
|
|
TAG_PREFIX: ${{ inputs.tag_prefix }}
|
|
run: |
|
|
TAG="${GITHUB_REF#refs/tags/}"
|
|
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
|
|
|
# Build regex pattern from tag prefix
|
|
PATTERN="^${TAG_PREFIX}([0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?)\$"
|
|
|
|
if [[ ! "$TAG" =~ $PATTERN ]]; then
|
|
echo "ERROR: Tag '$TAG' does not match expected format (${TAG_PREFIX}X.Y.Z)"
|
|
exit 1
|
|
fi
|
|
|
|
VERSION="${BASH_REMATCH[1]}"
|
|
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
|
|
# Check if this is a prerelease
|
|
if [[ "$VERSION" =~ -[a-zA-Z0-9.]+ ]]; then
|
|
echo "is_prerelease=true" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "is_prerelease=false" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
echo "Parsed version: $VERSION"
|
|
|
|
- name: Verify macro version in files
|
|
env:
|
|
VERSION: ${{ steps.version.outputs.version }}
|
|
MACRO_DIR: ${{ inputs.macro_dir }}
|
|
MACRO_FILE: ${{ inputs.macro_file }}
|
|
MACRO_NAME: ${{ inputs.macro_name }}
|
|
run: |
|
|
MACRO_PATH="macros/${MACRO_DIR}/${MACRO_FILE}"
|
|
|
|
echo "Verifying version in source files matches tag: $VERSION"
|
|
|
|
# Check __Version__ in .FCMacro file
|
|
if [ -f "$MACRO_PATH" ]; then
|
|
MACRO_VERSION=$(grep -o '__Version__ = "[^"]*"' "$MACRO_PATH" | cut -d'"' -f2)
|
|
if [ "$MACRO_VERSION" != "$VERSION" ]; then
|
|
echo "ERROR: Version mismatch in $MACRO_PATH"
|
|
echo " Expected: $VERSION"
|
|
echo " Found: $MACRO_VERSION"
|
|
echo ""
|
|
echo "The version in source files must be updated before tagging."
|
|
echo "Run the appropriate bump command first."
|
|
exit 1
|
|
fi
|
|
echo "✓ $MACRO_PATH: $MACRO_VERSION"
|
|
else
|
|
echo "ERROR: Macro file not found: $MACRO_PATH"
|
|
exit 1
|
|
fi
|
|
|
|
# Check package.xml
|
|
PKG_VERSION=$(awk -v name="$MACRO_NAME" '
|
|
/<macro>/ { in_macro=1 }
|
|
/<\/macro>/ { in_macro=0; found_name=0 }
|
|
in_macro && index($0, name) > 0 { found_name=1 }
|
|
in_macro && found_name && /<version>/ {
|
|
gsub(/.*<version>/, ""); gsub(/<\/version>.*/, ""); print; exit
|
|
}
|
|
' package.xml)
|
|
if [ "$PKG_VERSION" != "$VERSION" ]; then
|
|
echo "ERROR: Version mismatch in package.xml ($MACRO_NAME section)"
|
|
echo " Expected: $VERSION"
|
|
echo " Found: $PKG_VERSION"
|
|
exit 1
|
|
fi
|
|
echo "✓ package.xml ($MACRO_NAME): $PKG_VERSION"
|
|
|
|
echo ""
|
|
echo "Version verification passed!"
|
|
|
|
- name: Create macro archive
|
|
env:
|
|
VERSION: ${{ steps.version.outputs.version }}
|
|
MACRO_DIR: ${{ inputs.macro_dir }}
|
|
MACRO_FILE: ${{ inputs.macro_file }}
|
|
ARCHIVE_NAME: ${{ inputs.archive_name }}
|
|
README_FILE: ${{ inputs.readme_file }}
|
|
run: |
|
|
# Create staging directory
|
|
mkdir -p "staging/${ARCHIVE_NAME}-${VERSION}"
|
|
|
|
# Copy macro files
|
|
cp "macros/${MACRO_DIR}/${MACRO_FILE}" "staging/${ARCHIVE_NAME}-${VERSION}/"
|
|
|
|
# Copy icon if exists
|
|
for ext in svg png; do
|
|
ICON_FILE="macros/${MACRO_DIR}/${ARCHIVE_NAME}.${ext}"
|
|
if [ -f "$ICON_FILE" ]; then
|
|
cp "$ICON_FILE" "staging/${ARCHIVE_NAME}-${VERSION}/"
|
|
fi
|
|
done
|
|
|
|
# Copy README
|
|
if [ -f "macros/${MACRO_DIR}/${README_FILE}" ]; then
|
|
cp "macros/${MACRO_DIR}/${README_FILE}" "staging/${ARCHIVE_NAME}-${VERSION}/README.md"
|
|
fi
|
|
|
|
# Copy LICENSE
|
|
cp LICENSE "staging/${ARCHIVE_NAME}-${VERSION}/"
|
|
|
|
# Create tar.gz archive
|
|
cd staging
|
|
tar -czvf "${ARCHIVE_NAME}-${VERSION}.tar.gz" "${ARCHIVE_NAME}-${VERSION}"
|
|
|
|
# Create zip archive
|
|
zip -r "${ARCHIVE_NAME}-${VERSION}.zip" "${ARCHIVE_NAME}-${VERSION}"
|
|
|
|
mv "${ARCHIVE_NAME}-${VERSION}.tar.gz" ../
|
|
mv "${ARCHIVE_NAME}-${VERSION}.zip" ../
|
|
cd ..
|
|
|
|
echo "Created archives:"
|
|
ls -la "${ARCHIVE_NAME}-${VERSION}."*
|
|
|
|
- name: Extract changelog section
|
|
id: changelog
|
|
env:
|
|
VERSION: ${{ steps.version.outputs.version }}
|
|
MACRO_NAME: ${{ inputs.macro_name }}
|
|
DESCRIPTION: ${{ inputs.description }}
|
|
MACRO_FILE: ${{ inputs.macro_file }}
|
|
MACRO_DIR: ${{ inputs.macro_dir }}
|
|
README_FILE: ${{ inputs.readme_file }}
|
|
WIKI_URL: ${{ inputs.wiki_url }}
|
|
run: |
|
|
# Match header exactly as it appears in CHANGELOG.md
|
|
HEADER="### ${MACRO_NAME} Macro v${VERSION}"
|
|
|
|
# Extract section between this version header and the next component header or separator
|
|
# Only exit on: "---" separator OR "### " followed by component name (capital letter)
|
|
# This allows #### Added, #### Changed, etc. to be included
|
|
CHANGELOG_CONTENT=$(awk -v header="$HEADER" '
|
|
BEGIN { found=0 }
|
|
$0 == header || $0 == header " " { found=1; next }
|
|
found && /^---$/ { exit }
|
|
found && /^### [A-Z]/ { exit }
|
|
found { print }
|
|
' CHANGELOG.md)
|
|
|
|
# Build release body
|
|
cat > release_body.md << EOF
|
|
## ${MACRO_NAME} Macro v${VERSION}
|
|
|
|
${DESCRIPTION}
|
|
|
|
### Installation
|
|
|
|
Copy \`${MACRO_FILE}\` to your FreeCAD macro directory:
|
|
|
|
- **macOS**: \`~/Library/Application Support/FreeCAD/Macro/\`
|
|
- **Linux**: \`~/.local/share/FreeCAD/Macro/\`
|
|
- **Windows**: \`%APPDATA%/FreeCAD/Macro/\`
|
|
|
|
Optionally copy the icon file (\`.svg\` or \`.png\`) to the same location.
|
|
|
|
### Documentation
|
|
|
|
- [Full README](https://github.com/spkane/freecad-robust-mcp-and-more/blob/main/macros/${MACRO_DIR}/${README_FILE})
|
|
EOF
|
|
|
|
if [ -n "$WIKI_URL" ]; then
|
|
echo "- [FreeCAD Wiki Page](${WIKI_URL})" >> release_body.md
|
|
fi
|
|
|
|
if [ -n "$CHANGELOG_CONTENT" ]; then
|
|
{
|
|
echo ""
|
|
echo "### Changelog"
|
|
echo ""
|
|
echo "$CHANGELOG_CONTENT"
|
|
} >> release_body.md
|
|
fi
|
|
|
|
- name: Create GitHub Release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
name: "${{ inputs.macro_name }} Macro v${{ steps.version.outputs.version }}"
|
|
tag_name: ${{ github.ref_name }}
|
|
prerelease: ${{ steps.version.outputs.is_prerelease == 'true' }}
|
|
generate_release_notes: true
|
|
body_path: release_body.md
|
|
files: |
|
|
${{ inputs.archive_name }}-${{ steps.version.outputs.version }}.tar.gz
|
|
${{ inputs.archive_name }}-${{ steps.version.outputs.version }}.zip
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Generate summary
|
|
env:
|
|
VERSION: ${{ steps.version.outputs.version }}
|
|
MACRO_NAME: ${{ inputs.macro_name }}
|
|
ARCHIVE_NAME: ${{ inputs.archive_name }}
|
|
run: |
|
|
{
|
|
echo "## ${MACRO_NAME} Macro Release"
|
|
echo ""
|
|
echo "**Version:** ${VERSION}"
|
|
echo ""
|
|
echo "### Downloads"
|
|
echo ""
|
|
echo "- \`${ARCHIVE_NAME}-${VERSION}.tar.gz\`"
|
|
echo "- \`${ARCHIVE_NAME}-${VERSION}.zip\`"
|
|
} >> "$GITHUB_STEP_SUMMARY"
|