Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
695ff78
try render each case study separately; deploy successful case studies…
e-perl-NOAA Jul 22, 2026
7ade448
fix issues in workflows
e-perl-NOAA Jul 22, 2026
58c42d6
try quarto render location fix
e-perl-NOAA Jul 22, 2026
6e6edf7
remove continue on error so workflow fails but still completes if any…
e-perl-NOAA Jul 22, 2026
8f2cfea
add concurrency statements
e-perl-NOAA Jul 22, 2026
21f9f95
try again
e-perl-NOAA Jul 22, 2026
f688b50
test replacing fleet_name with fleet to see if it works on goa pollock
e-perl-NOAA Jul 22, 2026
d351f37
since it's now in a PR have push trigger just be on main
e-perl-NOAA Jul 22, 2026
3a11aa2
replacing fleet_name with fleet did not work
e-perl-NOAA Jul 22, 2026
8693909
Make advanced-features run
kellijohnson-NOAA Jul 22, 2026
6e242ab
Make GoA Pollock run
kellijohnson-NOAA Jul 22, 2026
243e6c3
Make Yellowtail run
kellijohnson-NOAA Jul 22, 2026
47c16a5
revise petrale case study to use new convert in r4ss
iantaylor-NOAA Feb 13, 2026
2741a0d
clean up comments, description of changes to petrale
iantaylor-NOAA Feb 13, 2026
8aa6b26
update petrale case study in lots of ways
iantaylor-NOAA Mar 18, 2026
96358c1
update to petrale simplification script
iantaylor-NOAA Apr 23, 2026
7b67106
update petrale to use fleet instead of fleet_name, remove plotting code
iantaylor-NOAA Jul 22, 2026
236d761
delete obsolete R scripts
iantaylor-NOAA Jul 22, 2026
2b8fc52
don't run SS3 simplification code when compiling case studies
iantaylor-NOAA Jul 22, 2026
68ed8a3
Updates scamp
kellijohnson-NOAA Jul 22, 2026
b916465
bring changes from opakapaka-update branch
iantaylor-NOAA Jul 22, 2026
4043e94
remove growth & plotting for opakapaka to compile on main
iantaylor-NOAA Jul 22, 2026
e4a8c93
test fix to render with inclusion of all case studies in _quarto.yml
Jul 23, 2026
bd4d6e4
revert back to previous file structure
Jul 23, 2026
d235d63
don't copy/move rendered file
Jul 23, 2026
364d5f6
make sure status is always recorded
Jul 23, 2026
898b41a
make sure status' always are uploaded
Jul 23, 2026
3e7831c
test deploy case studies with run id from a render that had some succ…
Jul 23, 2026
bd9b2f0
actually add run id
Jul 23, 2026
6753d31
actually install R for readme update
Jul 23, 2026
67bf287
try again with combined site deploy
Jul 23, 2026
e083f40
remove temp test
Jul 23, 2026
0d82bcf
comment out stockplotr line that breaks petrale
iantaylor-NOAA Jul 28, 2026
16312e5
minor changes to sardine to match current FIMS format
iantaylor-NOAA Jul 28, 2026
d9bb3e2
more sardine changes to get model to run
iantaylor-NOAA Jul 28, 2026
2de03f3
one more change to sardine to get it to work
iantaylor-NOAA Jul 28, 2026
a8bf6e3
don't fail workflow if qmd not published and shouldn't be added as ar…
e-perl-NOAA Aug 3, 2026
e84cf96
remove push trigger
e-perl-NOAA Aug 3, 2026
16303fe
attempt to get pacific-hake running
iantaylor-NOAA Aug 3, 2026
579db39
functionalize the petrale simplification script
iantaylor-NOAA Aug 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 190 additions & 0 deletions .github/workflows/deploy-case-studies.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
name: Deploy Case Studies

on:
workflow_run:
workflows: ["Render Case Studies"]
types:
- completed
workflow_dispatch:
inputs:
run_id:
description: 'Run ID of Render Case Studies to get artifacts from (for testing)'
required: false
type: string

permissions:
contents: write

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
deploy:
if: >
github.event_name == 'workflow_dispatch' || github.event_name == 'push' ||
(
github.event.workflow_run.event == 'push' &&
github.event.workflow_run.head_branch == 'main' &&
(github.event.workflow_run.conclusion == 'success' || github.event.workflow_run.conclusion == 'failure')
)
runs-on: ubuntu-latest

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Download current run artifacts
uses: actions/download-artifact@v4
with:
path: current-artifacts
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ inputs.run_id || github.event.workflow_run.id }}

- name: Fetch existing gh-pages branch
shell: bash
run: |
git fetch origin gh-pages:gh-pages || true

- name: Prepare site from previous deployment
shell: bash
run: |
rm -rf _site
mkdir -p _site

if git show-ref --verify --quiet refs/heads/gh-pages; then
# The previous site is deployed to the root of the gh-pages branch.
# We extract it directly into the _site directory.
git archive gh-pages | tar -x -C _site/
fi

- name: Overlay successful renders
shell: bash
run: |
shopt -s nullglob
for artifact_dir in current-artifacts/*; do
if [ -d "$artifact_dir" ] && [[ "$(basename "$artifact_dir")" != status-* ]]; then
cp -R "$artifact_dir"/. _site/
fi
done

- name: Copy status files for README update
shell: bash
run: |
mkdir -p statuses
find current-artifacts -name '*.json' -path '*/status-*' -exec cp {} statuses/ \;

- name: Setup R
uses: r-lib/actions/setup-r@v2

- name: Install jsonlite
run: Rscript -e 'install.packages("jsonlite", repos = "https://cloud.r-project.org")'

- name: Update README table
shell: Rscript {0}
run: |
readme_file <- "README.md"
content_dir <- "content"
excluded <- c("setup.qmd", "acknowledgements.qmd", "advanced-features.qmd")

parse_yaml <- function(filepath) {
lines <- readLines(filepath, warn = FALSE)
dash_lines <- which(lines == "---")
res <- list(stock = NA_character_, previous_model = "", features = "")

if (length(dash_lines) >= 2) {
yaml_lines <- lines[(dash_lines[1] + 1):(dash_lines[2] - 1)]
for (line in yaml_lines) {
if (grepl("^stock:", line)) res$stock <- trimws(gsub("^stock:\\s*|\"|'", "", line))
if (grepl("^previous_model:", line)) res$previous_model <- trimws(gsub("^previous_model:\\s*|\"|'", "", line))
if (grepl("^features:", line)) res$features <- trimws(gsub("^features:\\s*|\"|'", "", line))
}
}
res
}

status_files <- list.files("statuses", pattern = "\\.json$", full.names = TRUE)
status_map <- list()

if (length(status_files) > 0) {
for (sf in status_files) {
obj <- jsonlite::fromJSON(sf)
status_map[[obj$case_id]] <- obj$status
}
}

files <- list.files(content_dir, pattern = "\\.qmd$", full.names = TRUE)
basenames <- basename(files)
valid_idx <- !(basenames %in% excluded)
files <- files[valid_idx]
basenames <- basenames[valid_idx]

table_lines <- c(
"Stock | Previous Model | Status | Notable Features |",
"-- | -- | -- | --"
)

dir.create("badges", showWarnings = FALSE)

for (i in seq_along(files)) {
file <- files[i]
case_id <- sub("\\.qmd$", "", basenames[i])
meta <- parse_yaml(file)

stock <- if (!is.na(meta$stock) && nzchar(meta$stock)) meta$stock else gsub("[-_]", " ", case_id)
status <- if (!is.null(status_map[[case_id]])) status_map[[case_id]] else "failing"

badge_url <- if (status == "working") {
"https://img.shields.io/badge/Status-working-brightgreen"
} else {
"https://img.shields.io/badge/Status-failing-red"
}

badge_path <- file.path("badges", paste0(case_id, ".svg"))
download.file(badge_url, destfile = badge_path, mode = "wb", quiet = TRUE)

badge_md <- paste0("![Status](", badge_path, ")")
table_lines <- c(table_lines, paste(stock, meta$previous_model, badge_md, meta$features, sep = " | "))
}

readme <- readLines(readme_file, warn = FALSE)
start_idx <- which(trimws(readme) == "<!-- TABLE_START -->")
end_idx <- which(trimws(readme) == "<!-- TABLE_END -->")

if (length(start_idx) > 0 && length(end_idx) > 0) {
new_readme <- c(
readme[1:start_idx],
table_lines,
readme[end_idx:length(readme)]
)
writeLines(new_readme, readme_file)
} else {
stop("Could not find TABLE_START/TABLE_END markers in README.md")
}

- name: Upload test artifacts
if: github.event_name == 'workflow_dispatch'
uses: actions/upload-artifact@v4
with:
name: test-deploy-outputs
path: |
_site/
README.md

- name: Commit README update
if: github.event_name == 'workflow_run'
uses: peter-evans/create-pull-request@v6
with:
commit-message: "chore: auto-update README case study table [skip ci]"
title: "🤖 Auto-update case study table"
body: "Automated update of the case study status table."
branch: "auto-update-readme-table"
base: "main"

- name: Deploy merged site to gh-pages
if: github.event_name == 'workflow_run'
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./_site
keep_files: true
204 changes: 204 additions & 0 deletions .github/workflows/render-case-studies.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
name: Render Case Studies

on:
push:
branches: [ main ]
paths:
- "content/**"
- ".github/workflows/render-case-studies.yml"
pull_request:
branches: [ main ]
paths:
- "content/**"
- ".github/workflows/render-case-studies.yml"
workflow_dispatch:
schedule:
- cron: "30 0 * * 0"

permissions:
contents: read
actions: write

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
discover:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Setup R
uses: r-lib/actions/setup-r@v2

- name: Build matrix from content directory
id: set-matrix
shell: Rscript {0}
run: |
excluded <- c("setup.qmd", "acknowledgements.qmd", "advanced-features.qmd")

files <- list.files("content", pattern = "\\.qmd$", full.names = FALSE)
files <- sort(files[!files %in% excluded])

include <- lapply(files, function(f) {
list(
qmd_path = file.path("content", f),
artifact_name = paste0(tools::file_path_sans_ext(f), "-site"),
case_id = tools::file_path_sans_ext(f)
)
})

json_escape <- function(x) {
x <- gsub("\\\\", "\\\\\\\\", x)
x <- gsub('"', '\\"', x)
x
}

entries <- vapply(include, function(x) {
sprintf(
'{"qmd_path":"%s","artifact_name":"%s","case_id":"%s"}',
json_escape(x$qmd_path),
json_escape(x$artifact_name),
json_escape(x$case_id)
)
}, character(1))

matrix_json <- paste0('{"include":[', paste(entries, collapse = ","), ']}')

cat("matrix=", matrix_json, "\n", sep = "", file = Sys.getenv("GITHUB_OUTPUT"), append = TRUE)

render:
needs: discover
if: ${{ fromJson(needs.discover.outputs.matrix).include[0] != null }}
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.discover.outputs.matrix) }}
runs-on: ubuntu-latest

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Setup R
uses: r-lib/actions/setup-r@v2

- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libcurl4-openssl-dev \
libssl-dev \
libxml2-dev \
libfontconfig1-dev \
libfreetype6-dev \
libharfbuzz-dev \
libfribidi-dev \
libpng-dev \
libtiff5-dev \
libjpeg-dev \
libcairo2-dev \
libgit2-dev \
libx11-dev \
pandoc

- name: Set up R package dependencies
uses: r-lib/actions/setup-r-dependencies@v2
with:
pak-version: stable
cache: true
packages: |
cran::rmarkdown
cran::knitr
cran::jsonlite
cran::dplyr
cran::ggplot2
cran::tidyr
cran::TMB
cran::remotes
cran::reshape2
cran::Rcpp
cran::glue
cran::purrr
cran::ggridges
cran::yaml
extra-packages: |
github::nmfs-ost/stockplotr
github::stan-dev/cmdstanr
github::mjskay/tidybayes
github::stan-dev/shinystan
github::noaa-afsc/SparseNUTS
github::NOAA-FIMS/FIMS
github::r4ss/r4ss

- name: Setup Quarto
uses: quarto-dev/quarto-actions/setup@v2

- name: Render case study
id: render
shell: bash
run: |
set -e
quarto render "${{ matrix.qmd_path }}"

- name: Record status
if: always()
shell: bash
run: |
mkdir -p statuses
if [ "${{ steps.render.outcome }}" = "success" ]; then
status="working"
else
status="failing"
fi

cat > "statuses/${{ matrix.case_id }}.json" <<EOF
{
"case_id": "${{ matrix.case_id }}",
"qmd_path": "${{ matrix.qmd_path }}",
"artifact_name": "${{ matrix.artifact_name }}",
"status": "${status}"
}
EOF

- name: Check whether this case study is published
id: publish_check
shell: Rscript {0}
run: |
quarto <- yaml::read_yaml("_quarto.yml")
render_list <- quarto$project$render

published_qmds <- render_list[grepl("^content/.*\\.qmd$", render_list)]
published_cases <- tools::file_path_sans_ext(basename(published_qmds))

is_published <- "${{ matrix.case_id }}" %in% published_cases

cat("published=", if (is_published) "true" else "false", "\n",
sep = "", file = Sys.getenv("GITHUB_OUTPUT"), append = TRUE)

- name: Upload rendered artifact
if: steps.render.outcome == 'success' && steps.publish_check.outputs.published == 'true'
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact_name }}
path: _site
if-no-files-found: error

- name: Upload status artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: status-${{ matrix.case_id }}
path: statuses/${{ matrix.case_id }}.json

summarize:
needs: render
if: always()
runs-on: ubuntu-latest
steps:
- name: Summarize
run: |
echo "Case study render matrix completed."
Loading
Loading