Skip to content

feat: mirror releases + install.sh to S3-compatible storage#41

Merged
ysyneu merged 2 commits intomainfrom
feat/mirror-release-to-china
May 8, 2026
Merged

feat: mirror releases + install.sh to S3-compatible storage#41
ysyneu merged 2 commits intomainfrom
feat/mirror-release-to-china

Conversation

@ysyneu
Copy link
Copy Markdown
Collaborator

@ysyneu ysyneu commented May 8, 2026

Summary

  • After a release, mirror dist/*.{tar.gz,zip} + checksums.txt to an S3-compatible bucket and write a plain-text releases/latest pointer.
  • On push to main, mirror install.sh to the same bucket.
  • install.sh learns a MIRROR_URL env var: when set, version resolution and binary downloads go through the mirror instead of github.com. Default behavior unchanged.

Motivation: GitHub release URLs and raw.githubusercontent.com are unreachable for many users in mainland China. This lets a domestic CDN serve everything without advertising the URL in public docs.

Trust model

  • The mirror serves both the binary and checksums.txt. A tampered binary is still caught — install.sh continues to verify sha256 against checksums.txt after download.
  • A tampered checksums.txt together with a tampered binary would not be caught by the script alone (same model as the existing GitHub flow); attestations stay on GitHub Releases.
  • MIRROR_URL is required to be https://. The resolved tag from <MIRROR_URL>/releases/latest is validated against a charset + leading-v shape so a hostile mirror cannot inject path traversal or shell metacharacters.

Required secrets (skip silently if any of MIRROR_S3_BUCKET / MIRROR_S3_ENDPOINT are unset)

  • MIRROR_S3_ENDPOINT — e.g. https://cos.ap-shanghai.myqcloud.com
  • MIRROR_S3_REGION — e.g. ap-shanghai
  • MIRROR_S3_BUCKET
  • MIRROR_S3_ACCESS_KEY_ID
  • MIRROR_S3_SECRET_ACCESS_KEY
  • MIRROR_S3_PATH_PREFIX — optional, e.g. flashduty-runner

Usage (not in README on purpose)

curl -fsSL https://<cdn>/<prefix>/install.sh \
  | sudo MIRROR_URL=https://<cdn>/<prefix> TOKEN=wnt_xxx bash

Test plan

  • shellcheck -s sh install.sh + sh -n + bash -n pass
  • Existing install-sh.yml smoke test (no MIRROR_URL) — regression check on the GitHub path
  • Help text shows MIRROR_URL
  • MIRROR_URL=http://... exits with a clear "https:// required" error
  • Tag validator rejects v0.0.5/../etc, v 0.0.5, v0.0.5;rm, garbage, empty; accepts v0.0.5, v1.2.3-rc1, v1.2.3+build.1
  • After secrets are configured: change install.sh on main → mirror job uploads → curl https://<cdn>/<prefix>/install.sh returns the file
  • Cut vX.Y.Z-rc.1releases/download/<tag>/ populated and releases/latest contains the tag
  • On a China host: curl ...install.sh | sudo MIRROR_URL=... bash -s -- --no-service --version <tag> installs cleanly; logs show "Resolving latest release from mirror"
  • Negative test: corrupt checksums.txt in the mirror → install exits 4 (Checksum mismatch)

🤖 Generated with Claude Code

ysyneu and others added 2 commits May 8, 2026 14:51
GitHub release URLs and raw.githubusercontent.com are unreachable for
many users in mainland China. Add an opt-in mirror so a domestic CDN can
serve binaries and the installer without exposing the URL in public docs.

- goreleaser.yml: after a release, upload dist/*.{tar.gz,zip} +
  checksums.txt to s3://<bucket>/<prefix>/releases/download/<tag>/, then
  write a plain-text releases/latest pointer (last, so a partial upload
  doesn't advertise a broken version).
- install-sh.yml: on push to main, mirror install.sh to the same bucket.
- install.sh: add MIRROR_URL env var. When set, resolve_version reads
  <MIRROR_URL>/releases/latest and downloads come from
  <MIRROR_URL>/releases/download/<tag>/. Default behavior unchanged.
  Validates the resolved tag (charset + leading-v shape) to block
  garbage/path-traversal from a hostile mirror; sha256 against
  checksums.txt is still required, so binary tampering is detected.

Both workflow steps skip silently when MIRROR_S3_BUCKET /
MIRROR_S3_ENDPOINT secrets are absent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pre-existing whitespace drift in the TaskOperation const block —
golangci-lint flagged it on this PR. Pure re-alignment, no semantic change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ysyneu ysyneu merged commit 7a8e062 into main May 8, 2026
13 checks passed
@ysyneu ysyneu deleted the feat/mirror-release-to-china branch May 8, 2026 07:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant