Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9943033fdc |
@@ -1,2 +0,0 @@
|
|||||||
github: sudolulo
|
|
||||||
ko_fi: sudolulo
|
|
||||||
@@ -43,21 +43,20 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
# uv-managed interpreters instead of actions/setup-python: the prebuilt-CPython
|
- uses: actions/setup-python@v5
|
||||||
# download path setup-python relies on does not work on the self-hosted Gitea
|
with:
|
||||||
# runner (all three matrix jobs failed at setup there while passing on GitHub);
|
python-version: ${{ matrix.python }}
|
||||||
# uv works identically on both.
|
|
||||||
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
- name: install dev deps
|
||||||
|
run: python -m pip install --upgrade pip pytest ruff
|
||||||
|
|
||||||
- name: ruff
|
- name: ruff
|
||||||
# Pinned: an unpinned ruff means any upstream release can turn main red
|
run: ruff check patch tests tools
|
||||||
# with no code change.
|
|
||||||
run: uvx ruff@0.16.1 check patch tests tools
|
|
||||||
|
|
||||||
- name: pytest
|
- name: pytest
|
||||||
run: uvx --python ${{ matrix.python }} pytest tests -v
|
run: pytest tests -v
|
||||||
|
|
||||||
- name: verify injected middleware blocks compile
|
- name: verify injected middleware blocks compile
|
||||||
# Belt-and-braces: the *_BLOCK strings are appended into live middlewared
|
# Belt-and-braces: the *_BLOCK strings are appended into live middlewared
|
||||||
# modules. A syntax error there would break the box at boot.
|
# modules. A syntax error there would break the box at boot.
|
||||||
run: uvx --python ${{ matrix.python }} pytest tests/test_apply_blocks.py -v
|
run: pytest tests/test_apply_blocks.py -v
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ jobs:
|
|||||||
echo "--- release body ---"
|
echo "--- release body ---"
|
||||||
cat /tmp/notes.md
|
cat /tmp/notes.md
|
||||||
|
|
||||||
# This repo is canonically hosted on Gitea (git.arch.fyi) and mirrored to
|
# This repo is canonically hosted on Gitea (git.onetick.ninja) and mirrored to
|
||||||
# GitHub, and BOTH run this workflow -- Gitea reads .github/workflows too. So
|
# GitHub, and BOTH run this workflow -- Gitea reads .github/workflows too. So
|
||||||
# the publish step has to work on whichever forge it lands on. Everything
|
# the publish step has to work on whichever forge it lands on. Everything
|
||||||
# above is forge-agnostic; only the "create a release" API differs.
|
# above is forge-agnostic; only the "create a release" API differs.
|
||||||
|
|||||||
@@ -9,18 +9,6 @@ worse than no alert, because one day it carries a security fix.
|
|||||||
## Unreleased
|
## Unreleased
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **CI's python matrix is green on the self-hosted Gitea runner again.** The real
|
|
||||||
failure was that the Gitea runner image executes jobs as root, and the two
|
|
||||||
unreadable-sidecar tests build their scenario with `chmod(0)` — which cannot make
|
|
||||||
a file unreadable for root (`CAP_DAC_OVERRIDE`). Those two tests now skip as root
|
|
||||||
with that reason; GitHub's non-root runner still exercises them. The matrix also
|
|
||||||
moved to uv-managed interpreters (one toolchain across both runners) and ruff is
|
|
||||||
pinned to 0.16.1 so an upstream ruff release can't turn `main` red without a code
|
|
||||||
change.
|
|
||||||
- **README badges point at the public GitHub mirror** (workflow status and
|
|
||||||
releases) instead of the private forge. The release badge had also been reading
|
|
||||||
the stale Gitea v0.6.1 release instead of the current v0.7.0 on GitHub.
|
|
||||||
|
|
||||||
- **`master` is now labelled `27-dev`, because it is not the next release.** iX
|
- **`master` is now labelled `27-dev`, because it is not the next release.** iX
|
||||||
branches each major onto its own `release/` line and master rolls straight on to the
|
branches each major onto its own `release/` line and master rolls straight on to the
|
||||||
one after — on 2026-07-14 every recent commit on master targeted `27.0.0-BETA.1`
|
one after — on 2026-07-14 every recent commit on master targeted `27.0.0-BETA.1`
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
truenas-truecloud-patch
|
|
||||||
|
|
||||||
Parts of this project were written with AI assistance (Claude); all of it is
|
|
||||||
reviewed and tested before release.
|
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
# truenas-truecloud-patch
|
# truenas-truecloud-patch
|
||||||
|
|
||||||
[](https://git.arch.fyi/flan/truenas-truecloud-patch/actions)
|
|
||||||
|
|
||||||
Extends TrueNAS SCALE's **TrueCloud Backup** to:
|
Extends TrueNAS SCALE's **TrueCloud Backup** to:
|
||||||
|
|
||||||
- back up to **Backblaze B2 and any S3-compatible provider**, not just Storj;
|
- back up to **Backblaze B2 and any S3-compatible provider**, not just Storj;
|
||||||
@@ -238,7 +236,5 @@ and restores the original UI bundle from backup.
|
|||||||
- Filing a TrueNAS bug? **Remove the patch first** and reproduce on a stock system.
|
- Filing a TrueNAS bug? **Remove the patch first** and reproduce on a stock system.
|
||||||
- Provided as-is, no warranty. See LICENSE.
|
- Provided as-is, no warranty. See LICENSE.
|
||||||
|
|
||||||
## Support
|
Parts of this project were written with AI assistance (Claude); all of it is reviewed
|
||||||
|
and tested before release. Bugs are mine.
|
||||||
If truenas-truecloud-patch is useful to you, consider supporting development via
|
|
||||||
[GitHub Sponsors](https://github.com/sponsors/sudolulo) or [Ko-fi](https://ko-fi.com/sudolulo).
|
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ are worth calling out, because nothing else would catch what they catch:
|
|||||||
newest CHANGELOG entry. `VERSION=` had silently drifted to three different
|
newest CHANGELOG entry. `VERSION=` had silently drifted to three different
|
||||||
values across the scripts before anything checked.
|
values across the scripts before anything checked.
|
||||||
|
|
||||||
The project is hosted on **Gitea** (`git.arch.fyi/flan/truenas-truecloud-patch`)
|
The project is hosted on **Gitea** (`git.onetick.ninja/flan/truenas-truecloud-patch`)
|
||||||
and mirrored to GitHub. Both run the same workflows — Gitea reads
|
and mirrored to GitHub. Both run the same workflows — Gitea reads
|
||||||
`.github/workflows/` too — so a change is checked twice, on two independent runners.
|
`.github/workflows/` too — so a change is checked twice, on two independent runners.
|
||||||
|
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ _VERSION_RE = re.compile(r'^VERSION="([^"]+)"', re.M)
|
|||||||
#: owner/repo out of any of:
|
#: owner/repo out of any of:
|
||||||
#: git@github.com:sudolulo/repo.git
|
#: git@github.com:sudolulo/repo.git
|
||||||
#: https://github.com/sudolulo/repo.git
|
#: https://github.com/sudolulo/repo.git
|
||||||
#: ssh://git@git.arch.fyi:55214/flan/repo.git
|
#: ssh://git@git.onetick.ninja:55214/flan/repo.git
|
||||||
#: https://git.arch.fyi/flan/repo.git
|
#: https://git.onetick.ninja/flan/repo.git
|
||||||
#: The SSH port is deliberately not captured: it is not the web port.
|
#: The SSH port is deliberately not captured: it is not the web port.
|
||||||
_REMOTE_RE = re.compile(
|
_REMOTE_RE = re.compile(
|
||||||
r"^(?:\w+://)?(?:[^@/]+@)?([^:/]+)(?::\d+)?[:/]([^/]+)/([^/]+?)(?:\.git)?/?$"
|
r"^(?:\w+://)?(?:[^@/]+@)?([^:/]+)(?::\d+)?[:/]([^/]+)/([^/]+?)(?:\.git)?/?$"
|
||||||
|
|||||||
@@ -1914,9 +1914,6 @@ class TestTheSnapshotRecordIsNeverLostToAnUnreadableFile:
|
|||||||
only record of a tree it had just failed to read.
|
only record of a tree it had just failed to read.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@pytest.mark.skipif(os.geteuid() == 0, reason=
|
|
||||||
"chmod(0) cannot make a file unreadable for root (CAP_DAC_OVERRIDE); "
|
|
||||||
"the Gitea runner image executes jobs as root")
|
|
||||||
def test_an_unreadable_sidecar_raises_rather_than_reading_as_empty(self, tmp_path):
|
def test_an_unreadable_sidecar_raises_rather_than_reading_as_empty(self, tmp_path):
|
||||||
sc = tmp_path / "cloud_backup-5.snapshot"
|
sc = tmp_path / "cloud_backup-5.snapshot"
|
||||||
sc.write_text("Tap@snap\n")
|
sc.write_text("Tap@snap\n")
|
||||||
@@ -1930,9 +1927,6 @@ class TestTheSnapshotRecordIsNeverLostToAnUnreadableFile:
|
|||||||
def test_a_missing_sidecar_is_simply_empty(self, tmp_path):
|
def test_a_missing_sidecar_is_simply_empty(self, tmp_path):
|
||||||
assert tn._read_sidecar(str(tmp_path / "nope")) == []
|
assert tn._read_sidecar(str(tmp_path / "nope")) == []
|
||||||
|
|
||||||
@pytest.mark.skipif(os.geteuid() == 0, reason=
|
|
||||||
"chmod(0) cannot make a file unreadable for root (CAP_DAC_OVERRIDE); "
|
|
||||||
"the Gitea runner image executes jobs as root")
|
|
||||||
def test_cleanup_all_still_UNMOUNTS_when_a_sidecar_cannot_be_read(self, tmp_path):
|
def test_cleanup_all_still_UNMOUNTS_when_a_sidecar_cannot_be_read(self, tmp_path):
|
||||||
# cleanup_all is what recover.sh and uninstall.sh call, i.e. it runs precisely
|
# cleanup_all is what recover.sh and uninstall.sh call, i.e. it runs precisely
|
||||||
# when the box is already stuck. Its job is to get the mounts off. Aborting on
|
# when the box is already stuck. Its job is to get the mounts off. Aborting on
|
||||||
|
|||||||
Reference in New Issue
Block a user