Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 1 addition & 133 deletions .claude/skills/update-biobase.md
Original file line number Diff line number Diff line change
@@ -1,135 +1,3 @@
# Update biobase manifest

Check all container images in the biobase manifest for newer tags and create a PR with updates.

## Process

### 1. Find the current manifest

Look for the latest versioned biobase manifest in `bulker/`:

```bash
ls bulker/biobase_*.yaml | sort -V | tail -1
```

Read this file to get the current commands and image tags.

### 2. Check each image for updates

For each command entry, query the container registry API to find the latest available tag.

**Skip these entries** (pinned or custom registries):
- `nsheff/pigz` — custom image, no registry API
- `databio/refgenie` — custom image, uses `latest` tag
- Any image using the `latest` tag

`quay.io/xujishu/cellranger` is NOT skipped: it is a normal quay.io repo and
answers the same tag API as the biocontainers images below. Tags older than
6.0.0 are stored as Docker v1 manifests, which apptainer cannot convert, so
never move this entry backwards below 6.0.0.

**For quay.io/biocontainers images:**

```bash
curl -s "https://quay.io/api/v1/repository/biocontainers/<tool>/tag/?limit=100&onlyActiveTags=true"
```

Parse the JSON response. Tags follow the pattern `<version>--<hash>_<build>`. To find the latest:
1. Filter out tags named `latest`
2. Pick the highest version prefix (the part before `--`)
3. Among tags at that version, pick the highest `_<build>`. A different hash at
a higher build is a rebuild, not a variant -- take it. The hash changes
*because* the package was rebuilt.
4. Never move to a lower version or build than the current pin

Some tools publish parallel `pyXXX` builds at the same version and build number.
Those are ties; take the highest `pyXXX`.

**For `quay.io/xujishu/cellranger`:**

```bash
curl -s "https://quay.io/api/v1/repository/xujishu/cellranger/tag/?limit=100&onlyActiveTags=true"
```

Tags here are plain semantic versions (`3.1.0`, `6.0.0`, `6.0.1`) — NOT the
biocontainers `<version>--<hash>_<build>` pattern. Sort by semantic version and
pick the highest. Ignore any tag below 6.0.0: those are Docker v1 manifests
(`application/vnd.docker.distribution.manifest.v1+prettyjws`) that apptainer
cannot convert, so selecting one silently breaks every apptainer-based consumer.

**For Docker Hub images** (broadinstitute/*, bioconductor/*):

```bash
curl -s "https://hub.docker.com/v2/repositories/<namespace>/<repo>/tags/?page_size=100&ordering=last_updated"
```

For `broadinstitute/gatk`: pick the latest tag matching `<major>.<minor>.<patch>.<build>` pattern (semantic version sort).
For `broadinstitute/picard`: pick the latest tag matching `<major>.<minor>.<patch>` pattern.
For `bioconductor/bioconductor_docker`: pick the latest `RELEASE_<major>_<minor>` tag (highest major, then highest minor).

**For UCSC tools** (quay.io/biocontainers/ucsc-*):

These all use version numbers like `482--h0b57e2e_0`. Check for updates using the same quay.io API as other biocontainers.

### 3. Compare and decide

For each image, compare the current tag with the latest available:
- If the latest tag is different and represents a newer version, mark it for update
- Log each comparison result (tool name, current tag, latest tag, update needed)
- Present a summary table before making changes

### 4. Create the updated manifest

If any updates are found:

1. **Determine the new version.** Bump the patch version of the current manifest (e.g., `0.1.0` -> `0.1.1`). Use minor bump only if tools are added or removed.

2. **Create the new manifest file.** Copy the current manifest to `bulker/biobase_<new_version>.yaml`. Update the `version:` field in the YAML. Replace updated image tags.

3. **Update the symlink** (if one exists): `ln -sf biobase_<new_version>.yaml bulker/biobase.yaml`

4. **Do NOT delete the old versioned manifest.** Keep it for reference.

### 5. Commit and open a PR

```bash
git checkout -b biobase-update-<new_version>
git add bulker/biobase_<new_version>.yaml bulker/biobase.yaml
git commit -m "Update biobase to <new_version>

Updated images:
- <tool1>: <old_tag> -> <new_tag>
- <tool2>: <old_tag> -> <new_tag>
..."
git push -u origin biobase-update-<new_version>
```

Open a PR with:
- Title: `Update biobase to <new_version>`
- Body: use this template. All three sections are required, even if empty.

```markdown
## Updated

| Tool | Old tag | New tag |
|---|---|---|

## Checked, no update needed

Every other image, with the tag you confirmed is current.

## Skipped

Each skipped image and the rule that skipped it.
```

### 6. If no updates found

If all images are already at their latest versions, do not create any files or PRs. Just report that everything is up to date.

## Important rules

- **Same providers, just new tags.** Never switch an image from one registry to another. Only update the tag.
- **Preserve all other fields.** Keep `docker_command`, `docker_args`, `description`, and any other fields exactly as they are.
- **Preserve YAML formatting.** Match the indentation and style of the existing manifest.
- **Be conservative.** If you can't determine which tag is newer, skip that entry.
Follow `automation/update-biobase.md` completely.
24 changes: 0 additions & 24 deletions .github/workflows/scheduled-biobase-update-jules.yml

This file was deleted.

11 changes: 6 additions & 5 deletions .github/workflows/scheduled-biobase-update.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
name: Scheduled biobase update
name: Manual biobase update with Claude

# Manual fallback. Recurring biobase updates are scheduled in Jules.
# The complete procedure lives in automation/update-biobase.md.
on:
schedule:
- cron: "0 0 3 * *" # Once a month
workflow_dispatch:

permissions:
Expand All @@ -16,13 +17,13 @@ jobs:
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
fetch-depth: 0

- name: Run Claude Code to update biobase
uses: anthropics/claude-code-action@v1
with:
prompt: |
Use the update-biobase skill to check all biobase container images for newer versions and create a PR if any updates are found.
Follow automation/update-biobase.md completely.
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
claude_args: '--allowedTools "Bash(*),Read(*),Write(*),Edit(*),Glob(*),Grep(*)"'
show_full_output: true
6 changes: 6 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Agent instructions

## Biobase update

For any task that checks or updates biobase container tags or manifests, read
and follow `automation/update-biobase.md` completely.
21 changes: 11 additions & 10 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ Run `python validate_manifests.py --check-tags` to validate manifests locally. T

## Automated biobase updates

A scheduled GitHub Actions workflow (`.github/workflows/scheduled-biobase-update.yml`) runs every Thursday at midnight UTC. It uses Claude Code with the `.claude/skills/update-biobase.md` skill to:
The complete biobase update procedure lives in
`automation/update-biobase.md`. Recurring runs are handled by a native Jules
Scheduled Task. `AGENTS.md` and `.claude/skills/update-biobase.md` are thin
pointers to that canonical procedure.

1. Check all biobase container images for newer tags via registry APIs (Quay.io, Docker Hub)
2. Create a new versioned manifest with updated tags (patch version bump)
3. Open a PR for human review

The workflow can also be triggered manually via `workflow_dispatch`. Some images are intentionally skipped (cellranger, pigz, refgenie) because they use custom registries or pinned versions.
`.github/workflows/scheduled-biobase-update.yml` is retained as a manual
`workflow_dispatch` fallback using Claude Code. There should be only one
recurring scheduler for this task.

## Automated refgenie crate updates

Expand All @@ -45,10 +46,10 @@ build host.
Its pins are **derived from `bulker/biobase`** rather than discovered
independently — see `update_refgenie_crate.py`, the reviewable source map
`refgenie_crate_sources.yaml`, and `.claude/skills/update-refgenie-crate.md`.
`.github/workflows/scheduled-refgenie-update.yml` runs it **quarterly** (not
weekly like biobase) and always opens a PR: refgenie names each asset after the
tool version that built it, so a pin bump renames published assets, forces a
rebuild and orphans S3 objects.
`.github/workflows/scheduled-refgenie-update.yml` runs it **quarterly** and
always opens a PR: refgenie names each asset after the tool version that built
it, so a pin bump renames published assets, forces a rebuild and orphans S3
objects.

The interesting part is the **sibling map**. biobase pins `hisat2` but not
`hisat2-build`, `bowtie2` but not `bowtie2-build`, `tabix` but not `bgzip`,
Expand Down
Loading