diff --git a/.github/workflows/zola-deploy.yml b/.github/workflows/zola-deploy.yml index 9e39ec3d..d39216de 100644 --- a/.github/workflows/zola-deploy.yml +++ b/.github/workflows/zola-deploy.yml @@ -19,37 +19,37 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: ref: ${{ github.event_name != 'pull_request' && 'main' || '' }} path: website - name: Checkout valkey-doc - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: repository: valkey-io/valkey-doc path: valkey-doc - name: Checkout valkey - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: repository: valkey-io/valkey path: valkey - name: Checkout valkey-bloom - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: repository: valkey-io/valkey-bloom path: valkey-bloom - name: Checkout valkey-search - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: repository: valkey-io/valkey-search path: valkey-search - name: Checkout valkey-json - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: repository: valkey-io/valkey-json path: valkey-json @@ -64,7 +64,7 @@ jobs: ../valkey-json/src/commands ../valkey-search/src/commands - name: Build only - uses: shalzz/zola-deploy-action@v0.22.0 + uses: shalzz/zola-deploy-action@1be083648a1db2853ce4970e381740c0e2fd06de # v0.23.6 env: BUILD_DIR: website BUILD_ONLY: true @@ -72,7 +72,7 @@ jobs: - name: Upload artifact if: github.event_name != 'pull_request' - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3 with: path: ./website/public @@ -86,4 +86,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4 diff --git a/.github/workflows/zola-preview.yml b/.github/workflows/zola-preview.yml new file mode 100644 index 00000000..ef846e42 --- /dev/null +++ b/.github/workflows/zola-preview.yml @@ -0,0 +1,168 @@ +name: Preview website + +# Builds a full preview of the site (including the command reference, topics, +# and clients pages assembled from the sibling repos) for any pull request, and +# makes it available for reviewers to test. Production deploys are handled +# separately by zola-deploy.yml; this workflow never touches the production +# GitHub Pages deployment. +# +# Two ways to consume a preview are provided: +# +# 1. Downloadable artifact (always on, no setup): the built `public/` directory +# is uploaded as a workflow artifact. Download it from the run's Summary page +# and open index.html, or serve the folder with any static server. This uses +# the production base_url, so absolute links point at valkey.io; it is best +# for eyeballing pages and running the search indexer locally. +# +# 2. Hosted preview URL (opt-in): if the PREVIEW_REPOSITORY and PREVIEW_TOKEN +# secrets are set, the build is pushed to a SEPARATE preview repository whose +# GitHub Pages serves it at a per-branch subpath. A repository can serve only +# one GitHub Pages site, and this repo's Pages is already the production site, +# so a hosted preview must live in a different repo. The build then uses that +# repo's Pages origin as its base_url so internal links resolve. + +on: + pull_request: + branches: ["main"] + workflow_dispatch: + inputs: + ref: + description: "Branch or ref to build a preview for" + required: false + +permissions: + contents: read + +concurrency: + group: preview-${{ github.event.pull_request.head.ref || github.ref_name }} + cancel-in-progress: true + +jobs: + build-preview: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + ref: ${{ github.event.inputs.ref || github.event.pull_request.head.sha || github.ref }} + path: website + + - name: Checkout valkey-doc + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + repository: valkey-io/valkey-doc + path: valkey-doc + + - name: Checkout valkey + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + repository: valkey-io/valkey + path: valkey + + - name: Checkout valkey-bloom + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + repository: valkey-io/valkey-bloom + path: valkey-bloom + + - name: Checkout valkey-search + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + repository: valkey-io/valkey-search + path: valkey-search + + - name: Checkout valkey-json + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + repository: valkey-io/valkey-json + path: valkey-json + + - name: Init commands, topics and clients + run: | + cd website + ./build/init-topics-and-clients.sh ../valkey-doc/topics \ + ../valkey-doc/clients + ./build/init-commands.sh ../valkey-doc/commands \ + ../valkey/src/commands ../valkey-bloom/src/commands \ + ../valkey-json/src/commands ../valkey-search/src/commands + + - name: Compute preview path and base URL + id: slug + env: + # Pass the ref through the environment, never interpolate it directly + # into the shell script body: a branch name is attacker-controlled and + # inline ${{ }} expansion would allow shell injection. + PREVIEW_REF: ${{ github.event.pull_request.head.ref || github.event.inputs.ref || github.ref_name }} + PREVIEW_REPOSITORY: ${{ secrets.PREVIEW_REPOSITORY }} + PREVIEW_TOKEN: ${{ secrets.PREVIEW_TOKEN }} + run: | + RAW="$PREVIEW_REF" + # Build a readable but collision-resistant, always-nonempty path: + # a sanitized name plus a short hash of the raw ref. This keeps + # foo/bar and foo-bar distinct and never yields an empty path (which + # would publish at the repo root and, with keep_files, clobber peers). + NAME="$(printf '%s' "$RAW" | tr '/' '-' | tr -cd '[:alnum:]._-')" + HASH="$(printf '%s' "$RAW" | shasum -a 256 | cut -c1-8)" + SAFE="${NAME:-preview}-${HASH}" + echo "path=$SAFE" >> "$GITHUB_OUTPUT" + # Host a preview only when BOTH secrets are present. If only one is set, + # fall back to artifact-only so the run completes instead of invoking + # the publish step without a usable credential and failing. + if [ -n "$PREVIEW_REPOSITORY" ] && [ -n "$PREVIEW_TOKEN" ]; then + PV_OWNER="${PREVIEW_REPOSITORY%%/*}" + PV_REPO="${PREVIEW_REPOSITORY#*/}" + echo "hosted=true" >> "$GITHUB_OUTPUT" + echo "base_url=https://${PV_OWNER}.github.io/${PV_REPO}/${SAFE}/" >> "$GITHUB_OUTPUT" + else + echo "hosted=false" >> "$GITHUB_OUTPUT" + echo "base_url=" >> "$GITHUB_OUTPUT" + fi + + - name: Build (default base URL, for the downloadable artifact) + if: steps.slug.outputs.hosted != 'true' + uses: shalzz/zola-deploy-action@1be083648a1db2853ce4970e381740c0e2fd06de # v0.23.6 + env: + BUILD_DIR: website + BUILD_ONLY: true + BUILD_THEMES: false + + - name: Build (preview base URL, for the hosted preview) + if: steps.slug.outputs.hosted == 'true' + uses: shalzz/zola-deploy-action@1be083648a1db2853ce4970e381740c0e2fd06de # v0.23.6 + env: + BUILD_DIR: website + BUILD_ONLY: true + BUILD_THEMES: false + BUILD_FLAGS: --base-url ${{ steps.slug.outputs.base_url }} + + - name: Upload preview artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: site-preview-${{ steps.slug.outputs.path }} + path: ./website/public + retention-days: 14 + + - name: Publish hosted preview + if: steps.slug.outputs.hosted == 'true' + uses: peaceiris/actions-gh-pages@84c30a85c19949d7eee79c4ff27748b70285e453 # v4 + with: + personal_token: ${{ secrets.PREVIEW_TOKEN }} + external_repository: ${{ secrets.PREVIEW_REPOSITORY }} + publish_branch: gh-pages + publish_dir: ./website/public + destination_dir: ${{ steps.slug.outputs.path }} + keep_files: true + commit_message: "preview: ${{ steps.slug.outputs.path }} (${{ github.sha }})" + + - name: Summarize + run: | + echo "### Preview build ready" >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" + echo "Downloadable artifact: **site-preview-${{ steps.slug.outputs.path }}** (see the Artifacts section of this run). Unzip and open index.html, or serve the folder with any static server." >> "$GITHUB_STEP_SUMMARY" + if [ "${{ steps.slug.outputs.hosted }}" = "true" ]; then + echo "" >> "$GITHUB_STEP_SUMMARY" + echo "Hosted preview URL: ${{ steps.slug.outputs.base_url }}" >> "$GITHUB_STEP_SUMMARY" + else + echo "" >> "$GITHUB_STEP_SUMMARY" + echo "_Hosted preview URL not configured. Set the PREVIEW_REPOSITORY (owner/repo of a separate Pages repo) and PREVIEW_TOKEN secrets to publish a hosted preview URL._" >> "$GITHUB_STEP_SUMMARY" + fi diff --git a/CONTRIBUTING-BLOG-POST.md b/CONTRIBUTING-BLOG-POST.md index 29fc8ee8..8a8d1178 100644 --- a/CONTRIBUTING-BLOG-POST.md +++ b/CONTRIBUTING-BLOG-POST.md @@ -55,7 +55,8 @@ Unless you have specific authority (and you probably don’t!), avoid speaking f Reviewers use these as the basis for suggestions, so knowing them up front saves a round trip. This document follows them, so read its source as an example. -[`content/blog/example-post.md.example`](content/blog/example-post.md.example) is a short post that applies every rule below, with frontmatter, a tagged code block, and an image with alt text. +[`content/blog/example-post.md.example`](content/blog/example-post.md.example) is a short post that applies the core rules below, with frontmatter, a tagged code block, and an image with alt text. +It does not show the situational rules (14 and 15), which apply only to posts that embed a video or quote template-like syntax. Copy it as a starting point. 1. Put one sentence per line in the markdown source. @@ -107,6 +108,12 @@ The two cases that come up most in Valkey posts: If you find you have nothing to write in the body, the image is not carrying information worth showing. 2. Use empty alt text (`![]`) for a purely decorative image, and for one whose content the adjacent text already states in full. 13. Expand an acronym on first use with the acronym in parentheses. +14. Embed a YouTube video with the `youtube` component, not a raw ` + +{% endcomponent youtube %} diff --git a/templates/default.html b/templates/default.html index 10efa26d..b398aaa0 100644 --- a/templates/default.html +++ b/templates/default.html @@ -1,5 +1,5 @@ {%- block head -%}{%- endblock -%} - + {% include "includes/head.html" %} {%- if config.extra.banner -%}