bring repo into policy compliance; vendor assets; Gitea CI

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
This commit is contained in:
2026-07-26 23:55:21 +07:00
parent 000f5bbaa6
commit 3ab9637246
23 changed files with 1009 additions and 321 deletions

View File

@@ -1,3 +1,5 @@
// Package hn implements the orangesite Hacker News front-page scraper, its
// gorm-backed storage schema, and the HTTP handlers that render it.
package hn
import (
@@ -8,10 +10,17 @@ import (
// this schema is quite redundant, i know
// HNFrontPage records a story's tenure on the front page: when it appeared,
// when it disappeared, and the best rank it reached. The HN-prefixed name is
// retained deliberately: gorm derives the table name ("hn_front_pages") from
// it, so renaming would orphan the existing production database.
//
//nolint:revive // see above: renaming changes the gorm table name
type HNFrontPage struct {
gorm.Model
InternalID uint64 `gorm:"primary_key;auto_increment:true`
HNID uint // HN integer id
InternalID uint64
HNID uint // HN integer id
Appeared time.Time
Disappeared time.Time
HighestRank uint // frontpage index
@@ -21,9 +30,15 @@ type HNFrontPage struct {
URL string // duh
}
// HNStoryRank is a point-in-time snapshot of a single story's rank. The
// HN-prefixed name is retained deliberately for the same gorm table-name
// reason as HNFrontPage.
//
//nolint:revive // renaming changes the gorm table name
type HNStoryRank struct {
gorm.Model
InternalStoryID uint64 `gorm:"primary_key;auto_increment:true`
InternalStoryID uint64
HNID uint // HN integer id
Title string // submission title
URL string // duh
@@ -32,9 +47,11 @@ type HNStoryRank struct {
FetchedAt time.Time // identical within fetchid
}
// FrontPageCache is a cached view of a story's front-page lifetime.
type FrontPageCache struct {
gorm.Model
CacheID uint64 `gorm:"primary_key;auto_increment:true`
CacheID uint64
HNID uint
HighestRankReached uint
URL string