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
|
name: release
|
||||||
|
|
||||||
# Publishes an immutable, version-tagged image on ghcr.io (spec 10.1).
|
# Publishes an immutable, version-tagged image on ghcr.io (spec 10.1).
|
||||||
# Ordinary commits do not publish anything — only a pushed tag matching
|
# Ordinary commits do not publish anything. A pushed tag matching vX.Y.Z does,
|
||||||
# vX.Y.Z does. That tag is the single source the version comes from: it goes
|
# and so does workflow_dispatch when it supplies a SemVer X.Y.Z version (or
|
||||||
# into both the image tag and the panel binary's -ldflags version, so the two
|
# runs on such a tag). A dispatch from main without that input must fail in
|
||||||
# can never drift apart (the invariant restore's version check in spec 7.5.A
|
# prepare — it must not publish ghcr.io/...:main. The version is the single
|
||||||
# depends on).
|
# 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:
|
# Native per-architecture builds (see docs/development.md), not qemu:
|
||||||
# running the full Postfix/OpenDKIM stack under emulation for the e2e gate
|
# running the full Postfix/OpenDKIM stack under emulation for the e2e gate
|
||||||
@@ -21,6 +23,11 @@ on:
|
|||||||
tags:
|
tags:
|
||||||
- "v[0-9]+.[0-9]+.[0-9]+"
|
- "v[0-9]+.[0-9]+.[0-9]+"
|
||||||
workflow_dispatch:
|
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:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -32,9 +39,22 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
version: ${{ steps.version.outputs.version }}
|
version: ${{ steps.version.outputs.version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Derive version from tag
|
- name: Derive a SemVer X.Y.Z version
|
||||||
id: 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:
|
build:
|
||||||
needs: prepare
|
needs: prepare
|
||||||
|
|||||||
@@ -7,6 +7,11 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
|
|||||||
|
|
||||||
### Added
|
### 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
|
- docs: agreed roadmap item **queue-retries** — show this Postfix's retry
|
||||||
policy (first delay, backoff cap, queue lifetime) on Mail queue and on a
|
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
|
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
|
### 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.
|
- 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
|
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
|
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,
|
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
|
AGPL-3.0 §13 requires you to offer them the Corresponding Source of
|
||||||
your modified version. Update the Source link in the panel footer
|
your modified version. Update SourceURL in internal/legal/legal.go
|
||||||
(internal/web/view/templates/layout.html) so it points at your sources.
|
so the panel footer points at your sources.
|
||||||
|
|
||||||
Third-party software included in this distribution
|
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
|
IBM Plex Sans / IBM Plex Mono
|
||||||
Copyright © 2017 IBM Corp., with Reserved Font Name "Plex"
|
Copyright © 2017 IBM Corp., with Reserved Font Name "Plex"
|
||||||
Licence: SIL Open Font License 1.1
|
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
|
https://github.com/IBM/plex
|
||||||
Distributed unmodified as three latin-subset WOFF2 files served by the
|
Distributed unmodified as three latin-subset WOFF2 files served by the
|
||||||
control panel:
|
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
|
COPY --from=build /out/selfpost-backup /usr/local/bin/selfpost-backup
|
||||||
|
|
||||||
# Licence text shipped with the image (AGPL-3.0 conveyance). The panel also
|
# 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 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
|
# 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
|
# 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/opendkim.conf /etc/opendkim.conf
|
||||||
COPY --chmod=0644 build/logrotate-mail.conf /etc/logrotate.d/mail
|
COPY --chmod=0644 build/logrotate-mail.conf /etc/logrotate.d/mail
|
||||||
COPY --chmod=0755 build/postfix-wrapper.sh /usr/local/bin/postfix-wrapper.sh
|
COPY --chmod=0755 build/postfix-wrapper.sh /usr/local/bin/postfix-wrapper.sh
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
// the rate-limit checks.
|
// the rate-limit checks.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2026 Mikhail Yenuchenko
|
// Copyright (C) 2026 Mikhail Yenuchenko
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
// docker exec -i <container> selfpost-backup -decrypt < backup.spbk > backup.tar.gz
|
// docker exec -i <container> selfpost-backup -decrypt < backup.spbk > backup.tar.gz
|
||||||
//
|
//
|
||||||
// Copyright (C) 2026 Mikhail Yenuchenko
|
// Copyright (C) 2026 Mikhail Yenuchenko
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
+21
-10
@@ -93,8 +93,9 @@ mechanics → Haiku. Reviewers must not be the author of the code under review.
|
|||||||
## External libraries
|
## External libraries
|
||||||
|
|
||||||
The project is **AGPL-3.0** ([LICENSE](../LICENSE)). Copyright holder and
|
The project is **AGPL-3.0** ([LICENSE](../LICENSE)). Copyright holder and
|
||||||
third-party notices: [NOTICE](../NOTICE). New Go dependencies must be
|
third-party notices: [NOTICE](../NOTICE). The tree does not use per-file
|
||||||
permissive or GPL-family (see
|
`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)).
|
[.cursor/rules/agent-rules.mdc](../.cursor/rules/agent-rules.mdc)).
|
||||||
|
|
||||||
### Main module (`go.mod`)
|
### Main module (`go.mod`)
|
||||||
@@ -113,6 +114,7 @@ the tree are AGPL-3.0-compatible.
|
|||||||
| Asset | Version | Repository | License |
|
| Asset | Version | Repository | License |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| `internal/web/view/static/htmx.min.js` | 2.0.4 | <https://github.com/bigskysoftware/htmx> | 0BSD |
|
| `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`)
|
### E2e module (`test/e2e/go.mod`)
|
||||||
|
|
||||||
@@ -128,8 +130,10 @@ the image.
|
|||||||
Postfix, OpenDKIM, `supervisord`, `sasl2-bin`, `logrotate`, and others come
|
Postfix, OpenDKIM, `supervisord`, `sasl2-bin`, `logrotate`, and others come
|
||||||
from Debian bookworm repositories; licenses are in each package's `copyright`
|
from Debian bookworm repositories; licenses are in each package's `copyright`
|
||||||
file on <https://packages.debian.org/bookworm/>.
|
file on <https://packages.debian.org/bookworm/>.
|
||||||
The image also ships [LICENSE](../LICENSE) and [NOTICE](../NOTICE) under
|
The image also ships [LICENSE](../LICENSE), [NOTICE](../NOTICE), and the IBM
|
||||||
`/usr/share/doc/selfpost/`. The panel serves the AGPL text at `/license`.
|
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
|
### Release image
|
||||||
|
|
||||||
The release image is published **only on tag** `vX.Y.Z` (not on every push to
|
The release image is published **only** for a SemVer version `X.Y.Z`: a pushed
|
||||||
`main`). The tag is the single source of version: it drives the image tag and
|
tag `vX.Y.Z`, or a `workflow_dispatch` that supplies that version (or runs on
|
||||||
`-ldflags` in the binaries so they cannot drift apart.
|
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):**
|
**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).
|
`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]
|
→ build [matrix: ubuntu-latest / ubuntu-24.04-arm]
|
||||||
→ docker build --load (VERSION from tag)
|
→ docker build --load (VERSION from prepare)
|
||||||
→ e2e (test/e2e)
|
→ e2e (test/e2e)
|
||||||
→ push ghcr.io/...:X.Y.Z-amd64 | X.Y.Z-arm64
|
→ push ghcr.io/...:X.Y.Z-amd64 | X.Y.Z-arm64
|
||||||
→ merge
|
→ merge
|
||||||
|
|||||||
@@ -594,13 +594,18 @@ the override.
|
|||||||
**Model: Sonnet** for OFL/NOTICE prose; **Opus** for `release.yml`; **Haiku**
|
**Model: Sonnet** for OFL/NOTICE prose; **Opus** for `release.yml`; **Haiku**
|
||||||
for SPDX consistency and deleting the done logrotate plan.
|
for SPDX consistency and deleting the done logrotate plan.
|
||||||
|
|
||||||
- [ ] Add SIL OFL 1.1 text beside the Plex WOFF2 files; point `NOTICE` at it.
|
- [x] Add SIL OFL 1.1 text beside the Plex WOFF2 files; point `NOTICE` at it.
|
||||||
- [ ] `NOTICE` Source URL instructions → `internal/legal/legal.go`.
|
IBM Plex `LICENSE.txt` as `internal/web/view/static/OFL.txt` (copyright
|
||||||
- [ ] `release.yml`: `workflow_dispatch` must not publish `main` as a version
|
+ 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).
|
(require `vX.Y.Z` or an explicit `version` input that matches SemVer).
|
||||||
- [ ] Delete [plans/logrotate-mode.md](logrotate-mode.md) (done; git keeps it).
|
- [x] Delete [plans/logrotate-mode.md](logrotate-mode.md) (done; git keeps it).
|
||||||
- [ ] Decide SPDX-everywhere vs SPDX-nowhere; do not leave two files special
|
- [x] Decide SPDX-everywhere vs SPDX-nowhere; do not leave two files special
|
||||||
without a one-line note in development.md.
|
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
|
**Done when:** OFL travels with the fonts; a dispatch from `main` cannot tag
|
||||||
`ghcr.io/...:main`.
|
`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
|
**Done when:** see the criteria in
|
||||||
[plans/code-review.md](plans/code-review.md).
|
[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
|
**Dependencies / risks:** P0 is confidentiality between panel roles; it
|
||||||
jumps the feature queue. Implementation models are in the plan (Opus / Sonnet
|
jumps the feature queue. Implementation models are in the plan (Opus / Sonnet
|
||||||
/ Haiku / Fable per [development.md](development.md)).
|
/ Haiku / Fable per [development.md](development.md)).
|
||||||
|
|||||||
@@ -14,8 +14,9 @@ import (
|
|||||||
var License []byte
|
var License []byte
|
||||||
|
|
||||||
// SourceURL is where Corresponding Source for the published upstream
|
// SourceURL is where Corresponding Source for the published upstream
|
||||||
// releases lives. Operators who ship a modified version must point their
|
// releases lives. It is injected into the panel footer by view.go.
|
||||||
// users at their own sources instead (NOTICE; AGPL-3.0 §13).
|
// 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"
|
const SourceURL = "https://github.com/mixeme/selfpost"
|
||||||
|
|
||||||
// CopyrightLine is the short copyright notice shown in the panel footer.
|
// 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")
|
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
|
package view
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -26,6 +28,7 @@ func TestStaticAssetsCarryETag(t *testing.T) {
|
|||||||
// The fonts are the assets this matters most for: they are the largest
|
// 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.
|
// 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",
|
"ibm-plex-sans.woff2", "ibm-plex-mono-400.woff2", "ibm-plex-mono-600.woff2",
|
||||||
|
"OFL.txt",
|
||||||
} {
|
} {
|
||||||
rec := serveStatic("/static/"+name, nil)
|
rec := serveStatic("/static/"+name, nil)
|
||||||
if rec.Code != http.StatusOK {
|
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)
|
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
|
// 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 {
|
func checkLogrotateConfigMode(s *stack) error {
|
||||||
mode, err := s.execIn("selfpost", "stat", "-c", "%a", "/etc/logrotate.d/mail")
|
mode, err := s.execIn("selfpost", "stat", "-c", "%a", "/etc/logrotate.d/mail")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user