Previous fix (--exclude=*.so) only affects the strip phase. dh_strip
also runs a separate --only-keep-debug pass for the automatic dbgsym
package, and that pass does not honour --exclude. So objcopy still
trips on the ARM64 .so files and the build aborts.
Add --no-automatic-dbgsym to skip the dbgsym pass entirely. Trade-
off: no separate postit-dbg package is generated. That's fine for
this upstream — the only debug info in the .so files is from Avalonia
deps (HarfBuzz, Skia) and is not useful for debugging PostIt itself.
Discovered via the Forgejo Actions run #8 on tag 1.0.6.
When cross-compiling PostIt.Desktop for linux-arm64 from an amd64
runner container, the .deb ends up shipping HarfBuzzSharp.so and
SkiaSharp.so in ARM64 format. dh_strip invokes objcopy on every
file under debian/postit/, and objcopy on the amd64 host cannot
parse ARM64 .so files:
objcopy: Unable to recognise the format of the input file
`debian/postit/usr/lib/postit/libHarfBuzzSharp.so'
dh_strip: error: ... returned exit code 1
dh_strip: error: Aborting due to earlier error
Add --exclude=*.so to override_dh_strip. The upstream .so ships
with its own debug symbols; we don't lose anything by skipping
the strip on them.
Also drop the diag.yml workflow that diagnosed the initial
tag-not-found failure — no longer needed.
Discovered via the Forgejo Actions release.yml run on tag 1.0.6.
The previous version wrote RELEASE_BODY to a state file using the
'<<EOF ... EOF' heredoc syntax, then 'source'd that file at the
top of each subsequent step. Bash cannot parse that file as
shell input: the heredoc body contains markdown with backticks,
asterisks, colons, etc., which bash tries to interpret as
commands ('postit: command not found', '1.0.6: command not
found', etc.).
Switch to JSON via jq: jq handles all escaping correctly via
--arg/--argjson. Each step reads the fields it needs with
`jq -r '.field' $STATE_FILE`.
Also fixes a botched jq merge in the validation step that
mixed `jq -n ... > STATE_FILE` with a `<<< "" `
here-string to the same file.
Probes the runner setup so we can tell whether the release.yml
failure is upstream of our workflow (no runner, no network, no
tooling) or specific to a step.
- Container reachable + image usable
- DNS + outbound HTTPS to forgejo.pschneider.fr and hub.docker.com
- Required tooling available (git, dotnet, jq, curl, make, debhelper,
imagemagick)
- forgejo.* context populated
- secrets.GITHUB_TOKEN resolves (FORGEJO_TOKEN populated)
- API call with the token returns 200 on /repos/<repo>
Will be removed once we've confirmed the runner is healthy.
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.
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.
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.
- 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.
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/<tag> permalink stable — re-tag = le
mal, but a re-build of the same tag should not duplicate releases.
- Makefile + debian/rules: POSTIT_GIT_TAG default 1.0.0 → 1.0.6.
- CHANGELOG.md: document the 1.0.6 release (workflow rollout).
- .github/workflows/build-and-release-deb.yml: GitHub Actions workflow
that builds postit_*.deb (matrix amd64+arm64 via cross-RID .NET on
amd64 runners) from a tag pushed to this repo, validates the tag
(semver, patch-parity channel, CHANGELOG section), and publishes a
GitHub Release with both .deb as assets. Refuses to re-tag an
existing release by default (re-tag = le mal); opt-in via
workflow_dispatch + force_republish=true.
Pattern mirrors yavsc/.github/workflows/docker-publish-android.yml.
The previous override_dh_auto_build used 'git clone --branch <tag>'
which only accepts branch names. Feeding it 1.0.1-rc02 (a tag,
not yet pushed to origin) failed with 'La branche distante
1.0.1-rc02 n'a pas ete trouvee' and aborted the package build.
Switch to a 'git init + remote add + fetch --depth=1 origin <ref>
+ checkout FETCH_HEAD' sequence, which works for both branches
and tags, including local-only tags fetched via file:// (the
typical RC-staging workflow: 'git tag' on the local checkout,
then 'make POSTIT_GIT_URL=file:///... POSTIT_GIT_TAG=<tag>'
before pushing).
The fetch error now carries a diagnostic that points the operator
at the file:// override and at the missing 'git push'.
Adds tests/test-fetch-upstream.sh with four cases against the
real pazof/yavsc remote and a synthetic local repo: tag on
GitHub, branch on GitHub, .git reuse, and tag via file://.
Wired into 'make test'.
The .deb was hardcoded to 1.0.0-1 in debian/changelog regardless of
POSTIT_GIT_TAG, so 'make POSTIT_GIT_TAG=1.0.1-rc01' produced a
postit_1.0.0-1_amd64.deb (wrong name) and the trailing mv into
POSTIT_OUT_DIR silently fell back to the same wrong-name glob.
Move the version into a @VERSION@-bearing debian/changelog.in
template and render debian/changelog from it in the Makefile, before
dpkg-buildpackage runs (it reads debian/changelog during
dpkg-source --before-build, before any rule fires). debian/changelog
is .gitignored; the template is the source of truth.
debian/rules re-renders the changelog as a safety net for direct
dpkg-buildpackage invocations and adds it to override_dh_auto_clean
so partial builds leave no stale rendered file behind.
Default stays linux-x64 (the only architecture built today).
Override on the command line to target arm64 (or any other
RID supported by Avalonia 12 on Linux):
make deb POSTIT_RUNTIME=linux-arm64
The Makefile passes POSTIT_RUNTIME through to dpkg-buildpackage,
which propagates it to debian/rules, which threads it into
dotnet publish --runtime.
Note: the .deb is mono-architecture. For a multi-arch .deb,
the build must run twice (once per RID) and the resulting .debs
can be combined with dpkg-gencontrol / Multi-Arch: same.
Update README accordingly.
dh_install, by default, only installs files explicitly listed
in debian/<package>.install. Without that file, it silently
installs nothing — the build pipeline ends with an empty .deb
of just changelog and copyright.
List:
/usr/lib/postit/* (managed assemblies)
/usr/bin/postit (wrapper script)
/usr/share/applications/postit.desktop
/usr/share/icons/hicolor/{16,32,48,64,128,256}x{...}/apps/postit.png
/usr/share/icons/hicolor/scalable/apps/postit.svg
The original .gitignore caught *.deb in the source tree but not:
- debian/.debhelper/ (cache populated by every dh_* helper)
- debian/debhelper-build-stamp, debian/postit.debhelper.log,
debian/postit.substvars (regenerated per build)
- debian/tmp/ (staging tree for dh_install)
- postit_*.{deb,changes,buildinfo} in the parent workspace
(where dpkg-buildpackage drops artifacts)
Initial debian/rules wrote into debian/postit/usr/... directly.
That fails: dh_clean (run between override_dh_auto_build and
dh_install) wipes the package staging dir, and dh_install needs
debian/tmp/ as the canonical staging area to install files
into debian/postit/.
Move the cp-and-convert block out of override_dh_auto_build into
a 'stage_postit' make define, and call it from override_dh_install
right before dh_install moves files into the package tree.
Also: simplify POSTIT_* path variables — drop the duplicated
POSTIT_APP_DIR / POSTIT_LIB_DIR / POSTIT_BIN_DIR / POSTIT_SHARE_DIR
set (they all derived from debian/postit which is now what dh_install
populates).
Build-Depends already includes dotnet-sdk-10.0, imagemagick,
librsvg2-bin, git, ca-certificates. The debhelper-compat (= 13)
line was duplicated: the same version is set in debian/compat
(debhelper reads it from there by convention). dh errors out
with:
dh: error: debhelper compat level specified both in
debian/compat and in debian/control
Drop the line in control.