From 797abe5c7a1f541df876a19d99e222843c341014 Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Thu, 4 Sep 2025 15:03:01 -0600 Subject: [PATCH 1/9] build: allow forked PRs to build previews (experimental) --- .../workflows/cloudflare-preview-forks.yml | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 .github/workflows/cloudflare-preview-forks.yml diff --git a/.github/workflows/cloudflare-preview-forks.yml b/.github/workflows/cloudflare-preview-forks.yml new file mode 100644 index 00000000..95bd8464 --- /dev/null +++ b/.github/workflows/cloudflare-preview-forks.yml @@ -0,0 +1,175 @@ +name: Cloudflare Pages preview (forked PRs) +# Requires a Cloudflare Pages project (Direct Upload). CF_PAGES_PROJECT must be that project name. +# No GitHub App integration is required for this workflow; deployments are done via API token. + +on: + pull_request_target: + types: [opened, synchronize, reopened, ready_for_review, closed] + +# Least privilege at the workflow level +permissions: + contents: read + +concurrency: + group: fork-preview-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + build: + name: Build site (no secrets) + if: ${{ github.event.pull_request.head.repo.fork == true && github.event.action != 'closed' }} + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout PR code (from fork) + uses: actions/checkout@v4 + with: + # Important: explicit checkout of the fork + head SHA to avoid using base workflow code + repository: ${{ github.event.pull_request.head.repo.full_name }} + ref: ${{ github.event.pull_request.head.sha }} + persist-credentials: false + + # NOTE: + # - Configure your build exactly like your existing non-fork preview build, + # but without any secrets. Copy the same toolchain and commands. + # - The deploy job targets a Cloudflare Pages "Direct Upload" project. + - name: Setup build tooling + run: | + # ...existing code (e.g., setup Hugo/Node/PNPM/NPM/yarn/etc)... + echo "Setup steps as in your current preview workflow" + + - name: Build site + run: | + # ...existing code (exact same build commands you use today)... + # Example placeholders (replace with your real build): + # npm ci + # npm run build + # or: hugo --minify + echo "Build commands as in your current preview workflow" + + - name: Package built site + run: | + # Replace 'public' with your build output dir if different (e.g., 'dist') + # Ensure the directory exists before upload. + if [ ! -d "public" ] && [ ! -d "dist" ]; then + echo "Please adjust the output directory (public/dist) to match your build" + exit 1 + fi + OUTDIR="public" + [ -d "dist" ] && OUTDIR="dist" + echo "Using output dir: $OUTDIR" + mkdir -p artifact && cp -a "$OUTDIR"/. artifact/ + + - name: Upload built artifact + uses: actions/upload-artifact@v4 + with: + name: site-dist + path: artifact + if-no-files-found: error + retention-days: 7 + + deploy: + name: Deploy preview to Cloudflare Pages + if: ${{ github.event.pull_request.head.repo.fork == true && github.event.action != 'closed' }} + runs-on: ubuntu-latest + needs: build + permissions: + contents: read + pull-requests: write + steps: + - name: Check required secrets + env: + CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }} + CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }} + CF_PAGES_PROJECT: ${{ secrets.CF_PAGES_PROJECT }} + run: | + missing=0 + for v in CF_API_TOKEN CF_ACCOUNT_ID CF_PAGES_PROJECT; do + if [ -z "${!v}" ]; then + echo "::error::Missing repository secret '$v'." + missing=1 + fi + done + if [ "$missing" -ne 0 ]; then + echo "Set CF_API_TOKEN, CF_ACCOUNT_ID, CF_PAGES_PROJECT in repo settings. CF_PAGES_PROJECT must be a Cloudflare Pages Direct Upload project." + exit 1 + fi + + - name: Download built artifact + uses: actions/download-artifact@v4 + with: + name: site-dist + path: site-dist + + - name: Publish to Cloudflare Pages (preview) + id: pages + uses: cloudflare/pages-action@v1 + with: + # Required repo secrets (GitHub > Settings > Secrets and variables > Actions) + # CF_PAGES_PROJECT should be a Pages project created as "Direct Upload" (no Git integration). + apiToken: ${{ secrets.CF_API_TOKEN }} + accountId: ${{ secrets.CF_ACCOUNT_ID }} + projectName: ${{ secrets.CF_PAGES_PROJECT }} + directory: site-dist + # Stable per-PR preview + branch: pr-${{ github.event.pull_request.number }} + commitHash: ${{ github.event.pull_request.head.sha }} + wranglerVersion: '3' + + - name: Comment preview URL + if: ${{ always() }} + uses: actions/github-script@v7 + env: + PREVIEW_URL: ${{ steps.pages.outputs.deployment-url || steps.pages.outputs.url || '' }} + with: + script: | + const url = process.env.PREVIEW_URL; + if (!url) { + core.info('No preview URL found from Cloudflare action outputs.'); + return; + } + const body = `Cloudflare Pages preview: ${url}`; + // Update existing bot comment if present; otherwise create a new one + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + const existing = comments.find(c => + c.user.type === 'Bot' && c.body && c.body.includes('Cloudflare Pages preview:') + ); + if (existing) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existing.id, + body, + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body, + }); + } + + # Optional: do nothing on close (Cloudflare will mark preview inactive). + # You can add a small comment on close if desired. + closed-note: + name: Note on PR close + if: ${{ github.event.pull_request.head.repo.fork == true && github.event.action == 'closed' }} + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - uses: actions/github-script@v7 + with: + script: | + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: 'PR closed. The Cloudflare Pages preview is no longer updated.', + }); From 26a55e8d29b121fa174d5086781659b853fe106e Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Thu, 4 Sep 2025 15:07:27 -0600 Subject: [PATCH 2/9] details --- .github/workflows/cloudflare-preview-forks.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cloudflare-preview-forks.yml b/.github/workflows/cloudflare-preview-forks.yml index 95bd8464..20f03dfe 100644 --- a/.github/workflows/cloudflare-preview-forks.yml +++ b/.github/workflows/cloudflare-preview-forks.yml @@ -1,3 +1,4 @@ +# Tip: This workflow must be present on the base repo's default branch (e.g., main) for pull_request_target to trigger. name: Cloudflare Pages preview (forked PRs) # Requires a Cloudflare Pages project (Direct Upload). CF_PAGES_PROJECT must be that project name. # No GitHub App integration is required for this workflow; deployments are done via API token. From a1a567b5e8c769ee3df695e665a04b8065e35872 Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Thu, 4 Sep 2025 15:16:55 -0600 Subject: [PATCH 3/9] Push the real thing up there in main --- .../workflows/cloudflare-preview-forks.yml | 108 ++++++++++++++---- 1 file changed, 86 insertions(+), 22 deletions(-) diff --git a/.github/workflows/cloudflare-preview-forks.yml b/.github/workflows/cloudflare-preview-forks.yml index 20f03dfe..160148ac 100644 --- a/.github/workflows/cloudflare-preview-forks.yml +++ b/.github/workflows/cloudflare-preview-forks.yml @@ -22,6 +22,11 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + env: + # Optional repo variables for precise control (Settings > Secrets and variables > Actions > Variables) + # If set, PAGES_BUILD_CMD will be executed and PAGES_OUTPUT_DIR used for packaging. + PAGES_BUILD_CMD: ${{ vars.PAGES_BUILD_CMD }} + PAGES_OUTPUT_DIR: ${{ vars.PAGES_OUTPUT_DIR }} steps: - name: Checkout PR code (from fork) uses: actions/checkout@v4 @@ -31,36 +36,94 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} persist-credentials: false - # NOTE: - # - Configure your build exactly like your existing non-fork preview build, - # but without any secrets. Copy the same toolchain and commands. - # - The deploy job targets a Cloudflare Pages "Direct Upload" project. - - name: Setup build tooling + - name: Print repo root for debugging run: | - # ...existing code (e.g., setup Hugo/Node/PNPM/NPM/yarn/etc)... - echo "Setup steps as in your current preview workflow" + pwd + ls -la - - name: Build site + - name: Setup Node.js (for common JS builds) + uses: actions/setup-node@v4 + with: + node-version: 20 + check-latest: true + + - name: Build (auto-detect or use PAGES_BUILD_CMD) + id: build run: | - # ...existing code (exact same build commands you use today)... - # Example placeholders (replace with your real build): - # npm ci - # npm run build - # or: hugo --minify - echo "Build commands as in your current preview workflow" + set -euo pipefail - - name: Package built site + run_cmd() { echo "+ $*"; eval "$*"; } + + if [ -n "${PAGES_BUILD_CMD:-}" ]; then + echo "Using PAGES_BUILD_CMD from repo variables: ${PAGES_BUILD_CMD}" + run_cmd "${PAGES_BUILD_CMD}" + else + echo "Auto-detecting build system..." + if [ -f "pnpm-lock.yaml" ]; then + echo "Detected pnpm" + corepack enable >/dev/null 2>&1 || true + run_cmd "pnpm --version" + run_cmd "pnpm install --frozen-lockfile" + if jq -e '.scripts.build' package.json >/dev/null 2>&1; then + run_cmd "pnpm run build" + else + echo "No build script found in package.json"; exit 1 + fi + elif [ -f "yarn.lock" ]; then + echo "Detected yarn" + corepack enable >/dev/null 2>&1 || true + run_cmd "yarn --version" + run_cmd "yarn install --frozen-lockfile" + if jq -e '.scripts.build' package.json >/dev/null 2>&1; then + run_cmd "yarn build" + else + echo "No build script found in package.json"; exit 1 + fi + elif [ -f "package-lock.json" ] || [ -f "package.json" ]; then + echo "Detected npm" + run_cmd "npm ci || npm install" + if jq -e '.scripts.build' package.json >/dev/null 2>&1; then + run_cmd "npm run build" + else + echo "No build script found in package.json"; exit 1 + fi + elif [ -f "hugo.toml" ] || [ -f "hugo.yaml" ] || [ -f "hugo.yml" ] || [ -f "config.toml" ] || [ -f "config.yaml" ] || [ -f "config.yml" ]; then + echo "Detected Hugo" + sudo apt-get update -y + sudo apt-get install -y hugo + run_cmd "hugo version" + run_cmd "hugo --minify" + else + echo "Could not detect build system. Set repo variable PAGES_BUILD_CMD (and optionally PAGES_OUTPUT_DIR)." + exit 1 + fi + fi + + - name: Determine output directory + id: outdir run: | - # Replace 'public' with your build output dir if different (e.g., 'dist') - # Ensure the directory exists before upload. - if [ ! -d "public" ] && [ ! -d "dist" ]; then - echo "Please adjust the output directory (public/dist) to match your build" + set -e + if [ -n "${PAGES_OUTPUT_DIR:-}" ]; then + OUTDIR="${PAGES_OUTPUT_DIR}" + else + # Try common static output directories in priority order + for d in dist build .output/public .vercel/output/static out public site _site; do + if [ -d "$d" ]; then OUTDIR="$d"; break; fi + done + fi + if [ -z "${OUTDIR:-}" ] || [ ! -d "$OUTDIR" ]; then + echo "Could not determine output directory. Set repo variable PAGES_OUTPUT_DIR to the static build output." + echo "Checked candidates: ${PAGES_OUTPUT_DIR:-}, dist, build, .output/public, .vercel/output/static, out, public, site, _site" exit 1 fi - OUTDIR="public" - [ -d "dist" ] && OUTDIR="dist" echo "Using output dir: $OUTDIR" - mkdir -p artifact && cp -a "$OUTDIR"/. artifact/ + echo "outdir=$OUTDIR" >> "$GITHUB_OUTPUT" + + - name: Package built site + run: | + mkdir -p artifact + cp -a "${{ steps.outdir.outputs.outdir }}"/. artifact/ + echo "Packaged $(find artifact -type f | wc -l) files." - name: Upload built artifact uses: actions/upload-artifact@v4 @@ -78,6 +141,7 @@ jobs: permissions: contents: read pull-requests: write + issues: write steps: - name: Check required secrets env: From 4143ac255b87e1b1ce4fc44f40282324b197e89e Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Thu, 4 Sep 2025 15:32:26 -0600 Subject: [PATCH 4/9] Another round? --- .../workflows/cloudflare-preview-forks.yml | 131 ++++++++++-------- 1 file changed, 75 insertions(+), 56 deletions(-) diff --git a/.github/workflows/cloudflare-preview-forks.yml b/.github/workflows/cloudflare-preview-forks.yml index 160148ac..a6c22c9d 100644 --- a/.github/workflows/cloudflare-preview-forks.yml +++ b/.github/workflows/cloudflare-preview-forks.yml @@ -23,7 +23,7 @@ jobs: permissions: contents: read env: - # Optional repo variables for precise control (Settings > Secrets and variables > Actions > Variables) + # Optional repo variables (Settings > Secrets and variables > Actions > Variables) # If set, PAGES_BUILD_CMD will be executed and PAGES_OUTPUT_DIR used for packaging. PAGES_BUILD_CMD: ${{ vars.PAGES_BUILD_CMD }} PAGES_OUTPUT_DIR: ${{ vars.PAGES_OUTPUT_DIR }} @@ -41,79 +41,98 @@ jobs: pwd ls -la - - name: Setup Node.js (for common JS builds) + - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 20 check-latest: true - - name: Build (auto-detect or use PAGES_BUILD_CMD) - id: build + - name: Detect build type + id: detect + shell: bash run: | set -euo pipefail - - run_cmd() { echo "+ $*"; eval "$*"; } - if [ -n "${PAGES_BUILD_CMD:-}" ]; then - echo "Using PAGES_BUILD_CMD from repo variables: ${PAGES_BUILD_CMD}" - run_cmd "${PAGES_BUILD_CMD}" - else - echo "Auto-detecting build system..." - if [ -f "pnpm-lock.yaml" ]; then - echo "Detected pnpm" - corepack enable >/dev/null 2>&1 || true - run_cmd "pnpm --version" - run_cmd "pnpm install --frozen-lockfile" - if jq -e '.scripts.build' package.json >/dev/null 2>&1; then - run_cmd "pnpm run build" - else - echo "No build script found in package.json"; exit 1 - fi - elif [ -f "yarn.lock" ]; then - echo "Detected yarn" - corepack enable >/dev/null 2>&1 || true - run_cmd "yarn --version" - run_cmd "yarn install --frozen-lockfile" - if jq -e '.scripts.build' package.json >/dev/null 2>&1; then - run_cmd "yarn build" - else - echo "No build script found in package.json"; exit 1 - fi - elif [ -f "package-lock.json" ] || [ -f "package.json" ]; then - echo "Detected npm" - run_cmd "npm ci || npm install" - if jq -e '.scripts.build' package.json >/dev/null 2>&1; then - run_cmd "npm run build" - else - echo "No build script found in package.json"; exit 1 - fi - elif [ -f "hugo.toml" ] || [ -f "hugo.yaml" ] || [ -f "hugo.yml" ] || [ -f "config.toml" ] || [ -f "config.yaml" ] || [ -f "config.yml" ]; then - echo "Detected Hugo" - sudo apt-get update -y - sudo apt-get install -y hugo - run_cmd "hugo version" - run_cmd "hugo --minify" - else - echo "Could not detect build system. Set repo variable PAGES_BUILD_CMD (and optionally PAGES_OUTPUT_DIR)." - exit 1 - fi + echo "type=custom" >> "$GITHUB_OUTPUT" + exit 0 + fi + if [ -f pnpm-lock.yaml ]; then + echo "type=pnpm" >> "$GITHUB_OUTPUT"; exit 0 + fi + if [ -f yarn.lock ]; then + echo "type=yarn" >> "$GITHUB_OUTPUT"; exit 0 fi + if [ -f package.json ]; then + echo "type=npm" >> "$GITHUB_OUTPUT"; exit 0 + fi + # Detect Hugo by common config files + if [ -f hugo.toml ] || [ -f hugo.yaml ] || [ -f hugo.yml ] || [ -f config.toml ] || [ -f config.yaml ] || [ -f config.yml ]; then + echo "type=hugo" >> "$GITHUB_OUTPUT"; exit 0 + fi + echo "::error::Could not detect build system. Set repo variable PAGES_BUILD_CMD (and optionally PAGES_OUTPUT_DIR)." + exit 1 + + - name: Build (custom) + if: ${{ steps.detect.outputs.type == 'custom' }} + run: | + set -euo pipefail + echo "+ ${PAGES_BUILD_CMD}" + eval "${PAGES_BUILD_CMD}" + + - name: Enable Corepack (pnpm/yarn) + if: ${{ steps.detect.outputs.type == 'pnpm' || steps.detect.outputs.type == 'yarn' }} + run: corepack enable + + - name: Install deps and build (pnpm) + if: ${{ steps.detect.outputs.type == 'pnpm' }} + run: | + pnpm --version + pnpm install --frozen-lockfile + pnpm run build + + - name: Install deps and build (yarn) + if: ${{ steps.detect.outputs.type == 'yarn' }} + run: | + yarn --version + yarn install --frozen-lockfile + yarn build + + - name: Install deps and build (npm) + if: ${{ steps.detect.outputs.type == 'npm' }} + run: | + npm ci || npm install + npm run build + + - name: Setup Hugo + if: ${{ steps.detect.outputs.type == 'hugo' }} + uses: peaceiris/actions-hugo@v2 + with: + hugo-version: 'latest' + extended: true + + - name: Build (Hugo) + if: ${{ steps.detect.outputs.type == 'hugo' }} + run: hugo --minify - name: Determine output directory id: outdir + shell: bash run: | - set -e + set -euo pipefail if [ -n "${PAGES_OUTPUT_DIR:-}" ]; then OUTDIR="${PAGES_OUTPUT_DIR}" else - # Try common static output directories in priority order - for d in dist build .output/public .vercel/output/static out public site _site; do - if [ -d "$d" ]; then OUTDIR="$d"; break; fi - done + # Prefer Hugo 'public' for hugo builds + if [ "${{ steps.detect.outputs.type }}" = "hugo" ] && [ -d public ]; then + OUTDIR="public" + else + for d in dist build .output/public .vercel/output/static out public site _site; do + if [ -d "$d" ]; then OUTDIR="$d"; break; fi + done + fi fi if [ -z "${OUTDIR:-}" ] || [ ! -d "$OUTDIR" ]; then - echo "Could not determine output directory. Set repo variable PAGES_OUTPUT_DIR to the static build output." - echo "Checked candidates: ${PAGES_OUTPUT_DIR:-}, dist, build, .output/public, .vercel/output/static, out, public, site, _site" + echo "::error::Could not determine output directory. Set repo variable PAGES_OUTPUT_DIR." exit 1 fi echo "Using output dir: $OUTDIR" From 1a2ade5c10c04f1446c422ed77ceef9e93928025 Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Thu, 4 Sep 2025 15:40:05 -0600 Subject: [PATCH 5/9] Add debugging --- .../workflows/cloudflare-preview-forks.yml | 56 +++++++++++++++++-- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cloudflare-preview-forks.yml b/.github/workflows/cloudflare-preview-forks.yml index a6c22c9d..b7b97845 100644 --- a/.github/workflows/cloudflare-preview-forks.yml +++ b/.github/workflows/cloudflare-preview-forks.yml @@ -27,6 +27,8 @@ jobs: # If set, PAGES_BUILD_CMD will be executed and PAGES_OUTPUT_DIR used for packaging. PAGES_BUILD_CMD: ${{ vars.PAGES_BUILD_CMD }} PAGES_OUTPUT_DIR: ${{ vars.PAGES_OUTPUT_DIR }} + # New: Optional working directory override (e.g., "site", "website", "docs") + PAGES_WORKING_DIR: ${{ vars.PAGES_WORKING_DIR }} steps: - name: Checkout PR code (from fork) uses: actions/checkout@v4 @@ -36,10 +38,44 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} persist-credentials: false - - name: Print repo root for debugging + - name: Detect working directory + id: workdir + shell: bash + run: | + set -euo pipefail + if [ -n "${PAGES_WORKING_DIR:-}" ]; then + if [ ! -d "$PAGES_WORKING_DIR" ]; then + echo "::error::PAGES_WORKING_DIR '$PAGES_WORKING_DIR' does not exist." + exit 1 + fi + echo "workdir=${PAGES_WORKING_DIR}" >> "$GITHUB_OUTPUT" + exit 0 + fi + # Look for common project subdirs with recognizable configs + is_proj_dir() { + local d="$1" + test -d "$d" || return 1 + [ -f "$d/package.json" ] && return 0 + [ -f "$d/pnpm-lock.yaml" ] && return 0 + [ -f "$d/yarn.lock" ] && return 0 + [ -f "$d/hugo.toml" ] || [ -f "$d/hugo.yaml" ] || [ -f "$d/hugo.yml" ] && return 0 + [ -f "$d/config.toml" ] || [ -f "$d/config.yaml" ] || [ -f "$d/config.yml" ] && return 0 + return 1 + } + if is_proj_dir "."; then echo "workdir=." >> "$GITHUB_OUTPUT"; exit 0; fi + for d in site website web docs app; do + if is_proj_dir "$d"; then echo "workdir=$d" >> "$GITHUB_OUTPUT"; exit 0; fi + done + # Fallback to repo root + echo "workdir=." >> "$GITHUB_OUTPUT" + + - name: Print repo and workdir for debugging run: | - pwd + echo "Repo root: $(pwd)" + echo "Chosen workdir: ${{ steps.workdir.outputs.workdir }}" ls -la + echo "---" + ls -la "${{ steps.workdir.outputs.workdir }}" - name: Setup Node.js uses: actions/setup-node@v4 @@ -50,6 +86,7 @@ jobs: - name: Detect build type id: detect shell: bash + working-directory: ${{ steps.workdir.outputs.workdir }} run: | set -euo pipefail if [ -n "${PAGES_BUILD_CMD:-}" ]; then @@ -69,11 +106,12 @@ jobs: if [ -f hugo.toml ] || [ -f hugo.yaml ] || [ -f hugo.yml ] || [ -f config.toml ] || [ -f config.yaml ] || [ -f config.yml ]; then echo "type=hugo" >> "$GITHUB_OUTPUT"; exit 0 fi - echo "::error::Could not detect build system. Set repo variable PAGES_BUILD_CMD (and optionally PAGES_OUTPUT_DIR)." + echo "::error::Could not detect build system in $PWD. Set repo variable PAGES_BUILD_CMD and optionally PAGES_OUTPUT_DIR/PAGES_WORKING_DIR." exit 1 - name: Build (custom) if: ${{ steps.detect.outputs.type == 'custom' }} + working-directory: ${{ steps.workdir.outputs.workdir }} run: | set -euo pipefail echo "+ ${PAGES_BUILD_CMD}" @@ -81,10 +119,12 @@ jobs: - name: Enable Corepack (pnpm/yarn) if: ${{ steps.detect.outputs.type == 'pnpm' || steps.detect.outputs.type == 'yarn' }} + working-directory: ${{ steps.workdir.outputs.workdir }} run: corepack enable - name: Install deps and build (pnpm) if: ${{ steps.detect.outputs.type == 'pnpm' }} + working-directory: ${{ steps.workdir.outputs.workdir }} run: | pnpm --version pnpm install --frozen-lockfile @@ -92,6 +132,7 @@ jobs: - name: Install deps and build (yarn) if: ${{ steps.detect.outputs.type == 'yarn' }} + working-directory: ${{ steps.workdir.outputs.workdir }} run: | yarn --version yarn install --frozen-lockfile @@ -99,6 +140,7 @@ jobs: - name: Install deps and build (npm) if: ${{ steps.detect.outputs.type == 'npm' }} + working-directory: ${{ steps.workdir.outputs.workdir }} run: | npm ci || npm install npm run build @@ -112,11 +154,13 @@ jobs: - name: Build (Hugo) if: ${{ steps.detect.outputs.type == 'hugo' }} + working-directory: ${{ steps.workdir.outputs.workdir }} run: hugo --minify - name: Determine output directory id: outdir shell: bash + working-directory: ${{ steps.workdir.outputs.workdir }} run: | set -euo pipefail if [ -n "${PAGES_OUTPUT_DIR:-}" ]; then @@ -132,7 +176,7 @@ jobs: fi fi if [ -z "${OUTDIR:-}" ] || [ ! -d "$OUTDIR" ]; then - echo "::error::Could not determine output directory. Set repo variable PAGES_OUTPUT_DIR." + echo "::error::Could not determine output directory in $PWD. Set repo variable PAGES_OUTPUT_DIR." exit 1 fi echo "Using output dir: $OUTDIR" @@ -141,7 +185,9 @@ jobs: - name: Package built site run: | mkdir -p artifact - cp -a "${{ steps.outdir.outputs.outdir }}"/. artifact/ + SRC="${{ steps.workdir.outputs.workdir }}/${{ steps.outdir.outputs.outdir }}" + echo "Copying from: $SRC" + cp -a "$SRC"/. artifact/ echo "Packaged $(find artifact -type f | wc -l) files." - name: Upload built artifact From d43032a4b2dce3fd1936b6be7672332c809590eb Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Thu, 4 Sep 2025 15:46:21 -0600 Subject: [PATCH 6/9] it keeps fiddling --- .../workflows/cloudflare-preview-forks.yml | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cloudflare-preview-forks.yml b/.github/workflows/cloudflare-preview-forks.yml index b7b97845..9db88fd0 100644 --- a/.github/workflows/cloudflare-preview-forks.yml +++ b/.github/workflows/cloudflare-preview-forks.yml @@ -106,8 +106,8 @@ jobs: if [ -f hugo.toml ] || [ -f hugo.yaml ] || [ -f hugo.yml ] || [ -f config.toml ] || [ -f config.yaml ] || [ -f config.yml ]; then echo "type=hugo" >> "$GITHUB_OUTPUT"; exit 0 fi - echo "::error::Could not detect build system in $PWD. Set repo variable PAGES_BUILD_CMD and optionally PAGES_OUTPUT_DIR/PAGES_WORKING_DIR." - exit 1 + echo "::warning::Could not detect build system in $PWD. Will deploy a minimal placeholder site. Set repo variable PAGES_BUILD_CMD and optionally PAGES_OUTPUT_DIR/PAGES_WORKING_DIR for a real build." + echo "type=none" >> "$GITHUB_OUTPUT" - name: Build (custom) if: ${{ steps.detect.outputs.type == 'custom' }} @@ -176,8 +176,37 @@ jobs: fi fi if [ -z "${OUTDIR:-}" ] || [ ! -d "$OUTDIR" ]; then - echo "::error::Could not determine output directory in $PWD. Set repo variable PAGES_OUTPUT_DIR." - exit 1 + if [ "${{ steps.detect.outputs.type }}" = "none" ]; then + OUTDIR=".cloudflare-fallback" + mkdir -p "$OUTDIR" + cat > "$OUTDIR/index.html" <<'HTML' + + + + + Preview placeholder + + + + +

Cloudflare Pages preview placeholder

+

No build system or output directory was detected for this PR preview.

+

To enable real previews, set repository variables in the base repo:

+
    +
  • PAGES_WORKING_DIR (optional): project subfolder (e.g., site).
  • +
  • PAGES_BUILD_CMD (e.g., hugo --minify or npm ci && npm run build).
  • +
  • PAGES_OUTPUT_DIR (e.g., public or dist).
  • +
+ + +HTML + else + echo "::error::Could not determine output directory in $PWD. Set repo variable PAGES_OUTPUT_DIR." + exit 1 + fi fi echo "Using output dir: $OUTDIR" echo "outdir=$OUTDIR" >> "$GITHUB_OUTPUT" From b541a350c2d9dfb8c5653eeddef8a8920acb8dd8 Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Thu, 4 Sep 2025 15:10:59 -0600 Subject: [PATCH 7/9] Experimental blog --- .../blog/ddev-august-2026-newsletter.md | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/content/blog/ddev-august-2026-newsletter.md diff --git a/src/content/blog/ddev-august-2026-newsletter.md b/src/content/blog/ddev-august-2026-newsletter.md new file mode 100644 index 00000000..fc5bf623 --- /dev/null +++ b/src/content/blog/ddev-august-2026-newsletter.md @@ -0,0 +1,25 @@ +--- +title: "DDEV August 2026 Newsletter" +pubDate: 2026-08-12 +#modifiedDate: 2025-04-07 +summary: "Did nothing at all happen in the last year???" +author: Randy Fay +featureImage: + src: /img/blog/2025/08/laracon-photo.jpg + alt: Nuno Maduro at Laracon US 2025 + caption: "Nuno Maduro at Laracon US 2025" +categories: + - Community +--- + +🚀 Dive into August 2026 with DDEV! 🌟 + +We're right where we were a year ago! + +## Stay in the Loop—Follow Us and Join the Conversation + +- [Blog↗](https://ddev.com/blog/) +- [LinkedIn↗](https://www.linkedin.com/company/ddev-foundation) +- [Mastodon↗](https://fosstodon.org/@ddev) +- [Bluesky↗](https://bsky.app/profile/ddev.bsky.social) +- [Discord↗](/s/discord) From 29261ed92b96b5327496338fc20fe62b5c6d4cfb Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Mon, 22 Sep 2025 07:05:36 -0600 Subject: [PATCH 8/9] dummy commmit --- src/content/blog/ddev-august-2026-newsletter.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/blog/ddev-august-2026-newsletter.md b/src/content/blog/ddev-august-2026-newsletter.md index fc5bf623..1182dc14 100644 --- a/src/content/blog/ddev-august-2026-newsletter.md +++ b/src/content/blog/ddev-august-2026-newsletter.md @@ -1,6 +1,6 @@ --- title: "DDEV August 2026 Newsletter" -pubDate: 2026-08-12 +pubDate: 2026-09-12 #modifiedDate: 2025-04-07 summary: "Did nothing at all happen in the last year???" author: Randy Fay From 1b314fbb5c562cc171b3516ade0830867da103ca Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Mon, 22 Sep 2025 07:12:51 -0600 Subject: [PATCH 9/9] dummy --- src/content/blog/ddev-august-2026-newsletter.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/blog/ddev-august-2026-newsletter.md b/src/content/blog/ddev-august-2026-newsletter.md index 1182dc14..f754d03f 100644 --- a/src/content/blog/ddev-august-2026-newsletter.md +++ b/src/content/blog/ddev-august-2026-newsletter.md @@ -1,6 +1,6 @@ --- title: "DDEV August 2026 Newsletter" -pubDate: 2026-09-12 +pubDate: 2026-10-12 #modifiedDate: 2025-04-07 summary: "Did nothing at all happen in the last year???" author: Randy Fay