v1.1.3
This commit is contained in:
+38
-4
@@ -30,17 +30,51 @@ jobs:
|
||||
rpm-package:
|
||||
runs-on: ubuntu-latest
|
||||
container: fedora:44
|
||||
env:
|
||||
WORKSPACE: ${{ gitea.workspace }}
|
||||
steps:
|
||||
- name: Build dependencies
|
||||
run: dnf -y install git golang rpm-build systemd-rpm-macros curl python3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build backend and RPM
|
||||
- name: Bootstrap minimal checkout dependency
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p "$WORKSPACE/.dnf-cache"
|
||||
dnf -y \
|
||||
--setopt=system_cachedir="$WORKSPACE/.dnf-cache" \
|
||||
--setopt=install_weak_deps=False \
|
||||
--setopt=tsflags=nodocs \
|
||||
install git-core
|
||||
find "$WORKSPACE/.dnf-cache" -type f -name '*.rpm' -delete 2>/dev/null || true
|
||||
df -h /
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build backend with minimal Go toolchain
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
dnf -y \
|
||||
--setopt=system_cachedir="$WORKSPACE/.dnf-cache" \
|
||||
--setopt=install_weak_deps=False \
|
||||
--setopt=tsflags=nodocs \
|
||||
install golang-bin
|
||||
find "$WORKSPACE/.dnf-cache" -type f -name '*.rpm' -delete 2>/dev/null || true
|
||||
bash ./build.sh
|
||||
# The backend is fully static; release the compiler before bringing in rpmbuild.
|
||||
dnf -y --setopt=system_cachedir="$WORKSPACE/.dnf-cache" remove golang-bin || true
|
||||
find "$WORKSPACE/.dnf-cache" -type f -name '*.rpm' -delete 2>/dev/null || true
|
||||
df -h /
|
||||
- name: Build RPM in low-disk mode
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
dnf -y \
|
||||
--setopt=system_cachedir="$WORKSPACE/.dnf-cache" \
|
||||
--setopt=install_weak_deps=False \
|
||||
--setopt=tsflags=nodocs \
|
||||
install rpm-build
|
||||
find "$WORKSPACE/.dnf-cache" -type f -name '*.rpm' -delete 2>/dev/null || true
|
||||
bash ./packaging/build-rpm.sh
|
||||
VERSION="$(tr -d '[:space:]' < VERSION)"
|
||||
rpm -qpi "dist/citizen-launcher-${VERSION}-1.linux.x86_64.rpm"
|
||||
df -h /
|
||||
|
||||
arch-package:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -73,21 +73,56 @@ jobs:
|
||||
container: fedora:44
|
||||
env:
|
||||
CITIZEN_LAUNCHER_RELEASE_REPO: gitea:${{ gitea.api_url }}/repos/${{ gitea.repository }}
|
||||
WORKSPACE: ${{ gitea.workspace }}
|
||||
steps:
|
||||
- name: Build dependencies
|
||||
run: dnf -y install git golang rpm-build systemd-rpm-macros curl python3
|
||||
- name: Bootstrap minimal checkout/release dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p "$WORKSPACE/.dnf-cache"
|
||||
dnf -y \
|
||||
--setopt=system_cachedir="$WORKSPACE/.dnf-cache" \
|
||||
--setopt=install_weak_deps=False \
|
||||
--setopt=tsflags=nodocs \
|
||||
install git-core jq
|
||||
find "$WORKSPACE/.dnf-cache" -type f -name '*.rpm' -delete 2>/dev/null || true
|
||||
df -h /
|
||||
- uses: actions/checkout@v4
|
||||
- name: Verify tag and build RPM
|
||||
- name: Verify tag and build backend
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
VERSION="$(tr -d '[:space:]' < VERSION)"
|
||||
test "$TAG_NAME" = "v${VERSION}"
|
||||
dnf -y \
|
||||
--setopt=system_cachedir="$WORKSPACE/.dnf-cache" \
|
||||
--setopt=install_weak_deps=False \
|
||||
--setopt=tsflags=nodocs \
|
||||
install golang-bin
|
||||
find "$WORKSPACE/.dnf-cache" -type f -name '*.rpm' -delete 2>/dev/null || true
|
||||
bash ./build.sh
|
||||
# The backend is static, so free the compiler before installing rpmbuild.
|
||||
dnf -y --setopt=system_cachedir="$WORKSPACE/.dnf-cache" remove golang-bin || true
|
||||
find "$WORKSPACE/.dnf-cache" -type f -name '*.rpm' -delete 2>/dev/null || true
|
||||
df -h /
|
||||
- name: Build RPM in low-disk mode
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
dnf -y \
|
||||
--setopt=system_cachedir="$WORKSPACE/.dnf-cache" \
|
||||
--setopt=install_weak_deps=False \
|
||||
--setopt=tsflags=nodocs \
|
||||
install rpm-build
|
||||
find "$WORKSPACE/.dnf-cache" -type f -name '*.rpm' -delete 2>/dev/null || true
|
||||
bash ./packaging/build-rpm.sh
|
||||
VERSION="$(tr -d '[:space:]' < VERSION)"
|
||||
rpm -qpi "dist/citizen-launcher-${VERSION}-1.linux.x86_64.rpm"
|
||||
df -h /
|
||||
- name: Upload RPM to Gitea
|
||||
shell: bash
|
||||
env:
|
||||
CITIZEN_JSON_BACKEND: jq
|
||||
run: |
|
||||
set -euo pipefail
|
||||
VERSION="$(tr -d '[:space:]' < VERSION)"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Gitea Actions setup
|
||||
|
||||
Citizen Launcher 1.1.2 uses Gitea Actions natively. Workflows are in `.gitea/workflows/`; the old `.github/workflows/` directory is intentionally absent.
|
||||
Citizen Launcher 1.1.3 uses Gitea Actions natively. Workflows are in `.gitea/workflows/`; the old `.github/workflows/` directory is intentionally absent.
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -26,8 +26,8 @@ If your runner uses a different label, replace `runs-on: ubuntu-latest` in both
|
||||
Push a version tag matching `VERSION`, for example:
|
||||
|
||||
```bash
|
||||
git tag v1.1.2
|
||||
git push origin v1.1.2
|
||||
git tag v1.1.3
|
||||
git push origin v1.1.3
|
||||
```
|
||||
|
||||
`.gitea/workflows/release.yml` then:
|
||||
@@ -70,3 +70,24 @@ Existing `github:owner/repo` and legacy `owner/repo` sources remain supported.
|
||||
## Reruns
|
||||
|
||||
The release helper `scripts/gitea-release.sh` is intentionally rerun-safe. Existing same-named attachments are removed before a replacement is uploaded, so rerunning a failed release does not create duplicate package assets.
|
||||
|
||||
## Small runner / Fedora RPM jobs
|
||||
|
||||
The Fedora jobs are intentionally written for constrained `act_runner` Docker roots. Do not replace the staged dependency setup with one large command such as:
|
||||
|
||||
```text
|
||||
dnf install git golang rpm-build systemd-rpm-macros curl python3
|
||||
```
|
||||
|
||||
That pulls Fedora's full Go source package, weak RPM build dependencies and other tooling at the same time and can exceed a small container root filesystem before `rpmbuild` starts.
|
||||
|
||||
The 1.1.3 workflow instead:
|
||||
|
||||
1. installs only `git-core` for checkout;
|
||||
2. stores DNF cache data on `${{ gitea.workspace }}` rather than `/var/cache/libdnf5`;
|
||||
3. disables weak dependencies and docs in the disposable build container;
|
||||
4. installs `golang-bin`, builds the static backend, then removes the compiler;
|
||||
5. installs `rpm-build` only after Go has been removed;
|
||||
6. uses `jq` instead of Python for the RPM release upload path.
|
||||
|
||||
The workflow prints `df -h /` after the major phases. If a runner still cannot fit the native Fedora build after this reduction, increase the Docker/container root storage rather than silently dropping RPM verification.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Citizen Launcher 1.1.2
|
||||
# Citizen Launcher 1.1.3
|
||||
|
||||
Citizen Launcher is a cross-distribution Star Citizen setup, launch, repair and maintenance application for Linux. The same static Go core runs on Debian/Ubuntu, Fedora/RHEL derivatives, Arch derivatives, openSUSE and generic glibc-based desktop Linux. Omarchy support is an optional integration, not a runtime requirement.
|
||||
|
||||
@@ -8,7 +8,7 @@ Citizen Launcher is a cross-distribution Star Citizen setup, launch, repair and
|
||||
|
||||
The launcher owns the fragile user-space gaming stack so users do not have to pick Wine builds, copy DXVK DLLs or rebuild prefixes by hand. Kernel, GPU driver, firmware and base-distribution upgrades remain owned by the Linux distribution.
|
||||
|
||||
The 1.0.1 gaming path was confirmed end-to-end on real hardware: launcher, RSI installation and Star Citizen playability. 1.1.2 keeps that gaming core and adds native multi-distribution packaging/update integration.
|
||||
The 1.0.1 gaming path was confirmed end-to-end on real hardware: launcher, RSI installation and Star Citizen playability. 1.1.3 keeps that gaming core, the multi-distribution packaging/update layer, and hardens Fedora RPM CI for small Gitea runners by staging build tools instead of installing the whole toolchain at once.
|
||||
|
||||
## Supported Linux families
|
||||
|
||||
@@ -32,25 +32,25 @@ The installer detects the distro family, prefers a native package found in `dist
|
||||
### Debian / Ubuntu / Mint
|
||||
|
||||
```bash
|
||||
sudo apt install ./dist/citizen-launcher_1.1.2_amd64.deb
|
||||
sudo apt install ./dist/citizen-launcher_1.1.3_amd64.deb
|
||||
```
|
||||
|
||||
### Fedora / Nobara / RHEL family
|
||||
|
||||
```bash
|
||||
sudo dnf install ./dist/citizen-launcher-1.1.2-1.linux.x86_64.rpm
|
||||
sudo dnf install ./dist/citizen-launcher-1.1.3-1.linux.x86_64.rpm
|
||||
```
|
||||
|
||||
### openSUSE Tumbleweed / Slowroll
|
||||
|
||||
```bash
|
||||
sudo zypper install ./dist/citizen-launcher-1.1.2-1.linux.x86_64.rpm
|
||||
sudo zypper install ./dist/citizen-launcher-1.1.3-1.linux.x86_64.rpm
|
||||
```
|
||||
|
||||
### Arch / Manjaro / EndeavourOS / CachyOS / Omarchy
|
||||
|
||||
```bash
|
||||
sudo pacman -U ./dist/citizen-launcher-1.1.2-1-x86_64.pkg.tar.zst
|
||||
sudo pacman -U ./dist/citizen-launcher-1.1.3-1-x86_64.pkg.tar.zst
|
||||
```
|
||||
|
||||
### Generic / immutable desktop Linux
|
||||
|
||||
+19
-23
@@ -1,35 +1,31 @@
|
||||
# Citizen Launcher 1.1.2
|
||||
# Citizen Launcher 1.1.3
|
||||
|
||||
## Gitea-native CI/CD release
|
||||
## Gitea Fedora/RPM runner hardening
|
||||
|
||||
1.1.2 keeps the confirmed playable multi-distribution 1.1.x runtime and hardens the Gitea Actions pipeline introduced in 1.1.1.
|
||||
1.1.3 keeps the confirmed playable multi-distribution 1.1.x runtime and fixes the next real Gitea `act_runner` failure found in the Fedora RPM job.
|
||||
|
||||
### Gitea workflows
|
||||
### Root cause
|
||||
|
||||
- workflows now live exclusively under `.gitea/workflows/`
|
||||
- CI keeps the full Go/race/package verification plus Fedora RPM and Arch package builds
|
||||
- tag releases are created with Gitea's REST API and built-in `GITEA_TOKEN`
|
||||
- release publishing no longer depends on the `gh` CLI
|
||||
- release jobs upload `.deb`, `.rpm`, `.pkg.tar.zst`, generic tarball and one combined `SHA256SUMS.txt`
|
||||
- upload is idempotent: a rerun replaces same-named release attachments instead of duplicating them
|
||||
The previous workflow installed `git`, the full `golang` meta package, `rpm-build`, `systemd-rpm-macros`, `curl` and `python3` in one Fedora transaction. Fedora also enabled weak dependencies by default. On a small Docker root filesystem this expanded into hundreds of packages and exhausted `/` before the RPM build even started.
|
||||
|
||||
### Gitea-aware self-update
|
||||
### Fix
|
||||
|
||||
Packages produced by Gitea Actions embed an exact `gitea:<api-repository-url>` update source. The launcher can now resolve Gitea's latest-release API and hydrate per-asset SHA-256 values from the workflow-generated `SHA256SUMS.txt`. GitHub release sources remain supported for existing installations.
|
||||
- Fedora jobs now use `git-core` instead of the full Git package.
|
||||
- Go builds use `golang-bin` rather than the `golang` meta package, avoiding the large source package.
|
||||
- `systemd-rpm-macros`, Python and other unnecessary RPM-build dependencies are no longer installed in the Fedora build phase.
|
||||
- DNF weak dependencies are disabled and documentation payloads are skipped in CI containers.
|
||||
- DNF's root cache is redirected to the mounted Gitea workspace volume.
|
||||
- Downloaded RPM cache files are deleted after each transaction.
|
||||
- The static Go backend is built first, then `golang-bin` is removed before `rpm-build` is installed. The two heavy toolchains no longer occupy the container root simultaneously.
|
||||
- The Gitea release helper now supports a `jq` JSON backend, so the Fedora release job does not need the full Python runtime just to upload an RPM.
|
||||
- Disk usage is printed between phases to make future runner-capacity problems immediately visible.
|
||||
|
||||
For privileged updates, a configured Gitea source must use HTTPS. This preserves the fail-closed package-update model.
|
||||
### Regression guards
|
||||
|
||||
### Runner portability
|
||||
|
||||
The release flow does not depend on cross-job `upload-artifact` compatibility. Each native build uploads its package directly to the Gitea Release, and the final job downloads those release attachments to create the checksum manifest. This works across a wider range of act_runner versions.
|
||||
- `tests/rpm-ci-footprint.sh` asserts the low-disk policy in both CI and release RPM jobs.
|
||||
- Gitea release-helper tests now exercise both Python and `jq` JSON backends.
|
||||
- The earlier `0644`/`Permission denied` workflow hardening remains in place.
|
||||
|
||||
### Runtime
|
||||
|
||||
Wine, DXVK, RSI Launcher setup, hardware checks, single-instance protection, repair, support bundles and the already confirmed playable Star Citizen path are unchanged.
|
||||
## Gitea CI hardening
|
||||
|
||||
- Gitea Actions invokes repository shell scripts explicitly through `bash`.
|
||||
- Nested test, build and release scripts use the same mode-independent convention.
|
||||
- Added a regression guard against direct `.sh` execution in the critical CI graph.
|
||||
- Fixes Gitea/act exit code 126 (`Permission denied`) when checkout files are mode `0644`.
|
||||
|
||||
|
||||
+39
-35
@@ -1,14 +1,20 @@
|
||||
# Citizen Launcher 1.1.2 – Verification Report
|
||||
# Citizen Launcher 1.1.3 – Verification Report
|
||||
|
||||
Date: 2026-09-01
|
||||
|
||||
## Release scope
|
||||
|
||||
Citizen Launcher 1.1.2 keeps the confirmed playable 1.1.x multi-distribution gaming core and hardens the Gitea-native CI/CD introduced in 1.1.1 against checkout permission differences.
|
||||
Citizen Launcher 1.1.3 keeps the confirmed playable multi-distribution 1.1.x gaming core and hardens Gitea-native RPM CI against constrained Fedora job-container storage.
|
||||
|
||||
## Failure reproduced from real Gitea runner log
|
||||
|
||||
The real Fedora 44 job reached dependency installation but failed before checkout/build because the transaction could not fit on `/`. The original dependency set expanded to hundreds of packages. The log ultimately reported that packages needed roughly 407 MB more root filesystem space and the `Build dependencies` step exited with status 1.
|
||||
|
||||
1.1.3 therefore treats CI container footprint as a release property, not a runner-specific workaround.
|
||||
|
||||
## Automated release gate
|
||||
|
||||
The 1.1.2 tree passes the local release gate with:
|
||||
The 1.1.3 tree passes the local release gate with:
|
||||
|
||||
- shell syntax checks for installers, packaging, Gitea release helper and tests
|
||||
- `gofmt` cleanliness
|
||||
@@ -21,14 +27,30 @@ The 1.1.2 tree passes the local release gate with:
|
||||
- generic Linux amd64 tarball build and execution check
|
||||
- Gitea workflow YAML parsing
|
||||
- assertion that legacy `.github/workflows/` does not shadow `.gitea/workflows/`
|
||||
- assertion that the release workflow does not use `gh release` or cross-job artifact actions
|
||||
- mocked Gitea REST API test covering release creation, release update on rerun, asset upload, same-name asset replacement and asset download
|
||||
- assertion that release publishing does not use `gh release` or cross-job artifact actions
|
||||
- mocked Gitea REST API test covering release creation, update on rerun, asset upload, replacement and download
|
||||
- Gitea release helper exercised with both Python and `jq` JSON backends
|
||||
- Gitea release-source parsing and `SHA256SUMS.txt` parser regression tests
|
||||
- static validation of RPM spec and Arch PKGBUILD/package hooks
|
||||
- multi-distro platform-family and immutable-host regression tests
|
||||
- native package self-update parser/asset-selection tests for DEB, RPM and pacman formats
|
||||
- full regression suite repeated successfully after forcing every repository `*.sh` file to mode `0644`; CI does not depend on executable bits
|
||||
- regression guard rejects direct repository `.sh` execution in Gitea workflow entry points
|
||||
- mode-independent shell invocation checks for Gitea/act checkouts without execute bits
|
||||
- low-disk Fedora RPM workflow policy regression test
|
||||
|
||||
## Fedora RPM low-disk policy
|
||||
|
||||
Both `.gitea/workflows/ci.yml` and `.gitea/workflows/release.yml` now enforce this shape:
|
||||
|
||||
- DNF cache moved to the mounted Gitea workspace via `system_cachedir`
|
||||
- `install_weak_deps=False`
|
||||
- `tsflags=nodocs`
|
||||
- `git-core`, not the full `git` package
|
||||
- `golang-bin`, not the `golang` meta package
|
||||
- `golang-bin` removed before `rpm-build` is installed
|
||||
- no explicit `systemd-rpm-macros` in the build container
|
||||
- no Python requirement for Fedora release upload; `jq` is used by `gitea-release.sh`
|
||||
|
||||
`tests/rpm-ci-footprint.sh` fails if the heavy one-shot dependency pattern is reintroduced.
|
||||
|
||||
## Gitea CI/CD design verified
|
||||
|
||||
@@ -37,40 +59,22 @@ Workflows live in:
|
||||
- `.gitea/workflows/ci.yml`
|
||||
- `.gitea/workflows/release.yml`
|
||||
|
||||
The release workflow uses Gitea-native contexts (`gitea.api_url`, `gitea.repository`, `gitea.ref_name`, `gitea.sha`, `gitea.token`) and the built-in job token with `code: read` / `releases: write` permissions.
|
||||
|
||||
Release packages are uploaded directly to the Gitea Release rather than moved between jobs with `actions/upload-artifact`. The final job downloads the native release packages and publishes one deterministic `SHA256SUMS.txt`.
|
||||
|
||||
The release helper is rerun-safe: an existing release is refreshed and same-named attachments are replaced instead of duplicated.
|
||||
|
||||
## Gitea-aware launcher self-update
|
||||
|
||||
A Gitea workflow build injects this form as the launcher's trusted update source:
|
||||
|
||||
```text
|
||||
gitea:<gitea.api_url>/repos/<owner>/<repo>
|
||||
```
|
||||
|
||||
The launcher resolves Gitea's latest release API and maps the release `SHA256SUMS.txt` back onto the package assets before a privileged update is allowed. Privileged Gitea sources require HTTPS. Existing GitHub release-source syntax remains supported for migration/backward compatibility.
|
||||
|
||||
A separate build check confirmed that a `gitea:https://.../api/v1/repos/owner/repo` source is successfully embedded into the static binary and reported by `self-update status`.
|
||||
Release packages are uploaded directly to the Gitea Release. The final job downloads the native packages and publishes a deterministic `SHA256SUMS.txt`. The helper is rerun-safe and replaces same-named attachments.
|
||||
|
||||
## Native package build coverage
|
||||
|
||||
The current local build environment contains Debian packaging tools, therefore these artifacts can be built and inspected locally:
|
||||
The local verification environment builds and inspects:
|
||||
|
||||
- `dist/citizen-launcher_1.1.2_amd64.deb`
|
||||
- `dist/citizen-launcher-1.1.2-linux-amd64.tar.gz`
|
||||
- `dist/citizen-launcher_1.1.3_amd64.deb`
|
||||
- `dist/citizen-launcher-1.1.3-linux-amd64.tar.gz`
|
||||
|
||||
The local environment does not provide native `rpmbuild` / Arch `makepkg`; the Gitea workflows build those in Fedora and Arch job containers:
|
||||
The Gitea workflows build these in native job containers:
|
||||
|
||||
- `citizen-launcher-1.1.2-1.linux.x86_64.rpm`
|
||||
- `citizen-launcher-1.1.2-1-x86_64.pkg.tar.zst`
|
||||
- `citizen-launcher-1.1.3-1.linux.x86_64.rpm`
|
||||
- `citizen-launcher-1.1.3-1-x86_64.pkg.tar.zst`
|
||||
|
||||
The current sandbox does not provide Docker/rpmbuild, so the exact Fedora container transaction cannot be executed locally. Instead, the workflow structure is regression-tested and the full application/package suite is executed locally. The next Gitea Fedora run is the authoritative integration check for the runner's actual storage quota.
|
||||
|
||||
## Gaming-core acceptance
|
||||
|
||||
The Star Citizen install/play path is unchanged from the already accepted 1.0.1/1.1.0 line. The CI migration changes release and update plumbing, not Wine/DXVK/RSI launch behavior.
|
||||
|
||||
## Checkout permission regression
|
||||
|
||||
The complete `tests/full-verify.sh` suite was repeated after forcing every repository `*.sh` file to Unix mode `0644`. It still completed successfully. This reproduces the Gitea/act checkout condition that caused exit code 126 and verifies that CI/CD no longer depends on executable bits for repository shell scripts. Distributed archives still mark shell scripts executable for convenience.
|
||||
The Star Citizen install/play path is unchanged from the already accepted 1.0.1/1.1.x line. This release changes CI/release plumbing, not Wine/DXVK/RSI launch behavior.
|
||||
|
||||
Binary file not shown.
@@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
appVersion = "1.1.2"
|
||||
appVersion = "1.1.3"
|
||||
releaseRepo = "github:sendnwv/omarchy-sc"
|
||||
)
|
||||
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -12,7 +12,7 @@ Panel {
|
||||
property var anchorItem: null
|
||||
property var hostWidget: null
|
||||
|
||||
property string pluginVersion: "1.1.2"
|
||||
property string pluginVersion: "1.1.3"
|
||||
property string health: "checking"
|
||||
property string depsState: "checking"
|
||||
property string depsMissing: ""
|
||||
@@ -106,7 +106,7 @@ Panel {
|
||||
values[lines[i].slice(0, p)] = lines[i].slice(p + 1)
|
||||
}
|
||||
|
||||
pluginVersion = values.plugin_version || "1.1.2"
|
||||
pluginVersion = values.plugin_version || "1.1.3"
|
||||
health = values.health || "setup"
|
||||
depsState = values.deps || "missing"
|
||||
depsMissing = values.deps_missing || ""
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
set -u
|
||||
|
||||
PLUGIN_ID="local.omarchy-citizen"
|
||||
PLUGIN_VERSION="1.1.2"
|
||||
PLUGIN_VERSION="1.1.3"
|
||||
|
||||
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||
XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"schemaVersion": 1,
|
||||
"id": "local.omarchy-citizen",
|
||||
"name": "Citizen Launcher · Omarchy",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"author": "Community prototype",
|
||||
"license": "MIT",
|
||||
"description": "Optional Omarchy bar integration for the distro-neutral Citizen Launcher.",
|
||||
|
||||
@@ -104,7 +104,7 @@ fi
|
||||
%config(noreplace) %{_sysconfdir}/citizen-launcher/release-repo
|
||||
|
||||
%changelog
|
||||
* Tue Sep 01 2026 Citizen Launcher Project - 1.1.2-1
|
||||
- Gitea Actions checkout permission hardening
|
||||
* Tue Sep 01 2026 Citizen Launcher Project - 1.1.3-1
|
||||
- Low-disk Gitea Fedora RPM build and release hardening
|
||||
* Tue Sep 01 2026 Citizen Launcher Project - 1.1.1-1
|
||||
- Multi-distribution native package support
|
||||
|
||||
@@ -13,6 +13,6 @@
|
||||
<url type="homepage">https://github.com/sendnwv/omarchy-sc</url>
|
||||
<categories><category>Game</category></categories>
|
||||
<provides><binary>citizen-launcher</binary></provides>
|
||||
<releases><release version="1.1.2" date="2026-09-01"/><release version="1.1.1" date="2026-09-01"/><release version="1.0.1" date="2026-08-31"/><release version="1.0.0" date="2026-08-31"/></releases>
|
||||
<releases><release version="1.1.3" date="2026-09-01"/><release version="1.1.1" date="2026-09-01"/><release version="1.0.1" date="2026-08-31"/><release version="1.0.0" date="2026-08-31"/></releases>
|
||||
<content_rating type="oars-1.1"/>
|
||||
</component>
|
||||
|
||||
@@ -104,7 +104,7 @@ fi
|
||||
%config(noreplace) %{_sysconfdir}/citizen-launcher/release-repo
|
||||
|
||||
%changelog
|
||||
* Tue Sep 01 2026 Citizen Launcher Project - 1.1.2-1
|
||||
- Gitea Actions checkout permission hardening
|
||||
* Tue Sep 01 2026 Citizen Launcher Project - 1.1.3-1
|
||||
- Low-disk Gitea Fedora RPM build and release hardening
|
||||
* Tue Sep 01 2026 Citizen Launcher Project - 1.1.1-1
|
||||
- Multi-distribution native package support
|
||||
|
||||
+96
-29
@@ -8,8 +8,41 @@ set -euo pipefail
|
||||
api_base="${GITEA_API_URL%/}/repos/${GITEA_REPOSITORY}"
|
||||
auth=( -H "Authorization: token ${GITEA_TOKEN}" )
|
||||
|
||||
select_json_backend() {
|
||||
case "${CITIZEN_JSON_BACKEND:-auto}" in
|
||||
python|python3)
|
||||
command -v python3 >/dev/null 2>&1 || { echo "python3 is required by CITIZEN_JSON_BACKEND" >&2; exit 2; }
|
||||
printf '%s\n' python
|
||||
;;
|
||||
jq)
|
||||
command -v jq >/dev/null 2>&1 || { echo "jq is required by CITIZEN_JSON_BACKEND" >&2; exit 2; }
|
||||
printf '%s\n' jq
|
||||
;;
|
||||
auto|"")
|
||||
if command -v python3 >/dev/null 2>&1; then
|
||||
printf '%s\n' python
|
||||
elif command -v jq >/dev/null 2>&1; then
|
||||
printf '%s\n' jq
|
||||
else
|
||||
echo "Gitea release helper needs python3 or jq" >&2
|
||||
exit 2
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Unknown CITIZEN_JSON_BACKEND=${CITIZEN_JSON_BACKEND}" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
JSON_BACKEND="$(select_json_backend)"
|
||||
|
||||
urlencode() {
|
||||
python3 -c 'import sys,urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' "$1"
|
||||
if [[ "$JSON_BACKEND" == python ]]; then
|
||||
python3 -c 'import sys,urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' "$1"
|
||||
else
|
||||
jq -rn --arg value "$1" '$value | @uri'
|
||||
fi
|
||||
}
|
||||
|
||||
release_json() {
|
||||
@@ -19,8 +52,10 @@ release_json() {
|
||||
}
|
||||
|
||||
release_payload() {
|
||||
local tag="$1" title="$2" body_file="$3" target="${4:-}"
|
||||
python3 - "$tag" "$title" "$body_file" "$target" <<'PY'
|
||||
local tag="$1" title="$2" body_file="$3" target="${4:-}" body=""
|
||||
[[ -f "$body_file" ]] && body="$(cat "$body_file")"
|
||||
if [[ "$JSON_BACKEND" == python ]]; then
|
||||
python3 - "$tag" "$title" "$body_file" "$target" <<'PY'
|
||||
import json, pathlib, sys
|
||||
body_path = pathlib.Path(sys.argv[3])
|
||||
body = body_path.read_text(encoding='utf-8') if body_path.exists() else ''
|
||||
@@ -33,6 +68,55 @@ print(json.dumps({
|
||||
'target_commitish': sys.argv[4],
|
||||
}))
|
||||
PY
|
||||
else
|
||||
jq -cn \
|
||||
--arg tag "$tag" \
|
||||
--arg title "$title" \
|
||||
--arg body "$body" \
|
||||
--arg target "$target" \
|
||||
'{tag_name:$tag,name:$title,body:$body,draft:false,prerelease:false,target_commitish:$target}'
|
||||
fi
|
||||
}
|
||||
|
||||
json_release_id() {
|
||||
if [[ "$JSON_BACKEND" == python ]]; then
|
||||
python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])'
|
||||
else
|
||||
jq -er '.id'
|
||||
fi
|
||||
}
|
||||
|
||||
json_matching_asset_ids() {
|
||||
local name="$1"
|
||||
if [[ "$JSON_BACKEND" == python ]]; then
|
||||
python3 -c 'import json,sys; name=sys.argv[1]; [print(a["id"]) for a in json.load(sys.stdin).get("assets",[]) if a.get("name")==name]' "$name"
|
||||
else
|
||||
jq -er --arg name "$name" '.assets[]? | select(.name == $name) | .id' 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
json_downloadable_assets_tsv() {
|
||||
if [[ "$JSON_BACKEND" == python ]]; then
|
||||
python3 -c '
|
||||
import json, sys
|
||||
release = json.load(sys.stdin)
|
||||
for asset in release.get("assets", []):
|
||||
name = asset.get("name", "")
|
||||
url = asset.get("browser_download_url", "")
|
||||
if not name or not url or name == "SHA256SUMS.txt":
|
||||
continue
|
||||
if name.endswith(".deb") or name.endswith(".rpm") or name.endswith(".pkg.tar.zst") or name.endswith("-linux-amd64.tar.gz"):
|
||||
print(f"{name}\t{url}")
|
||||
'
|
||||
else
|
||||
jq -r '
|
||||
.assets[]?
|
||||
| select(.name != null and .browser_download_url != null and .name != "SHA256SUMS.txt")
|
||||
| select(.name | endswith(".deb") or endswith(".rpm") or endswith(".pkg.tar.zst") or endswith("-linux-amd64.tar.gz"))
|
||||
| [.name, .browser_download_url]
|
||||
| @tsv
|
||||
'
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_release() {
|
||||
@@ -40,7 +124,7 @@ ensure_release() {
|
||||
local payload current id
|
||||
payload="$(release_payload "$tag" "$title" "$body_file" "$target")"
|
||||
if current="$(release_json "$tag" 2>/dev/null)"; then
|
||||
id="$(printf '%s' "$current" | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')"
|
||||
id="$(printf '%s' "$current" | json_release_id)"
|
||||
curl -fsS "${auth[@]}" -H 'Content-Type: application/json' \
|
||||
-X PATCH -d "$payload" "${api_base}/releases/${id}" >/dev/null
|
||||
echo "Updated Gitea release ${tag}"
|
||||
@@ -56,10 +140,10 @@ upload_asset() {
|
||||
[[ -s "$file" ]] || { echo "Asset missing/empty: $file" >&2; exit 1; }
|
||||
local rel id name enc existing_ids
|
||||
rel="$(release_json "$tag")"
|
||||
id="$(printf '%s' "$rel" | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')"
|
||||
id="$(printf '%s' "$rel" | json_release_id)"
|
||||
name="$(basename "$file")"
|
||||
enc="$(urlencode "$name")"
|
||||
existing_ids="$(printf '%s' "$rel" | python3 -c 'import json,sys; name=sys.argv[1]; [print(a["id"]) for a in json.load(sys.stdin).get("assets",[]) if a.get("name")==name]' "$name")"
|
||||
existing_ids="$(printf '%s' "$rel" | json_matching_asset_ids "$name")"
|
||||
if [[ -n "$existing_ids" ]]; then
|
||||
while IFS= read -r aid; do
|
||||
[[ -n "$aid" ]] || continue
|
||||
@@ -75,30 +159,13 @@ upload_asset() {
|
||||
download_assets() {
|
||||
local tag="$1" dir="$2"
|
||||
mkdir -p "$dir"
|
||||
local rel
|
||||
local rel name url
|
||||
rel="$(release_json "$tag")"
|
||||
printf '%s' "$rel" | python3 -c '
|
||||
import json, os, pathlib, sys, urllib.request
|
||||
out = pathlib.Path(sys.argv[1])
|
||||
release = json.load(sys.stdin)
|
||||
for asset in release.get("assets", []):
|
||||
name = asset.get("name", "")
|
||||
if not name or name == "SHA256SUMS.txt":
|
||||
continue
|
||||
if not (name.endswith(".deb") or name.endswith(".rpm") or name.endswith(".pkg.tar.zst") or name.endswith("-linux-amd64.tar.gz")):
|
||||
continue
|
||||
req = urllib.request.Request(asset["browser_download_url"])
|
||||
token = os.environ.get("GITEA_TOKEN", "")
|
||||
if token:
|
||||
req.add_header("Authorization", f"token {token}")
|
||||
with urllib.request.urlopen(req, timeout=120) as r, open(out / name, "wb") as f:
|
||||
while True:
|
||||
block = r.read(1024 * 1024)
|
||||
if not block:
|
||||
break
|
||||
f.write(block)
|
||||
print(name)
|
||||
' "$dir"
|
||||
while IFS=$'\t' read -r name url; do
|
||||
[[ -n "$name" && -n "$url" ]] || continue
|
||||
curl -fsSL "${auth[@]}" "$url" -o "$dir/$name"
|
||||
echo "$name"
|
||||
done < <(printf '%s' "$rel" | json_downloadable_assets_tsv)
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
|
||||
@@ -3,6 +3,7 @@ set -euo pipefail
|
||||
ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
bash "$ROOT/tests/verify.sh"
|
||||
bash "$ROOT/tests/mode-independence.sh"
|
||||
bash "$ROOT/tests/rpm-ci-footprint.sh"
|
||||
(cd "$ROOT/backend" && go test -race ./...)
|
||||
bash "$ROOT/backend/integration-test.sh"
|
||||
bash "$ROOT/tests/gitea-release-helper.sh"
|
||||
|
||||
@@ -25,7 +25,7 @@ class H(http.server.BaseHTTPRequestHandler):
|
||||
return r
|
||||
def do_GET(self):
|
||||
path=urllib.parse.urlparse(self.path).path
|
||||
if path.endswith('/releases/tags/v1.1.2'):
|
||||
if path.endswith('/releases/tags/v1.1.3'):
|
||||
if release is None: self.send_error(404); return
|
||||
self.sendj(200,self.rel()); return
|
||||
if path.startswith('/download/'):
|
||||
@@ -78,12 +78,23 @@ export GITEA_API_URL="http://127.0.0.1:${PORT}/api/v1"
|
||||
export GITEA_REPOSITORY="owner/repo"
|
||||
export GITEA_TOKEN="test-token"
|
||||
|
||||
echo first > "$TMP/citizen-launcher_1.1.2_amd64.deb"
|
||||
bash "$ROOT/scripts/gitea-release.sh" ensure v1.1.2 'Citizen Launcher 1.1.2' "$ROOT/RELEASE_NOTES.md" deadbeef
|
||||
bash "$ROOT/scripts/gitea-release.sh" ensure v1.1.2 'Citizen Launcher 1.1.2' "$ROOT/RELEASE_NOTES.md" deadbeef
|
||||
bash "$ROOT/scripts/gitea-release.sh" upload v1.1.2 "$TMP/citizen-launcher_1.1.2_amd64.deb"
|
||||
echo replacement > "$TMP/citizen-launcher_1.1.2_amd64.deb"
|
||||
bash "$ROOT/scripts/gitea-release.sh" upload v1.1.2 "$TMP/citizen-launcher_1.1.2_amd64.deb"
|
||||
bash "$ROOT/scripts/gitea-release.sh" download-assets v1.1.2 "$TMP/download"
|
||||
cmp "$TMP/citizen-launcher_1.1.2_amd64.deb" "$TMP/download/citizen-launcher_1.1.2_amd64.deb"
|
||||
echo 'Gitea release helper verification: OK'
|
||||
echo first > "$TMP/citizen-launcher_1.1.3_amd64.deb"
|
||||
bash "$ROOT/scripts/gitea-release.sh" ensure v1.1.3 'Citizen Launcher 1.1.3' "$ROOT/RELEASE_NOTES.md" deadbeef
|
||||
bash "$ROOT/scripts/gitea-release.sh" ensure v1.1.3 'Citizen Launcher 1.1.3' "$ROOT/RELEASE_NOTES.md" deadbeef
|
||||
bash "$ROOT/scripts/gitea-release.sh" upload v1.1.3 "$TMP/citizen-launcher_1.1.3_amd64.deb"
|
||||
echo replacement > "$TMP/citizen-launcher_1.1.3_amd64.deb"
|
||||
bash "$ROOT/scripts/gitea-release.sh" upload v1.1.3 "$TMP/citizen-launcher_1.1.3_amd64.deb"
|
||||
bash "$ROOT/scripts/gitea-release.sh" download-assets v1.1.3 "$TMP/download"
|
||||
cmp "$TMP/citizen-launcher_1.1.3_amd64.deb" "$TMP/download/citizen-launcher_1.1.3_amd64.deb"
|
||||
|
||||
# Fedora RPM jobs intentionally avoid Python to keep the container footprint low.
|
||||
# Exercise the jq backend against the same mock Gitea API.
|
||||
command -v jq >/dev/null 2>&1 || { echo 'jq required for Gitea helper jq test' >&2; exit 1; }
|
||||
export CITIZEN_JSON_BACKEND=jq
|
||||
echo jq-backend > "$TMP/citizen-launcher-1.1.3-1.linux.x86_64.rpm"
|
||||
bash "$ROOT/scripts/gitea-release.sh" ensure v1.1.3 'Citizen Launcher 1.1.3' "$ROOT/RELEASE_NOTES.md" deadbeef
|
||||
bash "$ROOT/scripts/gitea-release.sh" upload v1.1.3 "$TMP/citizen-launcher-1.1.3-1.linux.x86_64.rpm"
|
||||
bash "$ROOT/scripts/gitea-release.sh" download-assets v1.1.3 "$TMP/download-jq"
|
||||
cmp "$TMP/citizen-launcher-1.1.3-1.linux.x86_64.rpm" "$TMP/download-jq/citizen-launcher-1.1.3-1.linux.x86_64.rpm"
|
||||
|
||||
echo 'Gitea release helper verification: OK (python + jq)'
|
||||
|
||||
@@ -9,7 +9,7 @@ root = Path(sys.argv[1])
|
||||
check = [
|
||||
root/'build.sh', root/'install-omarchy.sh', root/'INSTALLIEREN.sh',
|
||||
root/'tests/full-verify.sh', root/'tests/verify.sh', root/'tests/package-verify.sh',
|
||||
root/'tests/gitea-release-helper.sh', root/'packaging/build-all.sh',
|
||||
root/'tests/gitea-release-helper.sh', root/'tests/rpm-ci-footprint.sh', root/'packaging/build-all.sh',
|
||||
root/'.gitea/workflows/ci.yml', root/'.gitea/workflows/release.yml',
|
||||
]
|
||||
for p in check:
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
python3 - "$ROOT" <<'PY'
|
||||
from pathlib import Path
|
||||
import re, sys, yaml
|
||||
root = Path(sys.argv[1])
|
||||
checks = [
|
||||
(root/'.gitea/workflows/ci.yml', 'rpm-package'),
|
||||
(root/'.gitea/workflows/release.yml', 'rpm'),
|
||||
]
|
||||
for path, job_name in checks:
|
||||
data = yaml.safe_load(path.read_text())
|
||||
job = data['jobs'][job_name]
|
||||
runs = '\n'.join(str(step.get('run','')) for step in job.get('steps',[]))
|
||||
flat = re.sub(r'\\\n\s*', ' ', runs)
|
||||
flat = re.sub(r'\s+', ' ', flat)
|
||||
required = [
|
||||
'system_cachedir=',
|
||||
'install_weak_deps=False',
|
||||
'tsflags=nodocs',
|
||||
'install git-core',
|
||||
'install golang-bin',
|
||||
'remove golang-bin',
|
||||
'install rpm-build',
|
||||
]
|
||||
for needle in required:
|
||||
if needle not in flat:
|
||||
raise SystemExit(f'{path.name}:{job_name} missing low-disk guard: {needle}')
|
||||
forbidden = ['systemd-rpm-macros', 'install git golang', 'install golang rpm-build', 'install python3']
|
||||
for needle in forbidden:
|
||||
if needle in flat:
|
||||
raise SystemExit(f'{path.name}:{job_name} reintroduced heavy dependency set: {needle}')
|
||||
if flat.index('install golang-bin') > flat.index('remove golang-bin') or flat.index('remove golang-bin') > flat.index('install rpm-build'):
|
||||
raise SystemExit(f'{path.name}:{job_name} no longer stages Go before rpmbuild')
|
||||
print('RPM CI low-disk dependency policy: OK')
|
||||
PY
|
||||
+1
-1
@@ -5,7 +5,7 @@ for f in \
|
||||
"$ROOT/install.sh" "$ROOT/uninstall.sh" "$ROOT/install-omarchy.sh" "$ROOT/INSTALLIEREN.sh" \
|
||||
"$ROOT/build.sh" "$ROOT/packaging/build-deb.sh" "$ROOT/packaging/build-rpm.sh" \
|
||||
"$ROOT/packaging/build-arch.sh" "$ROOT/packaging/build-tarball.sh" "$ROOT/packaging/build-all.sh" \
|
||||
"$ROOT/scripts/gitea-release.sh" "$ROOT/tests/gitea-release-helper.sh" "$ROOT/tests/mode-independence.sh"; do
|
||||
"$ROOT/scripts/gitea-release.sh" "$ROOT/tests/gitea-release-helper.sh" "$ROOT/tests/mode-independence.sh" "$ROOT/tests/rpm-ci-footprint.sh"; do
|
||||
bash -n "$f"
|
||||
done
|
||||
(cd "$ROOT/backend" && gofmt -w cmd/citizen-launcher && go test ./... && go vet ./...)
|
||||
|
||||
Reference in New Issue
Block a user