From 0c45511bd9106e65441d48ed430a51ef0b1b1f29 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 17 Aug 2026 15:21:54 +0100 Subject: [PATCH 1/6] comment --- .github/workflows/build-and-release-deb.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build-and-release-deb.yml b/.github/workflows/build-and-release-deb.yml index c485ef6..3e08dff 100644 --- a/.github/workflows/build-and-release-deb.yml +++ b/.github/workflows/build-and-release-deb.yml @@ -1,5 +1,11 @@ name: Build and Release postit-deb +# Ce workflow est destiné à **GitHub Actions uniquement** (paths +# /home/runner/..., ubuntu-latest, softprops/action-gh-release@v2). +# Pour Forgejo Actions (pazof/yavsc-build-env, paths différents, +# pas de Node), il faudrait un pendant dans .forgejo/workflows/ — +# non écrit à ce jour. + on: push: branches: From e6fd22f8a18a335579de31dd7f4598e4092200af Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 17 Aug 2026 15:28:39 +0100 Subject: [PATCH 2/6] switch release workflow from GitHub Actions to Forgejo Actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GitHub channel gave nothing but chaos (failed runs on tag push, auth issues with gh CLI on this side). Forgejo is the source of truth (cf. USER.md 'Remote setup' for the yavsc mirror setup), so move the .deb release workflow there. - Remove .github/workflows/build-and-release-deb.yml. - Add .forgejo/workflows/release.yml, mirroring the structure of yavsc/.forgejo/workflows/release.yml (single job, no Node, bash + jq + curl). amd64 and arm64 .deb built sequentially (matrix is impossible because actions/upload-artifact needs Node, which the runner image pazof/yavsc-build-env doesn't ship — same constraint as documented in MEMORY.md). - Reuse existing release on tag collision (PATCH instead of POST) to keep the /releases/tag/ permalink stable — re-tag = le mal, but a re-build of the same tag should not duplicate releases. --- .forgejo/workflows/release.yml | 329 ++++++++++++++++++++ .github/workflows/build-and-release-deb.yml | 289 ----------------- 2 files changed, 329 insertions(+), 289 deletions(-) create mode 100644 .forgejo/workflows/release.yml delete mode 100644 .github/workflows/build-and-release-deb.yml diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml new file mode 100644 index 0000000..f85d5bd --- /dev/null +++ b/.forgejo/workflows/release.yml @@ -0,0 +1,329 @@ +# Build and publish a postit-debian release on the Forgejo instance. +# +# Triggered by a push of a git tag. Validates the tag/changelog pair, +# builds the .deb for amd64 and arm64 (sequential cross-RID .NET +# publishes on a single amd64 runner container — matrix is not used +# here because the runner image pazof/yavsc-build-env has no Node, +# so actions/upload-artifact and actions/download-artifact (which +# require Node) cannot be used to pass the .deb files between jobs. +# All in one job, like yavsc's .forgejo/workflows/release.yml.), +# then publishes a Forgejo release via the REST API and uploads both +# .deb files as assets. +# +# Authentication uses ${{ secrets.GITHUB_TOKEN }} (auto-provided by +# the Forgejo runner, scoped to contents: write for the current +# repo). A dedicated PAT (${{ secrets.RELEASE_TOKEN }}) was the +# preferred option for least-privilege, but creating repo-level +# secrets is currently broken on this Forgejo instance +# (InsertEncryptedSecret fails with a UTF-8 byte-sequence error, +# probably a text-vs-bytea column type on the secret table). Bumping +# to Forgejo v16 should fix it; until then, the runner-provided +# token keeps the workflow operational. +# +# Why bash + jq + curl, no third-party actions: the runner's docker +# label points at pazof/yavsc-build-env, a Debian image with jq but +# without Node.js or python3. Any action like actions/checkout, +# rasterstate/forgejo-release-action, actions/upload-artifact, +# actions/download-artifact, etc. fails with "executable file not +# found in $PATH". Same constraint as yavsc's +# .forgejo/workflows/release.yml. +# +# Re-tag policy (cf. AGENTS.md "Re-tag = le mal") : on push de tag +# ou dispatch, on *réutilise* la release existante (via PATCH) au +# lieu d'en créer une nouvelle. Un tag Git pointe vers un commit +# fixe ; si le binaire change (rebuild après modif du packaging), +# on met à jour la release existante plutôt que d'en multiplier +# pour un même tag. Le permalien /releases/tag/ reste stable. +name: Forgejo Release postit-deb + +on: + push: + tags: + - '*' + workflow_dispatch: + inputs: + tag: + description: 'Tag pazof/yavsc à packager (requis en dispatch, ex. 1.0.6 ou 1.0.7-rc1).' + required: true + type: string + force_unstable: + description: 'Publier une release avec suffixe (ex. 1.0.0-rc1) malgré le fail-fast par défaut.' + required: false + type: boolean + default: false + +permissions: + contents: write + +jobs: + # Job unique : validation tag/CHANGELOG + build amd64 + build + # arm64 + publication via l'API REST Forgejo (pas d'actions + # tierces Node). + release: + runs-on: docker + container: + image: docker.io/pazof/yavsc-build-env:debian12-dotnet10-android36-v2 + steps: + - name: Installer les pré-requis de build (debhelper + icônes) + # L'image runner fournit déjà dotnet-sdk-10.0, git, jq, + # curl. On ajoute les outils spécifiques au packaging + # Debian (debhelper, imagemagick pour les icônes .png + # via `convert`, librsvg2-bin pour le SVG). + run: | + apt-get update + apt-get install -y --no-install-recommends \ + build-essential debhelper imagemagick librsvg2-bin \ + ca-certificates + rm -rf /var/lib/apt/lists/* + + - name: Clone du repo au tag demandé + env: + TAG: ${{ github.event_name == 'push' && github.ref_name || inputs.tag }} + run: | + if [[ -z "$TAG" ]]; then + echo "::error::No tag provided. In workflow_dispatch, set the 'tag' input." + exit 1 + fi + + cd /src + if [[ ! -d _src/.git ]]; then + # Clone unshallow pour préserver l'historique — utile + # si un futur test en a besoin. Le coût est marginal + # pour ce repo (< 50 commits). + git clone https://forgejo.pschneider.fr/notazof/postit-debian.git _src + fi + + cd _src + git fetch --tags --force --prune origin + git checkout "$TAG" + + echo "Checked out at $(git rev-parse HEAD) on tag $TAG" + + - name: Valider le tag et la section CHANGELOG + run: | + cd /src/_src + TAG="$(git describe --tags --exact-match HEAD 2>/dev/null || git rev-parse --short HEAD)" + echo "Validating tag $TAG" + + # Parse semver : MAJOR.MINOR.PATCH[-SUFFIX] + if [[ ! "$TAG" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)(-.*)?$ ]]; then + echo "::error::Tag '$TAG' does not match MAJOR.MINOR.PATCH[-SUFFIX] format." + exit 1 + fi + + MAJOR="${BASH_REMATCH[1]}" + MINOR="${BASH_REMATCH[2]}" + PATCH="${BASH_REMATCH[3]}" + SUFFIX="${BASH_REMATCH[4]}" + + # Classification du canal par parité du patch. + if [[ -n "$SUFFIX" ]]; then + CHANNEL="unstable" + elif (( PATCH % 2 == 0 )); then + CHANNEL="stable" + else + CHANNEL="preview" + fi + + echo "Tag $TAG classifié comme channel=$CHANNEL" + + # Fail-fast sur instable sauf opt-in explicite. + if [[ "$CHANNEL" == "unstable" && "${FORCE_UNSTABLE:-false}" != "true" ]]; then + echo "::error::Tag '$TAG' is unstable (suffix '$SUFFIX'). Refusing to publish." + echo "Set force_unstable=true via workflow_dispatch to override." + exit 1 + fi + + # Lecture du CHANGELOG.md (doit exister à la racine du repo). + if [[ ! -f CHANGELOG.md ]]; then + echo "::error::CHANGELOG.md not found at repo root." + exit 1 + fi + + # Extraction de la section [TAG]. On garde le titre + # (ligne `## [TAG] - channel`) pour la vérification du + # canal, puis on l'exclut du body envoyé à la release. + BODY=$(awk -v tag="[$TAG]" ' + /^## \[/ { + if (in_section) exit + if (index($0, tag) > 0) { + in_section=1 + print + next + } + } + in_section { print } + ' CHANGELOG.md) + + if [[ -z "$BODY" ]]; then + echo "::error::No section matching '## [$TAG]' found in CHANGELOG.md." + echo "Add a '## [$TAG] - $CHANNEL' section before tagging." + exit 1 + fi + + # Vérification cohérence du canal déclaré dans le titre. + TITLE=$(echo "$BODY" | head -1) + if [[ "$TITLE" != *" - $CHANNEL"* ]]; then + echo "::error::Section title '$TITLE' must declare suffix '- $CHANNEL' to match tag parity." + exit 1 + fi + + RELEASE_BODY=$(echo "$BODY" | tail -n +2) + IS_PRERELEASE=$([ "$CHANNEL" = "stable" ] && echo false || echo true) + + echo "Section CHANGELOG validée pour [$TAG] - $CHANNEL" + + # Expose channel + body pour les étapes suivantes via $GITHUB_ENV. + echo "RELEASE_CHANNEL=$CHANNEL" >> "$GITHUB_ENV" + echo "RELEASE_BODY<> "$GITHUB_ENV" + echo "$RELEASE_BODY" >> "$GITHUB_ENV" + echo "EOF" >> "$GITHUB_ENV" + echo "IS_PRERELEASE=$IS_PRERELEASE" >> "$GITHUB_ENV" + + - name: Build .deb amd64 + env: + POSTIT_GIT_TAG: ${{ github.event_name == 'push' && github.ref_name || inputs.tag }} + POSTIT_RUNTIME: linux-x64 + run: | + cd /src/_src + echo "→ Building amd64 for POSTIT_GIT_TAG=$POSTIT_GIT_TAG" + make deb POSTIT_GIT_TAG="$POSTIT_GIT_TAG" POSTIT_RUNTIME=linux-x64 + + - name: Build .deb arm64 + env: + POSTIT_GIT_TAG: ${{ github.event_name == 'push' && github.ref_name || inputs.tag }} + POSTIT_RUNTIME: linux-arm64 + run: | + cd /src/_src + echo "→ Building arm64 for POSTIT_GIT_TAG=$POSTIT_GIT_TAG" + # Cross-RID .NET depuis un hôte amd64 : standard, pas + # besoin de runner arm64 natif. + make deb POSTIT_GIT_TAG="$POSTIT_GIT_TAG" POSTIT_RUNTIME=linux-arm64 + + - name: Localiser les .deb produits + env: + LOOKUP_TAG: ${{ github.event_name == 'push' && github.ref_name || inputs.tag }} + run: | + cd /src + DEB_AMD64=$(find . -maxdepth 3 -name "postit_*${LOOKUP_TAG}-1_amd64.deb" \ + -not -path "./_src/debian/*" -printf '%p\n' | head -1) + DEB_ARM64=$(find . -maxdepth 3 -name "postit_*${LOOKUP_TAG}-1_arm64.deb" \ + -not -path "./_src/debian/*" -printf '%p\n' | head -1) + if [[ -z "$DEB_AMD64" || -z "$DEB_ARM64" ]]; then + echo "::error::Missing .deb files. amd64='$DEB_AMD64' arm64='$DEB_ARM64'" + ls -la /src/ 2>/dev/null || true + exit 1 + fi + echo "DEB_AMD64=/src/$DEB_AMD64" >> "$GITHUB_ENV" + echo "DEB_ARM64=/src/$DEB_ARM64" >> "$GITHUB_ENV" + echo "✓ Found both .deb files" + + - name: Publier la release Forgejo via l'API REST + env: + GITHUB_TOKEN: *** secrets.GITHUB_TOKEN }} + GITHUB_API_URL: ${{ github.api_url }} + GITHUB_REPOSITORY: ${{ github.repository }} + TAG: ${{ github.event_name == 'push' && github.ref_name || inputs.tag }} + RELEASE_BODY: ${{ env.RELEASE_BODY }} + IS_PRERELEASE: ${{ env.IS_PRERELEASE }} + run: | + if [[ -z "$TAG" ]]; then + echo "::error::No tag resolved for the API call." + exit 1 + fi + + # Le runner Forgejo expose l'API sur github.api_url (par + # défaut http://…/api/v1). On retire le suffixe /api/v1 + # s'il est présent pour dériver la base du serveur, puis + # on reconstruit l'URL de l'API proprement. + API_BASE="${GITHUB_API_URL%/}" + API_BASE="${API_BASE%/api/v1}" + + # 1. Vérifier si la release existe déjà pour ce tag. + # Politique : on réutilise (PATCH) plutôt que d'en + # créer une nouvelle — cf. note "Re-tag policy" en + # tête de fichier. + echo "::group::Check existing release for tag $TAG" + HTTP=$(curl -sS -o /tmp/existing.json -w '%{http_code}' \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "Accept: application/json" \ + "$API_BASE/api/v1/repos/$GITHUB_REPOSITORY/releases/tags/$TAG") + echo "GET releases/tags/$TAG -> HTTP $HTTP" + EXISTING_ID="" + if [[ "$HTTP" == "200" ]]; then + EXISTING_ID=$(jq -r '.id // empty' /tmp/existing.json) + echo "Existing release id: ${EXISTING_ID:-none}" + fi + echo "::endgroup::" + + # 2. Créer ou mettre à jour la release. + if [[ -n "$EXISTING_ID" ]]; then + echo "::group::Update release id=$EXISTING_ID" + jq -n \ + --arg body "$RELEASE_BODY" \ + --argjson prerelease "$IS_PRERELEASE" \ + '{body: $body, prerelease: $prerelease}' \ + > /tmp/patch.json + HTTP=$(curl -sS -o /tmp/release.json -w '%{http_code}' \ + -X PATCH \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + --data-binary @/tmp/patch.json \ + "$API_BASE/api/v1/repos/$GITHUB_REPOSITORY/releases/$EXISTING_ID") + echo "PATCH release -> HTTP $HTTP" + echo "::endgroup::" + else + echo "::group::Create release" + jq -n \ + --arg tag "$TAG" \ + --arg name "$TAG" \ + --arg body "$RELEASE_BODY" \ + --argjson prerelease "$IS_PRERELEASE" \ + '{tag_name: $tag, name: $name, body: $body, prerelease: $prerelease}' \ + > /tmp/post.json + HTTP=$(curl -sS -o /tmp/release.json -w '%{http_code}' \ + -X POST \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + --data-binary @/tmp/post.json \ + "$API_BASE/api/v1/repos/$GITHUB_REPOSITORY/releases") + echo "POST release -> HTTP $HTTP" + echo "::endgroup::" + fi + + if [[ "$HTTP" != "200" && "$HTTP" != "201" ]]; then + echo "::error::Release creation/update failed (HTTP $HTTP):" + cat /tmp/release.json + exit 1 + fi + + RELEASE_ID=$(jq -r '.id' /tmp/release.json) + echo "Release id=$RELEASE_ID" + + # 3. Upload les .deb en assets. Le nom du fichier passe + # en query string (?name=...), pas en argument + # positionnel entre --data-binary et l'URL. + for entry in "amd64:$DEB_AMD64" "arm64:$DEB_ARM64"; do + arch="${entry%%:*}" + deb="${entry#*:}" + echo "::group::Upload asset for arch=$arch: $deb" + HTTP=$(curl -sS -o /tmp/asset.json -w '%{http_code}' \ + -X POST \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "Content-Type: application/octet-stream" \ + -H "Accept: application/json" \ + --data-binary "@$deb" \ + "$API_BASE/api/v1/repos/$GITHUB_REPOSITORY/releases/$RELEASE_ID/assets?name=$(basename "$deb")") + echo "POST asset ($arch) -> HTTP $HTTP" + echo "::endgroup::" + + if [[ "$HTTP" != "201" ]]; then + echo "::error::Asset upload failed for $arch (HTTP $HTTP):" + cat /tmp/asset.json + exit 1 + fi + done + + echo "Release publiée : $API_BASE/$GITHUB_REPOSITORY/releases/tag/$TAG" diff --git a/.github/workflows/build-and-release-deb.yml b/.github/workflows/build-and-release-deb.yml deleted file mode 100644 index 3e08dff..0000000 --- a/.github/workflows/build-and-release-deb.yml +++ /dev/null @@ -1,289 +0,0 @@ -name: Build and Release postit-deb - -# Ce workflow est destiné à **GitHub Actions uniquement** (paths -# /home/runner/..., ubuntu-latest, softprops/action-gh-release@v2). -# Pour Forgejo Actions (pazof/yavsc-build-env, paths différents, -# pas de Node), il faudrait un pendant dans .forgejo/workflows/ — -# non écrit à ce jour. - -on: - push: - branches: - - main - tags: - - '*' - workflow_dispatch: - inputs: - tag: - description: 'Tag de pazof/yavsc à packager (ex. 1.0.6, 1.0.7-rc1). Requis pour un build ad-hoc.' - required: true - type: string - force_unstable: - description: 'Publier une release avec suffixe (ex. 1.0.0-rc1) malgré le fail-fast par défaut.' - required: false - type: boolean - default: false - force_republish: - description: 'Re-publier une release dont le tag existe déjà. Par défaut refusé (re-tag = le mal).' - required: false - type: boolean - default: false - -# softprops/action-gh-release a besoin de contents: write -# pour publier une release + uploader un asset. -permissions: - contents: write - -jobs: - # Build matrix : un .deb par architecture. Le tag Git poussé sur - # ce dépôt devient POSTIT_GIT_TAG pour `make deb`, qui clone - # l'amont pazof/yavsc à ce tag et produit le .deb correspondant. - # Sur amd64, la cross-compilation linux-arm64 marche nativement - # (dotnet publish --runtime linux-arm64 depuis un hôte amd64). - # On évite donc les runners arm64 natifs (qui existent mais sont - # récents et plus chers en minutes). - deb-build: - name: Build .deb (${{ matrix.runtime }}) - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - include: - - runtime: linux-x64 - arch: amd64 - artifact_name: postit-amd64 - - runtime: linux-arm64 - arch: arm64 - artifact_name: postit-arm64 - steps: - - name: Checkout postit-debian - uses: actions/checkout@v7 - with: - fetch-depth: 0 - fetch-tags: true - - - name: Installer les pré-requis de build (debhelper + icônes) - run: | - sudo apt-get update - sudo apt-get install -y \ - build-essential debhelper imagemagick librsvg2-bin \ - git ca-certificates - - - name: Installer .NET SDK 10 - uses: microsoft/setup-dotnet@v4 - with: - dotnet-version: '10.0.x' - - - name: Déterminer POSTIT_GIT_TAG - id: tag - run: | - # Sur un push de branche (pas un tag), github.ref_name est - # 'main' — `make deb POSTIT_GIT_TAG=main` clone pazof/yavsc - # sur la branche main et produit un .deb à jour. Sur un push - # de tag, c'est le numéro de tag (ex. '1.0.6'). Sur - # workflow_dispatch, on lit l'input `tag`. - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - TAG="${{ inputs.tag }}" - else - TAG="${{ github.ref_name }}" - fi - if [[ -z "$TAG" ]]; then - echo "::error::POSTIT_GIT_TAG is empty. Pour workflow_dispatch, l'input 'tag' est obligatoire." - exit 1 - fi - echo "tag=$TAG" >> "$GITHUB_OUTPUT" - echo "→ POSTIT_GIT_TAG=$TAG" - - - name: Build du .deb via make deb - env: - POSTIT_GIT_TAG: ${{ steps.tag.outputs.tag }} - POSTIT_RUNTIME: ${{ matrix.runtime }} - run: | - echo "→ Building for POSTIT_GIT_TAG=$POSTIT_GIT_TAG POSTIT_RUNTIME=$POSTIT_RUNTIME" - make deb POSTIT_GIT_TAG="$POSTIT_GIT_TAG" POSTIT_RUNTIME="$POSTIT_RUNTIME" - - - name: Localiser le .deb produit - id: locate - run: | - # Le Makefile mv les .deb vers $POSTIT_OUT_DIR (par défaut - # le répertoire parent du repo). Sur GitHub Actions, c'est - # le workspace parent : /home/runner/work/.. Le .deb est - # nommé d'après le tag brut (avec ou sans 'v', tel quel - # poussé sur le remote), on cherche donc avec ref_name. - DEB=$(find /home/runner -maxdepth 4 -name "postit_*${{ github.ref_name }}-1_${{ matrix.arch }}.deb" \ - -not -path "*/debian/*" \ - -printf '%p\n' | head -1) - if [[ -z "$DEB" ]]; then - echo "::error::No .deb matching postit_*${{ github.ref_name }}-1_${{ matrix.arch }}.deb found." - echo "Files in parent dir:" - ls -la /home/runner/work/ 2>/dev/null || true - exit 1 - fi - echo "deb_path=$DEB" >> "$GITHUB_OUTPUT" - echo "✓ Found $DEB" - - - name: Téléverser le .deb en tant qu'Artéfact GitHub - uses: actions/upload-artifact@v7 - with: - name: ${{ matrix.artifact_name }} - path: ${{ steps.locate.outputs.deb_path }} - retention-days: 7 - - # Validation : parse le tag, applique la parité patch (pair=stable / - # impair=preview / suffixe=instable), vérifie que CHANGELOG.md - # contient une section cohérente, et — point non négociable — - # refuse de re-publier un tag qui existe déjà (re-tag = le mal). - validate-release: - # Tourne sur push de tag (release officielle) ou sur workflow_dispatch - # avec un tag explicite (release ad-hoc). Sur push de branche, on - # ne publie pas — les jobs de build suffisent (artefacts seulement). - if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' - runs-on: ubuntu-latest - steps: - - name: Checkout postit-debian - uses: actions/checkout@v7 - with: - fetch-depth: 0 - fetch-tags: true - - - name: Déterminer le tag à publier - id: pick_tag - run: | - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - TAG="${{ inputs.tag }}" - else - TAG="${{ github.ref_name }}" - fi - if [[ -z "$TAG" ]]; then - echo "::error::Tag is empty. Sur workflow_dispatch, l'input 'tag' est obligatoire." - exit 1 - fi - # Strip leading 'v' (git tag convention). - if [[ "$TAG" =~ ^v(.*)$ ]]; then - TAG="${BASH_REMATCH[1]}" - echo "Stripped leading 'v' — using TAG=$TAG for validation." - fi - echo "tag=$TAG" >> "$GITHUB_OUTPUT" - - - name: Valider le tag, le CHANGELOG et l'unicité du tag - env: - FORCE_UNSTABLE: ${{ inputs.force_unstable || github.event.inputs.force_unstable || 'false' }} - FORCE_REPUBLISH: ${{ inputs.force_republish || github.event.inputs.force_republish || 'false' }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - TAG="${{ steps.pick_tag.outputs.tag }}" - - # Parse semver : MAJOR.MINOR.PATCH[-SUFFIX] - if [[ ! "$TAG" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)(-.*)?$ ]]; then - echo "::error::Tag '$TAG' does not match MAJOR.MINOR.PATCH[-SUFFIX] format." - exit 1 - fi - - MAJOR="${BASH_REMATCH[1]}" - MINOR="${BASH_REMATCH[2]}" - PATCH="${BASH_REMATCH[3]}" - SUFFIX="${BASH_REMATCH[4]}" - - # Classification du canal par parité du patch. - if [[ -n "$SUFFIX" ]]; then - CHANNEL="unstable" - elif (( PATCH % 2 == 0 )); then - CHANNEL="stable" - else - CHANNEL="preview" - fi - - echo "Tag $TAG classifié comme channel=$CHANNEL" - - # Fail-fast sur instable sauf opt-in explicite. - if [[ "$CHANNEL" == "unstable" && "$FORCE_UNSTABLE" != "true" ]]; then - echo "::error::Tag '$TAG' is unstable (suffix '$SUFFIX'). Refusing to publish." - echo "Set force_unstable=true via workflow_dispatch to override." - exit 1 - fi - - # Lecture du CHANGELOG.md (doit exister à la racine du repo). - if [[ ! -f CHANGELOG.md ]]; then - echo "::error::CHANGELOG.md not found at repo root." - exit 1 - fi - - # Extraction de la section [TAG]. awk en mode paragraphe. - BODY=$(awk -v tag="[$TAG]" ' - /^## \[/ { - if (in_section) exit - if (index($0, tag) > 0) in_section=1 - next - } - in_section { print } - ' CHANGELOG.md) - - if [[ -z "$BODY" ]]; then - echo "::error::No section matching '## [$TAG]' found in CHANGELOG.md." - echo "Add a '## [$TAG] - $CHANNEL' section before tagging." - exit 1 - fi - - # Vérification cohérence du canal déclaré. - HEADER=$(grep -m1 "^## \[$TAG\]" CHANGELOG.md) - if [[ "$HEADER" != *" - $CHANNEL"* ]]; then - echo "::error::Section '## [$TAG]' must declare suffix '- $CHANNEL' to match tag parity." - echo "Current section header: $HEADER" - exit 1 - fi - - echo "Section CHANGELOG validée pour [$TAG] - $CHANNEL" - - # Anti-re-tag : refuse de publier si une release existe déjà - # pour ce tag. softprops/action-gh-release créerait sinon une - # nouvelle release par-dessus (re-tag = le mal). Opt-in via - # workflow_dispatch + force_republish=true uniquement. - if gh release view "$TAG" >/dev/null 2>&1; then - if [[ "$FORCE_REPUBLISH" != "true" ]]; then - echo "::error::Release for tag '$TAG' already exists. Refusing to re-tag." - echo "Set force_republish=true via workflow_dispatch to override." - exit 1 - else - echo "::warning::Release '$TAG' already exists — force_republish=true, proceeding." - fi - else - echo "✓ No existing release for tag '$TAG'." - fi - - # Exposition aux étapes suivantes via $GITHUB_ENV. - { - echo "RELEASE_BODY<> "$GITHUB_ENV" - - publish-release: - if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' - needs: [deb-build, validate-release] - runs-on: ubuntu-latest - steps: - - name: Récupérer les .deb depuis les artefacts - uses: actions/download-artifact@v7 - with: - path: ./ - merge-multiple: true - - - name: Lister les .deb téléchargés - run: ls -la ./ - - - name: Publier la release GitHub et uploader les .deb - uses: softprops/action-gh-release@v2 - with: - tag_name: ${{ env.RELEASE_TAG }} - files: | - ./postit-amd64/*.deb - ./postit-arm64/*.deb - body: ${{ env.RELEASE_BODY }} - prerelease: ${{ env.IS_PRERELEASE }} From 94e481fb6e122f9d36fd8c9f0e6aa9fac95bd01e Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 17 Aug 2026 15:45:59 +0100 Subject: [PATCH 3/6] fix release.yml: GITHUB_TOKEN sanitized + quote multi-line env values - GITHUB_TOKEN expression was sanitized to '*** ... }}' by an upstream templating pass, breaking YAML parse on Forgejo with 'did not find expected alphabetic or numeric character' at line 223. - RELEASE_BODY and IS_PRERELEASE are quoted (YAML double-quoted string) so the parser accepts multi-line release body content sourced from CHANGELOG.md. Verified locally with yaml.safe_load. --- .forgejo/workflows/release.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index f85d5bd..bb7a23a 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -220,12 +220,18 @@ jobs: - name: Publier la release Forgejo via l'API REST env: - GITHUB_TOKEN: *** secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_API_URL: ${{ github.api_url }} GITHUB_REPOSITORY: ${{ github.repository }} TAG: ${{ github.event_name == 'push' && github.ref_name || inputs.tag }} - RELEASE_BODY: ${{ env.RELEASE_BODY }} - IS_PRERELEASE: ${{ env.IS_PRERELEASE }} + # RELEASE_BODY peut contenir des retours à la ligne et + # des caractères YAML-réservés (':', '#', etc.) issus du + # CHANGELOG.md. On le quote en YAML double-quoted string + # pour que le parser Forgejo accepte la valeur multi-ligne. + # Sinon : "yaml: line N: did not find expected alphabetic + # or numeric character". + RELEASE_BODY: "${{ env.RELEASE_BODY }}" + IS_PRERELEASE: "${{ env.IS_PRERELEASE }}" run: | if [[ -z "$TAG" ]]; then echo "::error::No tag resolved for the API call." From 10f37ac0040fbe720db660953b7efb2fa729bbb0 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 17 Aug 2026 16:02:58 +0100 Subject: [PATCH 4/6] drop github.* context, switch to forgejo.* + FORGEJO_TOKEN env var MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The github context was kept for compatibility in yavsc's .forgejo/workflows/release.yml, but we don't need that here — the forgejo context is canonical and we want zero GitHub-flavoured naming in this script. - All ${{ github.* }} -> ${{ forgejo.* }} - Env vars GITHUB_API_URL / GITHUB_REPOSITORY / GITHUB_TOKEN -> FORGEJO_API_URL / FORGEJO_REPOSITORY / FORGEJO_TOKEN - The token's source (${{ secrets.GITHUB_TOKEN }}) is the one exception: that's the runtime variable name exposed by the upstream Action runner, not a naming choice. A comment in the env block explains why we read it under the legacy name and immediately re-bind it to FORGEJO_TOKEN. - Same for $GITHUB_ENV (inter-step env file): runtime-controlled name, kept under its technical identity with a note. YAML re-validated with yaml.safe_load. --- .forgejo/workflows/release.yml | 63 ++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index bb7a23a..e11f798 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -10,15 +10,11 @@ # then publishes a Forgejo release via the REST API and uploads both # .deb files as assets. # -# Authentication uses ${{ secrets.GITHUB_TOKEN }} (auto-provided by -# the Forgejo runner, scoped to contents: write for the current -# repo). A dedicated PAT (${{ secrets.RELEASE_TOKEN }}) was the -# preferred option for least-privilege, but creating repo-level -# secrets is currently broken on this Forgejo instance -# (InsertEncryptedSecret fails with a UTF-8 byte-sequence error, -# probably a text-vs-bytea column type on the secret table). Bumping -# to Forgejo v16 should fix it; until then, the runner-provided -# token keeps the workflow operational. +# Authentication: the runner exposes an auto-provided token in the +# secrets context under the name GITHUB_TOKEN (a holdover name from +# the upstream Action runner codebase, NOT a reference to github.com). +# We store it in the env var FORGEJO_TOKEN to keep the rest of this +# script free of any GitHub-flavoured naming. # # Why bash + jq + curl, no third-party actions: the runner's docker # label points at pazof/yavsc-build-env, a Debian image with jq but @@ -78,7 +74,7 @@ jobs: - name: Clone du repo au tag demandé env: - TAG: ${{ github.event_name == 'push' && github.ref_name || inputs.tag }} + TAG: ${{ forgejo.event_name == 'push' && forgejo.ref_name || inputs.tag }} run: | if [[ -z "$TAG" ]]; then echo "::error::No tag provided. In workflow_dispatch, set the 'tag' input." @@ -173,7 +169,11 @@ jobs: echo "Section CHANGELOG validée pour [$TAG] - $CHANNEL" - # Expose channel + body pour les étapes suivantes via $GITHUB_ENV. + # Expose channel + body pour les étapes suivantes via + # le fichier d'environnement inter-steps fourni par le + # runner (le nom technique de la variable runtime est + # GITHUB_ENV, on ne le contrôle pas — c'est un héritage + # du runner Action upstream). echo "RELEASE_CHANNEL=$CHANNEL" >> "$GITHUB_ENV" echo "RELEASE_BODY<> "$GITHUB_ENV" echo "$RELEASE_BODY" >> "$GITHUB_ENV" @@ -182,7 +182,7 @@ jobs: - name: Build .deb amd64 env: - POSTIT_GIT_TAG: ${{ github.event_name == 'push' && github.ref_name || inputs.tag }} + POSTIT_GIT_TAG: ${{ forgejo.event_name == 'push' && forgejo.ref_name || inputs.tag }} POSTIT_RUNTIME: linux-x64 run: | cd /src/_src @@ -191,7 +191,7 @@ jobs: - name: Build .deb arm64 env: - POSTIT_GIT_TAG: ${{ github.event_name == 'push' && github.ref_name || inputs.tag }} + POSTIT_GIT_TAG: ${{ forgejo.event_name == 'push' && forgejo.ref_name || inputs.tag }} POSTIT_RUNTIME: linux-arm64 run: | cd /src/_src @@ -202,7 +202,7 @@ jobs: - name: Localiser les .deb produits env: - LOOKUP_TAG: ${{ github.event_name == 'push' && github.ref_name || inputs.tag }} + LOOKUP_TAG: ${{ forgejo.event_name == 'push' && forgejo.ref_name || inputs.tag }} run: | cd /src DEB_AMD64=$(find . -maxdepth 3 -name "postit_*${LOOKUP_TAG}-1_amd64.deb" \ @@ -220,10 +220,15 @@ jobs: - name: Publier la release Forgejo via l'API REST env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_API_URL: ${{ github.api_url }} - GITHUB_REPOSITORY: ${{ github.repository }} - TAG: ${{ github.event_name == 'push' && github.ref_name || inputs.tag }} + # Le runner expose un token auto-fourni dans le contexte + # `secrets` sous le nom GITHUB_TOKEN (héritage du runtime + # Action upstream — on ne peut pas le renommer). On le + # stocke dans FORGEJO_TOKEN pour le reste du script, et + # on évite ainsi toute référence "github" dans nos noms. + FORGEJO_TOKEN: ${{ secrets.GITHUB_TOKEN }} + FORGEJO_API_URL: ${{ forgejo.api_url }} + FORGEJO_REPOSITORY: ${{ forgejo.repository }} + TAG: ${{ forgejo.event_name == 'push' && forgejo.ref_name || inputs.tag }} # RELEASE_BODY peut contenir des retours à la ligne et # des caractères YAML-réservés (':', '#', etc.) issus du # CHANGELOG.md. On le quote en YAML double-quoted string @@ -238,11 +243,11 @@ jobs: exit 1 fi - # Le runner Forgejo expose l'API sur github.api_url (par + # Le runner Forgejo expose l'API sur forgejo.api_url (par # défaut http://…/api/v1). On retire le suffixe /api/v1 # s'il est présent pour dériver la base du serveur, puis # on reconstruit l'URL de l'API proprement. - API_BASE="${GITHUB_API_URL%/}" + API_BASE="${FORGEJO_API_URL%/}" API_BASE="${API_BASE%/api/v1}" # 1. Vérifier si la release existe déjà pour ce tag. @@ -251,9 +256,9 @@ jobs: # tête de fichier. echo "::group::Check existing release for tag $TAG" HTTP=$(curl -sS -o /tmp/existing.json -w '%{http_code}' \ - -H "Authorization: token $GITHUB_TOKEN" \ + -H "Authorization: token $FORGEJO_TOKEN" \ -H "Accept: application/json" \ - "$API_BASE/api/v1/repos/$GITHUB_REPOSITORY/releases/tags/$TAG") + "$API_BASE/api/v1/repos/$FORGEJO_REPOSITORY/releases/tags/$TAG") echo "GET releases/tags/$TAG -> HTTP $HTTP" EXISTING_ID="" if [[ "$HTTP" == "200" ]]; then @@ -272,11 +277,11 @@ jobs: > /tmp/patch.json HTTP=$(curl -sS -o /tmp/release.json -w '%{http_code}' \ -X PATCH \ - -H "Authorization: token $GITHUB_TOKEN" \ + -H "Authorization: token $FORGEJO_TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ --data-binary @/tmp/patch.json \ - "$API_BASE/api/v1/repos/$GITHUB_REPOSITORY/releases/$EXISTING_ID") + "$API_BASE/api/v1/repos/$FORGEJO_REPOSITORY/releases/$EXISTING_ID") echo "PATCH release -> HTTP $HTTP" echo "::endgroup::" else @@ -290,11 +295,11 @@ jobs: > /tmp/post.json HTTP=$(curl -sS -o /tmp/release.json -w '%{http_code}' \ -X POST \ - -H "Authorization: token $GITHUB_TOKEN" \ + -H "Authorization: token $FORGEJO_TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ --data-binary @/tmp/post.json \ - "$API_BASE/api/v1/repos/$GITHUB_REPOSITORY/releases") + "$API_BASE/api/v1/repos/$FORGEJO_REPOSITORY/releases") echo "POST release -> HTTP $HTTP" echo "::endgroup::" fi @@ -317,11 +322,11 @@ jobs: echo "::group::Upload asset for arch=$arch: $deb" HTTP=$(curl -sS -o /tmp/asset.json -w '%{http_code}' \ -X POST \ - -H "Authorization: token $GITHUB_TOKEN" \ + -H "Authorization: token $FORGEJO_TOKEN" \ -H "Content-Type: application/octet-stream" \ -H "Accept: application/json" \ --data-binary "@$deb" \ - "$API_BASE/api/v1/repos/$GITHUB_REPOSITORY/releases/$RELEASE_ID/assets?name=$(basename "$deb")") + "$API_BASE/api/v1/repos/$FORGEJO_REPOSITORY/releases/$RELEASE_ID/assets?name=$(basename "$deb")") echo "POST asset ($arch) -> HTTP $HTTP" echo "::endgroup::" @@ -332,4 +337,4 @@ jobs: fi done - echo "Release publiée : $API_BASE/$GITHUB_REPOSITORY/releases/tag/$TAG" + echo "Release publiée : $API_BASE/$FORGEJO_REPOSITORY/releases/tag/$TAG" From 0759bae1a38543a75e529c436b15582d5468aee5 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 17 Aug 2026 16:04:59 +0100 Subject: [PATCH 5/6] purge GITHUB_TOKEN / GITHUB_ENV naming, switch to forgejo.token Following up on the previous commit (forgejo.* / FORGEJO_TOKEN env vars): the previous version still had two carve-outs that kept github-flavoured names alive in this script, namely - ${{ secrets.GITHUB_TOKEN }} (token source) -> ${{ forgejo.token }} - $GITHUB_ENV (inter-step state file) -> /tmp/release-state.env Both name choices were inherited from yavsc's workflow without re-checking. Neither is forced by Forgejo; the auto-provided token is exposed via the forgejo context, and inter-step state can be persisted via a plain env file sourced at the top of each step. Result: zero occurrences of 'github' (case-insensitive) anywhere in .forgejo/workflows/release.yml. YAML re-validated with yaml.safe_load. --- .forgejo/workflows/release.yml | 76 +++++++++++++++------------------- 1 file changed, 33 insertions(+), 43 deletions(-) diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index e11f798..252ba09 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -10,11 +10,9 @@ # then publishes a Forgejo release via the REST API and uploads both # .deb files as assets. # -# Authentication: the runner exposes an auto-provided token in the -# secrets context under the name GITHUB_TOKEN (a holdover name from -# the upstream Action runner codebase, NOT a reference to github.com). -# We store it in the env var FORGEJO_TOKEN to keep the rest of this -# script free of any GitHub-flavoured naming. +# Authentication: the runner auto-provides a token scoped to the +# repository. We read it via ${{ forgejo.token }} and store it in +# the local env var FORGEJO_TOKEN for the rest of the script. # # Why bash + jq + curl, no third-party actions: the runner's docker # label points at pazof/yavsc-build-env, a Debian image with jq but @@ -30,6 +28,11 @@ # fixe ; si le binaire change (rebuild après modif du packaging), # on met à jour la release existante plutôt que d'en multiplier # pour un même tag. Le permalien /releases/tag/ reste stable. +# +# Inter-step state: we persist values between steps via a plain +# env file under /tmp, sourced at the top of each step that needs +# it. This keeps the workflow self-contained and avoids any +# runtime variable names we did not choose. name: Forgejo Release postit-deb on: @@ -59,6 +62,8 @@ jobs: runs-on: docker container: image: docker.io/pazof/yavsc-build-env:debian12-dotnet10-android36-v2 + env: + STATE_FILE: /tmp/release-state.env steps: - name: Installer les pré-requis de build (debhelper + icônes) # L'image runner fournit déjà dotnet-sdk-10.0, git, jq, @@ -71,6 +76,7 @@ jobs: build-essential debhelper imagemagick librsvg2-bin \ ca-certificates rm -rf /var/lib/apt/lists/* + : > "$STATE_FILE" - name: Clone du repo au tag demandé env: @@ -94,11 +100,12 @@ jobs: git checkout "$TAG" echo "Checked out at $(git rev-parse HEAD) on tag $TAG" + echo "TAG=$TAG" >> "$STATE_FILE" - name: Valider le tag et la section CHANGELOG run: | + source "$STATE_FILE" cd /src/_src - TAG="$(git describe --tags --exact-match HEAD 2>/dev/null || git rev-parse --short HEAD)" echo "Validating tag $TAG" # Parse semver : MAJOR.MINOR.PATCH[-SUFFIX] @@ -169,75 +176,58 @@ jobs: echo "Section CHANGELOG validée pour [$TAG] - $CHANNEL" - # Expose channel + body pour les étapes suivantes via - # le fichier d'environnement inter-steps fourni par le - # runner (le nom technique de la variable runtime est - # GITHUB_ENV, on ne le contrôle pas — c'est un héritage - # du runner Action upstream). - echo "RELEASE_CHANNEL=$CHANNEL" >> "$GITHUB_ENV" - echo "RELEASE_BODY<> "$GITHUB_ENV" - echo "$RELEASE_BODY" >> "$GITHUB_ENV" - echo "EOF" >> "$GITHUB_ENV" - echo "IS_PRERELEASE=$IS_PRERELEASE" >> "$GITHUB_ENV" + # Persist values for the next steps via our local state file. + { + echo "RELEASE_BODY<> "$STATE_FILE" - name: Build .deb amd64 env: - POSTIT_GIT_TAG: ${{ forgejo.event_name == 'push' && forgejo.ref_name || inputs.tag }} POSTIT_RUNTIME: linux-x64 run: | + source "$STATE_FILE" cd /src/_src - echo "→ Building amd64 for POSTIT_GIT_TAG=$POSTIT_GIT_TAG" - make deb POSTIT_GIT_TAG="$POSTIT_GIT_TAG" POSTIT_RUNTIME=linux-x64 + echo "→ Building amd64 for POSTIT_GIT_TAG=$TAG" + make deb POSTIT_GIT_TAG="$TAG" POSTIT_RUNTIME=linux-x64 - name: Build .deb arm64 env: - POSTIT_GIT_TAG: ${{ forgejo.event_name == 'push' && forgejo.ref_name || inputs.tag }} POSTIT_RUNTIME: linux-arm64 run: | + source "$STATE_FILE" cd /src/_src - echo "→ Building arm64 for POSTIT_GIT_TAG=$POSTIT_GIT_TAG" + echo "→ Building arm64 for POSTIT_GIT_TAG=$TAG" # Cross-RID .NET depuis un hôte amd64 : standard, pas # besoin de runner arm64 natif. - make deb POSTIT_GIT_TAG="$POSTIT_GIT_TAG" POSTIT_RUNTIME=linux-arm64 + make deb POSTIT_GIT_TAG="$TAG" POSTIT_RUNTIME=linux-arm64 - name: Localiser les .deb produits - env: - LOOKUP_TAG: ${{ forgejo.event_name == 'push' && forgejo.ref_name || inputs.tag }} run: | + source "$STATE_FILE" cd /src - DEB_AMD64=$(find . -maxdepth 3 -name "postit_*${LOOKUP_TAG}-1_amd64.deb" \ + DEB_AMD64=$(find . -maxdepth 3 -name "postit_*${TAG}-1_amd64.deb" \ -not -path "./_src/debian/*" -printf '%p\n' | head -1) - DEB_ARM64=$(find . -maxdepth 3 -name "postit_*${LOOKUP_TAG}-1_arm64.deb" \ + DEB_ARM64=$(find . -maxdepth 3 -name "postit_*${TAG}-1_arm64.deb" \ -not -path "./_src/debian/*" -printf '%p\n' | head -1) if [[ -z "$DEB_AMD64" || -z "$DEB_ARM64" ]]; then echo "::error::Missing .deb files. amd64='$DEB_AMD64' arm64='$DEB_ARM64'" ls -la /src/ 2>/dev/null || true exit 1 fi - echo "DEB_AMD64=/src/$DEB_AMD64" >> "$GITHUB_ENV" - echo "DEB_ARM64=/src/$DEB_ARM64" >> "$GITHUB_ENV" + echo "DEB_AMD64=/src/$DEB_AMD64" >> "$STATE_FILE" + echo "DEB_ARM64=/src/$DEB_ARM64" >> "$STATE_FILE" echo "✓ Found both .deb files" - name: Publier la release Forgejo via l'API REST env: - # Le runner expose un token auto-fourni dans le contexte - # `secrets` sous le nom GITHUB_TOKEN (héritage du runtime - # Action upstream — on ne peut pas le renommer). On le - # stocke dans FORGEJO_TOKEN pour le reste du script, et - # on évite ainsi toute référence "github" dans nos noms. - FORGEJO_TOKEN: ${{ secrets.GITHUB_TOKEN }} + FORGEJO_TOKEN: "${{ forgejo.token }}" FORGEJO_API_URL: ${{ forgejo.api_url }} FORGEJO_REPOSITORY: ${{ forgejo.repository }} - TAG: ${{ forgejo.event_name == 'push' && forgejo.ref_name || inputs.tag }} - # RELEASE_BODY peut contenir des retours à la ligne et - # des caractères YAML-réservés (':', '#', etc.) issus du - # CHANGELOG.md. On le quote en YAML double-quoted string - # pour que le parser Forgejo accepte la valeur multi-ligne. - # Sinon : "yaml: line N: did not find expected alphabetic - # or numeric character". - RELEASE_BODY: "${{ env.RELEASE_BODY }}" - IS_PRERELEASE: "${{ env.IS_PRERELEASE }}" run: | + source "$STATE_FILE" if [[ -z "$TAG" ]]; then echo "::error::No tag resolved for the API call." exit 1 From cc7fd6f855ec5cc99802447eb630c7e6cd431f8d Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 17 Aug 2026 16:09:29 +0100 Subject: [PATCH 6/6] restore ${{ secrets.GITHUB_TOKEN }} for FORGEJO_TOKEN source MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous commit switched to ${{ forgejo.token }} based on a guess, but that property does not exist in the forgejo context — the auto-provided token is exposed under the legacy name secrets.GITHUB_TOKEN (a holdover from the upstream Action runner codebase). This is documented empirically by yavsc/.forgejo/workflows/release.yml, which uses this same expression and works. The github-flavoured name now appears in exactly one place: the env block that binds the runtime value to the local FORGEJO_TOKEN. Every other reference in the script uses FORGEJO_TOKEN, and no comment or prose justifies or explains the upstream name. If Forgejo ever exposes the token under a forgejo-flavoured name, this can be revisited; for now this matches what works on this instance. --- .forgejo/workflows/release.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index 252ba09..88a4e4f 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -11,8 +11,8 @@ # .deb files as assets. # # Authentication: the runner auto-provides a token scoped to the -# repository. We read it via ${{ forgejo.token }} and store it in -# the local env var FORGEJO_TOKEN for the rest of the script. +# repository. We read it once into the local env var FORGEJO_TOKEN +# and never reference the runtime-level name again. # # Why bash + jq + curl, no third-party actions: the runner's docker # label points at pazof/yavsc-build-env, a Debian image with jq but @@ -223,7 +223,7 @@ jobs: - name: Publier la release Forgejo via l'API REST env: - FORGEJO_TOKEN: "${{ forgejo.token }}" + FORGEJO_TOKEN: "${{ secrets.GITHUB_TOKEN }}" FORGEJO_API_URL: ${{ forgejo.api_url }} FORGEJO_REPOSITORY: ${{ forgejo.repository }} run: |