oficina / docs Public

Merge remote-tracking branch 'origin/main' into native/server-release

# Conflicts:
#	.gitignore
Paul Campbell pushed by codex agent, operated by paul@keymail.dev b673a1445e324b927874ebc83050b4ecece4a907 parent 8e66e59parent 016a82f
4 files changed, +66 −6
  • .gitignore +1 −0
  • Makefile +23 −0
  • cmd/docs/release_test.go +20 −4
  • scripts/build-release.sh +22 −2
diff --git a/.gitignore b/.gitignore
index 0d54ff6..a5d87be 100644
--- a/.gitignore
+++ b/.gitignore
@@ -52,3 +52,4 @@ Thumbs.db
# Python native review/build helpers.
__pycache__/
*.pyc
+/releases/
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..2e12f11
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,23 @@
+# docs is script-driven, not make-driven: the gate is .amadan/ci.d/10-gate
+# and the release build is scripts/build-release.sh, which builds from a
+# `git archive` of the revision rather than from the working tree — so a
+# release can never pick up an uncommitted edit, and there is no
+# dirty-tree case to refuse.
+#
+# This Makefile exists so that `make release` means the same thing in
+# docs as it does in calendar, home, meet, memoria, sheets and slides.
+# It delegates rather than restating the build: two definitions of how
+# docs ships would drift, and the one in the script is the one CI uses.
+
+APP := docs
+RELEASE_GOOS ?= linux
+RELEASE_GOARCH ?= arm64
+RELEASE_BIN := releases/$(APP)-$(RELEASE_GOOS)-$(RELEASE_GOARCH)
+
+.PHONY: release
+
+release:
+ @mkdir -p releases
+ GOOS=$(RELEASE_GOOS) GOARCH=$(RELEASE_GOARCH) ./scripts/build-release.sh $(RELEASE_BIN) $(REVISION)
+ @echo "publish it with:"
+ @echo " amadan release create -repo oficina/$(APP) -notes-file NOTES.md <tag> $(RELEASE_BIN)"
diff --git a/cmd/docs/release_test.go b/cmd/docs/release_test.go
index f3d594f..a4e079d 100644
--- a/cmd/docs/release_test.go
+++ b/cmd/docs/release_test.go
@@ -15,15 +15,31 @@ import (
"time"
)
-func TestReleaseBinaryReportsItsSourceCommit(t *testing.T) {
+// TestReleaseBinaryReportsItsVersion builds the real release artifact and
+// asks the running process what it is. The failure this guards against is
+// a release that answers "dev": rastrillo's BuildVersion default, which
+// the platform's deploy check compares against the release it believes it
+// adopted — so an unstamped binary makes that check structurally unable to
+// fail while still reporting green.
+//
+// The expected value is whatever scripts/build-release.sh stamps, computed
+// the same way it computes it: the tag when this revision carries one, and
+// the abbreviated sha when it does not. Asserting the full sha instead
+// would pass only for untagged builds, which is the case that matters
+// least.
+func TestReleaseBinaryReportsItsVersion(t *testing.T) {
root, err := filepath.Abs("../..")
if err != nil {
t.Fatal(err)
}
- commit, err := exec.Command("git", "-C", root, "rev-parse", "HEAD").Output()
+ described, err := exec.Command("git", "-C", root, "describe", "--tags", "--always", "HEAD").Output()
if err != nil {
t.Fatal(err)
}
+ want := strings.TrimSpace(string(described))
+ if want == "" || want == "dev" {
+ t.Fatalf("git describe gave %q, which is not a version this test can check for", want)
+ }
dir := t.TempDir()
binary := filepath.Join(dir, "docs")
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
@@ -64,8 +80,8 @@ func TestReleaseBinaryReportsItsSourceCommit(t *testing.T) {
if readErr != nil {
t.Fatal(readErr)
}
- if response.StatusCode != http.StatusOK || strings.TrimSpace(string(body)) != strings.TrimSpace(string(commit)) {
- t.Fatalf("version response %d %q; want commit %q", response.StatusCode, body, strings.TrimSpace(string(commit)))
+ if response.StatusCode != http.StatusOK || strings.TrimSpace(string(body)) != want {
+ t.Fatalf("version response %d %q; want %q", response.StatusCode, body, want)
}
return
}
diff --git a/scripts/build-release.sh b/scripts/build-release.sh
index 1869b7e..5ecafa1 100755
--- a/scripts/build-release.sh
+++ b/scripts/build-release.sh
@@ -4,14 +4,34 @@ export GOPRIVATE="${GOPRIVATE:+$GOPRIVATE,}amadan.net/oficina/estilo.git"
test "$#" -ge 1
test "$#" -le 2
-docs_output=$(realpath -m -- "$1")
+# The output path has to be absolute before the cd into the archive
+# below, and it has to resolve even though the file does not exist yet.
+# `realpath -m` does that on Linux, where this has always run, but BSD
+# realpath has no -m, so it fails on a Mac. dirname + pwd is the same
+# thing in POSIX, once the directory is there to cd into.
+docs_output_dir=$(dirname -- "$1")
+mkdir -p -- "$docs_output_dir"
+docs_output=$(cd -- "$docs_output_dir" && pwd)/$(basename -- "$1")
cd "$(dirname "$0")/.."
docs_revision=$(git rev-parse --verify "${2:-HEAD}^{commit}")
+# What the built binary answers GET /api/version with. rastrillo's
+# BuildVersion defaults to "dev", and the platform's deploy check
+# compares that field against the release it believes it adopted — so an
+# unstamped binary makes the check incapable of failing.
+#
+# git describe --tags --always resolves to the tag when the revision
+# carries one and to the same abbreviated sha when it does not, so a
+# published release reports the name it was published under and an
+# ordinary build still says something true about itself. Name it
+# yourself for a one-off: DOCS_VERSION=v0.1.0-wip scripts/build-release.sh out
+docs_version="${DOCS_VERSION:-$(git describe --tags --always "$docs_revision")}"
docs_source=$(mktemp -d)
trap 'rm -rf -- "$docs_source"' EXIT
git archive "$docs_revision" | tar -x -C "$docs_source"
cd "$docs_source"
CGO_ENABLED=0 GOOS="${GOOS:-linux}" GOARCH="${GOARCH:-arm64}" \
go build -mod=readonly -trimpath \
- -ldflags "-X github.com/carlosframework/rastrillo.BuildVersion=$docs_revision" \
+ -ldflags "-s -w -X github.com/carlosframework/rastrillo.BuildVersion=$docs_version" \
-o "$docs_output" ./cmd/docs
+
+echo "built $docs_output reporting version $docs_version"