Move CI to Gitea Actions; this project is hosted on Gitea, not GitHub
Per explicit direction: this repository is not going on GitHub. Moved .github/workflows/ci.yml to .gitea/workflows/ci.yml (Gitea Actions' convention) and updated every doc that referenced the old path or assumed GitHub-specific features: - .gitea/workflows/ci.yml: added a header comment on the two things that are genuinely Gitea-specific and instance-dependent, not just a renamed file -- `runs-on: ubuntu-latest` must match a label the actual registered Gitea runner advertises (there is no GitHub-hosted-runner equivalent, this is self-hosted), and `actions/checkout@v4` resolves against whatever action source that runner is configured with. - CONTRIBUTING.md: corrected a claim that no longer holds -- it previously said CI "runs on a normal, unrestricted GitHub Actions VM where TSan is expected to work"; since this is actually a self-hosted Gitea runner whose environment isn't controlled by this repo, that assumption isn't something this repo can vouch for, so the text now says so rather than carrying the old (GitHub-shaped) assumption forward silently. - SECURITY.md: removed a claim this project can't back up (that "private security advisories" are available once hosted -- that's a GitHub feature this repo never had access to); reporting is by direct email to the maintainer only. - README.md: fixed a real gap while in here -- the "Security" section never actually linked to SECURITY.md despite it existing since the previous commit. - CLAUDE.md, CHANGELOG.md: updated path references; CLAUDE.md's self-evaluation section (a historical record of an audit finding) keeps the old .github path where it describes what was literally true at that time, with a note explaining the rename, rather than rewriting history. Verified: clean make all + make test, all 6 binaries pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UqJpkdJ6Njnt1pw3CbghzB
This commit is contained in:
@@ -1,3 +1,15 @@
|
||||
# Gitea Actions workflow (not GitHub Actions — this project is hosted on
|
||||
# Gitea, see CONTRIBUTING.md). Gitea Actions' YAML is GitHub-Actions-
|
||||
# compatible, but two things here are Gitea-specific and need to match
|
||||
# your actual instance, not just this repo:
|
||||
# - `runs-on: ubuntu-latest` must match a label your registered Gitea
|
||||
# runner (act_runner) actually advertises; there is no GitHub-hosted-
|
||||
# runner equivalent, this is entirely self-hosted.
|
||||
# - `uses: actions/checkout@v4` resolves against whatever action source
|
||||
# your instance's runner is configured with (by default, Gitea Actions
|
||||
# fetches actions from github.com unless DEFAULT_ACTIONS_URL is
|
||||
# overridden); use `https://gitea.com/actions/checkout@v4` instead if
|
||||
# your runner is configured to disallow GitHub as an action source.
|
||||
name: CI
|
||||
|
||||
on:
|
||||
+11
-4
@@ -47,10 +47,17 @@ pushed to any remote — there is no public release yet, only a local one.
|
||||
- **`backend_pack_new` was declared in `include/packfs.h` but never
|
||||
implemented** — any program calling it failed at link time. Implemented
|
||||
as a standalone, read-only `pack` `Backend`.
|
||||
- `.github/workflows/ci.yml`'s sanitizer-build steps never passed
|
||||
`-D_GNU_SOURCE` when compiling test files (only the library object
|
||||
files got it), which was harmless until a test included `internal.h`
|
||||
(needed for `pthread_rwlock_t`) and became a link failure.
|
||||
- The CI config's (`.gitea/workflows/ci.yml`) sanitizer-build steps never
|
||||
passed `-D_GNU_SOURCE` when compiling test files (only the library
|
||||
object files got it), which was harmless until a test included
|
||||
`internal.h` (needed for `pthread_rwlock_t`) and became a link failure.
|
||||
|
||||
### Changed
|
||||
- CI moved from a GitHub-Actions-convention config (`.github/workflows/`)
|
||||
to Gitea Actions (`.gitea/workflows/`) — this project is hosted on
|
||||
Gitea, not GitHub, and was never actually hosted on GitHub; only the
|
||||
scaffolding's starting convention changed. `SECURITY.md`, `CLAUDE.md`,
|
||||
`CONTRIBUTING.md`, and `README.md` updated to match.
|
||||
|
||||
### Documented
|
||||
- **`vfs.c`'s mount table (`MountSnapshot`) is O(n²) in mount count, the
|
||||
|
||||
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## Repository status
|
||||
|
||||
This repository contains a working v0 implementation of the `concept.md` specification: `include/packfs.h` (public API), `src/*.c` (implementation), `tests/test_*.c` (test suite), and open-source project scaffolding (`README.md`, `LICENSE`, `CONTRIBUTING.md`, `CHANGELOG.md`, `SECURITY.md`, `packfs.pc.in`, `.github/workflows/ci.yml`), alongside the frozen `concept.md` and this file. Every file under `src/` and `include/` carries an `SPDX-License-Identifier: MIT` tag; `include/packfs.h`'s `PACKFS_VERSION_*` macros are the single source of truth for the project's version — `pfs_version()` (runtime) and `packfs.pc` (generated by `make install`) are both derived from them, never maintained separately.
|
||||
This repository contains a working v0 implementation of the `concept.md` specification: `include/packfs.h` (public API), `src/*.c` (implementation), `tests/test_*.c` (test suite), and open-source project scaffolding (`README.md`, `LICENSE`, `CONTRIBUTING.md`, `CHANGELOG.md`, `SECURITY.md`, `packfs.pc.in`, `.gitea/workflows/ci.yml` — this project is hosted on Gitea, not GitHub), alongside the frozen `concept.md` and this file. Every file under `src/` and `include/` carries an `SPDX-License-Identifier: MIT` tag; `include/packfs.h`'s `PACKFS_VERSION_*` macros are the single source of truth for the project's version — `pfs_version()` (runtime) and `packfs.pc` (generated by `make install`) are both derived from them, never maintained separately.
|
||||
|
||||
## Build, test, and lint commands
|
||||
|
||||
@@ -17,7 +17,7 @@ make install PREFIX=/some/prefix
|
||||
|
||||
A single test: `make build/test_mem && ./build/test_mem` (substitute any `test_*` basename). There is no separate lint step — the build itself uses `-Wall -Wextra -Wpedantic`, and a warning introduced by a change is a build failure, not something to leave in place.
|
||||
|
||||
Sanitizer builds are not wired into `make test` (they need per-file compilation with sanitizer flags plus `-D_GNU_SOURCE -Iinclude -Isrc`); see `.github/workflows/ci.yml` for the exact invocation, which CI runs on every push. **Any change to `upper.c`, `overlay.c`, or `vfs.c` must be verified under `-fsanitize=address,undefined` and `-fsanitize=thread` before being considered done** — this is not a formality: exactly this process caught a real use-after-free in the snapshot-reclamation logic during initial development (see the `reclaim_gate` note below), which the plain build and even repeated plain test runs never surfaced.
|
||||
Sanitizer builds are not wired into `make test` (they need per-file compilation with sanitizer flags plus `-D_GNU_SOURCE -Iinclude -Isrc`); see `.gitea/workflows/ci.yml` (Gitea Actions) for the exact invocation, which CI runs on every push. **Any change to `upper.c`, `overlay.c`, or `vfs.c` must be verified under `-fsanitize=address,undefined` and `-fsanitize=thread` before being considered done** — this is not a formality: exactly this process caught a real use-after-free in the snapshot-reclamation logic during initial development (see the `reclaim_gate` note below), which the plain build and even repeated plain test runs never surfaced.
|
||||
|
||||
**If your environment cannot run ThreadSanitizer at all, say so rather than skipping it silently.** TSan needs `personality(ADDR_NO_RANDOMIZE)` to disable ASLR for itself; some sandboxes block that syscall outright, in which case *every* TSan build fails identically (`FATAL: ThreadSanitizer: unexpected memory mapping`), including a trivial unrelated pthread program — that is the confirming test, not a PackFS-specific symptom. In that situation, ASan/UBSan are still run and still matter (they are what actually caught the `reclaim_gate` bug above), but they do not perform TSan's happens-before race analysis and are not a substitute for it; a change is TSan-verified only once it has passed on a machine or CI run that can actually execute it, not merely because ASan/UBSan passed.
|
||||
|
||||
@@ -97,7 +97,7 @@ These are hard requirements stated in the spec, not stylistic suggestions — an
|
||||
|
||||
## Self-evaluation
|
||||
|
||||
**Methodology.** This file was checked against the repository's actual state (`make test` passing, including two new tests, `test_pack_write_perf` and the dedup-verification block added to `test_pack_overlay`; `include/`, `src/`, `tests/`, `bench/` present and matching the description below; confirmed by directory listing and a live build), against `concept.md` as frozen (for factual consistency of the constraints and architecture summarized above), and against the documentation standard stated in this file. This revision followed a deliberate audit for other instances of the file index's O(n²) shape elsewhere in the codebase — prompted by a request to leave no caveats undocumented — which found two more real issues, not zero: `pack_write`'s compaction dedup (O(n²), plus a latent hash-collision correctness bug, both now fixed) and the mount table (O(n²), confirmed and deliberately left unfixed, with the reasoning recorded). The audit also found and fixed a CI gap the new tests exposed — `.github/workflows/ci.yml`'s sanitizer-build steps never passed `-D_GNU_SOURCE` when compiling test files, which was harmless while no test included `internal.h` and became a real link failure once two did (`internal.h` needs it for `pthread_rwlock_t`) — and documented a sandbox flake (ASan/UBSan's own `DEADLYSIGNAL` startup race, distinct from and in addition to the already-documented TSan limitation) observed directly during this audit's own sanitizer runs, in `CONTRIBUTING.md` and cross-referenced here. Every finding below was confirmed empirically (direct `pack_write` timing, `bench/bench.c`'s new mount-scaling category, repeated sanitizer runs with `timeout`), not asserted.
|
||||
**Methodology.** This file was checked against the repository's actual state (`make test` passing, including two new tests, `test_pack_write_perf` and the dedup-verification block added to `test_pack_overlay`; `include/`, `src/`, `tests/`, `bench/` present and matching the description below; confirmed by directory listing and a live build), against `concept.md` as frozen (for factual consistency of the constraints and architecture summarized above), and against the documentation standard stated in this file. This revision followed a deliberate audit for other instances of the file index's O(n²) shape elsewhere in the codebase — prompted by a request to leave no caveats undocumented — which found two more real issues, not zero: `pack_write`'s compaction dedup (O(n²), plus a latent hash-collision correctness bug, both now fixed) and the mount table (O(n²), confirmed and deliberately left unfixed, with the reasoning recorded). The audit also found and fixed a CI gap the new tests exposed — the CI config's (now `.gitea/workflows/ci.yml`; at the time of this finding it lived at `.github/workflows/ci.yml`, before this project's scaffolding was set up for Gitea hosting instead of the GitHub-Actions convention it started from — this repository was never actually hosted on GitHub) sanitizer-build steps never passed `-D_GNU_SOURCE` when compiling test files, which was harmless while no test included `internal.h` and became a real link failure once two did (`internal.h` needs it for `pthread_rwlock_t`) — and documented a sandbox flake (ASan/UBSan's own `DEADLYSIGNAL` startup race, distinct from and in addition to the already-documented TSan limitation) observed directly during this audit's own sanitizer runs, in `CONTRIBUTING.md` and cross-referenced here. Every finding below was confirmed empirically (direct `pack_write` timing, `bench/bench.c`'s new mount-scaling category, repeated sanitizer runs with `timeout`), not asserted.
|
||||
|
||||
| Category | Grade | Notes |
|
||||
|---|---|---|
|
||||
|
||||
+10
-5
@@ -19,7 +19,7 @@ project is written in.
|
||||
|
||||
```sh
|
||||
make test # must pass before any PR
|
||||
cc ... -fsanitize=address,undefined # ASan/UBSan: see .github/workflows/ci.yml for exact flags
|
||||
cc ... -fsanitize=address,undefined # ASan/UBSan: see .gitea/workflows/ci.yml for exact flags
|
||||
cc ... -fsanitize=thread # TSan, for anything touching src/upper.c, src/overlay.c, or src/vfs.c
|
||||
```
|
||||
|
||||
@@ -41,10 +41,15 @@ it or claiming verification that didn't happen — ASan/UBSan still catch
|
||||
real bugs (they found and fixed a genuine heap-use-after-free during this
|
||||
project's development, see the `reclaim_gate` note in `internal.h`) but do
|
||||
not do TSan's happens-before race analysis, so they are not a substitute
|
||||
for it. CI (`.github/workflows/ci.yml`) runs on a normal, unrestricted
|
||||
GitHub Actions VM where TSan is expected to work; treat a change as
|
||||
TSan-verified only once it has actually passed there or on a local machine
|
||||
that can run it, not merely because ASan/UBSan passed.
|
||||
for it. CI (`.gitea/workflows/ci.yml`, Gitea Actions — this project is
|
||||
hosted on Gitea, not GitHub) runs on this project's own self-hosted
|
||||
runner; whether that runner can execute TSan depends on that runner's own
|
||||
environment, which is not controlled by this repository the way a
|
||||
hosted-runner VM would be — do not assume CI's TSan step passing means
|
||||
what it would on an unrestricted machine without having actually checked
|
||||
what environment the registered runner provides. Treat a change as
|
||||
TSan-verified only once it has actually passed on a machine confirmed able
|
||||
to run it, not merely because a CI step reported success.
|
||||
|
||||
**A second, separate environment quirk, also observed directly rather than
|
||||
assumed:** in the same kind of sandboxed environment, an ASan/UBSan-built
|
||||
|
||||
@@ -260,7 +260,7 @@ never mutates a buffer address a reader might be reading (Section 5.7):
|
||||
growth always allocates a new buffer and publishes it, never reallocates in
|
||||
place. `tests/test_concurrency.c` exercises this under concurrent reader and
|
||||
writer threads, and the suite is regularly run under ThreadSanitizer and
|
||||
AddressSanitizer (see `.github/workflows/ci.yml`).
|
||||
AddressSanitizer (see `.gitea/workflows/ci.yml`).
|
||||
|
||||
## Security
|
||||
|
||||
@@ -274,7 +274,9 @@ silently assumed equivalent. Pack files are treated as untrusted input unless
|
||||
they came from this process's own compaction: every on-disk offset is
|
||||
bounds-checked and the pack's checksum is verified before any of it is
|
||||
trusted (Section 7). See `tests/test_dir.c` for a containment regression test
|
||||
and `tests/test_pack_overlay.c` for a corrupted-pack rejection test.
|
||||
and `tests/test_pack_overlay.c` for a corrupted-pack rejection test. See
|
||||
[`SECURITY.md`](SECURITY.md) for exactly what is and isn't claimed as a
|
||||
security boundary, and how to report a vulnerability.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
+6
-6
@@ -61,10 +61,10 @@ known limitations, not silent gaps:
|
||||
|
||||
## Reporting a vulnerability
|
||||
|
||||
Please do not open a public GitHub issue for a suspected security
|
||||
vulnerability. Once this repository has a hosting remote and private
|
||||
security advisories are available there, prefer that. Until then, or as an
|
||||
alternative, report privately to the maintainer:
|
||||
This project is hosted on Gitea, not GitHub (see `CONTRIBUTING.md`).
|
||||
Please do not open a public issue on the issue tracker for a suspected
|
||||
security vulnerability — report it privately, by email, to the
|
||||
maintainer:
|
||||
|
||||
**retoor** — `retoor@molodetz.nl`
|
||||
|
||||
@@ -82,5 +82,5 @@ to pass under `-fsanitize=address,undefined` and `-fsanitize=thread`
|
||||
before being considered done (`CLAUDE.md`) — this process has already
|
||||
caught and fixed a real heap-use-after-free in the snapshot-reclamation
|
||||
logic during development (see the `reclaim_gate` note in `src/internal.h`).
|
||||
`.github/workflows/ci.yml` runs the full test suite plus both sanitizer
|
||||
passes on every push.
|
||||
`.gitea/workflows/ci.yml` (Gitea Actions) runs the full test suite plus
|
||||
both sanitizer passes on every push.
|
||||
|
||||
Reference in New Issue
Block a user