From 97a0c7e50857a4a6eba41018d78f3ef5d0ab4526 Mon Sep 17 00:00:00 2001 From: Mikhail Yenuchenko Date: Fri, 14 Aug 2026 09:47:33 +0300 Subject: [PATCH] licence,ci: ship OFL with Plex fonts and guard release dispatch (P5) IBM Plex WOFF2 files were shipped without the SIL OFL 1.1 text, NOTICE told modifiers to edit layout.html for a Source URL that lives in legal.go, and workflow_dispatch took GITHUB_REF_NAME as the version so a run from main would publish ghcr.io/...:main. Closes P5 of docs/plans/code-review.md. CHANGELOG updated. Co-Authored-By: Cursor Grok 4.6 Co-authored-by: Cursor --- .github/workflows/release.yml | 34 +++++++++--- CHANGELOG.md | 15 ++++++ NOTICE | 7 ++- build/Dockerfile | 8 ++- cmd/panel/main.go | 1 - cmd/selfpost-backup/main.go | 1 - docs/development.md | 31 +++++++---- docs/plans/code-review.md | 17 +++--- docs/plans/logrotate-mode.md | 28 ---------- docs/roadmap.md | 3 ++ internal/legal/legal.go | 5 +- internal/legal/license_test.go | 19 +++++++ internal/web/view/static/OFL.txt | 93 ++++++++++++++++++++++++++++++++ internal/web/view/static_test.go | 27 ++++++++++ test/e2e/logrotate_check.go | 3 +- 15 files changed, 232 insertions(+), 60 deletions(-) delete mode 100644 docs/plans/logrotate-mode.md create mode 100644 internal/web/view/static/OFL.txt diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0e2bb58..f03d60c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,11 +1,13 @@ name: release # Publishes an immutable, version-tagged image on ghcr.io (spec 10.1). -# Ordinary commits do not publish anything — only a pushed tag matching -# vX.Y.Z does. That tag is the single source the version comes from: it goes -# into both the image tag and the panel binary's -ldflags version, so the two -# can never drift apart (the invariant restore's version check in spec 7.5.A -# depends on). +# Ordinary commits do not publish anything. A pushed tag matching vX.Y.Z does, +# and so does workflow_dispatch when it supplies a SemVer X.Y.Z version (or +# runs on such a tag). A dispatch from main without that input must fail in +# prepare — it must not publish ghcr.io/...:main. The version is the single +# source that goes into both the image tag and the panel binary's -ldflags +# version, so the two can never drift apart (the invariant restore's version +# check in spec 7.5.A depends on). # # Native per-architecture builds (see docs/development.md), not qemu: # running the full Postfix/OpenDKIM stack under emulation for the e2e gate @@ -21,6 +23,11 @@ on: tags: - "v[0-9]+.[0-9]+.[0-9]+" workflow_dispatch: + inputs: + version: + description: "Image version as X.Y.Z (no v prefix). Required unless this run is already on a vX.Y.Z tag." + required: false + type: string permissions: contents: read @@ -32,9 +39,22 @@ jobs: outputs: version: ${{ steps.version.outputs.version }} steps: - - name: Derive version from tag + - name: Derive a SemVer X.Y.Z version id: version - run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" + env: + INPUT_VERSION: ${{ github.event.inputs.version }} + run: | + set -euo pipefail + raw="${INPUT_VERSION:-}" + if [ -z "$raw" ] && [[ "${GITHUB_REF_NAME}" == v[0-9]*.[0-9]*.[0-9]* ]]; then + raw="${GITHUB_REF_NAME#v}" + fi + raw="${raw#v}" + if ! [[ "$raw" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "::error::release version is not SemVer X.Y.Z (ref is ${GITHUB_REF_NAME}; pass inputs.version on workflow_dispatch). Refusing to publish ghcr.io/${{ github.repository }}:${GITHUB_REF_NAME}" + exit 1 + fi + echo "version=${raw}" >> "$GITHUB_OUTPUT" build: needs: prepare diff --git a/CHANGELOG.md b/CHANGELOG.md index df5f9ab..f987dd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version ### Added +- licence: the SIL Open Font License 1.1 text now travels with the IBM Plex + WOFF2 files (`internal/web/view/static/OFL.txt`). The image copies it next + to LICENSE and NOTICE under `/usr/share/doc/selfpost/`; the panel serves it + at `/static/OFL.txt`. OFL requires the licence to accompany the font. + - docs: agreed roadmap item **queue-retries** — show this Postfix's retry policy (first delay, backoff cap, queue lifetime) on Mail queue and on a delivery's history, reading `postconf -h` once at panel start so a manual @@ -61,6 +66,16 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version ### Changed +- licence: [NOTICE](NOTICE) tells modifiers to update `SourceURL` in + `internal/legal/legal.go` (the value the panel footer actually injects), not + `layout.html`. `release.yml` refuses a `workflow_dispatch` whose version is + not SemVer `X.Y.Z`, so a run from `main` cannot publish `ghcr.io/...:main`. + Per-file `SPDX-License-Identifier` headers on the two command packages were + dropped so the tree is consistent; AGPL-3.0 does not require them + ([development.md](docs/development.md) § External libraries). Deleted the + completed `docs/plans/logrotate-mode.md` (history in git and + [1.2.3](#123---2026-08-12)). + - test: the authorization and sign-in surfaces that had no tests now have them. The login limiter is covered for its ceiling, its per-address scope, the reset at the end of a window and the sweep that keeps finished buckets out of diff --git a/NOTICE b/NOTICE index ca4c34c..a4d7e16 100644 --- a/NOTICE +++ b/NOTICE @@ -10,8 +10,8 @@ Corresponding Source for the published releases is at: If you modify SelfPost and let users interact with it over a network, AGPL-3.0 §13 requires you to offer them the Corresponding Source of -your modified version. Update the Source link in the panel footer -(internal/web/view/templates/layout.html) so it points at your sources. +your modified version. Update SourceURL in internal/legal/legal.go +so the panel footer points at your sources. Third-party software included in this distribution ---------------------------------------------------- @@ -24,6 +24,9 @@ htmx 2.0.4 (internal/web/view/static/htmx.min.js) IBM Plex Sans / IBM Plex Mono Copyright © 2017 IBM Corp., with Reserved Font Name "Plex" Licence: SIL Open Font License 1.1 + Full text: internal/web/view/static/OFL.txt + (also /usr/share/doc/selfpost/OFL.txt in the image, and + /static/OFL.txt from the control panel) https://github.com/IBM/plex Distributed unmodified as three latin-subset WOFF2 files served by the control panel: diff --git a/build/Dockerfile b/build/Dockerfile index 6215816..6173b5f 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -87,12 +87,16 @@ COPY --from=build /out/panel /usr/local/bin/panel COPY --from=build /out/selfpost-backup /usr/local/bin/selfpost-backup # Licence text shipped with the image (AGPL-3.0 conveyance). The panel also -# serves the same text at /license from an embedded copy. +# serves the same text at /license from an embedded copy. OFL.txt is the SIL +# Open Font License 1.1 that must travel with the IBM Plex WOFF2 files +# embedded in the panel binary (NOTICE). COPY --chmod=0644 LICENSE NOTICE /usr/share/doc/selfpost/ +COPY --chmod=0644 internal/web/view/static/OFL.txt /usr/share/doc/selfpost/OFL.txt # File modes are pinned here so a build context copied from a checkout without # POSIX permissions (e.g. Windows tar sync) cannot land group-writable config -# that logrotate would silently ignore — see docs/plans/logrotate-mode.md. +# that logrotate would silently ignore — see docs/development.md § Building +# binaries and the image. COPY --chmod=0644 build/opendkim.conf /etc/opendkim.conf COPY --chmod=0644 build/logrotate-mail.conf /etc/logrotate.d/mail COPY --chmod=0755 build/postfix-wrapper.sh /usr/local/bin/postfix-wrapper.sh diff --git a/cmd/panel/main.go b/cmd/panel/main.go index 1f1ffa1..f07b959 100644 --- a/cmd/panel/main.go +++ b/cmd/panel/main.go @@ -4,7 +4,6 @@ // the rate-limit checks. // // Copyright (C) 2026 Mikhail Yenuchenko -// SPDX-License-Identifier: AGPL-3.0-only package main import ( diff --git a/cmd/selfpost-backup/main.go b/cmd/selfpost-backup/main.go index 7231e40..b1631a0 100644 --- a/cmd/selfpost-backup/main.go +++ b/cmd/selfpost-backup/main.go @@ -18,7 +18,6 @@ // docker exec -i selfpost-backup -decrypt < backup.spbk > backup.tar.gz // // Copyright (C) 2026 Mikhail Yenuchenko -// SPDX-License-Identifier: AGPL-3.0-only package main import ( diff --git a/docs/development.md b/docs/development.md index 1513b89..cb8b2da 100644 --- a/docs/development.md +++ b/docs/development.md @@ -93,8 +93,9 @@ mechanics → Haiku. Reviewers must not be the author of the code under review. ## External libraries The project is **AGPL-3.0** ([LICENSE](../LICENSE)). Copyright holder and -third-party notices: [NOTICE](../NOTICE). New Go dependencies must be -permissive or GPL-family (see +third-party notices: [NOTICE](../NOTICE). The tree does not use per-file +`SPDX-License-Identifier` headers; AGPL-3.0 does not require them. New Go +dependencies must be permissive or GPL-family (see [.cursor/rules/agent-rules.mdc](../.cursor/rules/agent-rules.mdc)). ### Main module (`go.mod`) @@ -113,6 +114,7 @@ the tree are AGPL-3.0-compatible. | Asset | Version | Repository | License | |---|---|---|---| | `internal/web/view/static/htmx.min.js` | 2.0.4 | | 0BSD | +| `internal/web/view/static/ibm-plex-*.woff2` | latin subset | | SIL OFL 1.1 (`OFL.txt` beside the files) | ### E2e module (`test/e2e/go.mod`) @@ -128,8 +130,10 @@ the image. Postfix, OpenDKIM, `supervisord`, `sasl2-bin`, `logrotate`, and others come from Debian bookworm repositories; licenses are in each package's `copyright` file on . -The image also ships [LICENSE](../LICENSE) and [NOTICE](../NOTICE) under -`/usr/share/doc/selfpost/`. The panel serves the AGPL text at `/license`. +The image also ships [LICENSE](../LICENSE), [NOTICE](../NOTICE), and the IBM +Plex [OFL.txt](../internal/web/view/static/OFL.txt) under +`/usr/share/doc/selfpost/`. The panel serves the AGPL text at `/license` and +the OFL text at `/static/OFL.txt`. --- @@ -187,9 +191,11 @@ tag / push only on explicit request (see `release.yml`). ### Release image -The release image is published **only on tag** `vX.Y.Z` (not on every push to -`main`). The tag is the single source of version: it drives the image tag and -`-ldflags` in the binaries so they cannot drift apart. +The release image is published **only** for a SemVer version `X.Y.Z`: a pushed +tag `vX.Y.Z`, or a `workflow_dispatch` that supplies that version (or runs on +such a tag). Ordinary commits, and a dispatch from `main` without a version +input, do not publish. The version is the single source that drives the image +tag and `-ldflags` in the binaries so they cannot drift apart. **Steps (on explicit request):** @@ -284,12 +290,17 @@ Workflows in [.github/workflows/](../.github/workflows/). What each job runs — `gofmt -l` → `go vet ./...` → `go test ./...` (main module, no e2e). -### `release.yml` — push of tag `vX.Y.Z` or `workflow_dispatch` +### `release.yml` — push of tag `vX.Y.Z`, or `workflow_dispatch` with SemVer + +`prepare` takes the version from the tag (`v1.2.5` → `1.2.5`) or from the +`workflow_dispatch` `version` input. A dispatch whose ref is not a `vX.Y.Z` +tag and whose input is missing or not `X.Y.Z` fails in `prepare` — it must +not publish `ghcr.io/...:main`. ``` -prepare (version from tag) +prepare (version from tag or workflow_dispatch input) → build [matrix: ubuntu-latest / ubuntu-24.04-arm] - → docker build --load (VERSION from tag) + → docker build --load (VERSION from prepare) → e2e (test/e2e) → push ghcr.io/...:X.Y.Z-amd64 | X.Y.Z-arm64 → merge diff --git a/docs/plans/code-review.md b/docs/plans/code-review.md index 9f2ea5c..bb095dd 100644 --- a/docs/plans/code-review.md +++ b/docs/plans/code-review.md @@ -594,13 +594,18 @@ the override. **Model: Sonnet** for OFL/NOTICE prose; **Opus** for `release.yml`; **Haiku** for SPDX consistency and deleting the done logrotate plan. -- [ ] Add SIL OFL 1.1 text beside the Plex WOFF2 files; point `NOTICE` at it. -- [ ] `NOTICE` Source URL instructions → `internal/legal/legal.go`. -- [ ] `release.yml`: `workflow_dispatch` must not publish `main` as a version +- [x] Add SIL OFL 1.1 text beside the Plex WOFF2 files; point `NOTICE` at it. + IBM Plex `LICENSE.txt` as `internal/web/view/static/OFL.txt` (copyright + + OFL 1.1). Copied into the image at `/usr/share/doc/selfpost/OFL.txt`; + served at `/static/OFL.txt`. +- [x] `NOTICE` Source URL instructions → `internal/legal/legal.go`. +- [x] `release.yml`: `workflow_dispatch` must not publish `main` as a version (require `vX.Y.Z` or an explicit `version` input that matches SemVer). -- [ ] Delete [plans/logrotate-mode.md](logrotate-mode.md) (done; git keeps it). -- [ ] Decide SPDX-everywhere vs SPDX-nowhere; do not leave two files special - without a one-line note in development.md. +- [x] Delete [plans/logrotate-mode.md](logrotate-mode.md) (done; git keeps it). +- [x] Decide SPDX-everywhere vs SPDX-nowhere; do not leave two files special + without a one-line note in development.md. SPDX-nowhere: dropped the + two `cmd/` headers; development.md § External libraries records that + AGPL-3.0 does not require per-file SPDX. **Done when:** OFL travels with the fonts; a dispatch from `main` cannot tag `ghcr.io/...:main`. diff --git a/docs/plans/logrotate-mode.md b/docs/plans/logrotate-mode.md deleted file mode 100644 index e16ecdd..0000000 --- a/docs/plans/logrotate-mode.md +++ /dev/null @@ -1,28 +0,0 @@ -# Plan: logrotate-mode (mail.log stops rotating in some images) - -**Status:** done -**Version:** patch; no schema, no configuration surface. - ---- - -## Summary - -`mail.log` stopped rotating when `/etc/logrotate.d/mail` landed in the image -with group/other write permission (e.g. build context from a Windows tar sync). -logrotate ignores such configs but exits 0, so the loop looked healthy while -the log grew without bound. - -## What shipped - -- [`build/Dockerfile`](../../build/Dockerfile): `COPY --chmod` pins config - (`0644`) and script (`0755`) modes so the image no longer depends on checkout - file modes. -- [`build/logrotate-loop.sh`](../../build/logrotate-loop.sh): preflight and - per-iteration checks refuse group/other-writable configs; logrotate stderr - mentioning `Ignoring` is fatal. -- [`test/e2e/logrotate_check.go`](../../test/e2e/logrotate_check.go): asserts - mode `644`, forced `logrotate -f`, and that a group-writable context file - still produces `644` in the image. - -`create 0640 postfix selfpost` in [`build/logrotate-mail.conf`](../../build/logrotate-mail.conf) -is unchanged — required for panel readability after rotation. diff --git a/docs/roadmap.md b/docs/roadmap.md index 40fecfd..6abc08f 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -59,6 +59,9 @@ Not inbound-relay, not DMARC ingestion, not a layer rewrite. **Done when:** see the criteria in [plans/code-review.md](plans/code-review.md). +**Progress:** P0–P5 done. Remaining: P6 (optional cleanup), P7 (Fable review +of the P0–P1 diff). + **Dependencies / risks:** P0 is confidentiality between panel roles; it jumps the feature queue. Implementation models are in the plan (Opus / Sonnet / Haiku / Fable per [development.md](development.md)). diff --git a/internal/legal/legal.go b/internal/legal/legal.go index 3eda2d9..8b69ea6 100644 --- a/internal/legal/legal.go +++ b/internal/legal/legal.go @@ -14,8 +14,9 @@ import ( var License []byte // SourceURL is where Corresponding Source for the published upstream -// releases lives. Operators who ship a modified version must point their -// users at their own sources instead (NOTICE; AGPL-3.0 §13). +// releases lives. It is injected into the panel footer by view.go. +// Operators who ship a modified version must change this constant so the +// footer points at their own sources (NOTICE; AGPL-3.0 §13). const SourceURL = "https://github.com/mixeme/selfpost" // CopyrightLine is the short copyright notice shown in the panel footer. diff --git a/internal/legal/license_test.go b/internal/legal/license_test.go index d0f11e9..35d5077 100644 --- a/internal/legal/license_test.go +++ b/internal/legal/license_test.go @@ -19,3 +19,22 @@ func TestEmbeddedLicenseMatchesRoot(t *testing.T) { t.Fatal("embedded LICENSE is empty") } } + +// NOTICE used to tell modifiers to edit layout.html for the Source URL. The +// footer reads legal.SourceURL; a fork that only changed the template would +// still advertise the upstream repo. +func TestNoticePointsAtSourceURLConstant(t *testing.T) { + notice, err := os.ReadFile(filepath.Join("..", "..", "NOTICE")) + if err != nil { + t.Fatalf("read NOTICE: %v", err) + } + if !bytes.Contains(notice, []byte("internal/legal/legal.go")) { + t.Error("NOTICE must tell modifiers to update SourceURL in internal/legal/legal.go") + } + if bytes.Contains(notice, []byte("layout.html")) { + t.Error("NOTICE still tells modifiers to edit layout.html for the Source URL") + } + if !bytes.Contains(notice, []byte("internal/web/view/static/OFL.txt")) { + t.Error("NOTICE must point at the OFL text that travels with the Plex fonts") + } +} diff --git a/internal/web/view/static/OFL.txt b/internal/web/view/static/OFL.txt new file mode 100644 index 0000000..01497cc --- /dev/null +++ b/internal/web/view/static/OFL.txt @@ -0,0 +1,93 @@ +Copyright © 2017 IBM Corp. with Reserved Font Name "Plex" + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/internal/web/view/static_test.go b/internal/web/view/static_test.go index 78e6ba9..066cafc 100644 --- a/internal/web/view/static_test.go +++ b/internal/web/view/static_test.go @@ -1,8 +1,10 @@ package view import ( + "io/fs" "net/http" "net/http/httptest" + "strings" "testing" ) @@ -26,6 +28,7 @@ func TestStaticAssetsCarryETag(t *testing.T) { // The fonts are the assets this matters most for: they are the largest // thing the panel serves and the ones a browser is most willing to keep. "ibm-plex-sans.woff2", "ibm-plex-mono-400.woff2", "ibm-plex-mono-600.woff2", + "OFL.txt", } { rec := serveStatic("/static/"+name, nil) if rec.Code != http.StatusOK { @@ -77,3 +80,27 @@ func TestStaticETagsAreContentDerived(t *testing.T) { t.Errorf("favicon.png and favicon.svg share the ETag %s", png) } } + +// OFL condition 2: the licence text must travel with the Font Software. The +// WOFF2 files are embedded; OFL.txt sits next to them so a copy of the panel +// (source tree, image, or /static/OFL.txt) always has it. +func TestOFLTravelsWithFonts(t *testing.T) { + b, err := fs.ReadFile(assetsFS, "static/OFL.txt") + if err != nil { + t.Fatalf("OFL.txt is not embedded next to the Plex WOFF2 files: %v", err) + } + body := string(b) + if !strings.Contains(body, `Reserved Font Name "Plex"`) { + t.Error("OFL.txt is missing the IBM Plex reserved-font-name notice") + } + if !strings.Contains(body, "SIL OPEN FONT LICENSE Version 1.1") { + t.Error("OFL.txt is missing the SIL OFL 1.1 text") + } + rec := serveStatic("/static/OFL.txt", nil) + if rec.Code != http.StatusOK { + t.Fatalf("GET /static/OFL.txt: status %d, want 200", rec.Code) + } + if !strings.Contains(rec.Body.String(), "SIL OPEN FONT LICENSE Version 1.1") { + t.Error("GET /static/OFL.txt did not serve the OFL text") + } +} diff --git a/test/e2e/logrotate_check.go b/test/e2e/logrotate_check.go index 98fde8c..c4ade23 100644 --- a/test/e2e/logrotate_check.go +++ b/test/e2e/logrotate_check.go @@ -10,7 +10,8 @@ import ( ) // checkLogrotateConfigMode verifies the image pins /etc/logrotate.d/mail at 0644 -// so logrotate will not silently ignore it (docs/plans/logrotate-mode.md). +// so logrotate will not silently ignore it (docs/development.md § Building +// binaries and the image). func checkLogrotateConfigMode(s *stack) error { mode, err := s.execIn("selfpost", "stat", "-c", "%a", "/etc/logrotate.d/mail") if err != nil {