Compare commits
7 Commits
9e3f955e91
...
security-a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c930bf4d8 | ||
|
|
4919779c08 | ||
|
|
1fd7dd2f03 | ||
|
|
5965b69d53 | ||
|
|
4b114c9dcd | ||
|
|
582a3bae4d | ||
|
|
ff1a6462ac |
@@ -1,4 +0,0 @@
|
|||||||
.git
|
|
||||||
public
|
|
||||||
resources
|
|
||||||
.hugo_build.lock
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
name: check
|
|
||||||
on: [push]
|
|
||||||
jobs:
|
|
||||||
check:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
# actions/checkout v4.2.2, 2026-02-28
|
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
|
||||||
- run: script/cibuild
|
|
||||||
@@ -3,64 +3,28 @@ name: Build and Deploy to Cloudflare Pages
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
- feat/initial-site
|
||||||
- main
|
- main
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
# Same digest the Dockerfile pins: one pinned base image and the
|
image: klakegg/hugo:ext-alpine
|
||||||
# same dependency list (script/bootstrap) for both the check build
|
|
||||||
# and the deploy build. The one extra thing this job needs on top
|
|
||||||
# of the Dockerfile is the Actions runner's own prerequisites --
|
|
||||||
# see the first step.
|
|
||||||
# alpine 3.21, 2026-02-28
|
|
||||||
image: alpine@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4709
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
# The default step shell is bash; this image has only busybox
|
|
||||||
# sh, so say so explicitly rather than rely on a fallback.
|
|
||||||
shell: sh
|
|
||||||
steps:
|
steps:
|
||||||
# This image is bare busybox+musl. act_runner executes JavaScript
|
|
||||||
# actions (checkout, upload-artifact) with `node` *inside* the job
|
|
||||||
# container and does not inject one, so node has to exist before
|
|
||||||
# the first `uses:` step -- script/bootstrap runs too late. git is
|
|
||||||
# needed for checkout's `submodules: recursive` (without it
|
|
||||||
# checkout degrades to a tarball download that cannot do
|
|
||||||
# submodules). An inline `run:` needs only a shell, so this step
|
|
||||||
# works on the bare image. These apk packages resolve at run time
|
|
||||||
# and are not hash-pinned; that gap is repo-wide (script/bootstrap
|
|
||||||
# has it too) and is tracked in #19.
|
|
||||||
- name: Install runner prerequisites
|
|
||||||
run: apk add --no-cache nodejs git tar
|
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
# actions/checkout v4.2.2, 2026-02-28
|
uses: actions/checkout@v4
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: Install build dependencies
|
|
||||||
run: script/bootstrap
|
|
||||||
|
|
||||||
- name: Build site
|
- name: Build site
|
||||||
run: script/test
|
run: hugo --minify
|
||||||
|
|
||||||
- name: Archive site
|
- name: Archive site
|
||||||
run: tar -czf site.tar.gz public
|
run: tar -czf site.tar.gz public
|
||||||
|
|
||||||
# v3, not v4: artifacts v4 is a different wire protocol and this
|
|
||||||
# Gitea Actions instance does not serve it. That is what broke the
|
|
||||||
# deploy in run 25 -- measured by running two otherwise identical
|
|
||||||
# jobs on a branch, one ending in upload-artifact v4 (failed) and
|
|
||||||
# one without that step (passed). Tracked in #20. This SHA is the
|
|
||||||
# exact commit the mutable `@v3` used to resolve to, i.e. the code
|
|
||||||
# that was already deploying this site, now pinned rather than
|
|
||||||
# floating.
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
# actions/upload-artifact v3.2.1, 2026-08-09
|
uses: actions/upload-artifact@v3
|
||||||
uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5
|
|
||||||
with:
|
with:
|
||||||
name: site
|
name: site
|
||||||
path: site.tar.gz
|
path: site.tar.gz
|
||||||
@@ -68,41 +32,19 @@ jobs:
|
|||||||
deploy:
|
deploy:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
# Publishing guard. This job spends CLOUDFLARE_API_TOKEN and creates a
|
|
||||||
# real Cloudflare Pages deployment, so it must never run off main --
|
|
||||||
# not even if a branch is added to the push trigger above, deliberately
|
|
||||||
# or by accident. Costs one line; the build job stays exercisable from
|
|
||||||
# a branch without this job touching anything external.
|
|
||||||
if: github.ref_name == 'main'
|
|
||||||
container:
|
container:
|
||||||
# node 20.20.2-bookworm, 2026-08-09
|
image: node:20
|
||||||
image: node@sha256:8f693eaa7e0a8e71560c9a82b55fd54c2ae920a2ba5d2cde28bac7d1c01c9ba5
|
|
||||||
steps:
|
steps:
|
||||||
# Must match the upload-artifact major above -- v4 artifacts and
|
|
||||||
# v3 artifacts are different protocols and do not interoperate.
|
|
||||||
# Like the upload above, this is the exact commit `@v3` used to
|
|
||||||
# resolve to.
|
|
||||||
- name: Download artifact
|
- name: Download artifact
|
||||||
# actions/download-artifact v3.0.2, 2026-08-09
|
uses: actions/download-artifact@v3
|
||||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a
|
|
||||||
with:
|
with:
|
||||||
name: site
|
name: site
|
||||||
|
|
||||||
- name: Extract site
|
- name: Extract site
|
||||||
run: tar -xzf site.tar.gz
|
run: tar -xzf site.tar.gz
|
||||||
|
|
||||||
# 4.86.0, not the 4.120.0 that `latest` points at: wrangler
|
|
||||||
# 4.120.0 requires node >= 22 and refuses to start on this
|
|
||||||
# container's node 20. Note that the unpinned `npm install -g
|
|
||||||
# wrangler` this replaces was never installing `latest` either --
|
|
||||||
# npm picks the newest version whose engines the running node
|
|
||||||
# satisfies, which on node 20 is exactly 4.86.0. So this pins the
|
|
||||||
# version that has actually been deploying this site, rather than
|
|
||||||
# silently changing it. Moving the container to node 22 so the
|
|
||||||
# wrangler pin can advance is tracked in #21.
|
|
||||||
- name: Install Wrangler
|
- name: Install Wrangler
|
||||||
# wrangler 4.86.0, 2026-08-09
|
run: npm install -g wrangler
|
||||||
run: npm install -g wrangler@4.86.0
|
|
||||||
|
|
||||||
- name: Deploy to Cloudflare Pages
|
- name: Deploy to Cloudflare Pages
|
||||||
run: wrangler pages deploy public --project-name=lora-vegas --branch=${{ github.ref_name }}
|
run: wrangler pages deploy public --project-name=lora-vegas --branch=${{ github.ref_name }}
|
||||||
|
|||||||
13
.gitea/workflows/security-recon.yml
Normal file
13
.gitea/workflows/security-recon.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
name: Security Recon
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- security-audit
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
recon:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Placeholder
|
||||||
|
run: echo "Security audit complete. See issue #3."
|
||||||
23
Dockerfile
23
Dockerfile
@@ -1,23 +0,0 @@
|
|||||||
# Hugo static-site build image. The build runs `make check` (a clean
|
|
||||||
# `hugo --minify` production build, the `--printPathWarnings` lint
|
|
||||||
# build, then the read-only prettier docs check), so the image build
|
|
||||||
# fails on any formatting or Hugo build error. This is what CI
|
|
||||||
# (script/cibuild) runs on every push.
|
|
||||||
# alpine 3.21, 2026-02-28
|
|
||||||
FROM alpine@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4709
|
|
||||||
|
|
||||||
WORKDIR /src
|
|
||||||
|
|
||||||
# Install build dependencies first so the layer caches until the
|
|
||||||
# scripts change (script/bootstrap installs git, make, go, hugo,
|
|
||||||
# node/npm). Hugo is not an apk package here: script/bootstrap builds
|
|
||||||
# the exact pinned version with `go install`, hash-verified against
|
|
||||||
# sum.golang.org, so the published artifact does not depend on whatever
|
|
||||||
# hugo this base image's repos happen to serve.
|
|
||||||
COPY script/ script/
|
|
||||||
RUN script/bootstrap
|
|
||||||
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Run all checks - build fails if any check fails.
|
|
||||||
RUN make check
|
|
||||||
31
Makefile
31
Makefile
@@ -1,31 +0,0 @@
|
|||||||
.PHONY: bootstrap setup test lint fmt fmt-check check docker hooks serve
|
|
||||||
|
|
||||||
bootstrap:
|
|
||||||
@script/bootstrap
|
|
||||||
|
|
||||||
setup:
|
|
||||||
@script/setup
|
|
||||||
|
|
||||||
test:
|
|
||||||
@script/test
|
|
||||||
|
|
||||||
lint:
|
|
||||||
@script/lint
|
|
||||||
|
|
||||||
fmt:
|
|
||||||
@script/fmt
|
|
||||||
|
|
||||||
fmt-check:
|
|
||||||
@script/fmt-check
|
|
||||||
|
|
||||||
check:
|
|
||||||
@script/check
|
|
||||||
|
|
||||||
docker:
|
|
||||||
@script/docker
|
|
||||||
|
|
||||||
hooks:
|
|
||||||
@script/install-precommit
|
|
||||||
|
|
||||||
serve:
|
|
||||||
@hugo server
|
|
||||||
38
README.md
38
README.md
@@ -4,8 +4,7 @@ Las Vegas Meshtastic and LoRa community website.
|
|||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
This site provides information about the Las Vegas mesh networking community,
|
This site provides information about the Las Vegas mesh networking community, including:
|
||||||
including:
|
|
||||||
|
|
||||||
- Mesh channel configurations
|
- Mesh channel configurations
|
||||||
- Community coordination (Discord, Signal)
|
- Community coordination (Discord, Signal)
|
||||||
@@ -14,13 +13,11 @@ including:
|
|||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
To contribute to this site, contact **sneak@sneak.berlin** for git repository
|
To contribute to this site, contact **sneak@sneak.berlin** for git repository access.
|
||||||
access.
|
|
||||||
|
|
||||||
## Technical Details
|
## Technical Details
|
||||||
|
|
||||||
This is a static site built with Hugo. The site is deployed automatically via
|
This is a static site built with Hugo. The site is deployed automatically via GitHub Actions.
|
||||||
GitHub Actions.
|
|
||||||
|
|
||||||
### Local Development
|
### Local Development
|
||||||
|
|
||||||
@@ -38,35 +35,6 @@ hugo
|
|||||||
|
|
||||||
Output will be in the `public/` directory.
|
Output will be in the `public/` directory.
|
||||||
|
|
||||||
## Entrypoints
|
|
||||||
|
|
||||||
This repository adheres to the
|
|
||||||
[Scripts to Rule Them All](https://github.com/github/scripts-to-rule-them-all)
|
|
||||||
standard: normalized scripts in `script/` are the entrypoints for the
|
|
||||||
development workflow, and the Makefile targets are thin shims that call them. We
|
|
||||||
provide:
|
|
||||||
|
|
||||||
- `script/bootstrap` — install all build dependencies (git, make, go, hugo,
|
|
||||||
node/npm) idempotently. Hugo is pinned to an exact version and installed with
|
|
||||||
`go install`, which verifies it against `sum.golang.org`; the version is the
|
|
||||||
`HUGO_VERSION` constant at the top of the script
|
|
||||||
- `script/setup` — prepare a fresh clone: run `script/bootstrap` and install the
|
|
||||||
git pre-commit hook
|
|
||||||
- `script/test` — the correctness check: a clean `hugo --minify` production
|
|
||||||
build
|
|
||||||
- `script/lint` — a clean build that surfaces broken links and path collisions
|
|
||||||
- `script/fmt` — format the repo's own top-level markdown docs with prettier
|
|
||||||
- `script/fmt-check` — check that formatting (read-only)
|
|
||||||
- `script/check` — run `script/test`, `script/lint`, then `script/fmt-check`;
|
|
||||||
modifies no tracked files
|
|
||||||
- `script/docker` — build the Docker image tagged with the project name
|
|
||||||
- `script/cibuild` — the CI build (`docker build .`); the Dockerfile runs
|
|
||||||
`make check`
|
|
||||||
- `script/install-precommit` — install the git pre-commit hook that runs
|
|
||||||
`script/check`
|
|
||||||
|
|
||||||
A convenience `make serve` target runs `hugo server` for local preview.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Content is provided as-is for community use.
|
Content is provided as-is for community use.
|
||||||
|
|||||||
103
TODO.md
103
TODO.md
@@ -1,103 +0,0 @@
|
|||||||
# Workflow
|
|
||||||
|
|
||||||
- branch (from `main`)
|
|
||||||
- do the work in Next Step
|
|
||||||
- move Next Step to the top of Completed Steps
|
|
||||||
- move the top item of Future Steps into Next Step
|
|
||||||
- commit (`TODO.md` changes in the same commit as the work)
|
|
||||||
- merge to `main` if the branch is not protected, otherwise open a PR
|
|
||||||
- push
|
|
||||||
|
|
||||||
# Status
|
|
||||||
|
|
||||||
pre-1.0
|
|
||||||
|
|
||||||
No git tags. The site is live and now has the scripts-to-rule-them-all scaffold
|
|
||||||
(`Makefile`, `script/`, `Dockerfile`, `check.yml`); still missing `LICENSE` and
|
|
||||||
policy files. Every external reference in the repo is now pinned by
|
|
||||||
cryptographic hash (or, for the wrangler CLI install, an exact version), and the
|
|
||||||
Hugo that builds the published site is a deliberate pinned version rather than
|
|
||||||
whatever the base image's package repo serves.
|
|
||||||
|
|
||||||
# Next Step
|
|
||||||
|
|
||||||
Add the remaining policy scaffold: `LICENSE`, `REPO_POLICIES.md`,
|
|
||||||
`.editorconfig`, and prettier config files (`.prettierrc`, `.prettierignore`).
|
|
||||||
Update `README.md` accordingly.
|
|
||||||
|
|
||||||
# Completed Steps
|
|
||||||
|
|
||||||
- 2026-08-09: replaced `hugo.toml`'s deprecated `languageCode` key with `locale`
|
|
||||||
(closes #18). Hugo deprecated `languageCode` in v0.158.0, so the Hugo pinned
|
|
||||||
in the preceding commit warns about it; left alone it would become a third
|
|
||||||
routinely-ignored warning, and a latent breakage when the key is removed.
|
|
||||||
Deliberately sequenced **after** the Hugo version move and in the same branch:
|
|
||||||
under the apk hugo 0.139.0 that CI ran until now, `locale` is an unknown key
|
|
||||||
that is silently ignored, which downgrades the generated RSS from
|
|
||||||
`<language>en-us</language>` to `<language>en</language>` with no warning and
|
|
||||||
exit 0. Verified on hugo v0.164.0 that the RSS `<language>` still reads
|
|
||||||
`en-us`, the `lang` attribute is unchanged, and `public/` is byte-identical to
|
|
||||||
the preceding commit's output
|
|
||||||
- 2026-08-09: installed Hugo at a deliberate, hash-verified version instead of
|
|
||||||
taking whatever alpine ships (closes #26). `script/bootstrap` no longer does
|
|
||||||
`pkg_install hugo`; it installs `github.com/gohugoio/hugo@v0.164.0` with
|
|
||||||
`go install`, which verifies the module against `sum.golang.org`. The version
|
|
||||||
is a commented constant, as is the Go toolchain (`go1.26.5`) — hugo v0.164.0
|
|
||||||
requires go >= 1.26.0 and alpine 3.21 ships go 1.23.9 with
|
|
||||||
`GOTOOLCHAIN=local`, so a bare `go install` refuses to run. `CGO_ENABLED=0` is
|
|
||||||
deliberate: standard Hugo, not extended, because this site has no SCSS, no
|
|
||||||
`resources.ToCSS`, no PostCSS and no image processing. This moves the build
|
|
||||||
off apk's hugo 0.139.0, about two years behind, onto the current stable.
|
|
||||||
Rendered output across the whole `public/` tree is unchanged except the
|
|
||||||
`meta name=generator` version string
|
|
||||||
- 2026-08-09: made `script/check` run `script/lint` (closes #9). It previously
|
|
||||||
ran only `fmt-check` then `test`, so `script/lint` executed nowhere — not in
|
|
||||||
`make check`, not in the pre-commit hook, and not in CI, even though the
|
|
||||||
`Dockerfile` runs `make check` and `script/cibuild` builds it. It now runs
|
|
||||||
`test`, `lint`, `fmt-check` in the canonical order, so the
|
|
||||||
`hugo --printPathWarnings` render-target-collision signal is no longer
|
|
||||||
discarded. `README.md`'s Entrypoints line was corrected to match
|
|
||||||
- 2026-08-09: hash-pinned every external reference in
|
|
||||||
`.gitea/workflows/deploy.yml` (closes #7): both job container images are
|
|
||||||
pinned by digest, all three `uses:` are pinned by 40-hex commit SHA, and the
|
|
||||||
wrangler install is pinned to an exact version. The abandoned
|
|
||||||
`klakegg/hugo:ext-alpine` image is gone: the build job now runs on the same
|
|
||||||
pinned `alpine` digest the `Dockerfile` uses, with a pre-checkout
|
|
||||||
`apk add nodejs git tar` step (the Actions runner needs `node` inside the job
|
|
||||||
container to execute JavaScript actions), an explicit `shell: sh` default,
|
|
||||||
then `script/bootstrap` and `script/test`. The `deploy` job is guarded with
|
|
||||||
`if: github.ref_name == 'main'` so it can never publish from a branch. Also
|
|
||||||
dropped the dead `feat/initial-site` push trigger and reindented the file to
|
|
||||||
4-space YAML to match `check.yml`. This is the second attempt; the first broke
|
|
||||||
the deploy and was reverted, so this one was verified by temporarily
|
|
||||||
triggering the workflow on the PR branch and iterating until the `build` job
|
|
||||||
ran green for real
|
|
||||||
- 2026-07-25: added the scripts-to-rule-them-all scaffold (closes #4): `script/`
|
|
||||||
entrypoints, `Makefile` shims, a Hugo `Dockerfile` (sha256-pinned alpine) plus
|
|
||||||
`.dockerignore` that runs `make check`, `.gitea/workflows/check.yml` running
|
|
||||||
`script/cibuild`, and a README Entrypoints section. `test`/`lint` are a clean
|
|
||||||
`hugo --minify` build; `fmt`/`fmt-check` run prettier over the repo's own
|
|
||||||
top-level markdown only
|
|
||||||
- 2026-02-10: design pass: minimal light theme with inline CSS, grey wells for
|
|
||||||
mesh channels and signal groups, horizontal overflow fix, body width tuning,
|
|
||||||
map link update
|
|
||||||
- 2026-02-10: added README and footer contribute link
|
|
||||||
- 2026-02-10: added Gitea workflow that builds the site and deploys to
|
|
||||||
Cloudflare Pages
|
|
||||||
- 2026-02-08: initial Hugo static site for lora.vegas
|
|
||||||
|
|
||||||
# Future Steps
|
|
||||||
|
|
||||||
- Move the artifact actions to v4 once this Gitea Actions instance serves the v4
|
|
||||||
artifact protocol; they are pinned on the deprecated v3 line because v4 fails
|
|
||||||
here (#20)
|
|
||||||
- Move the deploy container to a pinned node 22 so the wrangler pin can advance
|
|
||||||
past 4.86.0 (#21)
|
|
||||||
- Rework README.md into the standard sections: Description, Getting Started,
|
|
||||||
Rationale, Design, TODO, License, Author (currently About, Contributing,
|
|
||||||
Technical Details, License)
|
|
||||||
- Replace the "content is provided as-is" README note with the text of the
|
|
||||||
committed LICENSE
|
|
||||||
- Expand .gitignore beyond Hugo outputs (OS and editor files)
|
|
||||||
- Verify the Cloudflare Pages deploy still works after the workflow changes
|
|
||||||
- Keep mesh channel and signal group listings current
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
baseURL = 'https://lora.vegas/'
|
baseURL = 'https://lora.vegas/'
|
||||||
locale = 'en-us'
|
languageCode = 'en-us'
|
||||||
title = 'LoRa Vegas — Las Vegas Meshtastic Community'
|
title = 'LoRa Vegas — Las Vegas Meshtastic Community'
|
||||||
theme = 'loravega'
|
theme = 'loravega'
|
||||||
|
|
||||||
|
|||||||
175
script/bootstrap
175
script/bootstrap
@@ -1,175 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# script/bootstrap: install all dependencies needed to build and develop
|
|
||||||
# this Hugo site, idempotently. Base tooling comes from nix, apt, brew,
|
|
||||||
# or apk (detected in that order); assumes NOTHING is present (not git,
|
|
||||||
# make, go, hugo, or node). Installs hugo (the site build, at the exact
|
|
||||||
# version pinned below) and node/npm (prettier, used to format the
|
|
||||||
# repo's own markdown docs). Every install is guarded by a check so
|
|
||||||
# already-installed tools are skipped.
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
||||||
|
|
||||||
PKGMGR=""
|
|
||||||
SUDO=""
|
|
||||||
|
|
||||||
# --- Hugo -------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# Hugo produces the published artifact, so its version is a property of
|
|
||||||
# the site's output, not of the build environment. It is therefore
|
|
||||||
# pinned here rather than taken from whatever the distro serves: before
|
|
||||||
# this, alpine 3.21's apk supplied hugo 0.139.0 -- a version chosen by
|
|
||||||
# nobody, roughly two years behind upstream, and liable to change
|
|
||||||
# silently whenever the base image digest moves.
|
|
||||||
#
|
|
||||||
# `go install` is the hash-verified mechanism: Go checks the module
|
|
||||||
# against the sum.golang.org checksum database. That is the mechanism
|
|
||||||
# REPO_POLICIES.md already names for Go, and it needs no hand-maintained
|
|
||||||
# sha256. The other tools this script installs stay on the package
|
|
||||||
# manager, which #19 settled is fine for build-time conveniences.
|
|
||||||
#
|
|
||||||
# hugo v0.164.0, 2026-07-06
|
|
||||||
HUGO_VERSION="v0.164.0"
|
|
||||||
|
|
||||||
# hugo v0.164.0's go.mod requires go >= 1.26.0, and alpine 3.21's `go`
|
|
||||||
# package is 1.23.9 built with GOTOOLCHAIN=local, so a bare `go install`
|
|
||||||
# refuses to run at all. Naming the toolchain explicitly makes Go fetch
|
|
||||||
# it through the module proxy and verify it against sum.golang.org like
|
|
||||||
# any other module, so the chain stays hash-verified end to end -- and
|
|
||||||
# the Go version that compiles hugo becomes deliberate too, instead of
|
|
||||||
# being inherited from whatever the base image happens to ship.
|
|
||||||
# go1.26.5, 2026-08-09
|
|
||||||
HUGO_GOTOOLCHAIN="go1.26.5"
|
|
||||||
|
|
||||||
# Standard hugo, not hugo extended: CGO_ENABLED=0 is deliberate.
|
|
||||||
# Verified that this site uses nothing extended provides -- there are no
|
|
||||||
# .scss/.sass files, no resources.ToCSS, no PostCSS, and no image
|
|
||||||
# processing (.Resize/.Fill/.Fit/images.* are all absent). The CSS is
|
|
||||||
# plain and inlined by `readFile` in baseof.html. The `+extended` on the
|
|
||||||
# apk build this replaces was incidental, not a requirement, so do not
|
|
||||||
# assume a future change needs it without rechecking the above.
|
|
||||||
HUGO_CGO_ENABLED="0"
|
|
||||||
|
|
||||||
# Where the hugo binary lands. It has to be on the default PATH of a
|
|
||||||
# *fresh* shell, not just of this script: the Dockerfile's `RUN make
|
|
||||||
# check` and deploy.yml's `script/test` step each start their own shell
|
|
||||||
# and would never see a GOPATH bin directory. Overridable so an
|
|
||||||
# unprivileged install can point somewhere writable.
|
|
||||||
HUGO_BIN_DIR="${HUGO_BIN_DIR:-/usr/local/bin}"
|
|
||||||
|
|
||||||
detect_pkgmgr() {
|
|
||||||
[ -n "$PKGMGR" ] && return 0
|
|
||||||
if command -v nix-env >/dev/null 2>&1; then
|
|
||||||
PKGMGR="nix"
|
|
||||||
elif command -v apt-get >/dev/null 2>&1; then
|
|
||||||
PKGMGR="apt"
|
|
||||||
elif command -v brew >/dev/null 2>&1; then
|
|
||||||
PKGMGR="brew"
|
|
||||||
elif command -v apk >/dev/null 2>&1; then
|
|
||||||
PKGMGR="apk"
|
|
||||||
else
|
|
||||||
echo "bootstrap: no supported package manager (nix, apt, brew, apk)" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if [ "$PKGMGR" = "apt" ]; then
|
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
|
||||||
detect_sudo
|
|
||||||
$SUDO env DEBIAN_FRONTEND=noninteractive apt-get update
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
detect_sudo() {
|
|
||||||
if [ -z "$SUDO" ] && [ "$(id -u)" != "0" ]; then
|
|
||||||
SUDO="sudo"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# pkg_install <nix-attr> <apt-pkg> <brew-formula> <apk-pkg>
|
|
||||||
pkg_install() {
|
|
||||||
detect_pkgmgr
|
|
||||||
case "$PKGMGR" in
|
|
||||||
nix) nix-env -iA "nixpkgs.$1" ;;
|
|
||||||
apt) $SUDO env DEBIAN_FRONTEND=noninteractive apt-get install -y "$2" ;;
|
|
||||||
brew) brew install "$3" ;;
|
|
||||||
apk) apk add --no-cache "$4" ;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
missing() {
|
|
||||||
! command -v "$1" >/dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
# True when the hugo already on PATH is the pinned version. Unlike the
|
|
||||||
# other tools, mere presence is not good enough here: an older hugo has
|
|
||||||
# to be replaced, not accepted, or the pin means nothing.
|
|
||||||
hugo_pinned() {
|
|
||||||
command -v hugo >/dev/null 2>&1 || return 1
|
|
||||||
# `hugo version` prints e.g. "hugo v0.164.0 linux/amd64 ..." for a
|
|
||||||
# `go install` build, or "hugo v0.164.0-ce2470e+extended ..." for an
|
|
||||||
# official release binary. Compare only the vX.Y.Z part: a build of
|
|
||||||
# the same version that happens to be extended renders this site
|
|
||||||
# identically (see HUGO_CGO_ENABLED above), so there is no reason to
|
|
||||||
# overwrite a developer's existing matching install.
|
|
||||||
have="$(hugo version 2>/dev/null | awk '{print $2}' | sed 's/[-+].*//')"
|
|
||||||
[ "$have" = "$HUGO_VERSION" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
install_hugo() {
|
|
||||||
detect_sudo
|
|
||||||
|
|
||||||
# The Go toolchain is a build-time convenience like git and make, so
|
|
||||||
# it comes from the package manager; the thing that must be
|
|
||||||
# deliberate is what it builds, which HUGO_VERSION and
|
|
||||||
# HUGO_GOTOOLCHAIN pin.
|
|
||||||
if missing go; then pkg_install go golang-go go go; fi
|
|
||||||
|
|
||||||
# Build as the invoking user into a scratch GOBIN, then place the
|
|
||||||
# binary with `install`. Running the whole `go install` under sudo
|
|
||||||
# would work but would populate root's module cache instead of the
|
|
||||||
# user's, which is needlessly slow and surprising on a workstation.
|
|
||||||
gobin="$(mktemp -d)"
|
|
||||||
CGO_ENABLED="$HUGO_CGO_ENABLED" \
|
|
||||||
GOTOOLCHAIN="$HUGO_GOTOOLCHAIN" \
|
|
||||||
GOBIN="$gobin" \
|
|
||||||
go install "github.com/gohugoio/hugo@${HUGO_VERSION}"
|
|
||||||
$SUDO install -d "$HUGO_BIN_DIR"
|
|
||||||
$SUDO install -m 0755 "$gobin/hugo" "$HUGO_BIN_DIR/hugo"
|
|
||||||
rm -rf "$gobin"
|
|
||||||
|
|
||||||
# Drop any cached PATH lookup of the hugo we just replaced, so the
|
|
||||||
# check below tests the new binary and not the old one.
|
|
||||||
hash -r 2>/dev/null || true
|
|
||||||
|
|
||||||
# Fail loudly rather than let a later build run on a shadowing hugo
|
|
||||||
# from somewhere earlier in PATH.
|
|
||||||
if ! hugo_pinned; then
|
|
||||||
echo "bootstrap: installed $HUGO_VERSION into $HUGO_BIN_DIR but" \
|
|
||||||
"'hugo' on PATH is still $(hugo version 2>/dev/null || echo absent)" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
cd "$ROOT"
|
|
||||||
|
|
||||||
# Base tooling.
|
|
||||||
if missing git; then pkg_install git git git git; fi
|
|
||||||
if missing make; then pkg_install gnumake make make make; fi
|
|
||||||
|
|
||||||
# The theme is vendored in-repo, but initialise submodules if any
|
|
||||||
# are ever added so a fresh clone is buildable.
|
|
||||||
if [ -f .gitmodules ]; then
|
|
||||||
git submodule update --init --recursive
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Site build. Pinned and hash-verified -- see the HUGO_* constants.
|
|
||||||
if ! hugo_pinned; then install_hugo; fi
|
|
||||||
|
|
||||||
# node/npm provide prettier (via npx) for formatting the docs.
|
|
||||||
if missing node; then pkg_install nodejs nodejs node nodejs; fi
|
|
||||||
if missing npx; then pkg_install nodejs npm npm npm; fi
|
|
||||||
|
|
||||||
echo "bootstrap complete"
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
16
script/check
16
script/check
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# script/check: run all checks. Our own extension to
|
|
||||||
# scripts-to-rule-them-all. Must not modify any tracked files. Runs the
|
|
||||||
# canonical order: the clean production build, then the lint build that
|
|
||||||
# reports path warnings, then the read-only formatting check.
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
|
||||||
|
|
||||||
main() {
|
|
||||||
"$SCRIPT_DIR/test"
|
|
||||||
"$SCRIPT_DIR/lint"
|
|
||||||
"$SCRIPT_DIR/fmt-check"
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# script/cibuild: run the CI build. The Dockerfile runs `make check`,
|
|
||||||
# so a successful build implies all checks pass. The Gitea workflow
|
|
||||||
# runs this on push.
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
||||||
|
|
||||||
main() {
|
|
||||||
cd "$ROOT"
|
|
||||||
docker build .
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# script/docker: build the Docker image tagged with the project name.
|
|
||||||
# The tag comes from script/projectname.
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
|
||||||
ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
|
|
||||||
|
|
||||||
main() {
|
|
||||||
cd "$ROOT"
|
|
||||||
docker build -t "$("$SCRIPT_DIR/projectname")" .
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
18
script/fmt
18
script/fmt
@@ -1,18 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# script/fmt: format the repo's own top-level markdown docs (README.md,
|
|
||||||
# TODO.md, ...) with prettier, using our standard settings. Scope is
|
|
||||||
# deliberately limited to top-level docs: site content under content/
|
|
||||||
# is left untouched so rendered output cannot change.
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
||||||
|
|
||||||
PRETTIER_VERSION="3.4.2"
|
|
||||||
|
|
||||||
main() {
|
|
||||||
cd "$ROOT"
|
|
||||||
npx --yes "prettier@${PRETTIER_VERSION}" --write \
|
|
||||||
'*.md' --tab-width 4 --prose-wrap always
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# script/fmt-check: check the formatting of the repo's own top-level
|
|
||||||
# markdown docs (read-only). Same scope as script/fmt, but fails
|
|
||||||
# instead of writing.
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
||||||
|
|
||||||
PRETTIER_VERSION="3.4.2"
|
|
||||||
|
|
||||||
main() {
|
|
||||||
cd "$ROOT"
|
|
||||||
npx --yes "prettier@${PRETTIER_VERSION}" --check \
|
|
||||||
'*.md' --tab-width 4 --prose-wrap always
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# script/install-precommit: install the git pre-commit hook that runs
|
|
||||||
# script/precommit. Our own extension to scripts-to-rule-them-all.
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
||||||
|
|
||||||
main() {
|
|
||||||
cd "$ROOT"
|
|
||||||
printf '#!/bin/sh\nset -e\nscript/precommit\n' > .git/hooks/pre-commit
|
|
||||||
chmod +x .git/hooks/pre-commit
|
|
||||||
echo "pre-commit hook installed: runs script/precommit"
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
15
script/lint
15
script/lint
@@ -1,15 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# script/lint: this Hugo site has no dedicated linter, so the lint gate
|
|
||||||
# is a clean build that surfaces broken internal links and template
|
|
||||||
# path problems. It is a real check: `hugo` fails on build errors, and
|
|
||||||
# --printPathWarnings reports render-target collisions.
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
||||||
|
|
||||||
main() {
|
|
||||||
cd "$ROOT"
|
|
||||||
hugo --minify --printPathWarnings
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# script/precommit: run by the git pre-commit hook; fails the commit if
|
|
||||||
# checks fail. Our own extension to scripts-to-rule-them-all.
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
|
||||||
|
|
||||||
main() {
|
|
||||||
"$SCRIPT_DIR/check"
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# script/projectname: output the name of this project. Our own
|
|
||||||
# extension to scripts-to-rule-them-all. Other scripts that need the
|
|
||||||
# name (e.g. script/docker) call this, so they can stay identical
|
|
||||||
# across all repos.
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
main() {
|
|
||||||
echo "lora.vegas"
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
13
script/setup
13
script/setup
@@ -1,13 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# script/setup: set up the repo for development after a fresh clone:
|
|
||||||
# installs dependencies (script/bootstrap) and the git pre-commit hook.
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
|
||||||
|
|
||||||
main() {
|
|
||||||
"$SCRIPT_DIR/bootstrap"
|
|
||||||
"$SCRIPT_DIR/install-precommit"
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
14
script/test
14
script/test
@@ -1,14 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# script/test: the correctness check for this static site is a clean
|
|
||||||
# production build. `hugo --minify` exits non-zero on any template,
|
|
||||||
# content, or config error, so a green build is a passing test.
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
||||||
|
|
||||||
main() {
|
|
||||||
cd "$ROOT"
|
|
||||||
hugo --minify
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
@@ -12,7 +12,6 @@
|
|||||||
<body>
|
<body>
|
||||||
{{ block "main" . }}{{ end }}
|
{{ block "main" . }}{{ end }}
|
||||||
<footer>
|
<footer>
|
||||||
<p>this site is a project by <a href="https://sneak.berlin">@sneak</a>.</p>
|
|
||||||
<p>lora.vegas — Las Vegas Meshtastic community <a href="https://git.eeqj.de/sneak/lora.vegas" class="contribute-link">[Contribute]</a></p>
|
<p>lora.vegas — Las Vegas Meshtastic community <a href="https://git.eeqj.de/sneak/lora.vegas" class="contribute-link">[Contribute]</a></p>
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user