182 lines
6.5 KiB
Makefile
182 lines
6.5 KiB
Makefile
# === Hugo: publish Markdown & sign with OpenPGP; add Download & Verify block ===
|
|
SHELL := /bin/bash
|
|
|
|
# --- Config ---
|
|
KEYID ?= 55A2A5DE84792BACC6CAEE3FB5882850E04C8D2A # or use your email: iman.alip2001@gmail.com
|
|
CONTENT_DIR ?= content
|
|
INCLUDE_DIRS ?= posts PhD_journey
|
|
PUBLISH_DIR ?= static/sources
|
|
MODE ?= interactive # interactive | loopback
|
|
|
|
# Find helper: $(call MD_FIND,<dir>)
|
|
MD_FIND = find $(1) -type f -name '*.md' -print0
|
|
|
|
.PHONY: verify-ready publish-md sign-md append-sigdl sigdl-shortcode publish-and-sign sign-content clean-published clean-signatures
|
|
|
|
# === One-command flow (matches your "Build flow end to end") ===
|
|
verify-ready: sigdl-shortcode publish-md sign-md append-sigdl
|
|
@echo "✅ Done: published, signed, and appended {{< sigdl >}} to posts."
|
|
|
|
# 1) Copy raw Markdown to static/sources so readers can download exact bytes.
|
|
publish-md:
|
|
@set -euo pipefail; \
|
|
for sub in $(INCLUDE_DIRS); do \
|
|
root="$(CONTENT_DIR)/$$sub"; \
|
|
if [[ -d "$$root" ]]; then \
|
|
$(call MD_FIND,$$root) | while IFS= read -r -d '' md; do \
|
|
rel="$${md#$(CONTENT_DIR)/}"; \
|
|
out="$(PUBLISH_DIR)/$$rel"; \
|
|
mkdir -p "$$(dirname "$$out")"; \
|
|
cp -f -- "$$md" "$$out"; \
|
|
echo "published: $$out"; \
|
|
done; \
|
|
else \
|
|
echo "skip missing: $$root"; \
|
|
fi; \
|
|
done
|
|
|
|
# 2) Sign the published Markdown (recommended target for readers to verify).
|
|
sign-md: publish-md
|
|
@set -euo pipefail; \
|
|
# Set up interactive pinentry if needed
|
|
if [[ "$(MODE)" == "interactive" ]]; then \
|
|
if tty >/dev/null 2>&1; then export GPG_TTY="$$(tty)"; fi; \
|
|
fi; \
|
|
# Require passphrase in env for loopback mode
|
|
if [[ "$(MODE)" == "loopback" ]] && [[ -z "$${GPG_PASSPHRASE:-}" ]]; then \
|
|
echo "ERROR: MODE=loopback but GPG_PASSPHRASE not set"; exit 1; \
|
|
fi; \
|
|
$(call MD_FIND,$(PUBLISH_DIR)) | while IFS= read -r -d '' f; do \
|
|
asc="$$f.asc"; \
|
|
echo "sign: $$f -> $$asc"; \
|
|
if [[ "$(MODE)" == "loopback" ]]; then \
|
|
printf "%s" "$$GPG_PASSPHRASE" | gpg --yes --pinentry-mode loopback --passphrase-fd 0 \
|
|
--local-user $(KEYID) --detach-sign --armor -o "$$asc" "$$f"; \
|
|
else \
|
|
gpg --yes --local-user $(KEYID) --detach-sign --armor -o "$$asc" "$$f"; \
|
|
fi; \
|
|
done
|
|
|
|
# Convenience alias (kept for compatibility)
|
|
publish-and-sign: sign-md
|
|
|
|
# 3) Ensure the shortcode file exists (created once if missing) — heredoc-free, make-safe.
|
|
sigdl-shortcode:
|
|
@set -euo pipefail; \
|
|
path="layouts/shortcodes/sigdl.html"; \
|
|
if [[ ! -f "$$path" ]]; then \
|
|
echo "creating $$path"; \
|
|
mkdir -p "$$(dirname "$$path")"; \
|
|
printf '%s\n' \
|
|
'{{- /* sigdl — Download & Verify block for each post.' \
|
|
' Assumes you publish .md to /static/sources/<relpath>.md and sign to .md.asc.' \
|
|
' Usage in post: {{< sigdl >}} */ -}}' \
|
|
'{{- $$rel := replace .Page.File.Path "content/" "" -}}' \
|
|
'{{- $$download := printf "/sources/%s" $$rel -}}' \
|
|
'{{- $$asc := printf "%s.asc" $$download -}}' \
|
|
'{{- $$staticAscPath := printf "static%s.asc" $$download -}}' \
|
|
'{{- $$sig := "" -}}' \
|
|
'{{- if (fileExists $$staticAscPath) -}}' \
|
|
' {{- $$sig = (readFile $$staticAscPath) | htmlEscape -}}' \
|
|
'{{- end -}}' \
|
|
'<div class="signature-block" style="margin-top:1rem">' \
|
|
' <p><strong>Downloads:</strong>' \
|
|
' <a href="{{ $$download | relURL }}">Markdown</a> ·' \
|
|
' <a href="{{ $$asc | relURL }}">Signature (.asc)</a>' \
|
|
' </p>' \
|
|
' {{- if $$sig -}}' \
|
|
' <details class="signature">' \
|
|
' <summary>View signature</summary>' \
|
|
' <pre style="font-size:0.85em; overflow-x:auto; padding:0.75rem;">{{$$sig}}</pre>' \
|
|
' </details>' \
|
|
' {{- end -}}' \
|
|
' <p><em>Verify locally:</em></p>' \
|
|
' <pre style="font-size:0.85em; overflow-x:auto; padding:0.75rem;">' \
|
|
'curl -O {{ $$download | absURL }}' \
|
|
'curl -O {{ $$asc | absURL }}' \
|
|
'gpg --verify {{ path.Base $$asc }} {{ path.Base $$download }}' \
|
|
' </pre>' \
|
|
'</div>' \
|
|
> "$$path"; \
|
|
else \
|
|
echo "exists: $$path"; \
|
|
fi
|
|
|
|
# 4) Append the shortcode to posts (idempotent).
|
|
append-sigdl:
|
|
@set -euo pipefail; \
|
|
for sub in $(INCLUDE_DIRS); do \
|
|
root="$(CONTENT_DIR)/$$sub"; \
|
|
[[ -d "$$root" ]] || { echo "skip missing: $$root"; continue; }; \
|
|
$(call MD_FIND,$$root) | while IFS= read -r -d '' md; do \
|
|
if grep -q '{{< *sigdl' "$$md"; then \
|
|
echo "exists: $$md"; \
|
|
else \
|
|
printf "\n\n---\n\n{{< sigdl >}}\n" >> "$$md"; \
|
|
echo "appended: $$md"; \
|
|
fi; \
|
|
done; \
|
|
done
|
|
|
|
# (Optional) Sign files directly under content/ (useful for your own archive; readers should prefer the published copies)
|
|
sign-content:
|
|
@set -euo pipefail; \
|
|
if [[ "$(MODE)" == "interactive" ]]; then \
|
|
if tty >/dev/null 2>&1; then export GPG_TTY="$$(tty)"; fi; \
|
|
fi; \
|
|
if [[ "$(MODE)" == "loopback" ]] && [[ -z "$${GPG_PASSPHRASE:-}" ]]; then \
|
|
echo "ERROR: MODE=loopback but GPG_PASSPHRASE not set"; exit 1; \
|
|
fi; \
|
|
for sub in $(INCLUDE_DIRS); do \
|
|
root="$(CONTENT_DIR)/$$sub"; \
|
|
[[ -d "$$root" ]] || continue; \
|
|
$(call MD_FIND,$$root) | while IFS= read -r -d '' f; do \
|
|
asc="$$f.asc"; \
|
|
echo "sign: $$f -> $$asc"; \
|
|
if [[ "$(MODE)" == "loopback" ]]; then \
|
|
printf "%s" "$$GPG_PASSPHRASE" | gpg --yes --pinentry-mode loopback --passphrase-fd 0 \
|
|
--local-user $(KEYID) --detach-sign --armor -o "$$asc" "$$f"; \
|
|
else \
|
|
gpg --yes --local-user $(KEYID) --detach-sign --armor -o "$$asc" "$$f"; \
|
|
fi; \
|
|
done; \
|
|
done
|
|
|
|
# Cleanup helpers
|
|
clean-published:
|
|
@echo "rm -rf $(PUBLISH_DIR)"; rm -rf -- "$(PUBLISH_DIR)"
|
|
|
|
clean-signatures:
|
|
@set -euo pipefail; \
|
|
find "$(PUBLISH_DIR)" -type f -name '*.md.asc' -delete 2>/dev/null || true; \
|
|
find "$(CONTENT_DIR)" -type f -name '*.md.asc' -delete 2>/dev/null || true
|
|
|
|
# --- Cleanup: remove old {{< sig ... >}} blocks so only {{< sigdl >}} remains ---
|
|
.ONESHELL:
|
|
.PHONY: remove-old-sig disable-old-sig-shortcode
|
|
|
|
# Delete any line that contains the legacy {{< sig ... >}} shortcode (but not {{< sigdl >}})
|
|
remove-old-sig:
|
|
@set -euo pipefail
|
|
for sub in $(INCLUDE_DIRS); do
|
|
root="$(CONTENT_DIR)/$$sub"
|
|
[[ -d "$$root" ]] || { echo "skip missing: $$root"; continue; }
|
|
find "$$root" -type f -name '*.md' -print0 | while IFS= read -r -d '' f; do
|
|
if grep -Eq '\{\{<\s*sig(\s|>)' "$$f"; then
|
|
sed -E -i '/\{\{<\s*sig(\s|>)/d' "$$f"
|
|
echo "removed old sig: $$f"
|
|
fi
|
|
done
|
|
done
|
|
|
|
# Disable the old layouts/shortcodes/sig.html so it can't render accidentally
|
|
disable-old-sig-shortcode:
|
|
@set -euo pipefail
|
|
path="layouts/shortcodes/sig.html"
|
|
if [[ -f "$$path" ]]; then
|
|
mv "$$path" "$$path.bak"
|
|
echo "moved $$path -> $$path.bak (legacy shortcode disabled)"
|
|
else
|
|
echo "no legacy shortcode found at $$path"
|
|
fi
|
|
|