From a90e0c83259d23f52ba8c63a5f965d7c84fc8fa7 Mon Sep 17 00:00:00 2001 From: richarddushime Date: Wed, 4 Feb 2026 20:48:37 +0100 Subject: [PATCH 1/4] consolidate staging deployment --- .github/workflows/deploy.yaml | 56 ++++-------------------- .github/workflows/staging-aggregate.yaml | 11 +++++ 2 files changed, 20 insertions(+), 47 deletions(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index ad8fd73455c..c6c3be878a7 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -11,18 +11,18 @@ on: push: branches: - master - pull_request: - branches: - - master workflow_dispatch: inputs: pr_number: - description: 'PR number to deploy (optional)' + description: 'PR number to deploy (optional, for manual testing)' required: false type: string repository_dispatch: types: [data-update] +# Note: PR staging deployments are handled by staging-aggregate.yaml +# This workflow focuses on production deployments + jobs: build: name: Build @@ -165,14 +165,9 @@ jobs: # ======================= - name: Build site run: | - if [ "$BRANCH" != 'refs/heads/master' ]; then - hugo --gc --minify --cleanDestinationDir --destination public --baseURL https://staging.forrt.org - else - hugo --gc --minify --cleanDestinationDir --destination public - fi + hugo --gc --minify --cleanDestinationDir --destination public env: - BRANCH: ${{ github.ref }} - HUGO_ENV: ${{ github.ref != 'refs/heads/master' && 'staging' || 'production' }} + HUGO_ENV: production # ======================= # Deployment Artifact @@ -186,50 +181,17 @@ jobs: path: public/ retention-days: 1 - #======================================== - # Deploy website to staging GitHub Pages - #======================================== - deploy-test: - name: Deploy - Test - runs-on: ubuntu-22.04 - concurrency: - group: staging - permissions: - contents: write - needs: build - steps: - #======================================== - # Download website artifact for staging deployment - #======================================== - - name: Download Artifact - Website - uses: actions/download-artifact@v4 - with: - name: forrt-website-${{ github.run_number }} - path: ${{ github.repository }}/forrt-website - - #======================================== - # Deploy website to staging GitHub Pages - #======================================== - - name: Deploy - GitHub Pages - uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e - with: - personal_token: ${{ secrets.STAGING_GITHUB_TOKEN }} - publish_dir: ${{ github.repository }}/forrt-website - external_repository: forrtproject/webpage-staging - publish_branch: staging - cname: staging.forrt.org - #======================================== # Deploy website to production GitHub Pages + # Note: Staging deployments are handled by staging-aggregate.yaml #======================================== deploy-prod: name: Deploy - Production runs-on: ubuntu-22.04 permissions: contents: write - needs: - - deploy-test - if: ((github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/heads/master' || github.event_name == 'repository_dispatch') && github.event.repository.fork == false + needs: build + if: github.event.repository.fork == false steps: #======================================== # Download website artifact for production deployment diff --git a/.github/workflows/staging-aggregate.yaml b/.github/workflows/staging-aggregate.yaml index 4d337592880..cf0c13594f2 100644 --- a/.github/workflows/staging-aggregate.yaml +++ b/.github/workflows/staging-aggregate.yaml @@ -11,6 +11,7 @@ on: pull_request: branches: - master + types: [opened, synchronize, reopened, ready_for_review] schedule: - cron: '0 1 1 * *' # 1 AM UTC on the 1st of each month workflow_dispatch: @@ -21,10 +22,18 @@ on: type: boolean default: false +# Workflow-level concurrency to queue staging builds (wait instead of cancel) +concurrency: + group: staging-aggregate + cancel-in-progress: false + jobs: aggregate-prs: name: Aggregate PRs for Staging runs-on: ubuntu-22.04 + timeout-minutes: 10 # Prevent blocking the queue + # Skip draft PRs entirely - they should not trigger staging builds + if: github.event.pull_request.draft != true permissions: contents: write pull-requests: read @@ -173,6 +182,7 @@ jobs: build: name: Build runs-on: ubuntu-22.04 + timeout-minutes: 20 # Prevent blocking the queue needs: [aggregate-prs] if: always() && (needs.aggregate-prs.outputs.has-prs == 'true' || github.event.inputs.force_deploy == 'true') permissions: @@ -346,6 +356,7 @@ jobs: deploy-staging: name: Deploy - Staging runs-on: ubuntu-22.04 + timeout-minutes: 10 # Prevent blocking the queue concurrency: group: staging permissions: From 05cdb54fa55a60979f246bc9b9a869156c4ae2c3 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 12:10:50 +0000 Subject: [PATCH 2/4] docs: Document staging deployment aggregation strategy (#621) * Initial plan * docs: Document staging deployment approach in README Co-authored-by: LukasWallrich <60155545+LukasWallrich@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: LukasWallrich <60155545+LukasWallrich@users.noreply.github.com> --- README.md | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/README.md b/README.md index d5137e66357..22e64129e86 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,68 @@ Please note that it's very important to us that we maintain a positive and suppo This is the website for the **Framework for Open and Reproducible Research Training (FORRT)**, built with [hugo](https://gohugo.io/), and deployed with [Github Actions](https://docs.github.com/en/actions). You can find the website at [forrt.org](https://forrt.org/). See CONTRIBUTING.md for more information on how to contribute. +## Deployment & Staging + +The FORRT website uses a dual deployment strategy to ensure quality and enable collaborative testing: + +### Production Deployment + +- **URL**: [https://forrt.org](https://forrt.org) +- **Workflow**: `.github/workflows/deploy.yaml` +- **Trigger**: Pushes to `master` branch +- **Target**: GitHub Pages (`gh-pages` branch) +- **Purpose**: Serves the live, production website + +### Staging Deployment + +- **URL**: [https://staging.forrt.org](https://staging.forrt.org) +- **Workflow**: `.github/workflows/staging-aggregate.yaml` +- **Trigger**: Pull requests to `master`, monthly schedule (1st of each month), or manual dispatch +- **Target**: External repository (`forrtproject/webpage-staging`) +- **Purpose**: Preview combined changes from all open PRs + +#### How Staging Works + +The staging deployment uses an **aggregation strategy** to provide a unified preview environment: + +1. **Automatic Aggregation**: When any PR is opened, synchronized, or reopened, the workflow: + - Collects all open, non-draft PRs targeting `master` + - Creates a temporary aggregation branch from `master` + - Attempts to merge each PR in sequence + +2. **Conflict Handling**: + - PRs that merge cleanly are included in the staging build + - PRs with merge conflicts are skipped but logged + - The deployment continues with all compatible PRs + +3. **Deployment Comments**: Each PR receives an automated comment indicating: + - ✅ Successfully deployed (for PRs without conflicts) + - ⚠️ Skipped due to conflicts (for conflicting PRs) + - Deployment timestamp and staging URL + +4. **Queuing & Timeouts**: + - Workflow uses concurrency control to queue builds (not cancel) + - Job timeouts (10-20 minutes) prevent indefinite blocking + - Draft PRs are filtered out to avoid unnecessary builds + +5. **Branch Cleanup**: + - Keeps only the 5 most recent staging branches + - Automatically cleans up older staging-aggregate branches + +#### Viewing Staging Changes + +- Visit [https://staging.forrt.org](https://staging.forrt.org) to see the combined state of all open, compatible PRs +- Note: Staging shows aggregated changes from **all** open PRs, not individual PR changes +- PRs with merge conflicts won't appear in staging until conflicts are resolved + +#### Monthly Reports + +On the 1st of each month, an automated deployment report is created as a GitHub issue with: +- Total PRs processed +- Successfully merged PRs +- Skipped PRs (with conflict information) +- Deployment statistics + ## License Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. From d7107caf4ce37f43a5852ce1550292e1a33a8afa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 12:15:14 +0000 Subject: [PATCH 3/4] Initial plan From 9e1bbab7a5dfbd6dfe80f4acaff4cf4f0342342e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 12:16:51 +0000 Subject: [PATCH 4/4] docs: Clarify single-PR deployment limitation in README Co-authored-by: LukasWallrich <60155545+LukasWallrich@users.noreply.github.com> --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 22e64129e86..c79b00310ed 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,7 @@ The FORRT website uses a dual deployment strategy to ensure quality and enable c - **Trigger**: Pull requests to `master`, monthly schedule (1st of each month), or manual dispatch - **Target**: External repository (`forrtproject/webpage-staging`) - **Purpose**: Preview combined changes from all open PRs +- **Note**: Staging always deploys aggregated changes from all open PRs. There is currently no option to deploy a single PR in isolation to staging. #### How Staging Works @@ -108,6 +109,16 @@ The staging deployment uses an **aggregation strategy** to provide a unified pre - Note: Staging shows aggregated changes from **all** open PRs, not individual PR changes - PRs with merge conflicts won't appear in staging until conflicts are resolved +#### Manual Single-PR Deployment + +**Currently Not Supported for Staging**: There is no option to deploy a single PR in isolation to the staging environment. All staging deployments include all compatible open PRs. + +**Workaround for Testing Individual PRs**: +- The `deploy.yaml` workflow supports manual dispatch with a `pr_number` input +- However, this deploys directly to **production** (forrt.org), not staging +- Use with extreme caution - only for emergency fixes or when you're certain the changes are ready for production +- For regular PR testing, rely on the aggregated staging deployment or test locally + #### Monthly Reports On the 1st of each month, an automated deployment report is created as a GitHub issue with: