licence,ci: ship OFL with Plex fonts and guard release dispatch (P5)
test / test (push) Has been cancelled
test / test (push) Has been cancelled
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 <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
+6
-2
@@ -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
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
// the rate-limit checks.
|
||||
//
|
||||
// Copyright (C) 2026 Mikhail Yenuchenko
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
package main
|
||||
|
||||
import (
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
// docker exec -i <container> selfpost-backup -decrypt < backup.spbk > backup.tar.gz
|
||||
//
|
||||
// Copyright (C) 2026 Mikhail Yenuchenko
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
package main
|
||||
|
||||
import (
|
||||
|
||||
+21
-10
@@ -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 | <https://github.com/bigskysoftware/htmx> | 0BSD |
|
||||
| `internal/web/view/static/ibm-plex-*.woff2` | latin subset | <https://github.com/IBM/plex> | 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 <https://packages.debian.org/bookworm/>.
|
||||
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
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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.
|
||||
@@ -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)).
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user