Skip to content
CI/CD Inventory

galaxyproject/training-material (opens in new tab)

23 workflows

Triggers

schedule workflow_dispatch

Jobs

Jobs for [Cron] Bluesky bot
Job Runs on Steps Actions used
rss-to-bluesky ubuntu-latest 3
actions/github-script@v8 actions/cache@v5 joschi/blueskyfeedbot@v1
Raw YAML
# This action will create a Bluesky post for every GTN news post (via RSS feed)

name: "[Cron] Bluesky bot"
on:
  schedule:
    # This will run every day at 14:00 UTC. Alter it using https://crontab.guru/.
    - cron: '0 14 * * *'
  workflow_dispatch: # This allows manually running the workflow from the GitHub actions page
concurrency:
  group: feedbot
jobs:
  rss-to-bluesky:
    if: (github.event_name == 'schedule' && github.repository == 'galaxyproject/training-material') || (github.event_name != 'schedule')
    runs-on: ubuntu-latest
    steps:
      - name: Generate cache key
        uses: actions/github-script@v8
        id: generate-key
        with:
          script: |
            core.setOutput('cache-key', new Date().valueOf())
      - name: Retrieve cache
        uses: actions/cache@v5
        with:
          path: ${{ github.workspace }}/blueskyfeedbot
          key: feed-cache-${{ steps.generate-key.outputs.cache-key }}
          restore-keys: feed-cache-
      - name: GitHub
        uses: 'joschi/blueskyfeedbot@v1'
        with:
          # This is the RSS feed you want to publish
          rss-feed: https://training.galaxyproject.org/training-material/feed.xml
          # Template of status posted to Bluesky (Handlebars)
          template: |
            {{item.title}}

            Read more at {{item.link}}

            @galaxyproject.bsky.social

          # This is your service URL (optional)
          service-url: https://bsky.social
          # This is the Bluesky username (example: username.bsky.social)
          username: galaxytraining.bsky.social
          # This is the app password you created earlier
          password: ${{ secrets.BLUESKY_TOKEN }}
          # This is a path to the cache file, using the above cache path
          cache-file: ${{ github.workspace }}/blueskyfeedbot/cache.json
          # The maximum number of posts created on the first run
          initial-post-limit: 2

Last fetched:

Triggers

pull_request

Jobs

Jobs for GTN Tutorial Linting
Job Runs on Steps Actions used
lint ubuntu-latest 9
actions/checkout@v6 reviewdog/action-setup@v1 actions/setup-python@v6 ruby/setup-ruby@v1 actions/cache@v5 actions/upload-artifact@v7
Raw YAML
name: "GTN Tutorial Linting"

concurrency:
  group: ci-tutsli-${{ github.head_ref }}
  cancel-in-progress: true

on:
  pull_request:
    paths:
      - 'Gemfile.lock'
      - 'topics/**'
      - '**/tutorial*.md'
      - '**/slides.html'
      - '**/slides/*.html'
      - 'learning-pathways/*'
      - 'faqs/**'
      - 'news/**'
      - 'events/**'
      - CONTRIBUTORS.yaml
      - GRANTS.yaml
      - ORGANISATIONS.yaml


jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 1000
          persist-credentials: false

      - uses: reviewdog/action-setup@v1
        with:
          reviewdog_version: latest

      # BEGIN Dependencies
      - uses: actions/setup-python@v6
        with:
          python-version: '3.11'
          architecture: 'x64'
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.2"
      - uses: actions/cache@v5
        with:
          path: |
            vendor/bundle
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}-
          restore-keys: |
            ${{ runner.os }}-gems-
      - name: Install dependencies
        run: |
          gem install bundler
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
          pip install pyyaml
          bundle pristine ffi
      # END Dependencies

      - name: Check Frontmatter
        run: |
          make check-diffs ACTIVATE_ENV=pwd
          make check-frontmatter ACTIVATE_ENV=pwd
          make check-contributors ACTIVATE_ENV=pwd
          python bin/mergeyaml.py --nondocker > /dev/null

      - name: Check Tutorial Formatting
        if: always()
        run: |
          mkdir -p ./pr

          echo "export CI_REPO_OWNER=galaxyproject" > pr/env.sh
          echo "export CI_REPO_NAME=training-material" >> pr/env.sh
          pr_num=$(echo "$GITHUB_REF_NAME" | sed 's|/.*||g')
          echo "export CI_PULL_REQUEST=${pr_num}" >> pr/env.sh
          echo "export CI_COMMIT=${{ github.event.pull_request.head.sha }}" >> pr/env.sh
          cat pr/env.sh

          find topics/ -name tutorial*.md | xargs -n 1 python bin/check-broken-boxes.py | reviewdog -efm="%f:%l: %m" -filter-mode=file -reporter=github-pr-review  -fail-level=error  | tee ./pr/reviewdog.txt
          set -o pipefail
          bundle exec ruby bin/lint.rb --format rdjson | reviewdog -filter-mode=file -f=rdjsonl -reporter=github-pr-review -fail-level=error | tee ./pr/reviewdog.json
        env:
            REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}


      - uses: actions/upload-artifact@v7
        if: always()
        with:
          name: reviewdog
          path: pr/


      # - name: rubocop
      #   uses: reviewdog/action-rubocop@v2
      #   with:
      #     rubocop_version: gemfile
      #     reporter: github-pr-review
      #     rubocop_flags: --except Layout/LineLength,Lint/RedundantCopDisableDirective
      #     fail_on_error: true

Last fetched:

Triggers

pull_request

Jobs

Jobs for [CI] GTN Build Testing
Job Runs on Steps Actions used
build-site ubuntu-latest 14
actions/checkout@v6 actions/setup-python@v6 ruby/setup-ruby@v1 actions/cache@v5
Raw YAML
name: "[CI] GTN Build Testing"

concurrency:
  group: ci-${{ github.head_ref }}
  cancel-in-progress: true

# https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#example-using-a-list-of-events
on:
  pull_request:
    types: [opened, reopened, synchronize, ready_for_review]

jobs:
  build-site:
    runs-on: ubuntu-latest
    if: github.event_name != 'pull_request' || !github.event.pull_request.draft
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 1
          persist-credentials: false

      # BEGIN Dependencies
      - uses: actions/setup-python@v6
        with:
          python-version: '3.11'
          architecture: 'x64'
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.2"
      - uses: actions/cache@v5
        with:
          path: |
            vendor/bundle
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}-
          restore-keys: |
            ${{ runner.os }}-gems-
      - name: Install dependencies
        run: |
          gem install bundler
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
          bundle pristine ffi
      # END Dependencies

      - name: Ensure that the site builds
        run: bundle exec jekyll build --strict_front_matter -d _site/training-material --trace --future

      - name: Validate all links, enforce alt text
        run: |
          bundle exec htmlproofer \
            --ignore-urls "/.*localhost.*/","/.*vimeo\.com.*/","/.*gitter\.im.*/","/.*drmaa\.org.*/","/.*slides.html#.*/,/#embedded_jbrowse/","/.*videos.*.mp4.png/","/krona_(all|multisample).html/","/workflows\/trs_import/","/api/","/by-tool/" \
            --ignore-files "/.*krona.*\.html/","/.*\/files\/.*/","/.*\/node_modules\/.*/","/\/tutorials\/.*\/docker\//","/.*content.html/","/.*recentrifuge.*\.html/","/short/","/test-data/" \
            --swap-urls "github.com/galaxyproject/training-material/tree/main:github.com/${GITHUB_REPOSITORY}/tree/${GITHUB_HEAD_REF}" \
            --disable-external \
            --no-enforce-https \
            ./_site

      - name: Ensure no unexpected encoded HTML in output, ask a GTN contributor for help with this one.
        run: |
          ! fgrep -R 'lt;blockquote' _site

      - name: Ensure no poorly rendered FAQs, generally this is fixed by removing whitespace/blank lines from the frontmatter
        run: |
          ! fgrep -R -A2 -B2 'box_type:' _site/

      - name: Ensure no poorly indented code blocks
        run: |
          bundle exec ruby bin/check-indent.rb

      - name: Ensure no unexpected jekyll in output. If this fails, generally it means you should add a page.description to the front matter.
        run: |
          ! fgrep -R 'site.pages' _site

      - name: Validate notebooks (If this fails, ask @hexylena to look at your notebook)
        run: |
          find _site | grep ipynb | xargs bundle exec ruby bin/check-valid-notebook.rb

      - name: Check URL persistence
        run: |
          bash bin/check-url-persistence.sh
      - name: Check File Sizes
        run: |
          bash bin/check-file-sizes.sh

Last fetched:

Triggers

workflow_dispatch schedule

Jobs

Jobs for [Cron] Update Commit Cache, PR Data
Job Runs on Steps Actions used
runner-job ubuntu-latest 8
actions/checkout@v6 ruby/setup-ruby@v1 actions/cache@v5 peter-evans/create-pull-request@v8
Raw YAML
name: "[Cron] Update Commit Cache, PR Data"
on:
  workflow_dispatch:
  schedule:
    - cron: '45 0 * * 1'
jobs:
  runner-job:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    # Only run on main repo on and PRs that match the main repo.
    if: |
      github.repository == 'galaxyproject/training-material' &&
      (github.event_name != 'pull_request' ||
       github.event.pull_request.head.repo.full_name == github.repository)
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 1000
          persist-credentials: false

      # BEGIN Dependencies
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.2"
      - uses: actions/cache@v5
        with:
          path: |
            vendor/bundle
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
          restore-keys: |
            ${{ runner.os }}-gems-
      - name: Install dependencies
        run: |
          gem install bundler
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
          bundle pristine ffi
      # END Dependencies

      - name: Update commit cache
        id: generate
        run: |
          # Check if the oldest commit of the commit cache is known in this history
          last_cached_commit=$(ls metadata/git-mod-*.txt | cut -d- -f 3 | cut -d. -f 1)
          git show $last_cached_commit
          ec=$?
          if (( ec != 0 )); then
            # Worst case, we need to fetch more. just fetch everything to be safe.
            git fetch --unshallow
          fi

          bundle exec ruby bin/commit-cache-update.rb

      - name: Update geocoding of events
        id: geocode
        run: |
          bundle exec ruby bin/geocode.rb

      - name: Update github metadata dataset
        id: ghmeta
        run: |
          bundle exec ruby bin/collect-gh.rb
        env:
          GH_TOKEN: ${{ github.token }}

      - name: Create Pull Request
        # If it's not a Pull Request then commit any changes as a new PR.
        uses: peter-evans/create-pull-request@v8
        with:
          title: Update Cached Commit Data
          branch-suffix: timestamp
          commit-message: Update Cached Commit Data
          add-paths: metadata/,events/
          author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
          committer: github-actions[bot] <github-actions[bot]@users.noreply.github.com>


Last fetched:

Triggers

push schedule

Jobs

Jobs for Deploy Website
Job Runs on Steps Actions used
deploy ubuntu-latest 11
actions/checkout@v6 actions/setup-python@v6 ruby/setup-ruby@v1 actions/setup-node@v6 actions/cache@v5 peaceiris/actions-gh-pages@v4
Raw YAML
name: Deploy Website

concurrency:
  group: deploy-${{ github.head_ref }}
  cancel-in-progress: false # Not sure about this.

on:
  push:
    branches:
      - main
  schedule:
    # nightly builds to keep in sync with changes to the video library
    - cron:  '0 0 * * *'


jobs:
  deploy:
    runs-on: ubuntu-latest
    if: github.repository_owner == 'galaxyproject'
    steps:
      - uses: actions/checkout@v6
        with:
          # Avg commits between successive monday:
          #  Min.   :  2.0
          #  1st Qu.: 25.0
          #  Median : 54.5
          #  Mean   : 65.2
          #  3rd Qu.: 94.0
          #  Max.   :282.0
          fetch-depth: 400
          persist-credentials: false

      # BEGIN Dependencies
      - uses: actions/setup-python@v6
        with:
          python-version: '3.11'
          architecture: 'x64'
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.2"
      - uses: actions/setup-node@v6
        with:
          node-version: '19'
      - uses: actions/cache@v5
        with:
          path: |
            vendor/bundle
            ~/.npm
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}-node-
            ${{ runner.os }}-gems-
      - name: Install dependencies
        run: |
          sudo apt-get install -y build-essential libxi-dev libglu1-mesa-dev libglew-dev pkg-config graphviz # for node
          gem install bundler
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
          rm -f package.json package-lock.json yarn.lock
          npm install markdown-yaml-metadata-parser lunr
          bundle pristine ffi
      # END Dependencies

      - name: Prepare Site Metadata
        run: |
          gem install bundler
          python -m pip install --upgrade pip
          pip install requests ephemeris
          export PATH=/home/runner/.local/bin:$PATH
          make annotate ACTIVATE_ENV=pwd
          curl -L https://docs.google.com/spreadsheets/d/1NfZhi5Jav7kl9zFCkeb7rIC2F8xW1isruv1TeO4WpNI/export\?format\=tsv | ruby bin/prepare_feedback.rb
          curl -L https://hexylena.github.io/toolshed-version-database/tool-meta.json > metadata/tool-meta.json
          curl -L https://edamontology.org/EDAM.csv > metadata/EDAM.csv
          make rebuild-search-index ACTIVATE_ENV=pwd
          bundle exec rdoc bin _plugins/ --output gtn_rdoc --template rorvswild

      - name: Build Site
        run: |
          JEKYLL_ENV=production bundle exec jekyll build --strict_front_matter -d _site/training-material
        env:
          GTN_FORK: ${{ github.repository_owner }}

      - name: Add jupyter notebooks
        run: |
          # Remove our existing directory which was a placeholder
          rm -rf _site/training-material/jupyter/

          # Collect all notebooks into a tmp dir
          mkdir /tmp/notebook/
          ruby bin/filter-pyolite-safe | xargs -I{} -n1 cp '{}' /tmp/notebook

          # Build the notebook site and add to deployment.
          pip install jupyterlab~=3.5.1 jupyterlite==0.1.0b18 jupyterlite-xeus-sqlite==0.2.1
          jupyter lite build --contents /tmp/notebook
          mv _output _site/training-material/jupyter/

      - name: Mandatory pre-deploy checks
        run: |
          bundle exec ruby bin/lint-deploy.rb

      - name: Deploy 🚀
        uses: peaceiris/actions-gh-pages@v4
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./_site/training-material/
          publish_branch: gh-pages

Last fetched:

Triggers

workflow_dispatch pull_request push

Jobs

Jobs for [CI] GIT-GAT
Job Runs on Steps Actions used
run ubuntu-latest 10
actions/checkout@v6 actions/setup-python@v6 shimataro/ssh-key-action@v2
Raw YAML
name: "[CI] GIT-GAT"

on:
  workflow_dispatch:
  pull_request:
    paths:
      - 'topics/admin/**'
      - 'bin/knit*'
  push:
    branches:
      - main
    paths:
      - 'topics/admin/**'
      - 'bin/knit*'

jobs:
  run:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 1
          persist-credentials: false
      - uses: actions/setup-python@v6
        with:
          python-version: '3.11'
          architecture: 'x64'

      - name: Export commits
        run: |
            bin/knit-automated.sh export;

      - name: Install SSH key
        uses: shimataro/ssh-key-action@v2
        with:
          key: ${{ secrets.GIT_GAT_SSH_KEY }}
          known_hosts: "github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ=="
          if_key_exists: ignore # replace / ignore / fail; optional (defaults to fail)
        if: github.event.pull_request.head.repo.full_name == 'galaxyproject/training-material' && github.event.pull_request.base.repo.full_name == 'galaxyproject/training-material'

      - name: Setup the repo
        run: |
            cd /tmp/git-gat/
            git config --global init.defaultBranch main
            git init
            git config user.email "galaxytrainingnetwork@gmail.com"
            git config user.name "The Galaxy Training Network"

      - name: Setup the origin (fork)
        run: |
            cd /tmp/git-gat/
            git remote add origin https://github.com/hexylena/git-gat
        if: github.event.pull_request.head.repo.full_name != 'galaxyproject/training-material' || github.event.pull_request.base.repo.full_name != 'galaxyproject/training-material'

      - name: Setup the origin (branch)
        run: |
            cd /tmp/git-gat/
            git remote add origin git@github.com:hexylena/git-gat
        if: github.event.pull_request.head.repo.full_name == 'galaxyproject/training-material' && github.event.pull_request.base.repo.full_name == 'galaxyproject/training-material'

      - name: Add scripts directory
        run: |
            cd /tmp/git-gat/
            git fetch origin --tags
            git add .scripts/
            git commit -m "admin/init/0000: Add scripts directory"
            git am 0-commit-0000-root-commit.patch
            ls -al

      - name: Commit the rounds of patches
        run: |
            cd /tmp/git-gat/
            for i in {10..50}; do
                # Commit those patches
                patches=$(ls $i-*.patch 2>/dev/null| wc -c)
                if (( patches > 0 )); then
                    git am -3 -C2 $i-*.patch;

                    # And tag it
                    git tag -f "step-$(( i - 9 ))";
                fi
            done
            rm -f *.patch
            ls -al

      - name: Push the results
        run: |
            cd /tmp/git-gat/
            # Push the results
            git push -f -u origin main
            today=$(date -I)
            git checkout -b $today
            git push -f --set-upstream origin $today
            git push -f --tags
        if: github.event.pull_request.head.repo.full_name == 'galaxyproject/training-material' && github.event.pull_request.base.repo.full_name == 'galaxyproject/training-material'
        # TODO: figure out the logic aroudn checking branch name.
        # && github.ref == 'refs/heads/main'

Last fetched:

Triggers

workflow_dispatch schedule

Jobs

Jobs for [Cron] Update Events from Google Form
Job Runs on Steps Actions used
runner-job ubuntu-latest 6
actions/checkout@v6 ruby/setup-ruby@v1 actions/cache@v5 peter-evans/create-pull-request@v8
Raw YAML
name: "[Cron] Update Events from Google Form"
on:
  workflow_dispatch:
  schedule:
    - cron: '0 9 * * 1-5'
jobs:
  runner-job:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    # Only run on main repo on and PRs that match the main repo.
    if: |
      github.repository == 'galaxyproject/training-material' &&
      (github.event_name != 'pull_request' ||
       github.event.pull_request.head.repo.full_name == github.repository)
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 1
          persist-credentials: false

      # BEGIN Dependencies
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.2"
      - uses: actions/cache@v5
        with:
          path: |
            vendor/bundle
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
          restore-keys: |
            ${{ runner.os }}-gems-
      - name: Install dependencies
        run: |
          gem install bundler
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
          bundle pristine ffi
      # END Dependencies

      - name: Update events from Google Form
        id: generate
        run: |
          bundle exec ruby bin/google-form-event.rb >> $GITHUB_OUTPUT

      - name: Create Pull Request for Events
        # If it's not a Pull Request then commit any changes as a new PR.
        if: |
          github.event_name != 'pull_request' &&
          steps.generate.outputs.new_ids != '0'
        uses: peter-evans/create-pull-request@v8
        with:
          commit-message: Import events from Google Form
          title: "[Google Form] New Event!"
          add-paths: events/
          branch: google-form/event
          author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
          committer: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
          body: |
             ${{steps.generate.outputs.pr_message}}

Last fetched:

Triggers

workflow_dispatch schedule

Jobs

Jobs for [Cron] Update FAQs from Google Form
Job Runs on Steps Actions used
runner-job ubuntu-latest 6
actions/checkout@v6 ruby/setup-ruby@v1 actions/cache@v5 peter-evans/create-pull-request@v8
Raw YAML
name: "[Cron] Update FAQs from Google Form"
on:
  workflow_dispatch:
  schedule:
    - cron: '0 9 * * 1-5'
jobs:
  runner-job:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    # Only run on main repo on and PRs that match the main repo.
    if: |
      github.repository == 'galaxyproject/training-material' &&
      (github.event_name != 'pull_request' ||
       github.event.pull_request.head.repo.full_name == github.repository)
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 1
          persist-credentials: false

      # BEGIN Dependencies
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.2"
      - uses: actions/cache@v5
        with:
          path: |
            vendor/bundle
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
          restore-keys: |
            ${{ runner.os }}-gems-
      - name: Install dependencies
        run: |
          gem install bundler
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
          bundle pristine ffi
      # END Dependencies

      - name: Update FAQs from Google Form
        id: generate
        run: |
          echo "new_ids=$(bundle exec ruby bin/google-form-faq.rb)" >> $GITHUB_OUTPUT

      - name: Create Pull Request for FAQs
        # If it's not a Pull Request then commit any changes as a new PR.
        if: |
          github.event_name != 'pull_request' &&
          steps.generate.outputs.new_ids != '0'
        uses: peter-evans/create-pull-request@v8
        with:
          commit-message: Import FAQs from Google Form
          title: "[Google Form] New FAQ!"
          branch: google-form/faq
          add-paths: faqs/
          author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
          committer: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

Last fetched:

Triggers

workflow_dispatch schedule

Jobs

Jobs for [Cron] Update news from Google Form
Job Runs on Steps Actions used
runner-job ubuntu-latest 6
actions/checkout@v6 ruby/setup-ruby@v1 actions/cache@v5 peter-evans/create-pull-request@v8
Raw YAML
name: "[Cron] Update news from Google Form"
on:
  workflow_dispatch:
  schedule:
    - cron: '21 10 * * *'
jobs:
  runner-job:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    # Only run on main repo on and PRs that match the main repo.
    if: |
      github.repository == 'galaxyproject/training-material' &&
      (github.event_name != 'pull_request' ||
       github.event.pull_request.head.repo.full_name == github.repository)
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 1
          persist-credentials: false

      # BEGIN Dependencies
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.2"
      - uses: actions/cache@v5
        with:
          path: |
            vendor/bundle
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
          restore-keys: |
            ${{ runner.os }}-gems-
      - name: Install dependencies
        run: |
          gem install bundler
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
          bundle pristine ffi
      # END Dependencies

      - name: Update news from Google Form
        id: generate
        run: |
          echo "new_ids=$(bundle exec ruby bin/google-form-news.rb)" >> $GITHUB_OUTPUT

      - name: Create Pull Request for News
        # If it's not a Pull Request then commit any changes as a new PR.
        if: |
          github.event_name != 'pull_request' &&
          steps.generate.outputs.new_ids != '0'
        uses: peter-evans/create-pull-request@v8
        with:
          commit-message: Import news posts from Google Form
          title: "[Google Form] New News Post!"
          branch: google-form/news
          add-paths: news/_posts/

Last fetched:

Triggers

workflow_dispatch schedule

Jobs

Jobs for [Cron] Update recordings from Google Form
Job Runs on Steps Actions used
runner-job ubuntu-latest 6
actions/checkout@v6 ruby/setup-ruby@v1 actions/cache@v5 peter-evans/create-pull-request@v8
Raw YAML
name: "[Cron] Update recordings from Google Form"
on:
  workflow_dispatch:
  schedule:
    - cron: '42 10 * * *'
jobs:
  runner-job:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    # Only run on main repo on and PRs that match the main repo.
    if: |
      github.repository == 'galaxyproject/training-material' &&
      (github.event_name != 'pull_request' ||
       github.event.pull_request.head.repo.full_name == github.repository)
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 1
          persist-credentials: false

      # BEGIN Dependencies
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.2"
      - uses: actions/cache@v5
        with:
          path: |
            vendor/bundle
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
          restore-keys: |
            ${{ runner.os }}-gems-
      - name: Install dependencies
        run: |
          gem install bundler
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
          bundle pristine ffi
      # END Dependencies

      - name: Update recordings from Google Form
        id: recordings
        run: |
           echo "new_recordings=$(bundle exec ruby bin/google-form-recordings.rb)" >> $GITHUB_OUTPUT

      - name: Create Pull Request for Recordings
        # If it's not a Pull Request then commit any changes as a new PR.
        if: |
          github.event_name != 'pull_request' &&
          steps.recordings.outputs.new_recordings == 'true'
        uses: peter-evans/create-pull-request@v8
        with:
          title: "[Google Form] New Recording Submission!"
          commit-message: add new recording from Google Form submission
          add-paths: topics/
          author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
          committer: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
          branch: google-form/recordings
          branch-suffix: timestamp
          body: |
            New recording submitted!

            **Submission Process checklist**
            - [x] **Instructor:** Record video
            - [x] **Instructor:** Submit video via form
            - [x] **GTN:** Pull request made by bot
            - [ ] **GTN:** Check [Submissions Spreadsheet](https://docs.google.com/spreadsheets/d/1iXjLlMEH5QMAMyUMHi1c_Lb7OiJhL_9hgJrtAsBoZ-Y/edit?usp=sharing)
              - [ ] Mark the 'PR made?' column as 'yes' in the spreadsheet
              - [ ] Ping speakers on this PR
              - [ ] Add any new contributors to `CONTRIBUTORS.yaml` file
            - [ ] **GTN:** Upload video to [GalaxyProject YouTube](https://www.youtube.com/c/galaxyproject)
              - [ ] **GTN:** Add YouTube video id to PR after upload
            - [ ] **GTN:** Put Autogenerated captions in Google Doc ([folder](https://drive.google.com/drive/folders/1liyqDQDbxMNXvpQIaqFmoE2fB2aJIH9N?usp=drive_link))
              - [ ] **GTN:** Check that permissions on the Doc are set to "Everybody with the link can edit"
            - [ ] **Instructor:** Fix autogenerated captions, comment here when done
            - [ ] **GTN:** Upload fixed captions to YouTube
            - [ ] **GTN:** Add the people who did the captioning to this PR
            - [ ] **GTN:** Merge PR!


Last fetched:

Triggers

pull_request_target

Jobs

Jobs for [CI] Pull Request Labeler
Job Runs on Steps Actions used
triage ubuntu-latest 1
actions/labeler@v6
Raw YAML
name: "[CI] Pull Request Labeler"
on:
- pull_request_target

jobs:
  triage:
    permissions:
      contents: read
      pull-requests: write
    runs-on: ubuntu-latest
    steps:
    - uses: actions/labeler@v6
      with:
        repo-token: "${{ secrets.GITHUB_TOKEN }}"
        sync-labels: true

Last fetched:

Triggers

schedule workflow_dispatch

Jobs

Jobs for [Cron] Send news to Matrix
Job Runs on Steps Actions used
runner-job ubuntu-latest 5
actions/checkout@v6 ruby/setup-ruby@v1 actions/cache@v5
Raw YAML
name: "[Cron] Send news to Matrix"

on:
  schedule:
    # * is a special character in YAML so you have to quote this string
    # We'll run this daily at noon.
    - cron:  '0 12 * * *'
  workflow_dispatch:

jobs:
  runner-job:
    if: github.repository_owner == 'galaxyproject'
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 200
          persist-credentials: false

      # BEGIN Dependencies
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.2"
      - uses: actions/cache@v5
        with:
          path: |
            vendor/bundle
            ~/.npm
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}-node-
            ${{ runner.os }}-gems-
      - name: Install dependencies
        run: |
          gem install bundler
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
          bundle pristine ffi
      # END Dependencies

      - name: Send announcements to matrix
        run: |
            commit=$(git log --since "24 hours ago" --format=%H --first-parent main| tail -n 1)
            bundle exec ruby bin/news.rb -p "${commit}~1" --matrix-post
        env:
            MATRIX_ACCESS_TOKEN: ${{ secrets.matrix_access_token }}

Last fetched:

Triggers

workflow_dispatch

Jobs

Jobs for [Archive] Backfill
Job Runs on Steps Actions used
setup ubuntu-latest 10
jlumbroso/free-disk-space@main actions/checkout@v6 actions/setup-python@v6 ruby/setup-ruby@v1 actions/setup-node@v6 actions/cache@v5 aws-actions/configure-aws-credentials@v6
Raw YAML
name: "[Archive] Backfill"

on:
  workflow_dispatch:
    inputs:
      selected_tag:
        type: string
        description: Target tag, this tag MUST ALREADY EXIST.
        required: true

jobs:
  setup:
    if: github.repository_owner == 'galaxyproject'
    runs-on: ubuntu-latest
    steps:
      - uses: jlumbroso/free-disk-space@main
        with:
          # all of these default to true, but feel free to set to
          # "false" if necessary for your workflow
          android: true
          dotnet: true
          haskell: true
          large-packages: false
          docker-images: false
          swap-storage: false

      - uses: actions/checkout@v6
        with:
          ref: "${{ github.event.inputs.selected_tag }}"
          fetch-depth: 0
          fetch-tags: true
          persist-credentials: false

      # BEGIN Dependencies
      - uses: actions/setup-python@v6
        with:
          python-version: '3.11'
          architecture: 'x64'
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.2"
      - uses: actions/setup-node@v6
        with:
          node-version: '19'
      - uses: actions/cache@v5
        with:
          path: |
            vendor/bundle
            ~/.cache/pip
            ~/.npm
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}-node-
            ${{ runner.os }}-gems-
      - name: Install dependencies
        run: |
          sudo apt-get install -y build-essential libxi-dev libglu1-mesa-dev libglew-dev pkg-config # for node
          gem install bundler
          pip install pyyaml
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
          rm -f package.json package-lock.json yarn.lock
          npm install markdown-yaml-metadata-parser lunr
          bundle pristine ffi
      # END Dependencies

      - name: Configure AWS credentials from GTN account
        uses: aws-actions/configure-aws-credentials@v6
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-east-1

      - name: Build Site
        run: |
          git tag -l
          git checkout ${SOURCE_TAG}
          gem install bundler
          bundle config path vendor/bundle
          sed -i s"|^baseurl: .*|baseurl: '/archive/${SOURCE_TAG}'|g" _config.yml
          sed -i s"|^github_repository_branch: .*|github_repository_branch: '${SOURCE_TAG}'|g" _config.yml
          sed -i s"|^title: .*|title: 'GTN Archive ${SOURCE_TAG}'|g" _config.yml
          curl -L https://hexylena.github.io/toolshed-version-database/tool-meta.json > metadata/tool-meta.json
          curl -L https://edamontology.org/EDAM.csv > metadata/EDAM.csv
          curl -L https://docs.google.com/spreadsheets/d/1NfZhi5Jav7kl9zFCkeb7rIC2F8xW1isruv1TeO4WpNI/export\?format\=tsv | ruby bin/prepare_feedback.rb
          make rebuild-search-index ACTIVATE_ENV=pwd
          JEKYLL_ENV=production bundle exec jekyll build --strict_front_matter -d _site/training-material
        env:
          SOURCE_TAG: ${{ github.event.inputs.selected_tag }}
          GTN_FORK: ${{ github.repository_owner }}

      - name: Deploy 🚀
        run: |
          pip install awscli
          ./bin/publish-archive
        env:
          SOURCE_TAG: ${{ github.event.inputs.selected_tag }}

Last fetched:

Triggers

schedule workflow_dispatch

Jobs

Jobs for [Archive] Monthly Release
Job Runs on Steps Actions used
setup ubuntu-latest 12
actions/checkout@v6 actions/setup-python@v6 ruby/setup-ruby@v1 actions/setup-node@v6 actions/cache@v5 aws-actions/configure-aws-credentials@v6
Raw YAML
name: "[Archive] Monthly Release"

on:
  schedule:
    # * is a special character in YAML so you have to quote this string
    - cron:  '0 4 1 * *'
  workflow_dispatch:

jobs:
  setup:
    if: github.repository_owner == 'galaxyproject'
    runs-on: ubuntu-latest

    # This is only needed for the final step of gh release creation.
    # That should be separated into a separate dependent job at some point.
    permissions:
      contents: write

    steps:
      - name: Release Name
        id: release_name
        run: |
          echo "release_title=$(LC_ALL=C date '+%Y %B %d')" >> $GITHUB_ENV
          echo "release_tag=$(LC_ALL=C date -I)" >> $GITHUB_ENV

      - uses: actions/checkout@v6
        with:
          # Based on logic in deploy.yml
          fetch-depth: 1200
          fetch-tags: true
          persist-credentials: false

      # BEGIN Dependencies
      - uses: actions/setup-python@v6
        with:
          python-version: '3.11'
          architecture: 'x64'
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.2"
      - uses: actions/setup-node@v6
        with:
          node-version: '19'
      - uses: actions/cache@v5
        with:
          path: |
            vendor/bundle
            ~/.cache/pip
            ~/.npm
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}-node-
            ${{ runner.os }}-gems-
      - name: Install dependencies
        run: |
          sudo apt-get install -y build-essential libxi-dev libglu1-mesa-dev libglew-dev pkg-config pandoc # for node, release notes
          gem install bundler
          pip install pyyaml
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
          rm -f package.json package-lock.json yarn.lock
          npm install markdown-yaml-metadata-parser lunr
          bundle pristine ffi
      # END Dependencies

      - name: List Tags
        run: |
          git tag -l

      - name: Build Site
        run: |
          gem install bundler
          bundle config path vendor/bundle
          sed -i s"|^baseurl: .*|baseurl: '/archive/${SOURCE_TAG}'|g" _config.yml
          sed -i s"|^github_repository_branch: .*|github_repository_branch: '${SOURCE_TAG}'|g" _config.yml
          sed -i s"|^title: .*|title: 'GTN Archive ${SOURCE_TAG}'|g" _config.yml
          curl -L https://hexylena.github.io/toolshed-version-database/tool-meta.json > metadata/tool-meta.json
          curl -L https://edamontology.org/EDAM.csv > metadata/EDAM.csv
          curl -L https://docs.google.com/spreadsheets/d/1NfZhi5Jav7kl9zFCkeb7rIC2F8xW1isruv1TeO4WpNI/export\?format\=tsv | ruby bin/prepare_feedback.rb
          make rebuild-search-index ACTIVATE_ENV=pwd
          JEKYLL_ENV=production bundle exec jekyll build --strict_front_matter -d _site/training-material
        env:
          SOURCE_TAG: ${{ env.release_tag }}
          GTN_FORK: ${{ github.repository_owner }}

      - name: Configure AWS credentials from GTN account
        uses: aws-actions/configure-aws-credentials@v6
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-east-1

      - name: Deploy 🚀
        run: |
          pip install awscli
          ./bin/publish-archive
        env:
          SOURCE_TAG: ${{ env.release_tag }}

      - name: Create Release
        id: create_release
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          RELEASE_TAG: ${{ env.release_tag }}
          RELEASE_TITLE: ${{ env.release_title }}
        run: |
          # Compile release notes
          echo "Monthly release of the GTN materials is now [available on the archive](https://training.galaxyproject.org/archive/$RELEASE_TAG/)." > /tmp/last-month-on.md
          echo >> /tmp/last-month-on.md
          bundle exec ruby bin/last-month-on.rb | pandoc --wrap none -t markdown -f html >> /tmp/last-month-on.md
          # Create the release
          gh release create "$RELEASE_TAG" --title "Release $RELEASE_TITLE" --notes-file /tmp/last-month-on.md  --target main --latest

Last fetched:

Triggers

workflow_dispatch schedule

Jobs

Jobs for [Cron] Compress images
Job Runs on Steps Actions used
calibreapp/image-actions ubuntu-latest 3
actions/checkout@v6 calibreapp/image-actions@main peter-evans/create-pull-request@v8
Raw YAML
# This Action will run in the following scenarios:
# - on Pull Requests containing images (not including forks)
# - on pushing of images to `master` (for forks)
# - on demand (https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/)
# - at 11 PM every Sunday if anything gets missed with any of the above scenarios
# For Pull Requests, the images are added to the PR.
# For other scenarios, a new PR will be opened if any images are compressed.
name: "[Cron] Compress images"
on:
  workflow_dispatch:
  schedule:
    - cron: '00 23 * * 0'
jobs:
  build:
    name: calibreapp/image-actions
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    # Only run on main repo on and PRs that match the main repo.
    if: |
      github.repository == 'galaxyproject/training-material' &&
      (github.event_name != 'pull_request' ||
       github.event.pull_request.head.repo.full_name == github.repository)
    steps:
      - name: Checkout Branch
        uses: actions/checkout@v6
        with:
          persist-credentials: false

      - name: Compress Images
        id: calibre
        uses: calibreapp/image-actions@main
        with:
          githubToken: ${{ secrets.GITHUB_TOKEN }}
          # For non-Pull Requests, run in compressOnly mode and we'll PR after.
          ##compressOnly: ${{ github.event_name != 'pull_request' }}
          minPctChange: '10'
      - name: Create Pull Request
        # If it's not a Pull Request then commit any changes as a new PR.
        if: |
          github.event_name != 'pull_request' &&
          steps.calibre.outputs.markdown != ''
        uses: peter-evans/create-pull-request@v8
        with:
          title: Auto Compress Images
          branch: action_compress_images
          commit-message: Compress Images
          author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
          committer: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
          body: ${{ steps.calibre.outputs.markdown }}
          draft: always-true

Last fetched:

Triggers

workflow_run

Jobs

Jobs for Review comments
Job Runs on Steps Actions used
comment ubuntu-latest 5
actions/checkout@v6 reviewdog/action-setup@v1 actions/github-script@v8
Raw YAML
name: "Review comments"

on:
  workflow_run:
    workflows: [GTN Tutorial Linting]
    types: [completed]

jobs:
  comment:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 1
          persist-credentials: false

      - uses: reviewdog/action-setup@v1
        with:
          reviewdog_version: latest

      - name: 'Download artifact'
        uses: actions/github-script@v8
        with:
          script: |
            let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
               owner: context.repo.owner,
               repo: context.repo.repo,
               run_id: context.payload.workflow_run.id,
            });
            let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
              return artifact.name == "reviewdog"
            })[0];
            let download = await github.rest.actions.downloadArtifact({
               owner: context.repo.owner,
               repo: context.repo.repo,
               artifact_id: matchArtifact.id,
               archive_format: 'zip',
            });
            const fs = require('fs');
            const path = require('path');
            const temp = '${{ runner.temp }}/artifacts';
            if (!fs.existsSync(temp)){
              fs.mkdirSync(temp);
            }
            fs.writeFileSync(path.join(temp, 'reviewdog.zip'), Buffer.from(download.data));

      - name: 'Unzip artifact'
        run:  unzip "${{ runner.temp }}/artifacts/reviewdog.zip"

      - name: Add review comments
        run: |
          . env.sh
          env | grep CI_ | sort
          # We are overriding the logic within reviewdog, to trick it into thinking it's running outside
          # https://github.com/reviewdog/reviewdog/issues/706
          unset GITHUB_EVENT_PATH
          unset GITHUB_ACTIONS
          env | grep GITHUB_ | grep -v TOKEN | sort

          cat reviewdog.txt | reviewdog -efm="%f:%l: %m" -reporter=github-pr-review -log-level debug -tee -filter-mode nofilter -name 'GTN Lint'

          cat reviewdog.json | reviewdog -reporter=github-pr-review -f=rdjsonl -log-level debug -tee -filter-mode nofilter -name 'GTN Lint'
        env:
            REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Last fetched:

[Cron] Send Single-cell Galaxy Help Topics to Matrix CoP Room

.github/workflows/scrna-galaxyhelp-matrix.yml (opens in new tab)
[Cron] Send Single-cell Galaxy Help Topics to Matrix CoP Room status

Triggers

schedule workflow_dispatch

Jobs

Jobs for [Cron] Send Single-cell Galaxy Help Topics to Matrix CoP Room
Job Runs on Steps Actions used
runner-job ubuntu-latest 2
Raw YAML
name: "[Cron] Send Single-cell Galaxy Help Topics to Matrix CoP Room"

on:
  schedule:
    # * is a special character in YAML so you have to quote this string
    # We'll run this every monday at noon
    - cron:  '0 12 * * 1'
  workflow_dispatch:

jobs:
  runner-job:
    if: github.repository_owner == 'galaxyproject'
    runs-on: ubuntu-latest

    steps:
      # BEGIN Dependencies
      - name: Install dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y coreutils curl libxml2-utils gawk sed grep jq wget
      # END Dependencies

      - name: Send announcements to single-cell matrix for unanswered posts
        run: |
            wget https://raw.githubusercontent.com/galaxyproject/training-material/main/bin/galaxy-help-news.sh
            HTML_TYPE="bullets" MAX_REPLIES="0" WANTED_TAGS="scrna scrna-seq" ROOM_ID='!TJRLNvfcbWbSRoUNpl:matrix.org' bash ./galaxy-help-news.sh
        env:
            MATRIX_ACCESS_TOKEN: ${{ secrets.matrix_access_token }}

Last fetched:

Triggers

workflow_dispatch schedule

Jobs

Jobs for [Cron] Update Shortlinks
Job Runs on Steps Actions used
runner-job ubuntu-latest 6
actions/checkout@v6 ruby/setup-ruby@v1 actions/cache@v5 peter-evans/create-pull-request@v8
Raw YAML

Last fetched:

[Social] Autogenerate missing social media cards

.github/workflows/social.yml (opens in new tab)
[Social] Autogenerate missing social media cards status

Triggers

schedule workflow_dispatch

Jobs

Jobs for [Social] Autogenerate missing social media cards
Job Runs on Steps Actions used
runner-job ubuntu-24.04 6
actions/checkout@v6 actions/setup-python@v6
Raw YAML
name: "[Social] Autogenerate missing social media cards"

on:
  schedule:
    # * is a special character in YAML so you have to quote this string
    # We'll run this weekly at noon.
    - cron: '0 12 * * 0'
  workflow_dispatch:
    inputs:
      all_old:
        type: string
        description: If you want to re-generate ALL images set to a non-empty value

jobs:
  runner-job:
    if: github.repository_owner == 'galaxyproject'
    runs-on: ubuntu-24.04
    steps:
      # Shallow should be fine for video
      - uses: actions/checkout@v6
        with:
          fetch-depth: 500
          persist-credentials: false

      # BEGIN Dependencies
      - uses: actions/setup-python@v6
        with:
          python-version: '3.11'
          architecture: 'x64'
      - name: Install dependencies
        run: |
          sudo apt-get install -y imagemagick optipng inkscape
          pip install requests awscli
          mkdir -p ~/.fonts/
          wget https://galaxy-training.s3.amazonaws.com/social/recursive.ttf -O ~/.fonts/recursive.ttf
          fc-cache -rv
      # END Dependencies


      # We get the previous build ID to know how many videos were changed since
      # then.
      #
      # We *could* fetch the diff in the past N days but if a build fails for
      # any reason, we'd lose those changes permanently and things would never
      # get built.
      #
      # So instead we just track the last successfully built timestamp
      - name: Previous build ID
        id: build_id
        run: |
          echo "timestamp=$(curl https://galaxy-training.s3.amazonaws.com/social/timestamp.txt -f 2>/dev/null || echo none)" >> $GITHUB_ENV

          # Support regenerating all
          if [[ "${{ github.event.inputs.all_old }}" != "" ]]; then
            echo "timestamp=0" >> $GITHUB_ENV
          fi

      # The actual compilation process deposits everything in the ./social/ folder.
      # And requires fetching metadata from the live website (api/social-meta.json)
      - name: Build Social Media Cards
        run: |
          mkdir -p social/
          python bin/social-cards.py $PREVIOUS_TIMESTAMP
        env:
          PREVIOUS_TIMESTAMP: ${{ env.timestamp }}

      # Deploy step, scary.
      - name: Build Social Media Cards
        run: |
          aws s3 cp --recursive ../gtn-social/ s3://galaxy-training/social/
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_DEFAULT_REGION: us-east-1

Last fetched:

[Cron] Add missing data-library.yaml files

.github/workflows/update-libraries.yaml (opens in new tab)
[Cron] Add missing data-library.yaml files status

Triggers

workflow_dispatch schedule

Jobs

Jobs for [Cron] Add missing data-library.yaml files
Job Runs on Steps Actions used
runner-job ubuntu-latest 6
actions/checkout@v6 ruby/setup-ruby@v1 actions/cache@v5 peter-evans/create-pull-request@v8
Raw YAML
name: "[Cron] Add missing data-library.yaml files"
on:
  workflow_dispatch:
  schedule:
    - cron: '45 0 * * 3'
jobs:
  runner-job:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    # Only run on main repo on and PRs that match the main repo.
    if: |
      github.repository == 'galaxyproject/training-material' &&
      (github.event_name != 'pull_request' ||
       github.event.pull_request.head.repo.full_name == github.repository)
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 1
          persist-credentials: false

      # BEGIN Dependencies
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.2"
      - uses: actions/cache@v5
        with:
          path: |
            vendor/bundle
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
          restore-keys: |
            ${{ runner.os }}-gems-
      - name: Install dependencies
        run: |
          gem install bundler
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
          bundle pristine ffi
      # END Dependencies

      - name: Update data libraries
        id: generate
        run: |
          grep zenodo_link: -R topics -l | grep '.md$' | xargs -r -n 1 bundle exec ruby bin/update-data-library update --fragile

      - name: Create Pull Request
        # If it's not a Pull Request then commit any changes as a new PR.
        if: |
          github.event_name != 'pull_request'
        uses: peter-evans/create-pull-request@v8
        with:
          title: Add missing data-library.yaml files
          branch-suffix: timestamp
          commit-message: Adds data-library.yaml for tutorials
          add-paths: '**/data-library.yaml'
          author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
          committer: github-actions[bot] <github-actions[bot]@users.noreply.github.com>


Last fetched:

[Video] Dry-run of Video Generation

.github/workflows/video-dry.yml (opens in new tab)
[Video] Dry-run of Video Generation status

Triggers

pull_request

Jobs

Jobs for [Video] Dry-run of Video Generation
Job Runs on Steps Actions used
runner-job ubuntu-latest 8
actions/checkout@v6 actions/setup-python@v6 ruby/setup-ruby@v1 actions/setup-node@v6 actions/cache@v5
Raw YAML
name: "[Video] Dry-run of Video Generation"

on:
  pull_request:
    paths:
      - 'bin/ari*'
      - 'topics/*.html'

jobs:
  runner-job:
    if: github.repository_owner == 'galaxyproject'
    runs-on: ubuntu-latest
    #services:
      # Label used to access the service container
      # mozillatts:
      #   image: synesthesiam/mozillatts
      #   ports:
      #     - 5002:5002
    steps:
      # Shallow should be fine for video
      - uses: actions/checkout@v6
        with:
          fetch-depth: 1
          persist-credentials: false

      # BEGIN Dependencies
      - uses: actions/setup-python@v6
        with:
          python-version: '3.11'
          architecture: 'x64'
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.2"
      - uses: actions/setup-node@v6
        with:
          node-version: '19'
      - uses: actions/cache@v5
        with:
          path: |
            vendor/bundle
            ~/.npm
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}-node-
            ${{ runner.os }}-gems-
      - name: Install dependencies
        run: |
          sudo apt-get install -y build-essential libxi-dev libglu1-mesa-dev libglew-dev pkg-config # for node
          gem install bundler
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
          npm install
          bundle pristine ffi
      # END Dependencies
      #

      - name: Check that all slides extract presenter notes successfully
        run: |
          find topics -name 'slides.html' -or -name introduction.html -or -name 'slides_*ES.html' | \
             xargs ./bin/filter-resource-metadata video | \
             xargs bundle exec ruby ./bin/ari-extract-script.rb

      - name: Check software versions
        run: |
          FFMPEG_PATH=$(echo "const ffmpeg = require('ffmpeg-static');console.log(ffmpeg.split('/').slice(0, -1).join('/'));" | node -)
          echo "Located FFMPEG at $FFMPEG_PATH"
          export PATH="$FFMPEG_PATH:$PATH"

          echo "Software Versions"
          $FFMPEG_PATH/ffmpeg -version
          ./node_modules/.bin/editly --version

Last fetched:

[Video] Autogenerated and Deploy Videos

.github/workflows/video.yml (opens in new tab)
[Video] Autogenerated and Deploy Videos status

Triggers

schedule workflow_dispatch

Jobs

Jobs for [Video] Autogenerated and Deploy Videos
Job Runs on Steps Actions used
runner-job ubuntu-24.04 12
actions/checkout@v6 actions/setup-python@v6 ruby/setup-ruby@v1 actions/setup-node@v6 actions/cache@v5 jakejarvis/s3-sync-action@v0.5.1
Raw YAML
name: "[Video] Autogenerated and Deploy Videos"

on:
  schedule:
    # * is a special character in YAML so you have to quote this string
    # We'll run this daily at noon.
    - cron:  '0 12 * * *'
  workflow_dispatch:

jobs:
  runner-job:
    if: github.repository_owner == 'galaxyproject'
    runs-on: ubuntu-24.04
    services:
      # Label used to access the service container
      mozillatts:
        image: synesthesiam/mozillatts
        ports:
          - 5002:5002
    steps:
      # Shallow should be fine for video
      - uses: actions/checkout@v6
        with:
          fetch-depth: 5000
          persist-credentials: false

      # BEGIN Dependencies
      - uses: actions/setup-python@v6
        with:
          python-version: '3.11'
          architecture: 'x64'
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.2"
      - uses: actions/setup-node@v6
        with:
          node-version: '22'
      - uses: actions/cache@v5
        with:
          path: |
            vendor/bundle
            ~/.npm
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}-node-
            ${{ runner.os }}-gems-
      - name: Install dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y build-essential libxi-dev libglu1-mesa-dev libglew-dev pkg-config libpixman-1-dev libcairo2-dev libpango1.0-dev mesa-utils xvfb imagemagick # for node
          rm Gemfile.lock
          gem install bundler
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
          npm install
          npm install github:sailplan/editly #temporary fix, see https://github.com/mifi/editly/issues/286, once fixed, remove this and restore line to package.json:  "editly": "^0.14.0"
          bundle pristine ffi
      # END Dependencies

      - name: Install rendering stuff
        run: |
          sudo apt-get update
          sudo apt-get install -y xvfb libfontconfig ghostscript ffmpeg

      - name: Change ImageMagick policy to allow pdf->png conversion.
        run: |
          sudo rm /etc/ImageMagick-6/policy.xml

      - name: Build Site
        run: |
          gem install bundler
          JEKYLL_ENV=production bundle exec jekyll build --strict_front_matter -d _site/training-material

      # We get the previous build ID to know how many videos were changed since
      # then.
      #
      # We *could* fetch the diff in the past N days but if a build fails for
      # any reason, we'd lose those changes permanently and things would never
      # get built.
      #
      # So instead we just track the last successfully built git commit.
      - name: Previous build ID
        id: build_id
        run: |
          echo "commit=$(curl https://galaxy-training.s3.amazonaws.com/videos/topics/last-commit -f 2>/dev/null || echo none)" >> $GITHUB_ENV

      # The actual compilation process deposits everything in the ./videos/ folder.
      - name: Build Videos
        run: |
          # Override permissions on _site to allow docker access.
          chmod -R ugo+rwx _site
          # Then we can build the slides
          xvfb-run --auto-servernum --server-args="-screen 0 1920x1080x24" bundle exec bash bin/ari-make.sh
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_POLLY_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_POLLY_SECRET_ACCESS_KEY }}
          AWS_DEFAULT_REGION: us-east-1
          PREVIOUS_COMMIT_ID: ${{ env.commit }}

      # Deploy step, scary.
      - uses: jakejarvis/s3-sync-action@v0.5.1
        with:
          args: --acl public-read --follow-symlinks
        env:
          AWS_S3_BUCKET: galaxy-training
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          SOURCE_DIR: './videos/topics/'
          DEST_DIR: 'videos/topics/'

Last fetched:

[Cron] Upload workflows to WorkflowHub

.github/workflows/workflowhub.yml (opens in new tab)
[Cron] Upload workflows to WorkflowHub status

Triggers

schedule workflow_dispatch

Jobs

Jobs for [Cron] Upload workflows to WorkflowHub
Job Runs on Steps Actions used
runner-job ubuntu-latest 9
actions/checkout@v6 actions/setup-python@v6 ruby/setup-ruby@v1 actions/cache@v5 peter-evans/create-pull-request@v8
Raw YAML
name: "[Cron] Upload workflows to WorkflowHub"

concurrency:
  group: wfh-${{ github.head_ref }}
  cancel-in-progress: false # Not sure about this.

on:
  schedule:
    - cron:  '55 12 * * 1'
  workflow_dispatch:

jobs:
  runner-job:
    if: github.repository_owner == 'galaxyproject'
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write

    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 2000
          persist-credentials: false

      # BEGIN Dependencies
      - uses: actions/setup-python@v6
        with:
          python-version: '3.11'
          architecture: 'x64'
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.1"
      - uses: actions/cache@v5
        with:
          path: |
            vendor/bundle
            ~/.npm
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}-node-
            ${{ runner.os }}-gems-
      - name: Install dependencies
        run: |
          gem install bundler
          pip install pyyaml requests
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
          bundle pristine ffi
          sudo apt install -y graphviz
      # END Dependencies

      # Required to build the RO-Crates
      - name: Build Site
        run: |
          JEKYLL_ENV=production bundle exec jekyll build --strict_front_matter -d _site/training-material

      - name: Upload workflows
        run: |
          python bin/wfh-upload.py --prod
        env:
          WFH_TOKEN: ${{ secrets.PROD_WFH_TOKEN }}

      - name: Any changes?
        run: |
          git diff

      - name: Create Pull Request
        uses: peter-evans/create-pull-request@v8
        with:
          title: Update WorkflowHub IDs
          branch-suffix: timestamp
          commit-message: Update WorkflowHub IDs
          add-paths: metadata/
          author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
          committer: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

Last fetched: