Improved the bootstrap script to write the canonical site origin and also, fixed some nasty bugs.
This commit is contained in:
+1
-1
@@ -10,7 +10,7 @@
|
||||
**/.build
|
||||
**/.swiftpm
|
||||
|
||||
# Test sources
|
||||
# Local database data directory.
|
||||
**/Tests/DB
|
||||
|
||||
# Xcode project (not used by the Linux build)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Template root Makefile — bootstrap convenience only.
|
||||
# This file is removed by `Tools/bootstrap` once the template is generated.
|
||||
# This file is removed by `Scripts/bootstrap` once the template is generated.
|
||||
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
|
||||
@@ -53,9 +53,9 @@ make bootstrap # or: ./Scripts/bootstrap
|
||||
|
||||
| Prompt | Example | Rewrites |
|
||||
| --- | --- | --- |
|
||||
| **Site display name** (PascalCase) | `Loud` | Server name (`LoudWebsite`), `Loud.xcodeproj`, README title. |
|
||||
| **Project slug** (lowercase) | `loud-ams` | Container owner, database name/user, Compose project name. |
|
||||
| **Canonical site URL** (scheme + host) | `https://loud.amsterdam` | The `Sitemap:` reference in `robots.txt` and the `<loc>` entry in `sitemap.xml`. |
|
||||
| **Site display name** (PascalCase) | `Acme` | Server name (`AcmeWebsite`), `Acme.xcodeproj`, README title. |
|
||||
| **Project slug** (lowercase) | `acme-web` | Container owner, database name/user, Compose project name. |
|
||||
| **Canonical site URL** (scheme + host) | `https://acme.example.com` | The `Sitemap:` reference in `robots.txt`, the `<loc>` entry in `sitemap.xml`, and `String.Site.origin`. |
|
||||
|
||||
- The URL defaults to the reserved `https://site.example.com`; leaving it is
|
||||
allowed (the script warns) and can be corrected later in the two crawler files.
|
||||
@@ -84,10 +84,14 @@ make bootstrap # or: ./Scripts/bootstrap
|
||||
set `ANALYTICS_WEBSITE_ID`. `ANALYTICS_DOMAINS` limits which hosts report;
|
||||
`ANALYTICS_RECORDER` opts into the session recorder. See
|
||||
[Analytics](Services/Website/README.md#analytics).
|
||||
5. **Secrets** — set a real `DATABASE_PASSWORD` in a git-ignored
|
||||
5. **Site origin** — bootstrap writes the canonical URL into `String.Site.origin`
|
||||
(override with `SITE_ORIGIN`), leaving it empty for the placeholder. An empty
|
||||
or non-HTTPS origin disables the HTTPS redirect, which
|
||||
`HTTPS_TRUST_FORWARDED_PROTO` must enable besides.
|
||||
6. **Secrets** — set a real `DATABASE_PASSWORD` in a git-ignored
|
||||
`Services/Website/.env`; the committed `.env.local` is an example and defaults
|
||||
the password to the slug.
|
||||
6. **Domain models** — replace the `Persistence` package's sample `ExampleRecord`
|
||||
7. **Domain models** — replace the `Persistence` package's sample `ExampleRecord`
|
||||
/ `ExampleRepository`. The default driver is in-memory SQLite, migrated on
|
||||
every boot; a real site sets `DATABASE_DRIVER=postgres` and migrates out of
|
||||
band (`swift run Website --database-migrate`). See
|
||||
|
||||
+26
-7
@@ -31,7 +31,7 @@ PLACEHOLDER_URL_PATTERN='https://site\.example\.com'
|
||||
|
||||
# --- Prompts ------------------------------------------------------------------
|
||||
|
||||
printf 'Site display name (PascalCase, e.g. Berlin) [Site]: '
|
||||
printf 'Site display name (PascalCase, e.g. Acme) [Site]: '
|
||||
read -r NAME
|
||||
NAME="${NAME:-Site}"
|
||||
|
||||
@@ -54,7 +54,7 @@ case "$NAME" in
|
||||
esac
|
||||
|
||||
DEFAULT_SLUG="$(printf '%s' "$NAME" | tr '[:upper:]' '[:lower:]')"
|
||||
printf 'Project slug (lowercase, used for owner/db/compose, e.g. loud-berlin) [%s]: ' "$DEFAULT_SLUG"
|
||||
printf 'Project slug (lowercase, used for owner/db/compose, e.g. acme-web) [%s]: ' "$DEFAULT_SLUG"
|
||||
read -r SLUG
|
||||
SLUG="${SLUG:-$DEFAULT_SLUG}"
|
||||
|
||||
@@ -75,7 +75,7 @@ case "$SLUG" in
|
||||
;;
|
||||
esac
|
||||
|
||||
printf 'Canonical site URL (scheme + host, e.g. https://berlin.example.com) [%s]: ' "$PLACEHOLDER_URL"
|
||||
printf 'Canonical site URL (scheme + host, e.g. https://acme.example.com) [%s]: ' "$PLACEHOLDER_URL"
|
||||
read -r URL
|
||||
URL="${URL:-$PLACEHOLDER_URL}"
|
||||
URL="${URL%/}" # the rewrites append their own path, so drop a trailing slash
|
||||
@@ -99,7 +99,7 @@ esac
|
||||
echo
|
||||
echo " display name : $NAME (server name \"${NAME}Website\", ${NAME}.xcodeproj)"
|
||||
echo " slug : $SLUG (container owner, database name/user, compose project)"
|
||||
echo " canonical URL: $URL (robots.txt sitemap reference, sitemap.xml entry)"
|
||||
echo " canonical URL: $URL (robots.txt, sitemap.xml, String.Site.origin)"
|
||||
echo
|
||||
printf 'Apply these values? [y/N]: '
|
||||
read -r CONFIRM
|
||||
@@ -136,6 +136,13 @@ rewrite "$W/Sources/Library/Public/Extensions/String+Constants.swift" \
|
||||
-e "s/SiteWebsite/${NAME}Website/g" \
|
||||
-e "s/= \"site\"/= \"${SLUG}\"/g"
|
||||
|
||||
# Canonical origin. Left empty for the placeholder, which keeps the HTTPS
|
||||
# redirect off rather than aimed at a reserved example domain.
|
||||
if [ "$URL" != "$PLACEHOLDER_URL" ]; then
|
||||
rewrite "$W/Sources/Library/Public/Extensions/String+Constants.swift" \
|
||||
-e "s|^ public static let origin = \"\"\$| public static let origin = \"${URL}\"|"
|
||||
fi
|
||||
|
||||
# Local env example.
|
||||
rewrite "$W/.env.local" \
|
||||
-e "s/SiteWebsite/${NAME}Website/g" \
|
||||
@@ -162,6 +169,17 @@ rewrite "$W/docker-compose.override.yml" \
|
||||
rewrite "$W/Makefile" \
|
||||
-e "s/),site)/),${SLUG})/g"
|
||||
|
||||
# Web app manifest: the identity shown by an install prompt.
|
||||
rewrite "$W/Resources/Static/site.webmanifest" \
|
||||
-e "s/^ \"short_name\": \"\"/ \"short_name\": \"${NAME}\"/" \
|
||||
-e "s/^ \"name\": \"\"/ \"name\": \"${NAME}\"/"
|
||||
|
||||
# Persistence integration test: its POSTGRES_TEST_* fallbacks address the local
|
||||
# container `make db-mount` creates, which is initialised from the slug.
|
||||
rewrite "Packages/Persistence/Tests/Cases/Public/Methods/ServiceTests.swift" \
|
||||
-e "s/?? \"site\"/?? \"${SLUG}\"/g" \
|
||||
-e "s/: \"site\",\$/: \"${SLUG}\",/"
|
||||
|
||||
# Crawler files: the absolute origin they must carry. `|` is the sed delimiter,
|
||||
# since both the placeholder and the replacement contain slashes.
|
||||
rewrite "$W/Resources/Static/robots.txt" \
|
||||
@@ -175,7 +193,9 @@ rewrite "$W/README.md" \
|
||||
-e "s/^# Site Website\$/# ${NAME} Website/" \
|
||||
-e "s/\*\*Site\*\*/**${NAME}**/" \
|
||||
-e "s/SiteWebsite/${NAME}Website/g" \
|
||||
-e "s/\`site\`/\`${SLUG}\`/g"
|
||||
-e "s/\`site\`/\`${SLUG}\`/g" \
|
||||
-e "s/\`Site\.xcodeproj\`/\`${NAME}.xcodeproj\`/g" \
|
||||
-e "s|^\`robots.txt\` and \`sitemap.xml\` need an absolute origin.*\$|\`robots.txt\` and \`sitemap.xml\` carry the absolute origin bootstrap wrote into them: ${URL}. Update both if the canonical origin ever changes.|"
|
||||
|
||||
# Xcode project: PBXProject name + directory.
|
||||
if [ -d "$XCODEPROJ" ]; then
|
||||
@@ -218,7 +238,6 @@ rm -f Scripts/bootstrap
|
||||
rmdir Scripts 2>/dev/null || true
|
||||
rm -f Makefile # root convenience Makefile (bootstrap only)
|
||||
rm -f README.md # template usage docs
|
||||
rm -rf .gitea # Gitea template metadata
|
||||
|
||||
# --- Done ---------------------------------------------------------------------
|
||||
|
||||
@@ -231,7 +250,7 @@ Next steps:
|
||||
- $W/Sources/Library/Catalogs/Localizable.xcstrings (copy)
|
||||
- $W/Sources/Library (landing / 404 pages)
|
||||
- $W/Resources/Static (css, js, favicon, icons)
|
||||
- $W/Resources/Static/site.webmanifest (name / short_name)
|
||||
- $W/Resources/Static/site.webmanifest (theme colours)
|
||||
2. Set a real database password in a git-ignored $W/.env
|
||||
(the committed .env.local defaults the password to the slug — do NOT ship that).
|
||||
3. Analytics ships OFF, and stays off until you opt in. To enable it: check
|
||||
|
||||
@@ -134,9 +134,9 @@ every `GET`/`HEAD` whose path ends in a slash is answered with a `301` to the fo
|
||||
### Site
|
||||
| Config key | Environment variable | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `site.origin` | `SITE_ORIGIN` | _(empty)_ | The public origin the site is served at (scheme and host, no trailing slash). The HTTPS redirect points at it, and absolute links derive from it. |
|
||||
| `site.origin` | `SITE_ORIGIN` | _(set by bootstrap)_ | The public origin the site is served at (scheme and host, no trailing slash). The HTTPS redirect points at it, and absolute links derive from it. |
|
||||
|
||||
Empty by default, which leaves the [HTTPS redirect](#https-redirect) off: a deployment that trusts the forwarded-protocol header without setting this would otherwise redirect at a host the template guessed, and a `301` is cached for a long time. Bootstrap does **not** fill it in — it rewrites the crawler files only.
|
||||
Bootstrap writes the canonical URL it prompts for here, leaving it empty for the placeholder. An empty or non-HTTPS origin disables the [HTTPS redirect](#https-redirect), which `https.trustForwardedProto` must enable besides — a `301` is cached for a long time, so it is never issued at a host nobody named.
|
||||
|
||||
### Logging
|
||||
| Config key | Environment variable | Default | Description |
|
||||
|
||||
@@ -56,10 +56,11 @@ extension String {
|
||||
}
|
||||
/// A namespace for the site string constants.
|
||||
public enum Site {
|
||||
/// The default public origin the site is served at (scheme and host, no trailing slash): empty, which leaves the HTTPS redirect off.
|
||||
/// The default public origin the site is served at (scheme and host, no trailing slash).
|
||||
///
|
||||
/// A deployment that trusts the forwarded-protocol header without also setting `site.origin` would otherwise redirect at a host the
|
||||
/// template guessed for it, and a `301` is cached for a long time.
|
||||
/// Bootstrap writes the canonical URL it prompts for here, leaving it empty for the placeholder. An empty or non-HTTPS origin disables
|
||||
/// the HTTPS redirect, which `https.trustForwardedProto` must enable besides — a `301` is cached for a long time, so it is never issued
|
||||
/// at a host nobody named.
|
||||
public static let origin = ""
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user