Skip to content

ci: add tag-triggered release.yml workflow - #520

Merged
mrjimenez merged 3 commits into
amule-project:masterfrom
got3nks:pr-release-workflow
May 3, 2026
Merged

ci: add tag-triggered release.yml workflow#520
mrjimenez merged 3 commits into
amule-project:masterfrom
got3nks:pr-release-workflow

Conversation

@got3nks

@got3nks got3nks commented May 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a Release workflow that fires when a release-like tag is pushed and assembles a draft GitHub Release with artifacts for every platform. Three commits:

  1. ci: fix Windows packaging artifact filenames — standalone fix for two latent bugs in the existing Packaging workflow that produced aMule-snapshot-Windows-*.zip and (after the first fix) aMule-<tag>-dirty-Windows-*.zip. Useful on its own even without release.yml.

  2. ci: add tag-triggered release.yml workflow — the Release workflow itself, plus a workflow_call trigger added to packaging.yml so release.yml can invoke the matrix as a reusable workflow.

  3. ci: relax smoke-test version banner grep to accept tagged builds — the post-build amuled --version smoke tests for macOS and Windows hardcoded '^aMuleD GIT', which only matched the dev placeholder. Tagged release builds (once the parallel release: propose 3.0.0-beta changelog (RFC) #521 PR lands the CMake auto-detection that flows the tag into VERSION) emit aMuleD <tag> ... instead, so the grep failed and aborted the job. Pattern relaxed to '^aMuleD ' — accepts both forms and any future version-string layout.

Commit 1: Windows packaging filename fixes

Two related bugs in the windows-zip job's version detection.

Bug 1 — aMule-snapshot-Windows-*.zip

packaging/windows/build.sh runs in MSYS2 bash (`shell: msys2 {0}`). setup-msys2 installs only the packages on its install: list — base MSYS2 git was missing from that list, so the MSYS2 shell had no git binary at all.

git describe --tags inside build.sh therefore failed silently (the script wraps it in `2>/dev/null || echo "snapshot"`), producing aMule-snapshot-Windows-*.zip on every Windows packaging run on master, instead of the correct aMule-<version>-Windows-*.zip.

Fix: add git to the setup-msys2 install list, plus a defensive git config --global --add safe.directory '*' step (actions/checkout configures safe.directory only for the Windows git at C:\Program Files\Git\bin\git.exe, not for MSYS2 git which uses a separate global config).

Bug 2 — aMule-<tag>-dirty-Windows-*.zip

After fix 1, the version string was correct except for a -dirty suffix. Root cause: actions/checkout on Windows uses core.autocrlf=true by default, which converts LF to CRLF in the working tree on text files. MSYS2 git then sees those files as differing from the (LF) blobs in the index, so git describe --tags --always --dirty appends -dirty to the version string.

Fix: drop --dirty from the git describe call in build.sh. --dirty is useful locally to flag uncommitted changes, but in CI a tagged commit should always produce a clean version string. Local developers can run git status separately if they want that signal.

Commit 2: Release workflow

Pushing a tag matching [0-9]* (aMule's bare-semver convention — 2.4.0, 2.4.0-rc1) or v[0-9]* (compat) triggers the full packaging matrix, then a release job collects each platform's final artifact and creates a draft Release on the repo the tag was pushed to. The release stays a draft so a maintainer can review the asset list and edit the auto-generated notes before publishing.

What gets attached

Seven assets:

  • aMule-<tag>-x86_64.AppImage
  • aMule-<tag>-aarch64.AppImage
  • aMule-<tag>-x86_64.flatpak
  • aMule-<tag>-aarch64.flatpak
  • aMule-<tag>-macOS-universal2.dmg
  • aMule-<tag>-Windows-x64.zip
  • aMule-<tag>-Windows-arm64.zip

The intermediate macos-app-arm64 / macos-app-x86_64 artifacts (inputs to the lipo merge job) are deliberately excluded — only the final per-platform output ships on the Release page.

Pre-release auto-detection

Any tag with a semver-style hyphenated suffix after the version core (2.4.0-rc1, 2.4.0-beta, 2.4.0-alpha.2) is flagged as a GitHub pre-release via gh release create --prerelease. Plain 2.4.0 / v1.0 / v3 is a full release. Regex: `^v?[0-9]+(.[0-9]+)*-`. Verified against historical tag samples:

Tag Classified as
2.3.3 full release
2.4.0-rc1 prerelease
v1.0.0 full release
v1.0.0-beta prerelease

Auto-generated notes

gh release create --generate-notes fills the body from PR titles since the previous tag. Since the release is always a draft, the maintainer can trim, replace, or rewrite before publishing.

Reusing packaging.yml

packaging.yml now also exposes a workflow_call trigger alongside its existing push and workflow_dispatch triggers. release.yml invokes it as a reusable workflow rather than duplicating the matrix.

Idempotent re-runs

The release job's create-or-upload logic (`gh release view ... && gh release upload --clobber || gh release create ...`) means re-running the workflow on the same tag refreshes assets in place rather than failing or creating duplicates.

Commit 3: Smoke-test grep relax

Both platform smoke-test steps post-build run amuled --version and grep the banner:

  • macOS (packaging.yml:207): ... | grep -q '^aMuleD GIT'
  • Windows (packaging.yml:367): grep -q '^aMuleD GIT' /tmp/version.txt

The hardcoded GIT matched only the dev-placeholder set by set (VERSION "GIT") in CMakeLists.txt. Once the parallel #521 PR lands the CMake auto-detection that pulls the tag name into VERSION for tagged builds, the binary banner becomes aMuleD 3.0.0-beta ... (or whatever the tag is), the grep fails, and the smoke-test step exits 1 — even though the binary is healthy.

Pattern relaxed to '^aMuleD ' so it accepts the dev placeholder, every tagged-release banner, and any future version-string format without further edits to the workflow.

The bug was discovered during fork testing of the combined #520 + #521 commit chain — the macOS .app (arm64) job failed at the smoke-test step with the binary banner reading aMuleD 3.0.0-beta against the hardcoded GIT grep.

Fork-tested

End-to-end run on a fork by pushing tag 3.0.0-beta against the combined #520 + #521 commit chain (run 25277950923):

  • Packaging matrix completed for 7 of 9 platforms — AppImage x86_64+aarch64, macOS .app x86_64+arm64, macOS Universal2 .dmg, Windows portable .zip x64+arm64. Flatpak (x86_64 and aarch64) consistently fails on the same libdbusmenu SSL connection timeout against git.launchpad.net across 3 separate retry attempts — same launchpad outage discussed in flatpak: vendor launchpad-only deps (intltool + libdbusmenu) to fix CI flakiness #517 (vendoring rejected, deferred until ecosystem stabilises). No code change in this PR affects the Flatpak path; expectation is it'll succeed on the upstream side once launchpad recovers.
  • -beta suffix correctly flagged the release as pre-release (visible in the prerelease detection regex; not draft-Release-confirmed since release job skipped, see below)
  • Windows artifact filenames include the tag (`aMule-3.0.0-beta-Windows-{x64,arm64}.zip`) — confirms commit 1's fix
  • macOS / Windows smoke tests pass against tagged builds — confirms commit 3's fix; both amuled --version smoke tests succeed where they previously failed against the hardcoded '^aMuleD GIT' grep
  • Re-running failed jobs on the same tag works (gh run rerun --failed) — exercised three times on the Flatpak retries
  • Draft Release with all 7 assets — not produced because the parent build job fails (Flatpak unavailability cascades to needs: buildrelease job skipped). Will be exercised on the upstream side when launchpad is healthy at tag-time, or when the maintainer reruns post-launchpad-recovery.

got3nks added 2 commits May 3, 2026 12:27
Two related fixes for the windows-zip job in the Packaging matrix.

1) Install git in MSYS2

   packaging/windows/build.sh runs in MSYS2 bash (`shell: msys2 {0}`).
   setup-msys2 installs only the packages explicitly listed in its
   'install:' list — base MSYS2 `git` was missing from that list, so
   the MSYS2 shell had no `git` binary at all.

   `git describe --tags` inside build.sh therefore failed silently
   (the script wraps it in `2>/dev/null || echo "snapshot"`),
   producing aMule-snapshot-Windows-*.zip on every Windows packaging
   run on master, instead of the correct aMule-<version>-Windows-*.zip.

   Fix: add `git` to the setup-msys2 install list, plus a defensive
   `git config --global --add safe.directory '*'` step (actions/checkout
   configures safe.directory only for the Windows git at C:\\Program
   Files\\Git\\bin\\git.exe; MSYS2 git uses a separate global config
   that may trip the dubious-ownership guard on the workspace dir).

2) Drop --dirty from git describe in packaging/windows/build.sh

   actions/checkout on Windows uses core.autocrlf=true by default,
   converting LF to CRLF in the working tree on text files. MSYS2 git
   then sees those files as differing from the (LF) blobs in the
   index, so `git describe --tags --always --dirty` appends "-dirty"
   to the version string. Result was artifacts named
   aMule-<version>-dirty-Windows-*.zip after fix (1) above made the
   tag visible.

   --dirty is useful locally to flag uncommitted changes, but in CI a
   tagged commit should always produce a clean version string. Local
   developers can run `git status` separately if they want that
   signal.
Adds a Release workflow that fires on push of release-like tags
(aMule convention: bare semver — 2.3.3, 2.4.0-rc1; also accepts
v-prefix tags for compatibility), runs the full packaging matrix,
and assembles a draft GitHub Release with all platforms' final
artifacts attached:

- AppImage x86_64 + aarch64
- Flatpak x86_64 + aarch64
- macOS Universal2 .dmg
- Windows portable .zip x64 + arm64

Tag filter (push.tags: [0-9]* and v[0-9]*) excludes branch-backup
and topic tags like backup/*, per-peer-cap-fix, pr-* that would
otherwise fire the workflow.

Pre-release tags are auto-detected: any tag with a semver-style
hyphenated suffix after the version core (2.4.0-rc1, 2.4.0-beta,
2.4.0-alpha.2, etc.) is flagged as a GitHub pre-release. Plain
2.4.0 / v1.0 / v3 is a full release.

The workflow always produces a draft Release so a maintainer can
review the asset list and edit the auto-generated release notes
(--generate-notes pulls PR titles since the previous tag) before
publishing.

To enable reuse, packaging.yml now also exposes a workflow_call
trigger alongside its existing push and workflow_dispatch triggers;
release.yml invokes it as a reusable workflow rather than
duplicating the matrix.

The workflow is fork-testable: pushing a tag (e.g. 0.0.0-fork-test)
to a fork triggers the matrix on the fork's runners and creates the
draft Release on the fork's Releases page; no upstream involvement
required.
The macOS and Windows smoke-test steps were hardcoded to require the
banner start with 'aMuleD GIT' — the literal placeholder set by
CMakeLists.txt's `set (VERSION "GIT")` for non-tagged builds.

Once HEAD is on a release tag and the new CMake auto-detection (in
the parallel 3.0.0-beta-changelog PR) picks the tag up, the banner
becomes 'aMuleD 3.0.0-beta ...', the grep fails, and the smoke step
exits 1 — even though the binary itself is healthy.

Relax both patterns to '^aMuleD ' so they accept the dev placeholder,
the tagged-release banner, and any future version-string format
without further edits.
@mrjimenez
mrjimenez merged commit ae54f0c into amule-project:master May 3, 2026
12 checks passed
@got3nks
got3nks deleted the pr-release-workflow branch May 3, 2026 13:08
got3nks added a commit to got3nks/amule that referenced this pull request May 3, 2026
… Releases API

`amule.cpp:636` was hitting `http://amule.sourceforge.net/lastversion`,
a plain-text `MAJOR.MINOR.UPDATE` file unmaintained since the project
moved to GitHub years ago.  Repoint the request at
`https://api.github.com/repos/amule-project/amule/releases/latest`,
which returns JSON describing the most recent non-prerelease,
non-draft Release.

Pairs with the release.yml flow added in amule-project#520: once a stable tag is
published on GitHub, every aMule installation with version-check
enabled picks it up automatically on next startup, with no
maintainer step beyond un-drafting the Release.  `/releases/latest`
excludes pre-releases by design, so users on 2.3.3 stable won't be
prompted to upgrade when we tag `3.0.0-beta` / `3.0.0-rc1` —
only when 3.0.0 stable is published.

Parser changes in `CheckNewVersion()`:

 - Concatenate all lines of the downloaded file before regex-matching
   (the JSON body is pretty-printed across many lines).
 - Extract `tag_name` via `wxRegEx` — simpler than dragging in a
   full JSON parser for one well-known field.
 - Strip optional `v` prefix and any pre-release / build-metadata
   suffix (`-beta`, `-rc1`, `+build42`) before the integer
   comparison.
 - Treat tags with fewer than three components (e.g. `3.1`) as
   missing-field-= 0 rather than erroring out.
 - Clean up the temp file in early-error paths too (the original
   only removed it on the success path).

HTTPS works without transport changes — wxWebRequest support landed
in amule-project#462.  The `s_NewVersionCheck` pref still controls whether the
request fires at all.
mrjimenez pushed a commit that referenced this pull request May 3, 2026
… Releases API

`amule.cpp:636` was hitting `http://amule.sourceforge.net/lastversion`,
a plain-text `MAJOR.MINOR.UPDATE` file unmaintained since the project
moved to GitHub years ago.  Repoint the request at
`https://api.github.com/repos/amule-project/amule/releases/latest`,
which returns JSON describing the most recent non-prerelease,
non-draft Release.

Pairs with the release.yml flow added in #520: once a stable tag is
published on GitHub, every aMule installation with version-check
enabled picks it up automatically on next startup, with no
maintainer step beyond un-drafting the Release.  `/releases/latest`
excludes pre-releases by design, so users on 2.3.3 stable won't be
prompted to upgrade when we tag `3.0.0-beta` / `3.0.0-rc1` —
only when 3.0.0 stable is published.

Parser changes in `CheckNewVersion()`:

 - Concatenate all lines of the downloaded file before regex-matching
   (the JSON body is pretty-printed across many lines).
 - Extract `tag_name` via `wxRegEx` — simpler than dragging in a
   full JSON parser for one well-known field.
 - Strip optional `v` prefix and any pre-release / build-metadata
   suffix (`-beta`, `-rc1`, `+build42`) before the integer
   comparison.
 - Treat tags with fewer than three components (e.g. `3.1`) as
   missing-field-= 0 rather than erroring out.
 - Clean up the temp file in early-error paths too (the original
   only removed it on the success path).

HTTPS works without transport changes — wxWebRequest support landed
in #462.  The `s_NewVersionCheck` pref still controls whether the
request fires at all.
got3nks added a commit to got3nks/amule that referenced this pull request Jul 18, 2026
…muleweb & amuleapi (amule-project#520)

Wire "View Files" (browse a peer's shared files) through the External Connection so amuleGUI, amuleweb and amuleapi can display it — previously monolithic-only (amule-project#399). A browse becomes just another addressable search, reusing the multi-search id-space and the existing result/SSE delivery.

- feat(ec): daemon allocates a wire-safe browse search id, files results under it, and reports a real browse lifecycle over SEARCH_PROGRESS; shared GUI helpers key browse tabs by peer ECID for both monolithic and remote.
- feat(webapi): POST /api/v0/clients/{ecid}/shared_files returns a search_id; results, progress and SSE flow through the existing search surface (kind "browse").
- fix(friends): stop browse from zeroing a friend's stored IP (SetIP after construction + a LinkClient guard), which otherwise showed 0.0.0.0 after a restart and let a random peer hijack the record.
- refactor(search): single-source the optimistic placeholder-id range so search and browse can never drift apart.

Backward compatible: gated on the multi-search capability; the new tags are additive and ignored by old readers.
got3nks added a commit to got3nks/amule that referenced this pull request Jul 18, 2026
…eaped (amule-project#522)

A "View Files" browse that failed (peer denied, connect failed, or dropped mid-list) left amuleGUI stuck at (N...) instead of (Failed): the daemon read the browse lifecycle from the transient browsing client, which is reaped before amuleGUI's next SEARCH_PROGRESS poll, so EC_TAG_SEARCH_BROWSE_STATUS was omitted. Persist the browse status by search id alongside the bar (pruned in RemoveResults, bounded by the same EC search ring) and report progress from that persisted state, so the terminal status survives the client teardown. Daemon-side only. Follow-up to amule-project#520.
got3nks added a commit to got3nks/amule that referenced this pull request Jul 21, 2026
…h selected peer (amule-project#539)

Three issues with "View Files" (browse a peer's shared files, amule-project#520), in both
the monolithic client and amuleGUI:

- Re-requesting a peer whose result tab was still open did not switch to that
  tab, and
- appended a second copy of the listing into it (assuming the peer's shares had
  not changed).
- Selecting several clients and choosing View Files did nothing (the handler
  bailed unless exactly one was selected), while the same action on several
  friends already opened a tab per friend -- an inconsistency.

Add CSearchDlg::ActivateBrowseTabIfOpen(ecid): if a browse tab keyed by the
peer's client-ECID is already open, bring the Search panel forward, select that
tab, and report that it handled the request. The Friends and Clients "View
Files" handlers call it before requesting: an already-open peer switches to its
tab instead of re-browsing (no redundant request, no duplicated results); only
once the tab is closed does a fresh request go out. Both handlers now loop over
the whole selection, so multi-select opens one tab per peer consistently.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants