From 25ad8971700d1886635d2eeecb30da5840232fe3 Mon Sep 17 00:00:00 2001 From: Douglas Lowe <10961945+douglowe@users.noreply.github.com> Date: Thu, 29 Oct 2026 17:13:14 +0000 Subject: [PATCH 1/2] remove old workflows --- .github/workflows/README.md | 198 ------------------- .github/workflows/pr-close-signal.yaml | 22 --- .github/workflows/pr-comment.yaml | 184 ----------------- .github/workflows/pr-post-remove-branch.yaml | 32 --- .github/workflows/pr-preflight.yaml | 39 ---- .github/workflows/pr-receive.yaml | 132 ------------- .github/workflows/sandpaper-main.yaml | 64 ------ .github/workflows/sandpaper-version.txt | 1 - .github/workflows/update-cache.yaml | 125 ------------ .github/workflows/update-workflows.yaml | 66 ------- 10 files changed, 863 deletions(-) delete mode 100644 .github/workflows/README.md delete mode 100644 .github/workflows/pr-close-signal.yaml delete mode 100644 .github/workflows/pr-comment.yaml delete mode 100644 .github/workflows/pr-post-remove-branch.yaml delete mode 100644 .github/workflows/pr-preflight.yaml delete mode 100644 .github/workflows/pr-receive.yaml delete mode 100644 .github/workflows/sandpaper-main.yaml delete mode 100644 .github/workflows/sandpaper-version.txt delete mode 100644 .github/workflows/update-cache.yaml delete mode 100644 .github/workflows/update-workflows.yaml diff --git a/.github/workflows/README.md b/.github/workflows/README.md deleted file mode 100644 index 7076ddd..0000000 --- a/.github/workflows/README.md +++ /dev/null @@ -1,198 +0,0 @@ -# Carpentries Workflows - -This directory contains workflows to be used for Lessons using the {sandpaper} -lesson infrastructure. Two of these workflows require R (`sandpaper-main.yaml` -and `pr-receive.yaml`) and the rest are bots to handle pull request management. - -These workflows will likely change as {sandpaper} evolves, so it is important to -keep them up-to-date. To do this in your lesson you can do the following in your -R console: - -```r -# Install/Update sandpaper -options(repos = c(carpentries = "https://carpentries.r-universe.dev/", - CRAN = "https://cloud.r-project.org")) -install.packages("sandpaper") - -# update the workflows in your lesson -library("sandpaper") -update_github_workflows() -``` - -Inside this folder, you will find a file called `sandpaper-version.txt`, which -will contain a version number for sandpaper. This will be used in the future to -alert you if a workflow update is needed. - -What follows are the descriptions of the workflow files: - -## Deployment - -### 01 Build and Deploy (sandpaper-main.yaml) - -This is the main driver that will only act on the main branch of the repository. -This workflow does the following: - - 1. checks out the lesson - 2. provisions the following resources - - R - - pandoc - - lesson infrastructure (stored in a cache) - - lesson dependencies if needed (stored in a cache) - 3. builds the lesson via `sandpaper:::ci_deploy()` - -#### Caching - -This workflow has two caches; one cache is for the lesson infrastructure and -the other is for the the lesson dependencies if the lesson contains rendered -content. These caches are invalidated by new versions of the infrastructure and -the `renv.lock` file, respectively. If there is a problem with the cache, -manual invaliation is necessary. You will need maintain access to the repository -and you can either go to the actions tab and [click on the caches button to find -and invalidate the failing cache](https://github.blog/changelog/2022-10-20-manage-caches-in-your-actions-workflows-from-web-interface/) -or by setting the `CACHE_VERSION` secret to the current date (which will -invalidate all of the caches). - -## Updates - -### Setup Information - -These workflows run on a schedule and at the maintainer's request. Because they -create pull requests that update workflows/require the downstream actions to run, -they need a special repository/organization secret token called -`SANDPAPER_WORKFLOW` and it must have the `public_repo` and `workflow` scope. - -This can be an individual user token, OR it can be a trusted bot account. If you -have a repository in one of the official Carpentries accounts, then you do not -need to worry about this token being present because the Carpentries Core Team -will take care of supplying this token. - -If you want to use your personal account: you can go to - -to create a token. Once you have created your token, you should copy it to your -clipboard and then go to your repository's settings > secrets > actions and -create or edit the `SANDPAPER_WORKFLOW` secret, pasting in the generated token. - -If you do not specify your token correctly, the runs will not fail and they will -give you instructions to provide the token for your repository. - -### 02 Maintain: Update Workflow Files (update-workflow.yaml) - -The {sandpaper} repository was designed to do as much as possible to separate -the tools from the content. For local builds, this is absolutely true, but -there is a minor issue when it comes to workflow files: they must live inside -the repository. - -This workflow ensures that the workflow files are up-to-date. The way it work is -to download the update-workflows.sh script from GitHub and run it. The script -will do the following: - -1. check the recorded version of sandpaper against the current version on github -2. update the files if there is a difference in versions - -After the files are updated, if there are any changes, they are pushed to a -branch called `update/workflows` and a pull request is created. Maintainers are -encouraged to review the changes and accept the pull request if the outputs -are okay. - -This update is run weekly or on demand. - -### 03 Maintain: Update Package Cache (update-cache.yaml) - -For lessons that have generated content, we use {renv} to ensure that the output -is stable. This is controlled by a single lockfile which documents the packages -needed for the lesson and the version numbers. This workflow is skipped in -lessons that do not have generated content. - -Because the lessons need to remain current with the package ecosystem, it's a -good idea to make sure these packages can be updated periodically. The -update cache workflow will do this by checking for updates, applying them in a -branch called `updates/packages` and creating a pull request with _only the -lockfile changed_. - -From here, the markdown documents will be rebuilt and you can inspect what has -changed based on how the packages have updated. - -## Pull Request and Review Management - -Because our lessons execute code, pull requests are a secruity risk for any -lesson and thus have security measures associted with them. **Do not merge any -pull requests that do not pass checks and do not have bots commented on them.** - -This series of workflows all go together and are described in the following -diagram and the below sections: - -![Graph representation of a pull request](https://carpentries.github.io/sandpaper/articles/img/pr-flow.dot.svg) - -### Pre Flight Pull Request Validation (pr-preflight.yaml) - -This workflow runs every time a pull request is created and its purpose is to -validate that the pull request is okay to run. This means the following things: - -1. The pull request does not contain modified workflow files -2. If the pull request contains modified workflow files, it does not contain - modified content files (such as a situation where @carpentries-bot will - make an automated pull request) -3. The pull request does not contain an invalid commit hash (e.g. from a fork - that was made before a lesson was transitioned from styles to use the - workbench). - -Once the checks are finished, a comment is issued to the pull request, which -will allow maintainers to determine if it is safe to run the -"Receive Pull Request" workflow from new contributors. - -### Receive Pull Request (pr-receive.yaml) - -**Note of caution:** This workflow runs arbitrary code by anyone who creates a -pull request. GitHub has safeguarded the token used in this workflow to have no -priviledges in the repository, but we have taken precautions to protect against -spoofing. - -This workflow is triggered with every push to a pull request. If this workflow -is already running and a new push is sent to the pull request, the workflow -running from the previous push will be cancelled and a new workflow run will be -started. - -The first step of this workflow is to check if it is valid (e.g. that no -workflow files have been modified). If there are workflow files that have been -modified, a comment is made that indicates that the workflow is not run. If -both a workflow file and lesson content is modified, an error will occurr. - -The second step (if valid) is to build the generated content from the pull -request. This builds the content and uploads three artifacts: - -1. The pull request number (pr) -2. A summary of changes after the rendering process (diff) -3. The rendered files (build) - -Because this workflow builds generated content, it follows the same general -process as the `sandpaper-main` workflow with the same caching mechanisms. - -The artifacts produced are used by the next workflow. - -### Comment on Pull Request (pr-comment.yaml) - -This workflow is triggered if the `pr-receive.yaml` workflow is successful. -The steps in this workflow are: - -1. Test if the workflow is valid and comment the validity of the workflow to the - pull request. -2. If it is valid: create an orphan branch with two commits: the current state - of the repository and the proposed changes. -3. If it is valid: update the pull request comment with the summary of changes - -Importantly: if the pull request is invalid, the branch is not created so any -malicious code is not published. - -From here, the maintainer can request changes from the author and eventually -either merge or reject the PR. When this happens, if the PR was valid, the -preview branch needs to be deleted. - -### Send Close PR Signal (pr-close-signal.yaml) - -Triggered any time a pull request is closed. This emits an artifact that is the -pull request number for the next action - -### Remove Pull Request Branch (pr-post-remove-branch.yaml) - -Tiggered by `pr-close-signal.yaml`. This removes the temporary branch associated with -the pull request (if it was created). diff --git a/.github/workflows/pr-close-signal.yaml b/.github/workflows/pr-close-signal.yaml deleted file mode 100644 index b1303c2..0000000 --- a/.github/workflows/pr-close-signal.yaml +++ /dev/null @@ -1,22 +0,0 @@ -name: "Bot: Send Close Pull Request Signal" - -on: - pull_request: - types: - [closed] - -jobs: - send-close-signal: - name: "Send closing signal" - runs-on: ubuntu-22.04 - if: ${{ github.event.action == 'closed' }} - steps: - - name: "Create PRtifact" - run: | - mkdir -p ./pr - printf ${{ github.event.number }} > ./pr/NUM - - name: Upload Diff - uses: actions/upload-artifact@v4 - with: - name: pr - path: ./pr diff --git a/.github/workflows/pr-comment.yaml b/.github/workflows/pr-comment.yaml deleted file mode 100644 index f80d9d0..0000000 --- a/.github/workflows/pr-comment.yaml +++ /dev/null @@ -1,184 +0,0 @@ -name: "Bot: Comment on the Pull Request" - -# read-write repo token -# access to secrets -on: - workflow_run: - workflows: ["Receive Pull Request"] - types: - - completed - -concurrency: - group: pr-${{ github.event.workflow_run.pull_requests[0].number }} - cancel-in-progress: true - - -jobs: - # Pull requests are valid if: - # - they match the sha of the workflow run head commit - # - they are open - # - no .github files were committed - test-pr: - name: "Test if pull request is valid" - runs-on: ubuntu-22.04 - if: > - github.event.workflow_run.event == 'pull_request' && - github.event.workflow_run.conclusion == 'success' - outputs: - is_valid: ${{ steps.check-pr.outputs.VALID }} - payload: ${{ steps.check-pr.outputs.payload }} - number: ${{ steps.get-pr.outputs.NUM }} - msg: ${{ steps.check-pr.outputs.MSG }} - steps: - - name: 'Download PR artifact' - id: dl - uses: carpentries/actions/download-workflow-artifact@main - with: - run: ${{ github.event.workflow_run.id }} - name: 'pr' - - - name: "Get PR Number" - if: ${{ steps.dl.outputs.success == 'true' }} - id: get-pr - run: | - unzip pr.zip - echo "NUM=$(<./NR)" >> $GITHUB_OUTPUT - - - name: "Fail if PR number was not present" - id: bad-pr - if: ${{ steps.dl.outputs.success != 'true' }} - run: | - echo '::error::A pull request number was not recorded. The pull request that triggered this workflow is likely malicious.' - exit 1 - - name: "Get Invalid Hashes File" - id: hash - run: | - echo "json<> $GITHUB_OUTPUT - - name: "Check PR" - id: check-pr - if: ${{ steps.dl.outputs.success == 'true' }} - uses: carpentries/actions/check-valid-pr@main - with: - pr: ${{ steps.get-pr.outputs.NUM }} - sha: ${{ github.event.workflow_run.head_sha }} - headroom: 3 # if it's within the last three commits, we can keep going, because it's likely rapid-fire - invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} - fail_on_error: true - - # Create an orphan branch on this repository with two commits - # - the current HEAD of the md-outputs branch - # - the output from running the current HEAD of the pull request through - # the md generator - create-branch: - name: "Create Git Branch" - needs: test-pr - runs-on: ubuntu-22.04 - if: ${{ needs.test-pr.outputs.is_valid == 'true' }} - env: - NR: ${{ needs.test-pr.outputs.number }} - permissions: - contents: write - steps: - - name: 'Checkout md outputs' - uses: actions/checkout@v4 - with: - ref: md-outputs - path: built - fetch-depth: 1 - - - name: 'Download built markdown' - id: dl - uses: carpentries/actions/download-workflow-artifact@main - with: - run: ${{ github.event.workflow_run.id }} - name: 'built' - - - if: ${{ steps.dl.outputs.success == 'true' }} - run: unzip built.zip - - - name: "Create orphan and push" - if: ${{ steps.dl.outputs.success == 'true' }} - run: | - cd built/ - git config --local user.email "actions@github.com" - git config --local user.name "GitHub Actions" - CURR_HEAD=$(git rev-parse HEAD) - git checkout --orphan md-outputs-PR-${NR} - git add -A - git commit -m "source commit: ${CURR_HEAD}" - ls -A | grep -v '^.git$' | xargs -I _ rm -r '_' - cd .. - unzip -o -d built built.zip - cd built - git add -A - git commit --allow-empty -m "differences for PR #${NR}" - git push -u --force --set-upstream origin md-outputs-PR-${NR} - - # Comment on the Pull Request with a link to the branch and the diff - comment-pr: - name: "Comment on Pull Request" - needs: [test-pr, create-branch] - runs-on: ubuntu-22.04 - if: ${{ needs.test-pr.outputs.is_valid == 'true' }} - env: - NR: ${{ needs.test-pr.outputs.number }} - permissions: - pull-requests: write - steps: - - name: 'Download comment artifact' - id: dl - uses: carpentries/actions/download-workflow-artifact@main - with: - run: ${{ github.event.workflow_run.id }} - name: 'diff' - - - if: ${{ steps.dl.outputs.success == 'true' }} - run: unzip ${{ github.workspace }}/diff.zip - - - name: "Comment on PR" - id: comment-diff - if: ${{ steps.dl.outputs.success == 'true' }} - uses: carpentries/actions/comment-diff@main - with: - pr: ${{ env.NR }} - path: ${{ github.workspace }}/diff.md - - # Comment if the PR is open and matches the SHA, but the workflow files have - # changed - comment-changed-workflow: - name: "Comment if workflow files have changed" - needs: test-pr - runs-on: ubuntu-22.04 - if: ${{ always() && needs.test-pr.outputs.is_valid == 'false' }} - env: - NR: ${{ github.event.workflow_run.pull_requests[0].number }} - body: ${{ needs.test-pr.outputs.msg }} - permissions: - pull-requests: write - steps: - - name: 'Check for spoofing' - id: dl - uses: carpentries/actions/download-workflow-artifact@main - with: - run: ${{ github.event.workflow_run.id }} - name: 'built' - - - name: 'Alert if spoofed' - id: spoof - if: ${{ steps.dl.outputs.success == 'true' }} - run: | - echo 'body<> $GITHUB_ENV - echo '' >> $GITHUB_ENV - echo '## :x: DANGER :x:' >> $GITHUB_ENV - echo 'This pull request has modified workflows that created output. Close this now.' >> $GITHUB_ENV - echo '' >> $GITHUB_ENV - echo 'EOF' >> $GITHUB_ENV - - - name: "Comment on PR" - id: comment-diff - uses: carpentries/actions/comment-diff@main - with: - pr: ${{ env.NR }} - body: ${{ env.body }} diff --git a/.github/workflows/pr-post-remove-branch.yaml b/.github/workflows/pr-post-remove-branch.yaml deleted file mode 100644 index 9419e2b..0000000 --- a/.github/workflows/pr-post-remove-branch.yaml +++ /dev/null @@ -1,32 +0,0 @@ -name: "Bot: Remove Temporary PR Branch" - -on: - workflow_run: - workflows: ["Bot: Send Close Pull Request Signal"] - types: - - completed - -jobs: - delete: - name: "Delete branch from Pull Request" - runs-on: ubuntu-22.04 - if: > - github.event.workflow_run.event == 'pull_request' && - github.event.workflow_run.conclusion == 'success' - permissions: - contents: write - steps: - - name: 'Download artifact' - uses: carpentries/actions/download-workflow-artifact@main - with: - run: ${{ github.event.workflow_run.id }} - name: pr - - name: "Get PR Number" - id: get-pr - run: | - unzip pr.zip - echo "NUM=$(<./NUM)" >> $GITHUB_OUTPUT - - name: 'Remove branch' - uses: carpentries/actions/remove-branch@main - with: - pr: ${{ steps.get-pr.outputs.NUM }} diff --git a/.github/workflows/pr-preflight.yaml b/.github/workflows/pr-preflight.yaml deleted file mode 100644 index 34ad7ae..0000000 --- a/.github/workflows/pr-preflight.yaml +++ /dev/null @@ -1,39 +0,0 @@ -name: "Pull Request Preflight Check" - -on: - pull_request_target: - branches: - ["main"] - types: - ["opened", "synchronize", "reopened"] - -jobs: - test-pr: - name: "Test if pull request is valid" - if: ${{ github.event.action != 'closed' }} - runs-on: ubuntu-22.04 - outputs: - is_valid: ${{ steps.check-pr.outputs.VALID }} - permissions: - pull-requests: write - steps: - - name: "Get Invalid Hashes File" - id: hash - run: | - echo "json<> $GITHUB_OUTPUT - - name: "Check PR" - id: check-pr - uses: carpentries/actions/check-valid-pr@main - with: - pr: ${{ github.event.number }} - invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} - fail_on_error: true - - name: "Comment result of validation" - id: comment-diff - if: ${{ always() }} - uses: carpentries/actions/comment-diff@main - with: - pr: ${{ github.event.number }} - body: ${{ steps.check-pr.outputs.MSG }} diff --git a/.github/workflows/pr-receive.yaml b/.github/workflows/pr-receive.yaml deleted file mode 100644 index 7fbff6c..0000000 --- a/.github/workflows/pr-receive.yaml +++ /dev/null @@ -1,132 +0,0 @@ -name: "Receive Pull Request" - -on: - pull_request: - types: - [opened, synchronize, reopened] - -concurrency: - group: ${{ github.ref }} - cancel-in-progress: true - -jobs: - test-pr: - name: "Record PR number" - if: ${{ github.event.action != 'closed' }} - runs-on: ubuntu-22.04 - outputs: - is_valid: ${{ steps.check-pr.outputs.VALID }} - steps: - - name: "Record PR number" - id: record - if: ${{ always() }} - run: | - echo ${{ github.event.number }} > ${{ github.workspace }}/NR # 2022-03-02: artifact name fixed to be NR - - name: "Upload PR number" - id: upload - if: ${{ always() }} - uses: actions/upload-artifact@v4 - with: - name: pr - path: ${{ github.workspace }}/NR - - name: "Get Invalid Hashes File" - id: hash - run: | - echo "json<> $GITHUB_OUTPUT - - name: "echo output" - run: | - echo "${{ steps.hash.outputs.json }}" - - name: "Check PR" - id: check-pr - uses: carpentries/actions/check-valid-pr@main - with: - pr: ${{ github.event.number }} - invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} - - build-md-source: - name: "Build markdown source files if valid" - needs: test-pr - runs-on: ubuntu-22.04 - if: ${{ needs.test-pr.outputs.is_valid == 'true' }} - env: - GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} - RENV_PATHS_ROOT: ~/.local/share/renv/ - CHIVE: ${{ github.workspace }}/site/chive - PR: ${{ github.workspace }}/site/pr - MD: ${{ github.workspace }}/site/built - steps: - - name: "Check Out Main Branch" - uses: actions/checkout@v4 - - - name: "Check Out Staging Branch" - uses: actions/checkout@v4 - with: - ref: md-outputs - path: ${{ env.MD }} - - - name: "Set up R" - uses: r-lib/actions/setup-r@v2 - with: - use-public-rspm: true - install-r: false - - - name: "Set up Pandoc" - uses: r-lib/actions/setup-pandoc@v2 - - - name: "Setup Lesson Engine" - uses: carpentries/actions/setup-sandpaper@main - with: - cache-version: ${{ secrets.CACHE_VERSION }} - - - name: "Setup Package Cache" - uses: carpentries/actions/setup-lesson-deps@main - with: - cache-version: ${{ secrets.CACHE_VERSION }} - - - name: "Validate and Build Markdown" - id: build-site - run: | - sandpaper::package_cache_trigger(TRUE) - sandpaper::validate_lesson(path = '${{ github.workspace }}') - sandpaper:::build_markdown(path = '${{ github.workspace }}', quiet = FALSE) - shell: Rscript {0} - - - name: "Generate Artifacts" - id: generate-artifacts - run: | - sandpaper:::ci_bundle_pr_artifacts( - repo = '${{ github.repository }}', - pr_number = '${{ github.event.number }}', - path_md = '${{ env.MD }}', - path_pr = '${{ env.PR }}', - path_archive = '${{ env.CHIVE }}', - branch = 'md-outputs' - ) - shell: Rscript {0} - - - name: "Upload PR" - uses: actions/upload-artifact@v4 - with: - name: pr - path: ${{ env.PR }} - overwrite: true - - - name: "Upload Diff" - uses: actions/upload-artifact@v4 - with: - name: diff - path: ${{ env.CHIVE }} - retention-days: 1 - - - name: "Upload Build" - uses: actions/upload-artifact@v4 - with: - name: built - path: ${{ env.MD }} - retention-days: 1 - - - name: "Teardown" - run: sandpaper::reset_site() - shell: Rscript {0} diff --git a/.github/workflows/sandpaper-main.yaml b/.github/workflows/sandpaper-main.yaml deleted file mode 100644 index b3d1de8..0000000 --- a/.github/workflows/sandpaper-main.yaml +++ /dev/null @@ -1,64 +0,0 @@ -name: "01 Build and Deploy Site" - -on: - push: - branches: - - main - - master - schedule: - - cron: '0 0 * * 2' - workflow_dispatch: - inputs: - name: - description: 'Who triggered this build?' - required: true - default: 'Maintainer (via GitHub)' - reset: - description: 'Reset cached markdown files' - required: false - default: false - type: boolean -jobs: - full-build: - name: "Build Full Site" - - # 2024-10-01: ubuntu-latest is now 24.04 and R is not installed by default in the runner image - # pin to 22.04 for now - runs-on: ubuntu-22.04 - permissions: - checks: write - contents: write - pages: write - env: - GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} - RENV_PATHS_ROOT: ~/.local/share/renv/ - steps: - - - name: "Checkout Lesson" - uses: actions/checkout@v4 - - - name: "Set up R" - uses: r-lib/actions/setup-r@v2 - with: - use-public-rspm: true - install-r: false - - - name: "Set up Pandoc" - uses: r-lib/actions/setup-pandoc@v2 - - - name: "Setup Lesson Engine" - uses: carpentries/actions/setup-sandpaper@main - with: - cache-version: ${{ secrets.CACHE_VERSION }} - - - name: "Setup Package Cache" - uses: carpentries/actions/setup-lesson-deps@main - with: - cache-version: ${{ secrets.CACHE_VERSION }} - - - name: "Deploy Site" - run: | - reset <- "${{ github.event.inputs.reset }}" == "true" - sandpaper::package_cache_trigger(TRUE) - sandpaper:::ci_deploy(reset = reset) - shell: Rscript {0} diff --git a/.github/workflows/sandpaper-version.txt b/.github/workflows/sandpaper-version.txt deleted file mode 100644 index f2f6c13..0000000 --- a/.github/workflows/sandpaper-version.txt +++ /dev/null @@ -1 +0,0 @@ -0.16.11 diff --git a/.github/workflows/update-cache.yaml b/.github/workflows/update-cache.yaml deleted file mode 100644 index a011c0c..0000000 --- a/.github/workflows/update-cache.yaml +++ /dev/null @@ -1,125 +0,0 @@ -name: "03 Maintain: Update Package Cache" - -on: - workflow_dispatch: - inputs: - name: - description: 'Who triggered this build (enter github username to tag yourself)?' - required: true - default: 'monthly run' - schedule: - # Run every tuesday - - cron: '0 0 * * 2' - -jobs: - preflight: - name: "Preflight Check" - runs-on: ubuntu-22.04 - outputs: - ok: ${{ steps.check.outputs.ok }} - steps: - - id: check - run: | - if [[ ${{ github.event_name }} == 'workflow_dispatch' ]]; then - echo "ok=true" >> $GITHUB_OUTPUT - echo "Running on request" - # using single brackets here to avoid 08 being interpreted as octal - # https://github.com/carpentries/sandpaper/issues/250 - elif [ `date +%d` -le 7 ]; then - # If the Tuesday lands in the first week of the month, run it - echo "ok=true" >> $GITHUB_OUTPUT - echo "Running on schedule" - else - echo "ok=false" >> $GITHUB_OUTPUT - echo "Not Running Today" - fi - - check_renv: - name: "Check if We Need {renv}" - runs-on: ubuntu-22.04 - needs: preflight - if: ${{ needs.preflight.outputs.ok == 'true'}} - outputs: - needed: ${{ steps.renv.outputs.exists }} - steps: - - name: "Checkout Lesson" - uses: actions/checkout@v4 - - id: renv - run: | - if [[ -d renv ]]; then - echo "exists=true" >> $GITHUB_OUTPUT - fi - - check_token: - name: "Check SANDPAPER_WORKFLOW token" - runs-on: ubuntu-22.04 - needs: check_renv - if: ${{ needs.check_renv.outputs.needed == 'true' }} - outputs: - workflow: ${{ steps.validate.outputs.wf }} - repo: ${{ steps.validate.outputs.repo }} - steps: - - name: "validate token" - id: validate - uses: carpentries/actions/check-valid-credentials@main - with: - token: ${{ secrets.SANDPAPER_WORKFLOW }} - - update_cache: - name: "Update Package Cache" - needs: check_token - if: ${{ needs.check_token.outputs.repo== 'true' }} - runs-on: ubuntu-22.04 - env: - GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} - RENV_PATHS_ROOT: ~/.local/share/renv/ - steps: - - - name: "Checkout Lesson" - uses: actions/checkout@v4 - - - name: "Set up R" - uses: r-lib/actions/setup-r@v2 - with: - use-public-rspm: true - install-r: false - - - name: "Update {renv} deps and determine if a PR is needed" - id: update - uses: carpentries/actions/update-lockfile@main - with: - cache-version: ${{ secrets.CACHE_VERSION }} - - - name: Create Pull Request - id: cpr - if: ${{ steps.update.outputs.n > 0 }} - uses: carpentries/create-pull-request@main - with: - token: ${{ secrets.SANDPAPER_WORKFLOW }} - delete-branch: true - branch: "update/packages" - commit-message: "[actions] update ${{ steps.update.outputs.n }} packages" - title: "Update ${{ steps.update.outputs.n }} packages" - body: | - :robot: This is an automated build - - This will update ${{ steps.update.outputs.n }} packages in your lesson with the following versions: - - ``` - ${{ steps.update.outputs.report }} - ``` - - :stopwatch: In a few minutes, a comment will appear that will show you how the output has changed based on these updates. - - If you want to inspect these changes locally, you can use the following code to check out a new branch: - - ```bash - git fetch origin update/packages - git checkout update/packages - ``` - - - Auto-generated by [create-pull-request][1] on ${{ steps.update.outputs.date }} - - [1]: https://github.com/carpentries/create-pull-request/tree/main - labels: "type: package cache" - draft: false diff --git a/.github/workflows/update-workflows.yaml b/.github/workflows/update-workflows.yaml deleted file mode 100644 index 6414cf2..0000000 --- a/.github/workflows/update-workflows.yaml +++ /dev/null @@ -1,66 +0,0 @@ -name: "02 Maintain: Update Workflow Files" - -on: - workflow_dispatch: - inputs: - name: - description: 'Who triggered this build (enter github username to tag yourself)?' - required: true - default: 'weekly run' - clean: - description: 'Workflow files/file extensions to clean (no wildcards, enter "" for none)' - required: false - default: '.yaml' - schedule: - # Run every Tuesday - - cron: '0 0 * * 2' - -jobs: - check_token: - name: "Check SANDPAPER_WORKFLOW token" - runs-on: ubuntu-22.04 - outputs: - workflow: ${{ steps.validate.outputs.wf }} - repo: ${{ steps.validate.outputs.repo }} - steps: - - name: "validate token" - id: validate - uses: carpentries/actions/check-valid-credentials@main - with: - token: ${{ secrets.SANDPAPER_WORKFLOW }} - - update_workflow: - name: "Update Workflow" - runs-on: ubuntu-22.04 - needs: check_token - if: ${{ needs.check_token.outputs.workflow == 'true' }} - steps: - - name: "Checkout Repository" - uses: actions/checkout@v4 - - - name: Update Workflows - id: update - uses: carpentries/actions/update-workflows@main - with: - clean: ${{ github.event.inputs.clean }} - - - name: Create Pull Request - id: cpr - if: "${{ steps.update.outputs.new }}" - uses: carpentries/create-pull-request@main - with: - token: ${{ secrets.SANDPAPER_WORKFLOW }} - delete-branch: true - branch: "update/workflows" - commit-message: "[actions] update sandpaper workflow to version ${{ steps.update.outputs.new }}" - title: "Update Workflows to Version ${{ steps.update.outputs.new }}" - body: | - :robot: This is an automated build - - Update Workflows from sandpaper version ${{ steps.update.outputs.old }} -> ${{ steps.update.outputs.new }} - - - Auto-generated by [create-pull-request][1] on ${{ steps.update.outputs.date }} - - [1]: https://github.com/carpentries/create-pull-request/tree/main - labels: "type: template and tools" - draft: false From 2cc056d9718f37c22ae3191538eb389ddaa3be36 Mon Sep 17 00:00:00 2001 From: Douglas Lowe <10961945+douglowe@users.noreply.github.com> Date: Thu, 29 Oct 2026 17:14:11 +0000 Subject: [PATCH 2/2] updated workflows and issue templates --- .github/ISSUE_TEMPLATE/bug.yml | 41 +++ .github/ISSUE_TEMPLATE/config.yml | 5 + .github/ISSUE_TEMPLATE/feature.yml | 28 ++ .github/ISSUE_TEMPLATE/task.yml | 22 ++ .github/PULL_REQUEST_TEMPLATE.md | 48 +++ .github/workbench-docker-version.txt | 1 + .github/workflows/README.md | 308 +++++++++++++++++++ .github/workflows/check-ruleset.yaml | 31 ++ .github/workflows/license-copyright-add.yml | 14 + .github/workflows/naming-conventions.yml | 35 +++ .github/workflows/pr-close-signal.yaml | 22 ++ .github/workflows/pr-comment.yaml | 184 +++++++++++ .github/workflows/pr-post-remove-branch.yaml | 32 ++ .github/workflows/pr-preflight.yaml | 39 +++ .github/workflows/pr-receive.yaml | 132 ++++++++ .github/workflows/sandpaper-main.yaml | 64 ++++ .github/workflows/update-cache.yaml | 125 ++++++++ .github/workflows/update-workflows.yaml | 66 ++++ .github/workflows/workflows-version.txt | 1 + 19 files changed, 1198 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature.yml create mode 100644 .github/ISSUE_TEMPLATE/task.yml create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workbench-docker-version.txt create mode 100644 .github/workflows/README.md create mode 100644 .github/workflows/check-ruleset.yaml create mode 100644 .github/workflows/license-copyright-add.yml create mode 100644 .github/workflows/naming-conventions.yml create mode 100644 .github/workflows/pr-close-signal.yaml create mode 100644 .github/workflows/pr-comment.yaml create mode 100644 .github/workflows/pr-post-remove-branch.yaml create mode 100644 .github/workflows/pr-preflight.yaml create mode 100644 .github/workflows/pr-receive.yaml create mode 100644 .github/workflows/sandpaper-main.yaml create mode 100644 .github/workflows/update-cache.yaml create mode 100644 .github/workflows/update-workflows.yaml create mode 100644 .github/workflows/workflows-version.txt diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml new file mode 100644 index 0000000..2631f7f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -0,0 +1,41 @@ +name: Bug Report +description: Report something not working with the project's code. +type: Bug +labels: [bug] +# See https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema +body: + - type: markdown + attributes: + value: > + Thank you for helping us by reporting a bug issue! + Help us help you get things fixed. + - type: textarea + id: what-happened + attributes: + label: What happened? + description: Also, what did you expect to happen? + placeholder: Tell us what you see! + validations: + required: true + - type: input + id: version + attributes: + label: What version of our software are you running? + placeholder: "I don't know..." + description: > + It can really help if you let us know what version of our software you are using. + Sometimes the fix to the bug has already been implemented and all that is needed is an update, but this will let us know for sure. + - type: textarea + id: environment + attributes: + label: Where were you running our software? + description: > + Operating system, browser, shell, anything to help us know what environment our software is (not) working within. + Sometimes, this is vital. + - type: textarea + id: logs + attributes: + label: Relevant log output + description: > + Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + render: shell diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..94da231 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Security Problems + url: https://www.itservices.manchester.ac.uk/help/connect/ + about: Security problems should be reported via Connect. diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml new file mode 100644 index 0000000..9c90345 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -0,0 +1,28 @@ +name: Feature Request +description: > + A request for a new feature to be added, for the software to do something that it did not previously do. Typically will take the form of a "User Story" and hence assumes that issue type. +type: Feature +labels: ["user story"] +body: + - type: markdown + attributes: + value: > + Thank you for making a suggestion of something new we should do. + Usually, the more detail you can provide about what you think we should do, the easier it is to implement. + - type: textarea + id: requested-feature + attributes: + label: What are you asking for + description: > + Please describe what it is you want. + placeholder: More information usually helps here. + validations: + required: true + - type: input + id: version + attributes: + label: What version of our software are you running? + placeholder: "I don't know..." + description: > + It can really help if you let us know what version of our software you are using. + Sometimes, features may already exist in later versions and all that is needed is an update, but this will let us know for sure. diff --git a/.github/ISSUE_TEMPLATE/task.yml b/.github/ISSUE_TEMPLATE/task.yml new file mode 100644 index 0000000..2098743 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/task.yml @@ -0,0 +1,22 @@ +name: New Task +description: A request for something to be done that isn't really a bug fix or a new feature. +type: Task +labels: ["task"] +body: + - type: markdown + attributes: + value: > + We know not all things to do with a repository are clearly bug fixes or new features. + Life isn't that simple. + If you need to ask for anything else, this is for you. + - type: textarea + id: task + attributes: + label: What do you want us to do? + description: > + What is this task to be about? + Please provide us with as much information as you think is relevant. + placeholder: > + I would like you to hop on one foot and let slip the doves of peace! + validations: + required: true diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..03cc3cd --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,48 @@ +--- +name: Pull Request +about: For submitting a code change. +--- + + + + + +## Issue Description + + + +### What Issue does this PR fix? +Is this fixing an issue? If so, please `#ref` its ID. This helps a lot! + + +For extra magic, write that reference as this sentence: `This fixes #ref.` or this `Closes #ref.` +This causes the PR to _automatically_ close the referenced issue when merged. + +### What does this PR do? +What do you think this PR does? We can see what it _actually_ does by reading the code, +but it's very helpful to have a short description of what you _intend_ it to do. + +### Do you know who could review this PR? +Don't forget to Request a Review from a team member when this PR is ready. + + +## Standard Review Checklist for _Authors_ + + +- [ ] Does the code change do what it is claimed to do? +- [ ] Is the code change able to be built? +- [ ] Is the code change tested? +- [ ] Is the code change documented? +- [ ] Does the code change follow the repository's style guide, if there is one? + + +The [RSE handbook](https://livemanchesterac.sharepoint.com/:b:/r/sites/UOM-ITS-Research-IT/Shared%20Documents/RSE%20Team/Read-Only/Policies%20and%20Processes/RSE_Agile_Methods_Handbook.pdf?csf=1&web=1&e=CNE4Nm) has further guidance to reviewers. diff --git a/.github/workbench-docker-version.txt b/.github/workbench-docker-version.txt new file mode 100644 index 0000000..d2db7db --- /dev/null +++ b/.github/workbench-docker-version.txt @@ -0,0 +1 @@ +v0.2.8 diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 0000000..4516bb1 --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,308 @@ +# Workbench Workflows Documentation + +These GitHub Actions workflows manage and maintain the build processes for lessons using the Carpentries Workbench on GitHub. + + +## Managing Workflow Updates + +By using prebuilt Docker containers that are managed by the Carpentries core Workbench maintainers, these workflows are designed to be rarely updated. + +However, is important to be able to keep them up-to-date when appropriate. +You can do this locally using your own R and Workbench installation, or via the "04 Maintain: Update Workflow Files" (`update-workflows.yaml`) GitHub Action. + +### Updating locally + +In a terminal/git bash, navigate to the lesson folder where you want to update the workflows, e.g.: + +```bash +cd ~/lessons/shell-novice +``` + +Then, start an R session and: + +```r +# Install/Update sandpaper +options(repos = c(carpentries = "https://carpentries.r-universe.dev/", CRAN = "https://cloud.r-project.org")) +install.packages("sandpaper") + +# update the workflows in your lesson +library("sandpaper") +sandpaper::update_github_workflows() +quit() +``` + +And then in a bash prompt/git bash terminal: + +```bash +$ git add .github/workflows +$ git commit -m "Manual update to docker workflows" +$ git push origin main +``` + +> [!NOTE] +> For non-renv lessons, this is all the setup you need! +> +> For renv-enabled lessons: +> - Cancel any "01 Maintain: Build and Deploy Site" workflow currently running +> - Run the "02 Maintain: Check for Updated Packages" workflow and merge any PR opened to update the renv lockfile +> - This should automatically run the "03 Maintain: Apply Package Cache" workflow to install packages and build the cache +> - A successful cache build should then trigger the "01 Maintain: Build and Deploy Site" workflow + +#### Updating to a specific workflow release or branch + +To test new Workbench workflow features or branches, or to pin to a specific release, the `branch` option can be supplied to `update_github_workflows()`. + +For a given branch: + +```r +sandpaper::update_github_workflows(branch="develop") +``` + +Or for a given release version: +```r +sandpaper::update_github_workflows(branch="1.0.1") +``` + +### Updating using GitHub + +#### Official lessons + +"Official" lessons are those in the lesson program repositories, Incubator, or Lab. +They need no extra setup as this is all managed for you as part of the Carpentries GitHub organisations. + +To update the workflows, either: +- wait for the scheduled run of the "04 Maintain: Update Workflow Files" at approximately midnight every Tuesday +- go to the Actions tab on GitHub, click "04 Maintain: Update Workflow Files" on the left, then "Run Workflow" on the right + +Once complete, this will raise a PR with any changes to the workflows that are needed. +If you are happy with the changes made, you can merge the PR into your lesson repository. + +#### Your own lessons + +This presumes you: + - already have a lesson repository available on GitHub + - have enabled workflows in the lesson repo + - have set up a SANDPAPER_WORKFLOW personal access token (PAT) in the lesson repo + +To go through these steps, please follow the [Forking a Workbench Lesson](https://docs.carpentries.org/resources/curriculum/lesson-forks.html#forking-a-workbench-lesson-repository) +documentation. + +Once set up, run the "04 Maintain: Update Workflow Files" (`update-workflows.yaml`) action. + +This will raise a PR with any changes to the workflows that are needed. +If you are happy with the changes made, you can merge the PR into your lesson repository. + + +## Dependency Images for RMarkdown Lessons + +Lessons that use R packages and RMarkdown are built on GitHub using Docker images within these workflows. +These images are based on the [workbench-docker](https://github.com/carpentries/workbench-docker) image. +This base image only contains the Workbench packages to build lessons and not any extra R packages your lesson might need. + +Therefore, there are two steps to perform to resolve the required R packages in a lesson, and then generate a Docker image layer comprising those packages. + +The "02 Maintain: Check for Updated Packages" workflow checks for any used R packages and their versions, and if successful, opens a Pull Request to update your lesson's renv lockfile (`renv.lock`). +Once the PR is merged, the "03 Maintain: Apply Package Cache" workflow builds the dependency image layer with `docker build` and publishes it in your user or organisation account Packages area. + +> [!NOTE] +> Caching is only relevant for lessons that use Rmd files and renv to manage R packages. +> If you are building basic markdown documents, caching will not apply to you, and the only +> workflow that needs to be run is "01 Maintain: Build and Deploy Site". + +### Publishing dependency images + +The two dependency workflows are separated to ensure that once you have a successful build with a working renv environment, the resulting dependency image is stored and will be reused by the Workbench Docker container. +This means that lesson builds will be faster and more consistent once a dependency image is created and reused. This is doubly important if you need very specific versions of R packages, i.e. "pinning". + +This setup means that this dependency image layer is available indefinitely: +- to build your lesson, improving robustness and reproducibility +- for others to use as a complete environment in their local builds, teaching environments, or Codespaces + +If and when you want to perform an update to the dependency image, you can re-run the "02 Maintain: Check for Updated Packages" workflow and verify that your lesson still builds with any new packages or changes. +The "03 Maintain: Apply Package Cache" workflow will publish a new repository- or organisation-local GHCR image for the lesson. + +As such, the dependency image is invalidated by new versions of the `renv.lock` file. +This happens: + - if you update your lockfile locally by using the `sandpaper::update_cache()` and `sandpaper::manage_deps()` functions, and then push it to the lesson repository + - when you run the "02 Maintain: Check for Updated Packages" and there are new packages to install + +More information on managing local renv-based lesson dependencies can be found in the [Sandpaper packages vignettes](https://carpentries.github.io/sandpaper/articles/building-with-renv.html). + +#### Using different dependency image versions + +There are times when you may want to go back to a previous dependency image: + - if you run "02 Maintain: Check for Updated Packages" and "03 Maintain: Apply Package Cache" and the cache generation fails for some reason + - if there is a new R package that produces incorrect or broken lesson output + - a new R version is released and downstream packages fail to build and install, and need updating by the package maintainer(s) + +Dependency images will have the following name format, where IMAGE is the workbench-docker image version, and HASHSUM is the `renv.lock` lockfile hash: + +``` +IMAGE HASHSUM +[ | ] [ | ] +v0.2.4_renv-2e499eb706112971b2cffceb49b55a6efe49f3ed75cd6579b10ff224489daca4 +``` + +Copy the hashsum part of the desired image tag you want to use, e.g. `2e499eb706112971b2cffceb49b55a6efe49f3ed75cd6579b10ff224489daca4`. + +Then either: + 1. Add a repository variable called CACHE_VERSION, and paste in the hash + 2. Run the "01 Maintain: Build and Deploy Site" manually, supplying the `Optional renv cache version override` input + +If you have no images listed, make sure to run the "02 Maintain: Check for Updated Packages" and "03 Maintain: Apply Package Cache" workflows to publish a new dependency image. + +> [!NOTE] +> If you are maintaining an official lesson, dependency images are saved to the Carpentries lesson program organisation, e.g. `datacarpentry`, GHCR package namespace. +> Once a successful dependency image has been published, the build workflows will use it automatically when the matching Docker version tag exists, e.g. 'latest' or a specific version. +> +> If you are developing a lesson in your own repository, the dependency images are stored in your repository's GHCR package namespace. +> You can see available images by going to your user or organisation's Packages tab, e.g. `https://github.com/?tab=packages`. + +#### Pruning dependency image layers + +Through the lifetime of a lesson, an increasing number of dependency images will be generated. +As the images are public, GitHub currently charges no storage, or network ingress or egress fees to upload or download them. + +The "03 Maintain: Apply Package Cache" workflow will automatically check the number of published dependency images and keep each version published plus one underlying untagged digest (if any) for each version. +This means it is possible to roll back easily to a previous version or digest, but not end up with a huge number of dependency images to manage. + +In any case, you can manually delete any versions you wish by: +- going to your user or organisation's Packages tab, e.g. `https://github.com/?tab=packages`. +- selecting the dependency image you want to manage, e.g. `-deps` +- selecting `Package settings` on the right hand side +- deleting any images + +> [!NOTE] +> Deleting these images manually may break your builds. +> Only perform this action if you are sure you want to delete the generated dependency images. +> +> If you mistakenly delete an image, you can rebuild it by rerunning the "03 Maintain: Apply Package Cache" workflow. + + +## User Settings + +Input level variables are documented in the `carpentries/actions` repository READMEs for each composite action. + +Specific repository level variables can be set that will force particular options across all workflow runs. + +### 01 Maintain: Build and Deploy Site (docker_build_deploy.yaml) + +Repository-level variables for this workflow are: +- WORKBENCH_TAG + - The workbench-docker release version to use for a given build + - This can be set to a specific version number to force all builds to use a given container version + - Default is unset or `latest` +- BUILD_RESET + - Force a reset of previously build markdown files + - Setting this variable value to `true` will force sandpaper to delete any previously build markdown files + - Default is unset or `false` +- AUTO_MERGE_WORKBENCH_VERSION_UPDATE + - Control merge behaviour of the workbench-docker version update PR + - When a new workbench Docker image version is detected, usually after a sandpaper, varnish, or pegboard update, its version number will be incremented + - If a newer version is available, a PR will be auto-generated that updates the `.github/workbench-docker-version.txt` file, and this PR will be auto-merged + - To not auto-merge this PR and to choose when to update the Docker version used, set this to `false`. + - Default is unset or `true` +- LANG_CODE + - Two-letter language code that triggers the use of Joel Nitta's {dovetail} package for lesson translation + - This is used in the internationalisation repos of the main Carpentry lesson programs + - Default is unset or `''` + +### 02 Maintain: Check for Updated Packages (update-cache.yaml) + +Repository-level variables for this workflow are: +- LOCKFILE_CACHE_GEN + - Passed to the `generate-cache` input of the [update-lockfile](https://github.com/carpentries/actions/tree/main/update-lockfile) action + - A temporary renv cache is generated when this workflow runs + - If this option is set to `false`, no temporary cache will be generated + - Default is `true` +- FORCE_RENV_INIT + - Passed to the `force-renv-init` input of the [update-lockfile](https://github.com/carpentries/actions/tree/main/update-lockfile) action + - renv initialises a cache based on a given lockfile + - If this lockfile is particularly old or packages have broken/unresolvable dependencies, then builds will fail + - If this option is set to `true`, a full renv reinitialisation will occur, "wiping the slate clean" + - This option is useful if you're using Bioconductor packages which often break when new Bioconductor releases happen + - Default is `false` +- UPDATE_PACKAGES + - Passed to the `update` input of the [update-lockfile](https://github.com/carpentries/actions/tree/main/update-lockfile) action + - If set to `false` only package hydration will happen and no package update checks will occur + - Default is `true` + +### 03 Maintain: Apply Package Cache (docker_apply_cache.yaml) + +Repository-level variables for this workflow are: +- WORKBENCH_TAG + - The workbench-docker release version to use for a given build + - This can be set to a specific version number to force all builds to use a given container version + - Default is unset or `latest` + +### 04 Maintain: Update Workflow Files (update-workflows.yaml) + +There are no repository variables for this workflow. + + +## Pull Request and Review Management + +Because our lessons execute code, pull requests are a security risk for any lesson and thus have security measures associated with them. +**Do not merge any pull requests that do not pass checks and do not have bots commented on them.** + +This series of workflows all go together and are described in the following diagram and the below sections: + +![Graph representation of a pull request](https://carpentries.github.io/sandpaper/articles/img/pr-flow.dot.svg) + +### Pre Flight Pull Request Validation (pr-preflight.yaml) + +This workflow runs every time a pull request is created and its purpose is to validate that the pull request is okay to run. +This means the following things: + +1. The pull request does not contain modified workflow files +2. If the pull request contains modified workflow files, it does not contain modified content files + (such as a situation where @carpentries-bot will make an automated pull request) +3. The pull request does not contain an invalid commit hash + (e.g. from a fork that was made before a lesson was transitioned from styles to use the Workbench). + +Once the checks are finished, a comment is issued to the pull request, which will allow maintainers to determine if it is safe to run the "Receive Pull Request" workflow from new contributors. + +### Receive Pull Request (docker_pr_receive.yaml) + +**Note of caution:** This workflow runs arbitrary code by anyone who creates a pull request. +GitHub has safeguarded the token used in this workflow to have no privileges in the repository, but we have taken precautions to protect against spoofing. + +This workflow is triggered with every push to a pull request. +If this workflow is already running and a new push is sent to the pull request, the workflow running from the previous push will be cancelled and a new workflow run will be started. + +The first step of this workflow is to check if it is valid (e.g. that no workflow files have been modified): +- If there are workflow files that have been modified, a comment is made that indicates that the workflow will not continue. +- If both a workflow file and lesson content is modified, an error will occur and the workflow will not continue. + +The second step (if valid) is to build the generated content from the pull request. +This builds the content and uploads three artifacts: + +1. The pull request number (pr) +2. A summary of changes after the rendering process (diff) +3. The rendered files (build) + +The artifacts produced are used by the "Comment on Pull Request" workflow. + +### Comment on Pull Request (pr-comment.yaml) + +This workflow is triggered if the `docker_pr_receive.yaml` workflow is successful. +The steps in this workflow are: + +1. Test if the workflow is valid and comment the validity of the workflow to the pull request. +2. If it is valid: create an orphan branch with two commits: the current state of the repository and the proposed changes. +3. If it is valid: update the pull request comment with the summary of changes + +Importantly: if the pull request is invalid, the branch is not created so any malicious code is not published. + +From here, the maintainer can request changes from the author and eventually either merge or reject the PR. +When this happens, if the PR was valid, the preview branch needs to be deleted. + +### Send Close PR Signal (pr-close-signal.yaml) + +Triggered any time a pull request is closed. +This emits an artifact that is the pull request number for the next action. + +### Remove Pull Request Branch (pr-post-remove-branch.yaml) + +Triggered by `pr-close-signal.yaml`. +This removes the temporary branch associated with the pull request (if it was created). diff --git a/.github/workflows/check-ruleset.yaml b/.github/workflows/check-ruleset.yaml new file mode 100644 index 0000000..cde50ed --- /dev/null +++ b/.github/workflows/check-ruleset.yaml @@ -0,0 +1,31 @@ +# Copyright (c) 2025 - 2026 The University of Manchester +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: Check Repository Ruleset + +on: + push: + branches: + - main + pull_request: + +jobs: + check: + if: github.repository_owner == 'UoMResearchIT' + name: Check Ruleset + uses: UoMResearchIT/actions/.github/workflows/check-ruleset.yaml@main + with: + bot-id: ${{ vars.ORG_ACTIONS_BOT_APP_ID }} + secrets: + bot-key: ${{ secrets.ORG_ACTIONS_BOT_PRIVATE_KEY }} diff --git a/.github/workflows/license-copyright-add.yml b/.github/workflows/license-copyright-add.yml new file mode 100644 index 0000000..fa5bb74 --- /dev/null +++ b/.github/workflows/license-copyright-add.yml @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2024 University of Manchester +# +# SPDX-License-Identifier: apache-2.0 + +name: Add License and Copyright Headers +on: + pull_request + +jobs: + check: + permissions: + pull-requests: write + contents: write + uses: UoMResearchIT/actions/.github/workflows/apply-reuse.yml@main diff --git a/.github/workflows/naming-conventions.yml b/.github/workflows/naming-conventions.yml new file mode 100644 index 0000000..90fcc2e --- /dev/null +++ b/.github/workflows/naming-conventions.yml @@ -0,0 +1,35 @@ +name: Enforce Handbook Naming Conventions + +on: + create: + pull_request: + branches-ignore: + - 'dependabot/**' + +jobs: + check-repo-name-conventions: + runs-on: ubuntu-latest + + steps: + - name: Check repository name + run: | + REPO_NAME=${GITHUB_REPOSITORY##*/} + if [[ ! "$REPO_NAME" =~ ^([A-Z][A-Za-z0-9]*)(-[A-Z0-9][A-Za-z0-9]*)*$ ]]; then + echo "Repository name '$REPO_NAME' does not follow the naming convention established in the RSE Agile Method Handbook." + exit 1 + fi + + check-branch-name-conventions: + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Check branch name + run: | + if [[ ! "$GITHUB_HEAD_REF" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]]; then + echo "Branch name '$GITHUB_HEAD_REF' does not follow the naming convention established in the RSE Agile Method Handbook." + exit 1 + fi diff --git a/.github/workflows/pr-close-signal.yaml b/.github/workflows/pr-close-signal.yaml new file mode 100644 index 0000000..b1303c2 --- /dev/null +++ b/.github/workflows/pr-close-signal.yaml @@ -0,0 +1,22 @@ +name: "Bot: Send Close Pull Request Signal" + +on: + pull_request: + types: + [closed] + +jobs: + send-close-signal: + name: "Send closing signal" + runs-on: ubuntu-22.04 + if: ${{ github.event.action == 'closed' }} + steps: + - name: "Create PRtifact" + run: | + mkdir -p ./pr + printf ${{ github.event.number }} > ./pr/NUM + - name: Upload Diff + uses: actions/upload-artifact@v4 + with: + name: pr + path: ./pr diff --git a/.github/workflows/pr-comment.yaml b/.github/workflows/pr-comment.yaml new file mode 100644 index 0000000..f80d9d0 --- /dev/null +++ b/.github/workflows/pr-comment.yaml @@ -0,0 +1,184 @@ +name: "Bot: Comment on the Pull Request" + +# read-write repo token +# access to secrets +on: + workflow_run: + workflows: ["Receive Pull Request"] + types: + - completed + +concurrency: + group: pr-${{ github.event.workflow_run.pull_requests[0].number }} + cancel-in-progress: true + + +jobs: + # Pull requests are valid if: + # - they match the sha of the workflow run head commit + # - they are open + # - no .github files were committed + test-pr: + name: "Test if pull request is valid" + runs-on: ubuntu-22.04 + if: > + github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.conclusion == 'success' + outputs: + is_valid: ${{ steps.check-pr.outputs.VALID }} + payload: ${{ steps.check-pr.outputs.payload }} + number: ${{ steps.get-pr.outputs.NUM }} + msg: ${{ steps.check-pr.outputs.MSG }} + steps: + - name: 'Download PR artifact' + id: dl + uses: carpentries/actions/download-workflow-artifact@main + with: + run: ${{ github.event.workflow_run.id }} + name: 'pr' + + - name: "Get PR Number" + if: ${{ steps.dl.outputs.success == 'true' }} + id: get-pr + run: | + unzip pr.zip + echo "NUM=$(<./NR)" >> $GITHUB_OUTPUT + + - name: "Fail if PR number was not present" + id: bad-pr + if: ${{ steps.dl.outputs.success != 'true' }} + run: | + echo '::error::A pull request number was not recorded. The pull request that triggered this workflow is likely malicious.' + exit 1 + - name: "Get Invalid Hashes File" + id: hash + run: | + echo "json<> $GITHUB_OUTPUT + - name: "Check PR" + id: check-pr + if: ${{ steps.dl.outputs.success == 'true' }} + uses: carpentries/actions/check-valid-pr@main + with: + pr: ${{ steps.get-pr.outputs.NUM }} + sha: ${{ github.event.workflow_run.head_sha }} + headroom: 3 # if it's within the last three commits, we can keep going, because it's likely rapid-fire + invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} + fail_on_error: true + + # Create an orphan branch on this repository with two commits + # - the current HEAD of the md-outputs branch + # - the output from running the current HEAD of the pull request through + # the md generator + create-branch: + name: "Create Git Branch" + needs: test-pr + runs-on: ubuntu-22.04 + if: ${{ needs.test-pr.outputs.is_valid == 'true' }} + env: + NR: ${{ needs.test-pr.outputs.number }} + permissions: + contents: write + steps: + - name: 'Checkout md outputs' + uses: actions/checkout@v4 + with: + ref: md-outputs + path: built + fetch-depth: 1 + + - name: 'Download built markdown' + id: dl + uses: carpentries/actions/download-workflow-artifact@main + with: + run: ${{ github.event.workflow_run.id }} + name: 'built' + + - if: ${{ steps.dl.outputs.success == 'true' }} + run: unzip built.zip + + - name: "Create orphan and push" + if: ${{ steps.dl.outputs.success == 'true' }} + run: | + cd built/ + git config --local user.email "actions@github.com" + git config --local user.name "GitHub Actions" + CURR_HEAD=$(git rev-parse HEAD) + git checkout --orphan md-outputs-PR-${NR} + git add -A + git commit -m "source commit: ${CURR_HEAD}" + ls -A | grep -v '^.git$' | xargs -I _ rm -r '_' + cd .. + unzip -o -d built built.zip + cd built + git add -A + git commit --allow-empty -m "differences for PR #${NR}" + git push -u --force --set-upstream origin md-outputs-PR-${NR} + + # Comment on the Pull Request with a link to the branch and the diff + comment-pr: + name: "Comment on Pull Request" + needs: [test-pr, create-branch] + runs-on: ubuntu-22.04 + if: ${{ needs.test-pr.outputs.is_valid == 'true' }} + env: + NR: ${{ needs.test-pr.outputs.number }} + permissions: + pull-requests: write + steps: + - name: 'Download comment artifact' + id: dl + uses: carpentries/actions/download-workflow-artifact@main + with: + run: ${{ github.event.workflow_run.id }} + name: 'diff' + + - if: ${{ steps.dl.outputs.success == 'true' }} + run: unzip ${{ github.workspace }}/diff.zip + + - name: "Comment on PR" + id: comment-diff + if: ${{ steps.dl.outputs.success == 'true' }} + uses: carpentries/actions/comment-diff@main + with: + pr: ${{ env.NR }} + path: ${{ github.workspace }}/diff.md + + # Comment if the PR is open and matches the SHA, but the workflow files have + # changed + comment-changed-workflow: + name: "Comment if workflow files have changed" + needs: test-pr + runs-on: ubuntu-22.04 + if: ${{ always() && needs.test-pr.outputs.is_valid == 'false' }} + env: + NR: ${{ github.event.workflow_run.pull_requests[0].number }} + body: ${{ needs.test-pr.outputs.msg }} + permissions: + pull-requests: write + steps: + - name: 'Check for spoofing' + id: dl + uses: carpentries/actions/download-workflow-artifact@main + with: + run: ${{ github.event.workflow_run.id }} + name: 'built' + + - name: 'Alert if spoofed' + id: spoof + if: ${{ steps.dl.outputs.success == 'true' }} + run: | + echo 'body<> $GITHUB_ENV + echo '' >> $GITHUB_ENV + echo '## :x: DANGER :x:' >> $GITHUB_ENV + echo 'This pull request has modified workflows that created output. Close this now.' >> $GITHUB_ENV + echo '' >> $GITHUB_ENV + echo 'EOF' >> $GITHUB_ENV + + - name: "Comment on PR" + id: comment-diff + uses: carpentries/actions/comment-diff@main + with: + pr: ${{ env.NR }} + body: ${{ env.body }} diff --git a/.github/workflows/pr-post-remove-branch.yaml b/.github/workflows/pr-post-remove-branch.yaml new file mode 100644 index 0000000..9419e2b --- /dev/null +++ b/.github/workflows/pr-post-remove-branch.yaml @@ -0,0 +1,32 @@ +name: "Bot: Remove Temporary PR Branch" + +on: + workflow_run: + workflows: ["Bot: Send Close Pull Request Signal"] + types: + - completed + +jobs: + delete: + name: "Delete branch from Pull Request" + runs-on: ubuntu-22.04 + if: > + github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.conclusion == 'success' + permissions: + contents: write + steps: + - name: 'Download artifact' + uses: carpentries/actions/download-workflow-artifact@main + with: + run: ${{ github.event.workflow_run.id }} + name: pr + - name: "Get PR Number" + id: get-pr + run: | + unzip pr.zip + echo "NUM=$(<./NUM)" >> $GITHUB_OUTPUT + - name: 'Remove branch' + uses: carpentries/actions/remove-branch@main + with: + pr: ${{ steps.get-pr.outputs.NUM }} diff --git a/.github/workflows/pr-preflight.yaml b/.github/workflows/pr-preflight.yaml new file mode 100644 index 0000000..34ad7ae --- /dev/null +++ b/.github/workflows/pr-preflight.yaml @@ -0,0 +1,39 @@ +name: "Pull Request Preflight Check" + +on: + pull_request_target: + branches: + ["main"] + types: + ["opened", "synchronize", "reopened"] + +jobs: + test-pr: + name: "Test if pull request is valid" + if: ${{ github.event.action != 'closed' }} + runs-on: ubuntu-22.04 + outputs: + is_valid: ${{ steps.check-pr.outputs.VALID }} + permissions: + pull-requests: write + steps: + - name: "Get Invalid Hashes File" + id: hash + run: | + echo "json<> $GITHUB_OUTPUT + - name: "Check PR" + id: check-pr + uses: carpentries/actions/check-valid-pr@main + with: + pr: ${{ github.event.number }} + invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} + fail_on_error: true + - name: "Comment result of validation" + id: comment-diff + if: ${{ always() }} + uses: carpentries/actions/comment-diff@main + with: + pr: ${{ github.event.number }} + body: ${{ steps.check-pr.outputs.MSG }} diff --git a/.github/workflows/pr-receive.yaml b/.github/workflows/pr-receive.yaml new file mode 100644 index 0000000..7fbff6c --- /dev/null +++ b/.github/workflows/pr-receive.yaml @@ -0,0 +1,132 @@ +name: "Receive Pull Request" + +on: + pull_request: + types: + [opened, synchronize, reopened] + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +jobs: + test-pr: + name: "Record PR number" + if: ${{ github.event.action != 'closed' }} + runs-on: ubuntu-22.04 + outputs: + is_valid: ${{ steps.check-pr.outputs.VALID }} + steps: + - name: "Record PR number" + id: record + if: ${{ always() }} + run: | + echo ${{ github.event.number }} > ${{ github.workspace }}/NR # 2022-03-02: artifact name fixed to be NR + - name: "Upload PR number" + id: upload + if: ${{ always() }} + uses: actions/upload-artifact@v4 + with: + name: pr + path: ${{ github.workspace }}/NR + - name: "Get Invalid Hashes File" + id: hash + run: | + echo "json<> $GITHUB_OUTPUT + - name: "echo output" + run: | + echo "${{ steps.hash.outputs.json }}" + - name: "Check PR" + id: check-pr + uses: carpentries/actions/check-valid-pr@main + with: + pr: ${{ github.event.number }} + invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} + + build-md-source: + name: "Build markdown source files if valid" + needs: test-pr + runs-on: ubuntu-22.04 + if: ${{ needs.test-pr.outputs.is_valid == 'true' }} + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + RENV_PATHS_ROOT: ~/.local/share/renv/ + CHIVE: ${{ github.workspace }}/site/chive + PR: ${{ github.workspace }}/site/pr + MD: ${{ github.workspace }}/site/built + steps: + - name: "Check Out Main Branch" + uses: actions/checkout@v4 + + - name: "Check Out Staging Branch" + uses: actions/checkout@v4 + with: + ref: md-outputs + path: ${{ env.MD }} + + - name: "Set up R" + uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + install-r: false + + - name: "Set up Pandoc" + uses: r-lib/actions/setup-pandoc@v2 + + - name: "Setup Lesson Engine" + uses: carpentries/actions/setup-sandpaper@main + with: + cache-version: ${{ secrets.CACHE_VERSION }} + + - name: "Setup Package Cache" + uses: carpentries/actions/setup-lesson-deps@main + with: + cache-version: ${{ secrets.CACHE_VERSION }} + + - name: "Validate and Build Markdown" + id: build-site + run: | + sandpaper::package_cache_trigger(TRUE) + sandpaper::validate_lesson(path = '${{ github.workspace }}') + sandpaper:::build_markdown(path = '${{ github.workspace }}', quiet = FALSE) + shell: Rscript {0} + + - name: "Generate Artifacts" + id: generate-artifacts + run: | + sandpaper:::ci_bundle_pr_artifacts( + repo = '${{ github.repository }}', + pr_number = '${{ github.event.number }}', + path_md = '${{ env.MD }}', + path_pr = '${{ env.PR }}', + path_archive = '${{ env.CHIVE }}', + branch = 'md-outputs' + ) + shell: Rscript {0} + + - name: "Upload PR" + uses: actions/upload-artifact@v4 + with: + name: pr + path: ${{ env.PR }} + overwrite: true + + - name: "Upload Diff" + uses: actions/upload-artifact@v4 + with: + name: diff + path: ${{ env.CHIVE }} + retention-days: 1 + + - name: "Upload Build" + uses: actions/upload-artifact@v4 + with: + name: built + path: ${{ env.MD }} + retention-days: 1 + + - name: "Teardown" + run: sandpaper::reset_site() + shell: Rscript {0} diff --git a/.github/workflows/sandpaper-main.yaml b/.github/workflows/sandpaper-main.yaml new file mode 100644 index 0000000..b3d1de8 --- /dev/null +++ b/.github/workflows/sandpaper-main.yaml @@ -0,0 +1,64 @@ +name: "01 Build and Deploy Site" + +on: + push: + branches: + - main + - master + schedule: + - cron: '0 0 * * 2' + workflow_dispatch: + inputs: + name: + description: 'Who triggered this build?' + required: true + default: 'Maintainer (via GitHub)' + reset: + description: 'Reset cached markdown files' + required: false + default: false + type: boolean +jobs: + full-build: + name: "Build Full Site" + + # 2024-10-01: ubuntu-latest is now 24.04 and R is not installed by default in the runner image + # pin to 22.04 for now + runs-on: ubuntu-22.04 + permissions: + checks: write + contents: write + pages: write + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + RENV_PATHS_ROOT: ~/.local/share/renv/ + steps: + + - name: "Checkout Lesson" + uses: actions/checkout@v4 + + - name: "Set up R" + uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + install-r: false + + - name: "Set up Pandoc" + uses: r-lib/actions/setup-pandoc@v2 + + - name: "Setup Lesson Engine" + uses: carpentries/actions/setup-sandpaper@main + with: + cache-version: ${{ secrets.CACHE_VERSION }} + + - name: "Setup Package Cache" + uses: carpentries/actions/setup-lesson-deps@main + with: + cache-version: ${{ secrets.CACHE_VERSION }} + + - name: "Deploy Site" + run: | + reset <- "${{ github.event.inputs.reset }}" == "true" + sandpaper::package_cache_trigger(TRUE) + sandpaper:::ci_deploy(reset = reset) + shell: Rscript {0} diff --git a/.github/workflows/update-cache.yaml b/.github/workflows/update-cache.yaml new file mode 100644 index 0000000..a011c0c --- /dev/null +++ b/.github/workflows/update-cache.yaml @@ -0,0 +1,125 @@ +name: "03 Maintain: Update Package Cache" + +on: + workflow_dispatch: + inputs: + name: + description: 'Who triggered this build (enter github username to tag yourself)?' + required: true + default: 'monthly run' + schedule: + # Run every tuesday + - cron: '0 0 * * 2' + +jobs: + preflight: + name: "Preflight Check" + runs-on: ubuntu-22.04 + outputs: + ok: ${{ steps.check.outputs.ok }} + steps: + - id: check + run: | + if [[ ${{ github.event_name }} == 'workflow_dispatch' ]]; then + echo "ok=true" >> $GITHUB_OUTPUT + echo "Running on request" + # using single brackets here to avoid 08 being interpreted as octal + # https://github.com/carpentries/sandpaper/issues/250 + elif [ `date +%d` -le 7 ]; then + # If the Tuesday lands in the first week of the month, run it + echo "ok=true" >> $GITHUB_OUTPUT + echo "Running on schedule" + else + echo "ok=false" >> $GITHUB_OUTPUT + echo "Not Running Today" + fi + + check_renv: + name: "Check if We Need {renv}" + runs-on: ubuntu-22.04 + needs: preflight + if: ${{ needs.preflight.outputs.ok == 'true'}} + outputs: + needed: ${{ steps.renv.outputs.exists }} + steps: + - name: "Checkout Lesson" + uses: actions/checkout@v4 + - id: renv + run: | + if [[ -d renv ]]; then + echo "exists=true" >> $GITHUB_OUTPUT + fi + + check_token: + name: "Check SANDPAPER_WORKFLOW token" + runs-on: ubuntu-22.04 + needs: check_renv + if: ${{ needs.check_renv.outputs.needed == 'true' }} + outputs: + workflow: ${{ steps.validate.outputs.wf }} + repo: ${{ steps.validate.outputs.repo }} + steps: + - name: "validate token" + id: validate + uses: carpentries/actions/check-valid-credentials@main + with: + token: ${{ secrets.SANDPAPER_WORKFLOW }} + + update_cache: + name: "Update Package Cache" + needs: check_token + if: ${{ needs.check_token.outputs.repo== 'true' }} + runs-on: ubuntu-22.04 + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + RENV_PATHS_ROOT: ~/.local/share/renv/ + steps: + + - name: "Checkout Lesson" + uses: actions/checkout@v4 + + - name: "Set up R" + uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + install-r: false + + - name: "Update {renv} deps and determine if a PR is needed" + id: update + uses: carpentries/actions/update-lockfile@main + with: + cache-version: ${{ secrets.CACHE_VERSION }} + + - name: Create Pull Request + id: cpr + if: ${{ steps.update.outputs.n > 0 }} + uses: carpentries/create-pull-request@main + with: + token: ${{ secrets.SANDPAPER_WORKFLOW }} + delete-branch: true + branch: "update/packages" + commit-message: "[actions] update ${{ steps.update.outputs.n }} packages" + title: "Update ${{ steps.update.outputs.n }} packages" + body: | + :robot: This is an automated build + + This will update ${{ steps.update.outputs.n }} packages in your lesson with the following versions: + + ``` + ${{ steps.update.outputs.report }} + ``` + + :stopwatch: In a few minutes, a comment will appear that will show you how the output has changed based on these updates. + + If you want to inspect these changes locally, you can use the following code to check out a new branch: + + ```bash + git fetch origin update/packages + git checkout update/packages + ``` + + - Auto-generated by [create-pull-request][1] on ${{ steps.update.outputs.date }} + + [1]: https://github.com/carpentries/create-pull-request/tree/main + labels: "type: package cache" + draft: false diff --git a/.github/workflows/update-workflows.yaml b/.github/workflows/update-workflows.yaml new file mode 100644 index 0000000..6414cf2 --- /dev/null +++ b/.github/workflows/update-workflows.yaml @@ -0,0 +1,66 @@ +name: "02 Maintain: Update Workflow Files" + +on: + workflow_dispatch: + inputs: + name: + description: 'Who triggered this build (enter github username to tag yourself)?' + required: true + default: 'weekly run' + clean: + description: 'Workflow files/file extensions to clean (no wildcards, enter "" for none)' + required: false + default: '.yaml' + schedule: + # Run every Tuesday + - cron: '0 0 * * 2' + +jobs: + check_token: + name: "Check SANDPAPER_WORKFLOW token" + runs-on: ubuntu-22.04 + outputs: + workflow: ${{ steps.validate.outputs.wf }} + repo: ${{ steps.validate.outputs.repo }} + steps: + - name: "validate token" + id: validate + uses: carpentries/actions/check-valid-credentials@main + with: + token: ${{ secrets.SANDPAPER_WORKFLOW }} + + update_workflow: + name: "Update Workflow" + runs-on: ubuntu-22.04 + needs: check_token + if: ${{ needs.check_token.outputs.workflow == 'true' }} + steps: + - name: "Checkout Repository" + uses: actions/checkout@v4 + + - name: Update Workflows + id: update + uses: carpentries/actions/update-workflows@main + with: + clean: ${{ github.event.inputs.clean }} + + - name: Create Pull Request + id: cpr + if: "${{ steps.update.outputs.new }}" + uses: carpentries/create-pull-request@main + with: + token: ${{ secrets.SANDPAPER_WORKFLOW }} + delete-branch: true + branch: "update/workflows" + commit-message: "[actions] update sandpaper workflow to version ${{ steps.update.outputs.new }}" + title: "Update Workflows to Version ${{ steps.update.outputs.new }}" + body: | + :robot: This is an automated build + + Update Workflows from sandpaper version ${{ steps.update.outputs.old }} -> ${{ steps.update.outputs.new }} + + - Auto-generated by [create-pull-request][1] on ${{ steps.update.outputs.date }} + + [1]: https://github.com/carpentries/create-pull-request/tree/main + labels: "type: template and tools" + draft: false diff --git a/.github/workflows/workflows-version.txt b/.github/workflows/workflows-version.txt new file mode 100644 index 0000000..570c796 --- /dev/null +++ b/.github/workflows/workflows-version.txt @@ -0,0 +1 @@ +v1.0.2