feat/release-page #2
3 changed files with 166 additions and 32 deletions
|
|
@ -29,10 +29,12 @@
|
||||||
# on met à jour la release existante plutôt que d'en multiplier
|
# on met à jour la release existante plutôt que d'en multiplier
|
||||||
# pour un même tag. Le permalien /releases/tag/<tag> reste stable.
|
# pour un même tag. Le permalien /releases/tag/<tag> reste stable.
|
||||||
#
|
#
|
||||||
# Inter-step state: we persist values between steps via a plain
|
# Inter-step state: persisted as JSON in /tmp/release-state.json,
|
||||||
# env file under /tmp, sourced at the top of each step that needs
|
# read at the top of each step with `jq -r .<field>`. Using JSON
|
||||||
# it. This keeps the workflow self-contained and avoids any
|
# sidesteps shell parsing issues that come with sourcing a file
|
||||||
# runtime variable names we did not choose.
|
# that contains heredocs / markdown / colons / etc. — RELEASE_BODY
|
||||||
|
# in particular is markdown content straight from CHANGELOG.md and
|
||||||
|
# cannot be safely `source`d.
|
||||||
name: Forgejo Release postit-deb
|
name: Forgejo Release postit-deb
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
|
@ -63,7 +65,7 @@ jobs:
|
||||||
container:
|
container:
|
||||||
image: docker.io/pazof/yavsc-build-env:debian12-dotnet10-android36-v2
|
image: docker.io/pazof/yavsc-build-env:debian12-dotnet10-android36-v2
|
||||||
env:
|
env:
|
||||||
STATE_FILE: /tmp/release-state.env
|
STATE_FILE: /tmp/release-state.json
|
||||||
steps:
|
steps:
|
||||||
- name: Installer les pré-requis de build (debhelper + icônes)
|
- name: Installer les pré-requis de build (debhelper + icônes)
|
||||||
# L'image runner fournit déjà dotnet-sdk-10.0, git, jq,
|
# L'image runner fournit déjà dotnet-sdk-10.0, git, jq,
|
||||||
|
|
@ -71,10 +73,27 @@ jobs:
|
||||||
# Debian (debhelper, imagemagick pour les icônes .png
|
# Debian (debhelper, imagemagick pour les icônes .png
|
||||||
# via `convert`, librsvg2-bin pour le SVG).
|
# via `convert`, librsvg2-bin pour le SVG).
|
||||||
run: |
|
run: |
|
||||||
|
apt-get update
|
||||||
|
# Cross-build deps for arm64:
|
||||||
|
# 1. dpkg --add-architecture arm64 + apt-get update — make
|
||||||
|
# apt aware of arm64 packages.
|
||||||
|
# 2. Install the arm64 RUNTIME libs (libc6:arm64, etc.)
|
||||||
|
# so dpkg-shlibdeps can resolve the .so dependencies
|
||||||
|
# of the arm64 binaries via the on-host shlibs cache.
|
||||||
|
# The runtime libs (not -dev:arm64) is what carries
|
||||||
|
# the SONAME metadata that dpkg-shlibdeps matches.
|
||||||
|
# 3. crossbuild-essential-arm64 pulls gcc/binutils for
|
||||||
|
# arm64, plus dpkg-cross CONFIG_SITE files under
|
||||||
|
# /etc/dpkg-cross/. The cross-gcc is unused for our
|
||||||
|
# dotnet-only build but harmless.
|
||||||
|
dpkg --add-architecture arm64
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install -y --no-install-recommends \
|
apt-get install -y --no-install-recommends \
|
||||||
build-essential debhelper imagemagick librsvg2-bin \
|
build-essential debhelper imagemagick librsvg2-bin \
|
||||||
ca-certificates
|
ca-certificates crossbuild-essential-arm64 \
|
||||||
|
libc6:arm64 libstdc++6:arm64 \
|
||||||
|
libfontconfig1:arm64 libfreetype6:arm64 \
|
||||||
|
libgtk-3-0:arm64
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
: > "$STATE_FILE"
|
: > "$STATE_FILE"
|
||||||
|
|
||||||
|
|
@ -100,11 +119,14 @@ jobs:
|
||||||
git checkout "$TAG"
|
git checkout "$TAG"
|
||||||
|
|
||||||
echo "Checked out at $(git rev-parse HEAD) on tag $TAG"
|
echo "Checked out at $(git rev-parse HEAD) on tag $TAG"
|
||||||
echo "TAG=$TAG" >> "$STATE_FILE"
|
|
||||||
|
# Persist TAG in the state file. --arg ensures proper
|
||||||
|
# JSON escaping of any special chars.
|
||||||
|
jq -n --arg tag "$TAG" '{tag: $tag}' > "$STATE_FILE"
|
||||||
|
|
||||||
- name: Valider le tag et la section CHANGELOG
|
- name: Valider le tag et la section CHANGELOG
|
||||||
run: |
|
run: |
|
||||||
source "$STATE_FILE"
|
TAG=$(jq -r '.tag' "$STATE_FILE")
|
||||||
cd /src/_src
|
cd /src/_src
|
||||||
echo "Validating tag $TAG"
|
echo "Validating tag $TAG"
|
||||||
|
|
||||||
|
|
@ -176,37 +198,76 @@ jobs:
|
||||||
|
|
||||||
echo "Section CHANGELOG validée pour [$TAG] - $CHANNEL"
|
echo "Section CHANGELOG validée pour [$TAG] - $CHANNEL"
|
||||||
|
|
||||||
# Persist values for the next steps via our local state file.
|
# Persist validation results. Use --arg for strings (so
|
||||||
{
|
# jq handles escaping of backticks, asterisks, colons,
|
||||||
echo "RELEASE_BODY<<EOF"
|
# etc.) and --argjson for booleans.
|
||||||
echo "$RELEASE_BODY"
|
jq -n \
|
||||||
echo "EOF"
|
--arg tag "$TAG" \
|
||||||
echo "IS_PRERELEASE=$IS_PRERELEASE"
|
--arg body "$RELEASE_BODY" \
|
||||||
} >> "$STATE_FILE"
|
--argjson is_prerelease "$IS_PRERELEASE" \
|
||||||
|
'{tag: $tag, body: $body, is_prerelease: $is_prerelease}' \
|
||||||
|
> "$STATE_FILE"
|
||||||
|
|
||||||
- name: Build .deb amd64
|
- name: Build .deb amd64
|
||||||
env:
|
env:
|
||||||
POSTIT_RUNTIME: linux-x64
|
POSTIT_RUNTIME: linux-x64
|
||||||
run: |
|
run: |
|
||||||
source "$STATE_FILE"
|
set -e
|
||||||
|
TAG=$(jq -r '.tag' "$STATE_FILE")
|
||||||
cd /src/_src
|
cd /src/_src
|
||||||
echo "→ Building amd64 for POSTIT_GIT_TAG=$TAG"
|
echo "→ Building amd64 for POSTIT_GIT_TAG=$TAG"
|
||||||
make deb POSTIT_GIT_TAG="$TAG" POSTIT_RUNTIME=linux-x64
|
make deb POSTIT_GIT_TAG="$TAG" POSTIT_RUNTIME=linux-x64
|
||||||
|
# make deb mv's the produced .deb(s) into /src/ (the
|
||||||
|
# parent of /src/_src/, $POSTIT_OUT_DIR default).
|
||||||
|
# Check there, not in the build dir.
|
||||||
|
DEB_AMD64=$(ls /src/postit_*${TAG}-1_amd64.deb 2>/dev/null || true)
|
||||||
|
if [[ -z "$DEB_AMD64" ]]; then
|
||||||
|
echo "::error::Build .deb amd64 did not produce /src/postit_*${TAG}-1_amd64.deb"
|
||||||
|
ls -la /src/ /src/_src/ 2>/dev/null
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "✓ Built $DEB_AMD64"
|
||||||
|
|
||||||
- name: Build .deb arm64
|
- name: Build .deb arm64
|
||||||
env:
|
env:
|
||||||
POSTIT_RUNTIME: linux-arm64
|
POSTIT_RUNTIME: linux-arm64
|
||||||
run: |
|
run: |
|
||||||
source "$STATE_FILE"
|
set -e -x
|
||||||
|
TAG=$(jq -r '.tag' "$STATE_FILE")
|
||||||
cd /src/_src
|
cd /src/_src
|
||||||
echo "→ Building arm64 for POSTIT_GIT_TAG=$TAG"
|
echo "→ Building arm64 for POSTIT_GIT_TAG=$TAG"
|
||||||
# Cross-RID .NET depuis un hôte amd64 : standard, pas
|
# Cross-RID .NET depuis un hôte amd64 : standard, pas
|
||||||
# besoin de runner arm64 natif.
|
# besoin de runner arm64 natif.
|
||||||
make deb POSTIT_GIT_TAG="$TAG" POSTIT_RUNTIME=linux-arm64
|
# set -x traces every command so a silent failure inside
|
||||||
|
# 'make deb' (e.g. dpkg-buildpackage aborting after the
|
||||||
|
# 'mv ... || true' swallows the error) is visible.
|
||||||
|
# Debian-recommended cross-build environment for dpkg-buildpackage:
|
||||||
|
# - CONFIG_SITE points autoconf at the cross-config for arm64
|
||||||
|
# (set up by crossbuild-essential-arm64)
|
||||||
|
# - DEB_HOST_ARCH=arm64 is the target architecture
|
||||||
|
# - DEB_BUILD_ARCH=amd64 stays the build host
|
||||||
|
# - DEB_BUILD_OPTIONS=nocheck skips tests in the cross context
|
||||||
|
CONFIG_SITE=/etc/dpkg-cross/cross-config.arm64 \
|
||||||
|
DEB_HOST_ARCH=arm64 DEB_BUILD_ARCH=amd64 \
|
||||||
|
DEB_BUILD_OPTIONS=nocheck \
|
||||||
|
make deb POSTIT_GIT_TAG="$TAG" POSTIT_RUNTIME=linux-arm64 || {
|
||||||
|
echo "::error::make deb for arm64 exited non-zero — see output above"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
# Same check as amd64: verify the .deb landed in /src/.
|
||||||
|
DEB_ARM64=$(ls /src/postit_*${TAG}-1_arm64.deb 2>/dev/null || true)
|
||||||
|
if [[ -z "$DEB_ARM64" ]]; then
|
||||||
|
echo "::error::Build .deb arm64 did not produce /src/postit_*${TAG}-1_arm64.deb"
|
||||||
|
echo "Inspect the dpkg-buildpackage output above for the root cause."
|
||||||
|
ls -la /src/ /src/_src/ 2>/dev/null
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "✓ Built $DEB_ARM64"
|
||||||
|
set +x
|
||||||
|
|
||||||
- name: Localiser les .deb produits
|
- name: Localiser les .deb produits
|
||||||
run: |
|
run: |
|
||||||
source "$STATE_FILE"
|
TAG=$(jq -r '.tag' "$STATE_FILE")
|
||||||
cd /src
|
cd /src
|
||||||
DEB_AMD64=$(find . -maxdepth 3 -name "postit_*${TAG}-1_amd64.deb" \
|
DEB_AMD64=$(find . -maxdepth 3 -name "postit_*${TAG}-1_amd64.deb" \
|
||||||
-not -path "./_src/debian/*" -printf '%p\n' | head -1)
|
-not -path "./_src/debian/*" -printf '%p\n' | head -1)
|
||||||
|
|
@ -217,8 +278,10 @@ jobs:
|
||||||
ls -la /src/ 2>/dev/null || true
|
ls -la /src/ 2>/dev/null || true
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo "DEB_AMD64=/src/$DEB_AMD64" >> "$STATE_FILE"
|
# Merge .deb paths into state file.
|
||||||
echo "DEB_ARM64=/src/$DEB_ARM64" >> "$STATE_FILE"
|
jq --arg amd64 "/src/$DEB_AMD64" --arg arm64 "/src/$DEB_ARM64" \
|
||||||
|
'. + {deb_amd64: $amd64, deb_arm64: $arm64}' \
|
||||||
|
"$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
|
||||||
echo "✓ Found both .deb files"
|
echo "✓ Found both .deb files"
|
||||||
|
|
||||||
- name: Publier la release Forgejo via l'API REST
|
- name: Publier la release Forgejo via l'API REST
|
||||||
|
|
@ -227,7 +290,11 @@ jobs:
|
||||||
FORGEJO_API_URL: ${{ forgejo.api_url }}
|
FORGEJO_API_URL: ${{ forgejo.api_url }}
|
||||||
FORGEJO_REPOSITORY: ${{ forgejo.repository }}
|
FORGEJO_REPOSITORY: ${{ forgejo.repository }}
|
||||||
run: |
|
run: |
|
||||||
source "$STATE_FILE"
|
TAG=$(jq -r '.tag' "$STATE_FILE")
|
||||||
|
RELEASE_BODY=$(jq -r '.body' "$STATE_FILE")
|
||||||
|
IS_PRERELEASE=$(jq -r '.is_prerelease' "$STATE_FILE")
|
||||||
|
DEB_AMD64=$(jq -r '.deb_amd64' "$STATE_FILE")
|
||||||
|
DEB_ARM64=$(jq -r '.deb_arm64' "$STATE_FILE")
|
||||||
if [[ -z "$TAG" ]]; then
|
if [[ -z "$TAG" ]]; then
|
||||||
echo "::error::No tag resolved for the API call."
|
echo "::error::No tag resolved for the API call."
|
||||||
exit 1
|
exit 1
|
||||||
|
|
|
||||||
59
Makefile
59
Makefile
|
|
@ -38,14 +38,57 @@ deb:
|
||||||
# step the .deb always comes out as the version hardcoded in
|
# step the .deb always comes out as the version hardcoded in
|
||||||
# debian/changelog.in, regardless of POSTIT_GIT_TAG.
|
# debian/changelog.in, regardless of POSTIT_GIT_TAG.
|
||||||
sed 's/@VERSION@/$(POSTIT_GIT_TAG)/g' debian/changelog.in > debian/changelog
|
sed 's/@VERSION@/$(POSTIT_GIT_TAG)/g' debian/changelog.in > debian/changelog
|
||||||
POSTIT_GIT_URL=$(POSTIT_GIT_URL) POSTIT_GIT_TAG=$(POSTIT_GIT_TAG) POSTIT_RUNTIME=$(POSTIT_RUNTIME) \
|
# Remove only this build's residual .deb (avoid glob-matching
|
||||||
dpkg-buildpackage -us -uc -b
|
# .debs from sibling builds — the workflow invokes us once per
|
||||||
# Move the produced .deb(s) into $POSTIT_OUT_DIR. The version
|
# architecture, and a wide glob would erase the .deb the
|
||||||
# segment we match against is the rendered changelog version
|
# previous build just produced). The pattern is the same one
|
||||||
# (e.g. 1.0.1-rc01-1), not the bare tag.
|
# dpkg-deb will reuse if we don't clean up first: postit_<ver>-
|
||||||
mv ../postit_*$(POSTIT_GIT_TAG)-1*.deb $(POSTIT_OUT_DIR)/ 2>/dev/null || \
|
# 1_<host_arch>.deb.
|
||||||
mv ../postit_*.deb $(POSTIT_OUT_DIR)/ || true
|
rm -f ../postit_$(POSTIT_GIT_TAG)-1_$${DPKG_HOST}.deb ../postit_$(POSTIT_GIT_TAG)-1_$${DPKG_HOST}.buildinfo ../postit_$(POSTIT_GIT_TAG)-1_$${DPKG_HOST}.changes
|
||||||
@echo " ✓ artifacts moved to $(POSTIT_OUT_DIR)"
|
# Use dpkg-architecture to set the target arch correctly for
|
||||||
|
# cross-builds. For POSTIT_RUNTIME=linux-arm64, this exports
|
||||||
|
# DEB_HOST_ARCH=arm64 (and friends) so dpkg-buildpackage names
|
||||||
|
# the .deb postit_*_arm64.deb instead of postit_*_amd64.deb.
|
||||||
|
# For linux-x64, it sets the host arch to amd64 explicitly
|
||||||
|
# (which matches the runner — no-op, but keeps the call site
|
||||||
|
# uniform). Other RIDs are rejected.
|
||||||
|
# Compute DPKG_ARCH_ARGS, eval dpkg-architecture, then call
|
||||||
|
# dpkg-buildpackage — all in ONE shell invocation so the
|
||||||
|
# vars set by dpkg-architecture are visible to dpkg-buildpackage.
|
||||||
|
# make runs each recipe line in its own shell, so we use
|
||||||
|
# backslash continuation to glue everything together.
|
||||||
|
# Cross-build configuration for dpkg-buildpackage.
|
||||||
|
#
|
||||||
|
# We set DEB_HOST_ARCH=arm64 and pass -aarm64 directly to
|
||||||
|
# dpkg-buildpackage, bypassing dpkg-architecture.
|
||||||
|
#
|
||||||
|
# Why bypass dpkg-architecture? It's deliberately conservative:
|
||||||
|
# it refuses to set up the cross-build env when the C compiler
|
||||||
|
# (CC) doesn't match the target arch. Our package has no C
|
||||||
|
# code — dh_auto_build only runs \`dotnet publish --runtime
|
||||||
|
# linux-arm64\` (a managed-only cross-publish), and we
|
||||||
|
# disable dh_strip (the only rule that needed an arch-specific
|
||||||
|
# objcopy). dh_shlibdeps uses the multi-arch arm64 libs we
|
||||||
|
# apt-get install in the runner. So no arm64 toolchain is
|
||||||
|
# actually needed; the dpkg-architecture CC check would
|
||||||
|
# unnecessarily block us.
|
||||||
|
#
|
||||||
|
# We do explicitly set the four DEB_* vars dpkg-architecture
|
||||||
|
# would normally export (host arch, build arch, host GNU
|
||||||
|
# type, build GNU type) so debhelper rules see a consistent
|
||||||
|
# cross-build environment.
|
||||||
|
DPKG_HOST=$$(case "$(POSTIT_RUNTIME)" in linux-arm64) echo arm64 ;; linux-x64) echo amd64 ;; *) echo "unsupported POSTIT_RUNTIME=$(POSTIT_RUNTIME)" >&2; exit 1 ;; esac) && DEB_HOST_ARCH=$$DPKG_HOST DEB_BUILD_ARCH=amd64 DEB_HOST_GNU_TYPE=aarch64-linux-gnu DEB_BUILD_GNU_TYPE=x86_64-linux-gnu POSTIT_GIT_URL=$(POSTIT_GIT_URL) POSTIT_GIT_TAG=$(POSTIT_GIT_TAG) POSTIT_RUNTIME=$(POSTIT_RUNTIME) dpkg-buildpackage -us -uc -b -d -Pcross -a$$DPKG_HOST
|
||||||
|
# dpkg-buildpackage already writes the produced .deb to
|
||||||
|
# /src/_src/../ = $POSTIT_OUT_DIR (its default — there's no
|
||||||
|
# flag to change it). So no 'mv' is needed. The old 'mv'
|
||||||
|
# caused a 'same file' error when the destination was the
|
||||||
|
# same as the source (which it always is). Just verify the
|
||||||
|
# .deb was actually produced.
|
||||||
|
if ! ls ../postit_*$(POSTIT_GIT_TAG)-1*.deb >/dev/null 2>&1; then \
|
||||||
|
echo " ERROR: dpkg-buildpackage produced no .deb for POSTIT_GIT_TAG=$(POSTIT_GIT_TAG)" >&2; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
@echo " ✓ artifacts in $(POSTIT_OUT_DIR)"
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf build debian/postit
|
rm -rf build debian/postit
|
||||||
|
|
|
||||||
28
debian/rules
vendored
28
debian/rules
vendored
|
|
@ -126,10 +126,34 @@ override_dh_auto_test:
|
||||||
# client). Build smoke is sufficient for the package.
|
# client). Build smoke is sufficient for the package.
|
||||||
|
|
||||||
override_dh_shlibdeps:
|
override_dh_shlibdeps:
|
||||||
dh_shlibdeps
|
# In a cross-build (DEB_HOST_ARCH != DEB_BUILD_ARCH), the
|
||||||
|
# system's arch-specific lib dir is at
|
||||||
|
# /usr/lib/<DEB_HOST_MULTIARCH>/. crossbuild-essential-arm64
|
||||||
|
# has transitively installed libc6:arm64 et al. there (it's
|
||||||
|
# a Depends chain: crossbuild-essential-arm64 → gcc-aarch64-
|
||||||
|
# linux-gnu → libc6-dev:arm64 → libc6:arm64). Pass that
|
||||||
|
# path via -l so dpkg-shlibdeps can resolve the arm64
|
||||||
|
# binaries' NEEDED entries (libc.so.6, libstdc++.so.6,
|
||||||
|
# libfontconfig, etc.) against the on-host shlibs cache.
|
||||||
|
if [ -n "$(DEB_HOST_ARCH)" ] && [ "$(DEB_HOST_ARCH)" != "$(DEB_BUILD_ARCH)" ]; then \
|
||||||
|
HOST_MULTIARCH=$$(dpkg-architecture -a$(DEB_HOST_ARCH) -q DEB_HOST_MULTIARCH 2>/dev/null) || \
|
||||||
|
HOST_MULTIARCH=aarch64-linux-gnu; \
|
||||||
|
HOST_LIB_DIR=/usr/lib/$${HOST_MULTIARCH}; \
|
||||||
|
if [ -d "$$HOST_LIB_DIR" ]; then \
|
||||||
|
echo " --> dh_shlibdeps: cross-arch $$HOST_LIB_DIR (DEB_HOST_ARCH=$(DEB_HOST_ARCH))"; \
|
||||||
|
dh_shlibdeps -- -l"$$HOST_LIB_DIR"; \
|
||||||
|
else \
|
||||||
|
echo " --> dh_shlibdeps: WARN cross-arch dir $$HOST_LIB_DIR missing"; \
|
||||||
|
dh_shlibdeps; \
|
||||||
|
fi \
|
||||||
|
else \
|
||||||
|
dh_shlibdeps; \
|
||||||
|
fi
|
||||||
|
|
||||||
override_dh_strip:
|
override_dh_strip:
|
||||||
dh_strip --exclude=.pdb
|
# dh_strip disabled entirely. See MEMORY.md / AGENTS.md for the
|
||||||
|
# rationale (cross-compiled native .so via NuGet from Avalonia
|
||||||
|
# deps cannot be parsed by amd64 objcopy/strip).
|
||||||
|
|
||||||
|
|
||||||
define stage_postit
|
define stage_postit
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue