pandorga 1.2.3 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/lib/pandorga/commands/new.rb +2 -2
- data/lib/pandorga/commands/publish.rb +2 -1
- data/lib/pandorga/registry/schema.yml +2 -1
- data/lib/pandorga/registry.rb +7 -2
- data/lib/pandorga/version.rb +1 -1
- data/scripts/content/publish-content-to-object-store.sh +16 -1
- data/scripts/test/test-content-backend.rb +50 -0
- data/scripts/test/test-new.rb +2 -2
- data/scripts/test/test-publish-site-root.rb +40 -0
- data/scripts/validate.sh +1 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 19d2883dc4b29f8c6b614997004f69d32d2cacfa67ab83ef61544364a7d57cb3
|
|
4
|
+
data.tar.gz: 73f29c402a3259ec374c2d15746f7a6898d10f24258c11d626e5afe561d6a2e5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 692b1745fea99d185aaf2ed170a584fb83bf9c870eaa6e03b9567e9d9883930cc136b7e7821cb4746781d87c5131f688bc79f9b0d4cb8aa90208a4d47ef6462f
|
|
7
|
+
data.tar.gz: e9a2698daffc89e5ee9502a1450dce6e736aad68ca500ed1e37dffa4e5c34ed9709ed0f724888959bee6bd680085d56d7beb7c80504610f2a04683a21d6386a7
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.3.0] — 2026-10-05
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Object-store publish fails fast when `PANDORGA_SITE_ROOT` is unset and the
|
|
8
|
+
script runs from the pandorga gem (no more silent skip of `content/media`)
|
|
9
|
+
- `pandorga publish` exports `PANDORGA_SITE_ROOT` even when delegating to a
|
|
10
|
+
site-local `publish-content-to-r2.sh` wrapper
|
|
11
|
+
|
|
12
|
+
## [1.2.4] — 2026-10-05
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- An omitted `pandorga.content.backend` keeps a configured `base_url` or legacy `content_api_base_url` as an object-store origin. `static` remains the default only when no public URL is set, and an explicit `backend: static` still wins.
|
|
17
|
+
|
|
3
18
|
## [1.2.3] — 2026-10-05
|
|
4
19
|
|
|
5
20
|
### Changed
|
|
@@ -22,9 +22,9 @@ module Pandorga
|
|
|
22
22
|
|
|
23
23
|
source "https://rubygems.org"
|
|
24
24
|
|
|
25
|
-
gem "pandorga", "~> 1.
|
|
25
|
+
gem "pandorga", "~> 1.3"
|
|
26
26
|
# Local checkout: gem "pandorga", path: "../pandorga"
|
|
27
|
-
# GitHub tag: gem "pandorga", github: "alexandrelheinen/pandorga", tag: "v1.
|
|
27
|
+
# GitHub tag: gem "pandorga", github: "alexandrelheinen/pandorga", tag: "v1.3.0"
|
|
28
28
|
gem "csv"
|
|
29
29
|
gem "base64"
|
|
30
30
|
RUBY
|
|
@@ -12,8 +12,9 @@ module Pandorga
|
|
|
12
12
|
root = Pathname.new(argv[0] || Dir.pwd).expand_path
|
|
13
13
|
site_script = root.join("scripts", "content", "publish-content-to-r2.sh")
|
|
14
14
|
if site_script.file? && site_script.expand_path != gem_publish_script
|
|
15
|
+
env = ENV.to_h.merge("PANDORGA_SITE_ROOT" => root.to_s)
|
|
15
16
|
Dir.chdir(root) do
|
|
16
|
-
exec("bash", site_script.to_s, *argv[1..])
|
|
17
|
+
exec(env, "bash", site_script.to_s, *argv[1..])
|
|
17
18
|
end
|
|
18
19
|
end
|
|
19
20
|
|
|
@@ -26,10 +26,11 @@ content:
|
|
|
26
26
|
title: "`pandorga.content`"
|
|
27
27
|
intro: |
|
|
28
28
|
Legacy `content_api_base_url` still works as a fallback for `base_url`.
|
|
29
|
+
When `backend` is omitted, a non-empty `base_url` or `content_api_base_url` selects `object_store`. With no origin, the default is `static`. An explicit `backend: static` still serves JSON from `_site` and clears the public URL at build time.
|
|
29
30
|
keys:
|
|
30
31
|
backend:
|
|
31
32
|
type: "`static` \\| `r2` \\| `object_store` \\| `s3`"
|
|
32
|
-
notes: "`static` serves JSON from `_site`. The others use `base_url` as the public object-store origin"
|
|
33
|
+
notes: "`static` serves JSON from `_site`. The others use `base_url` as the public object-store origin. Omitted plus a public URL selects `object_store`"
|
|
33
34
|
base_url:
|
|
34
35
|
type: string
|
|
35
36
|
notes: Public content origin when backend is not `static`
|
data/lib/pandorga/registry.rb
CHANGED
|
@@ -256,9 +256,14 @@ module PandorgaRegistry
|
|
|
256
256
|
|
|
257
257
|
def content_backend(config)
|
|
258
258
|
raw = config.dig("pandorga", "content", "backend").to_s.strip
|
|
259
|
-
return
|
|
259
|
+
return raw unless raw.empty?
|
|
260
260
|
|
|
261
|
-
|
|
261
|
+
# A public origin is the pre-registry signal that JSON lives on an object
|
|
262
|
+
# store. Static is the default only when no origin is configured; an
|
|
263
|
+
# explicit `backend: static` still wins and the build clears the URL.
|
|
264
|
+
return "object_store" unless content_base_url(config).empty?
|
|
265
|
+
|
|
266
|
+
"static"
|
|
262
267
|
end
|
|
263
268
|
|
|
264
269
|
def content_base_url(config)
|
data/lib/pandorga/version.rb
CHANGED
|
@@ -5,7 +5,19 @@
|
|
|
5
5
|
set -euo pipefail
|
|
6
6
|
|
|
7
7
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
8
|
+
|
|
9
|
+
# When this script lives in an installed (or checked-out) gem, ROOT is the gem
|
|
10
|
+
# tree — not the consumer site. Media sync must use the site root; without it
|
|
11
|
+
# we used to skip content/media silently and leave Studio uploads on GitHub
|
|
12
|
+
# only. Require an explicit site root whenever ROOT looks like the gem.
|
|
13
|
+
if [ -z "${PANDORGA_SITE_ROOT:-}" ] && [ -f "$ROOT/pandorga.gemspec" ]; then
|
|
14
|
+
echo "error: PANDORGA_SITE_ROOT must be set when publish-content-to-object-store.sh runs from the pandorga gem." >&2
|
|
15
|
+
echo "hint: export PANDORGA_SITE_ROOT to the Jekyll site root before exec (site wrappers must set this)." >&2
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
|
|
8
19
|
SITE_ROOT="${PANDORGA_SITE_ROOT:-$ROOT}"
|
|
20
|
+
SITE_ROOT="$(cd "$SITE_ROOT" && pwd)"
|
|
9
21
|
EXPORT_ROOT="${1:-$SITE_ROOT/_content_json}"
|
|
10
22
|
|
|
11
23
|
# Prefer S3_* names; fall back to R2_* for Cloudflare R2 callers.
|
|
@@ -55,6 +67,7 @@ sync_json_prefix() {
|
|
|
55
67
|
|
|
56
68
|
echo "==> Publishing content JSON to bucket: ${S3_BUCKET}"
|
|
57
69
|
echo "==> Endpoint: ${S3_ENDPOINT}"
|
|
70
|
+
echo "==> Site root: ${SITE_ROOT}"
|
|
58
71
|
sync_json_prefix collections
|
|
59
72
|
sync_json_prefix data
|
|
60
73
|
sync_json_prefix pages
|
|
@@ -67,12 +80,14 @@ aws s3 cp "$EXPORT_ROOT/manifest.json" "s3://${S3_BUCKET}/manifest.json" \
|
|
|
67
80
|
|
|
68
81
|
MEDIA_ROOT="$SITE_ROOT/content/media"
|
|
69
82
|
if [ -d "$MEDIA_ROOT" ]; then
|
|
70
|
-
echo "==> Sync media/"
|
|
83
|
+
echo "==> Sync media/ from ${MEDIA_ROOT}"
|
|
71
84
|
aws s3 sync "$MEDIA_ROOT" "s3://${S3_BUCKET}/media" \
|
|
72
85
|
--endpoint-url "$S3_ENDPOINT" \
|
|
73
86
|
--delete \
|
|
74
87
|
--size-only \
|
|
75
88
|
--cache-control "public,max-age=31536000,immutable"
|
|
89
|
+
else
|
|
90
|
+
echo "==> No content/media at ${MEDIA_ROOT} (skipping media sync)"
|
|
76
91
|
fi
|
|
77
92
|
|
|
78
93
|
echo "==> Object-store publish complete"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# An omitted backend must not discard a configured public origin.
|
|
4
|
+
# Explicit static still serves JSON from _site.
|
|
5
|
+
require "pathname"
|
|
6
|
+
|
|
7
|
+
ROOT = Pathname.new(__dir__).join("../..").expand_path
|
|
8
|
+
$LOAD_PATH.unshift(ROOT.join("lib").to_s)
|
|
9
|
+
require "pandorga/registry"
|
|
10
|
+
|
|
11
|
+
def check!(condition, message)
|
|
12
|
+
return if condition
|
|
13
|
+
|
|
14
|
+
warn "FAIL test-content-backend: #{message}"
|
|
15
|
+
exit 1
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
url = "https://pub-example.r2.dev"
|
|
19
|
+
|
|
20
|
+
check!(PandorgaRegistry.content_backend({}) == "static",
|
|
21
|
+
"no origin must stay static")
|
|
22
|
+
check!(PandorgaRegistry.static_backend?({}),
|
|
23
|
+
"static_backend? must be true when no origin is set")
|
|
24
|
+
|
|
25
|
+
legacy = { "content_api_base_url" => url }
|
|
26
|
+
check!(PandorgaRegistry.content_backend(legacy) == "object_store",
|
|
27
|
+
"legacy content_api_base_url must select object_store, got #{PandorgaRegistry.content_backend(legacy).inspect}")
|
|
28
|
+
check!(PandorgaRegistry.object_store_backend?(legacy),
|
|
29
|
+
"object_store_backend? must be true for a legacy URL")
|
|
30
|
+
check!(PandorgaRegistry.content_base_url(legacy) == url,
|
|
31
|
+
"legacy URL must remain the public origin")
|
|
32
|
+
|
|
33
|
+
base_only = { "pandorga" => { "content" => { "base_url" => "#{url}/" } } }
|
|
34
|
+
check!(PandorgaRegistry.content_backend(base_only) == "object_store",
|
|
35
|
+
"base_url without backend must select object_store")
|
|
36
|
+
check!(PandorgaRegistry.content_base_url(base_only) == url,
|
|
37
|
+
"base_url must be stripped of a trailing slash")
|
|
38
|
+
|
|
39
|
+
explicit_static = {
|
|
40
|
+
"content_api_base_url" => url,
|
|
41
|
+
"pandorga" => { "content" => { "backend" => "static" } }
|
|
42
|
+
}
|
|
43
|
+
check!(PandorgaRegistry.content_backend(explicit_static) == "static",
|
|
44
|
+
"explicit static must win over a leftover URL")
|
|
45
|
+
|
|
46
|
+
explicit_r2 = { "pandorga" => { "content" => { "backend" => "r2", "base_url" => url } } }
|
|
47
|
+
check!(PandorgaRegistry.content_backend(explicit_r2) == "r2",
|
|
48
|
+
"explicit r2 must be preserved")
|
|
49
|
+
|
|
50
|
+
puts "PASS test-content-backend"
|
data/scripts/test/test-new.rb
CHANGED
|
@@ -57,8 +57,8 @@ end
|
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
gemfile = DEST.join("Gemfile").read
|
|
60
|
-
unless gemfile.include?('gem "pandorga", "~> 1.
|
|
61
|
-
warn "FAIL test-new: Gemfile must pin pandorga ~> 1.
|
|
60
|
+
unless gemfile.include?('gem "pandorga", "~> 1.3"')
|
|
61
|
+
warn "FAIL test-new: Gemfile must pin pandorga ~> 1.3\n#{gemfile}"
|
|
62
62
|
exit 1
|
|
63
63
|
end
|
|
64
64
|
unless gemfile.include?("path:") && gemfile.include?("github:")
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Refs: media sync must not silently use the gem tree as SITE_ROOT.
|
|
5
|
+
require "open3"
|
|
6
|
+
require "pathname"
|
|
7
|
+
|
|
8
|
+
ROOT = Pathname.new(__dir__).join("../..").expand_path
|
|
9
|
+
SCRIPT = ROOT.join("scripts/content/publish-content-to-object-store.sh")
|
|
10
|
+
|
|
11
|
+
def fail!(message)
|
|
12
|
+
warn "FAIL test-publish-site-root: #{message}"
|
|
13
|
+
exit 1
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
fail!("missing #{SCRIPT}") unless SCRIPT.file?
|
|
17
|
+
|
|
18
|
+
env = ENV.to_h
|
|
19
|
+
env.delete("PANDORGA_SITE_ROOT")
|
|
20
|
+
# Avoid falling through to real credentials if a developer has them set.
|
|
21
|
+
%w[
|
|
22
|
+
S3_ENDPOINT S3_BUCKET S3_ACCESS_KEY_ID S3_SECRET_ACCESS_KEY
|
|
23
|
+
R2_ENDPOINT R2_BUCKET R2_ACCESS_KEY_ID R2_SECRET_ACCESS_KEY
|
|
24
|
+
].each { |key| env.delete(key) }
|
|
25
|
+
|
|
26
|
+
out, status = Open3.capture2e(env, "bash", SCRIPT.to_s)
|
|
27
|
+
fail!("expected exit 1 without PANDORGA_SITE_ROOT, got #{status.exitstatus}") unless status.exitstatus == 1
|
|
28
|
+
fail!("expected PANDORGA_SITE_ROOT error, got:\n#{out}") unless out.include?("PANDORGA_SITE_ROOT must be set")
|
|
29
|
+
|
|
30
|
+
ok_env = env.merge(
|
|
31
|
+
"PANDORGA_SITE_ROOT" => ROOT.join("examples/minimal").to_s,
|
|
32
|
+
"S3_ENDPOINT" => "https://example.invalid",
|
|
33
|
+
"S3_BUCKET" => "test-bucket",
|
|
34
|
+
"S3_ACCESS_KEY_ID" => "test",
|
|
35
|
+
"S3_SECRET_ACCESS_KEY" => "test"
|
|
36
|
+
)
|
|
37
|
+
out2, status2 = Open3.capture2e(ok_env, "bash", SCRIPT.to_s, ROOT.join("examples/minimal/_content_json").to_s)
|
|
38
|
+
fail!("with PANDORGA_SITE_ROOT set, must not fail the site-root guard; got #{status2.exitstatus}:\n#{out2}") if out2.include?("PANDORGA_SITE_ROOT must be set")
|
|
39
|
+
|
|
40
|
+
puts "PASS test-publish-site-root"
|
data/scripts/validate.sh
CHANGED
|
@@ -34,6 +34,7 @@ TESTS=(
|
|
|
34
34
|
scripts/test/test-dual-template-instances.rb
|
|
35
35
|
scripts/test/test-dual-template-runtime.rb
|
|
36
36
|
scripts/test/test-install-functions.rb
|
|
37
|
+
scripts/test/test-publish-site-root.rb
|
|
37
38
|
scripts/test/test-no-personal-data.rb
|
|
38
39
|
scripts/test/test-configuration-doc.rb
|
|
39
40
|
scripts/test/test-cv-export-contract.rb
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pandorga
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- The Pandorga contributors
|
|
@@ -365,6 +365,7 @@ files:
|
|
|
365
365
|
- scripts/test/test-cdn-pins.rb
|
|
366
366
|
- scripts/test/test-cloudflare-watch-paths-doc.rb
|
|
367
367
|
- scripts/test/test-configuration-doc.rb
|
|
368
|
+
- scripts/test/test-content-backend.rb
|
|
368
369
|
- scripts/test/test-content-detail-urls.rb
|
|
369
370
|
- scripts/test/test-content-keys.rb
|
|
370
371
|
- scripts/test/test-content-license.rb
|
|
@@ -394,6 +395,7 @@ files:
|
|
|
394
395
|
- scripts/test/test-new.rb
|
|
395
396
|
- scripts/test/test-no-personal-data.rb
|
|
396
397
|
- scripts/test/test-public-cv-export.rb
|
|
398
|
+
- scripts/test/test-publish-site-root.rb
|
|
397
399
|
- scripts/test/test-r2-config-consistency.rb
|
|
398
400
|
- scripts/test/test-r2-json-sync.rb
|
|
399
401
|
- scripts/test/test-registry-home.rb
|