Files
create/.gitea/workflows/release.yml
forbes-0023 761c750895
Some checks failed
Build and Test / build (pull_request) Has been cancelled
fix(ci): add CA certificate update before checkout
The job containers don't trust the Cloudflare origin cert by
default. Install and update ca-certificates as the first step
so git can clone over HTTPS before actions/checkout runs.
2026-02-09 11:19:11 -06:00

439 lines
16 KiB
YAML

# SPDX-License-Identifier: LGPL-2.1-or-later
name: Release Build
on:
push:
tags: ["v*", "latest"]
workflow_dispatch:
inputs:
tag:
description: "Release tag (e.g., v0.1.0)"
required: true
type: string
jobs:
# ---------------------------------------------------------------------------
# Linux: AppImage + .deb
# ---------------------------------------------------------------------------
build-linux:
runs-on: ubuntu-latest
env:
CCACHE_DIR: /tmp/ccache-kindred-create
CCACHE_COMPRESS: "true"
CCACHE_COMPRESSLEVEL: "6"
CCACHE_MAXSIZE: "4G"
CCACHE_SLOPPINESS: "include_file_ctime,include_file_mtime,pch_defines,time_macros"
CCACHE_BASEDIR: ${{ github.workspace }}
BUILD_TAG: ${{ github.ref_name || inputs.tag }}
CFLAGS: "-O3"
CXXFLAGS: "-O3"
DEBIAN_FRONTEND: noninteractive
steps:
- name: Trust Cloudflare origin CA
run: |
apt-get update -qq
apt-get install -y --no-install-recommends ca-certificates
update-ca-certificates
- name: Free disk space
run: |
echo "=== Disk usage before cleanup ==="
df -h /
# Remove pre-installed bloat common in runner images
rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache 2>/dev/null || true
rm -rf /usr/local/share/boost /usr/share/swift 2>/dev/null || true
apt-get autoremove -y 2>/dev/null || true
apt-get clean 2>/dev/null || true
echo "=== Disk usage after cleanup ==="
df -h /
- name: Install system prerequisites
run: |
apt-get update -qq
apt-get install -y --no-install-recommends \
ca-certificates curl git file fuse3 xvfb xauth openssl sudo dpkg-dev \
libgl1-mesa-dev libglu1-mesa-dev libx11-dev libxkbcommon-dev \
libxcb-xkb-dev libfontconfig1-dev
- name: Checkout repository
uses: https://git.kindred-systems.com/actions/checkout.git@v4
with:
submodules: recursive
fetch-depth: 1
- name: Fetch latest tag (for git describe)
run: |
latest_tag=$(git ls-remote --tags --sort=-v:refname origin 'refs/tags/v*' | grep -v '\^{}' | head -n1 | awk '{print $2}')
if [ -n "$latest_tag" ]; then
git fetch --no-recurse-submodules --force --depth=1 origin "+${latest_tag}:${latest_tag}"
fi
- name: Install pixi
run: |
curl -fsSL https://pixi.sh/install.sh | bash
echo "$HOME/.pixi/bin" >> $GITHUB_PATH
export PATH="$HOME/.pixi/bin:$PATH"
pixi --version
- name: Compute cache date key
id: cache-date
run: echo "date=$(date -u +%Y%m%d)" >> $GITHUB_OUTPUT
- name: Restore ccache
id: ccache-restore
uses: https://git.kindred-systems.com/actions/cache.git/restore@v4
with:
path: /tmp/ccache-kindred-create
key: ccache-release-linux-${{ steps.cache-date.outputs.date }}
restore-keys: |
ccache-release-linux-
- name: Prepare ccache
run: |
mkdir -p $CCACHE_DIR
# Ensure ccache is accessible to rattler-build's subprocess
export PATH="$(pixi run bash -c 'echo $PATH')"
pixi run ccache -z
pixi run ccache -p
- name: Build release package (AppImage)
working-directory: package/rattler-build
run: |
pixi install
pixi run -e package create_bundle
- name: Show ccache statistics
run: pixi run ccache -s
- name: Save ccache
if: always() && steps.ccache-restore.outputs.cache-hit != 'true'
uses: https://git.kindred-systems.com/actions/cache.git/save@v4
with:
path: /tmp/ccache-kindred-create
key: ccache-release-linux-${{ steps.cache-date.outputs.date }}
- name: Clean up intermediate build files
run: |
# Remove pixi package cache and build work dirs to free space for .deb
rm -rf package/rattler-build/.pixi/build 2>/dev/null || true
find /root/.cache/rattler -type f -delete 2>/dev/null || true
echo "=== Disk usage after cleanup ==="
df -h /
- name: Build .deb package
run: |
./package/debian/build-deb.sh \
package/rattler-build/linux/AppDir/usr \
package/rattler-build/linux \
"${BUILD_TAG}"
- name: List built artifacts
run: |
echo "=== Linux release artifacts ==="
ls -lah package/rattler-build/linux/*.AppImage* 2>/dev/null || true
ls -lah package/rattler-build/linux/*.deb* 2>/dev/null || true
ls -lah package/rattler-build/linux/*-SHA256.txt 2>/dev/null || true
- name: Upload Linux artifacts
uses: https://git.kindred-systems.com/actions/upload-artifact.git@v3
with:
name: release-linux
path: |
package/rattler-build/linux/FreeCAD_*.AppImage
package/rattler-build/linux/*.deb
package/rattler-build/linux/*-SHA256.txt
package/rattler-build/linux/*.sha256
if-no-files-found: error
# ---------------------------------------------------------------------------
# macOS: DMG (Intel + Apple Silicon)
# TODO: Re-enable when macOS runners are available or cross-compilation is set up
# ---------------------------------------------------------------------------
# build-macos:
# strategy:
# fail-fast: false
# matrix:
# include:
# - runner: macos-13
# arch: x86_64
# - runner: macos-14
# arch: arm64
#
# runs-on: ${{ matrix.runner }}
#
# env:
# CCACHE_DIR: /tmp/ccache-kindred-create
# CCACHE_COMPRESS: "true"
# CCACHE_COMPRESSLEVEL: "6"
# CCACHE_MAXSIZE: "4G"
# CCACHE_SLOPPINESS: "include_file_ctime,include_file_mtime,pch_defines,time_macros"
# CCACHE_BASEDIR: ${{ github.workspace }}
# BUILD_TAG: ${{ github.ref_name || inputs.tag }}
# CFLAGS: "-O3"
# CXXFLAGS: "-O3"
#
# steps:
# - name: Checkout repository
# uses: https://git.kindred-systems.com/actions/checkout.git@v4
# with:
# submodules: recursive
# fetch-depth: 1
#
# - name: Fetch tags
# run: git fetch --tags --force --no-recurse-submodules origin
#
# - name: Install pixi
# run: |
# curl -fsSL https://pixi.sh/install.sh | bash
# echo "$HOME/.pixi/bin" >> $GITHUB_PATH
# export PATH="$HOME/.pixi/bin:$PATH"
# pixi --version
#
# - name: Restore ccache
# id: ccache-restore
# uses: https://git.kindred-systems.com/actions/cache.git/restore@v4
# with:
# path: /tmp/ccache-kindred-create
# key: ccache-release-macos-${{ matrix.arch }}-${{ github.sha }}
# restore-keys: |
# ccache-release-macos-${{ matrix.arch }}-
#
# - name: Prepare ccache
# run: |
# mkdir -p $CCACHE_DIR
# pixi run ccache -z
#
# - name: Build release package (DMG)
# working-directory: package/rattler-build
# run: |
# pixi install
# pixi run -e package create_bundle
#
# - name: Show ccache statistics
# run: pixi run ccache -s
#
# - name: Save ccache
# if: always()
# uses: https://git.kindred-systems.com/actions/cache.git/save@v4
# with:
# path: /tmp/ccache-kindred-create
# key: ccache-release-macos-${{ matrix.arch }}-${{ github.sha }}
#
# - name: List built artifacts
# run: |
# echo "=== macOS ${{ matrix.arch }} release artifacts ==="
# ls -lah package/rattler-build/osx/*.dmg* 2>/dev/null || true
#
# - name: Upload macOS artifacts
# uses: https://git.kindred-systems.com/actions/upload-artifact.git@v3
# with:
# name: release-macos-${{ matrix.arch }}
# path: |
# package/rattler-build/osx/*.dmg
# package/rattler-build/osx/*-SHA256.txt
# if-no-files-found: error
# ---------------------------------------------------------------------------
# Windows: .exe installer + .7z archive
# TODO: Re-enable when Windows runners are available or cross-compilation is set up
# ---------------------------------------------------------------------------
# build-windows:
# runs-on: windows-latest
#
# env:
# CCACHE_DIR: C:\ccache-kindred-create
# CCACHE_COMPRESS: "true"
# CCACHE_COMPRESSLEVEL: "6"
# CCACHE_MAXSIZE: "4G"
# CCACHE_SLOPPINESS: "include_file_ctime,include_file_mtime,pch_defines,time_macros"
# CCACHE_BASEDIR: ${{ github.workspace }}
# BUILD_TAG: ${{ github.ref_name || inputs.tag }}
# CFLAGS: "/O2"
# CXXFLAGS: "/O2"
# MAKE_INSTALLER: "true"
#
# steps:
# - name: Checkout repository
# uses: https://git.kindred-systems.com/actions/checkout.git@v4
# with:
# submodules: recursive
# fetch-depth: 1
#
# - name: Fetch tags
# shell: bash
# run: git fetch --tags --force --no-recurse-submodules origin
#
# - name: Install pixi
# shell: bash
# run: |
# curl -fsSL https://pixi.sh/install.sh | bash
# echo "$HOME/.pixi/bin" >> $GITHUB_PATH
# export PATH="$HOME/.pixi/bin:$PATH"
# pixi --version
#
# - name: Restore ccache
# id: ccache-restore
# uses: https://git.kindred-systems.com/actions/cache.git/restore@v4
# with:
# path: C:\ccache-kindred-create
# key: ccache-release-windows-${{ github.sha }}
# restore-keys: |
# ccache-release-windows-
#
# - name: Build release package
# shell: bash
# working-directory: package/rattler-build
# run: |
# pixi install
# pixi run -e package create_bundle
#
# - name: Save ccache
# if: always()
# uses: https://git.kindred-systems.com/actions/cache.git/save@v4
# with:
# path: C:\ccache-kindred-create
# key: ccache-release-windows-${{ github.sha }}
#
# - name: List built artifacts
# shell: bash
# run: |
# echo "=== Windows release artifacts ==="
# ls -lah package/rattler-build/windows/*.7z* 2>/dev/null || true
# ls -lah package/rattler-build/windows/*.exe 2>/dev/null || true
# ls -lah package/rattler-build/windows/*-SHA256.txt 2>/dev/null || true
#
# - name: Upload Windows artifacts
# uses: https://git.kindred-systems.com/actions/upload-artifact.git@v3
# with:
# name: release-windows
# path: |
# package/rattler-build/windows/*.7z
# package/rattler-build/windows/*.exe
# package/rattler-build/windows/*-SHA256.txt
# if-no-files-found: error
# ---------------------------------------------------------------------------
# Create Gitea release from all platform artifacts
# ---------------------------------------------------------------------------
publish-release:
needs: [build-linux] # TODO: Add build-macos, build-windows when runners are available
runs-on: ubuntu-latest
env:
BUILD_TAG: ${{ github.ref_name || inputs.tag }}
steps:
- name: Trust Cloudflare origin CA
run: |
apt-get update -qq
apt-get install -y --no-install-recommends ca-certificates
update-ca-certificates
- name: Download all artifacts
uses: https://git.kindred-systems.com/actions/download-artifact.git@v3
with:
path: artifacts
- name: List all release artifacts
run: |
echo "=== All release artifacts ==="
find artifacts -type f | sort
- name: Collect release files
run: |
mkdir -p release
find artifacts -type f \( \
-name "*.AppImage" -o \
-name "*.deb" -o \
-name "*.dmg" -o \
-name "*.7z" -o \
-name "*.exe" -o \
-name "*SHA256*" -o \
-name "*.sha256" \
\) -exec cp {} release/ \;
echo "=== Release files ==="
ls -lah release/
- name: Create release
env:
GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
GITEA_URL: ${{ github.server_url }}
REPO: ${{ github.repository }}
run: |
TAG="${BUILD_TAG}"
# Build JSON payload entirely in Python to avoid shell/Python type mismatches
PAYLOAD=$(python3 -c "
import json, re
tag = '${TAG}'
prerelease = bool(re.search(r'(rc|beta|alpha)', tag))
body = '''## Kindred Create {tag}
### Downloads
| Platform | File |
|----------|------|
| Linux (AppImage) | \`KindredCreate-*-Linux-x86_64.AppImage\` |
| Linux (Debian/Ubuntu) | \`kindred-create_*.deb\` |
*macOS and Windows builds are not yet available.*
SHA256 checksums are provided alongside each artifact.'''.format(tag=tag)
print(json.dumps({
'tag_name': tag,
'name': f'Kindred Create {tag}',
'body': body,
'prerelease': prerelease,
}))
")
# Delete existing release for this tag (if any) so we can recreate
existing=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: token ${GITEA_TOKEN}" \
"${GITEA_URL}/api/v1/repos/${REPO}/releases/tags/${TAG}")
if [ "$existing" = "200" ]; then
release_id=$(curl -s \
-H "Authorization: token ${GITEA_TOKEN}" \
"${GITEA_URL}/api/v1/repos/${REPO}/releases/tags/${TAG}" | \
python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
curl -s -X DELETE \
-H "Authorization: token ${GITEA_TOKEN}" \
"${GITEA_URL}/api/v1/repos/${REPO}/releases/${release_id}"
echo "Deleted existing release ${release_id} for tag ${TAG}"
fi
# Create release
response=$(curl -s -w "\n%{http_code}" -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" \
"${GITEA_URL}/api/v1/repos/${REPO}/releases")
http_code=$(echo "$response" | tail -1)
body=$(echo "$response" | sed '$d')
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
echo "::error::Failed to create release (HTTP ${http_code}): ${body}"
exit 1
fi
release_id=$(echo "$body" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
echo "Created release ${release_id}"
# Upload assets
for file in release/*; do
filename=$(basename "$file")
echo "Uploading ${filename}..."
upload_resp=$(curl -s -w "\n%{http_code}" -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-F "attachment=@${file}" \
"${GITEA_URL}/api/v1/repos/${REPO}/releases/${release_id}/assets?name=${filename}")
upload_code=$(echo "$upload_resp" | tail -1)
if [ "$upload_code" -lt 200 ] || [ "$upload_code" -ge 300 ]; then
echo "::warning::Failed to upload ${filename} (HTTP ${upload_code})"
else
echo " done."
fi
done