Vendor the front-end assets and drop the third-party CDN dependencies (BootstrapCDN is being sunset): the bootstrap 4.0.0 css/js, jquery 3.2.1 slim, and popper 1.12.9 now live under static/ and are served from the app, byte-for-byte identical to the previous SRI-pinned files. Migrate CI from Drone to a Gitea Actions workflow that runs docker build . on push, with the checkout action pinned by SHA. Bring the repo up to standard: - add REPO_POLICIES.md, .editorconfig, .dockerignore, .golangci.yml, and a comprehensive root-anchored .gitignore - rewrite the Makefile with the required test/lint/fmt/fmt-check/check/ docker/hooks targets (golangci-lint, 30s test timeout, verbose rerun on failure, check modifies nothing) - rewrite the Dockerfile as a hash-pinned multistage build: a lint stage (golangci-lint), a glibc build+test stage (the legacy sqlite driver needs cgo+glibc), and a debian-slim runtime carrying the binary, templates, and static assets - add real tests for the hn package - bring the code into golangci-lint (default: all) compliance: fix the malformed gorm struct tags, check previously-ignored errors, dispatch the zerolog error event, avoid a uint->Duration overflow, split long functions, and add doc comments — all behaviour-preserving - expand the README with the required sections
81 lines
2.8 KiB
Markdown
81 lines
2.8 KiB
Markdown
# Orangesite Transparency Log
|
|
|
|
Orangesite is a WTFPL-licensed Go web application by
|
|
[@sneak](https://sneak.berlin) that records which stories drop off the Hacker
|
|
News front page and how long they lasted, as a small transparency log.
|
|
|
|
Live: <https://orangesite.sneak.cloud>
|
|
|
|
It shows stories that were on the HN front page within the last 24 hours but
|
|
are not any more, sorted by when they left the front page, most recent first.
|
|
Stories that were on the front page for less than half an hour (a likely sign
|
|
of moderator intervention) are marked in red.
|
|
|
|
## Getting Started
|
|
|
|
The service needs Go and a C compiler (the sqlite driver uses cgo). Run it
|
|
locally:
|
|
|
|
```sh
|
|
git clone https://git.eeqj.de/sneak/orangesite
|
|
cd orangesite
|
|
make run # builds ./server and serves on :8080
|
|
```
|
|
|
|
Or build and run the container image (which runs `make check` as part of the
|
|
build):
|
|
|
|
```sh
|
|
make docker
|
|
docker run -p 8080:8080 -v orangesite-data:/data sneak/orangesite
|
|
```
|
|
|
|
Configuration is via environment variables:
|
|
|
|
- `DATABASE_PATH` — path to the sqlite database file (default
|
|
`/data/storage.sqlite`, or `./storage.sqlite` under `make run`).
|
|
- `DEBUG` — set to any non-empty value to enable debug logging and gorm SQL
|
|
logging.
|
|
|
|
## Rationale
|
|
|
|
The Hacker News front page turns over constantly, and stories sometimes
|
|
disappear far faster than their score and age would predict. Orangesite keeps
|
|
an independent record of front-page tenure so that departures — especially
|
|
unusually fast ones — remain visible after the fact.
|
|
|
|
## Design
|
|
|
|
The program is a single Go binary:
|
|
|
|
- `cmd/server` — the entrypoint; wires build-time version info into the `hn`
|
|
package and runs the server.
|
|
- `hn` — the application package:
|
|
- `fetcher.go` scrapes the HN top-stories API once a minute and records
|
|
each story's first appearance, rank changes, best rank reached, and the
|
|
moment it leaves the front page.
|
|
- `db.go` defines the gorm models, persisted to sqlite.
|
|
- `handlers.go` renders the index and about pages.
|
|
- `server.go` sets up the echo HTTP server, logging, and routes.
|
|
- `view/` — pongo2 HTML templates, rendered at request time.
|
|
- `static/` — vendored front-end assets (bootstrap, jquery, popper), served
|
|
under `/static` so the site depends on no third-party CDNs.
|
|
|
|
## TODO
|
|
|
|
- Continue to resist the urge to use the orange.
|
|
- Embed the `view/` templates and `static/` assets into the binary rather than
|
|
shipping them alongside it.
|
|
- Honour a `PORT` environment variable instead of hard-coding `:8080`.
|
|
- Add graceful shutdown instead of relying on `Fatal`.
|
|
- Harden the HTTP surface (security headers, server timeouts, request size
|
|
limits) before tagging a `1.0`.
|
|
|
|
## License
|
|
|
|
WTFPL — see the [`LICENSE`](LICENSE) file.
|
|
|
|
## Author
|
|
|
|
[@sneak](https://sneak.berlin) — <sneak@sneak.berlin>
|