11 KiB
Weekly Missing Binaries Audit & Rebuild
Goal
A weekly CI workflow that identifies CRAN packages whose latest release version has no binary available, reports them in Forgejo issues grouped by OS family and arch, and rebuilds those that have no prior build failure recorded in the database.
Architecture Overview
Two independent workflow sets, each with one file per platform/arch combo (14 files each), plus a shared R script and an excluded-packages config file.
weekly-audit-missing-*-*.yaml (14 files)
│
▼
local/weekly-missing-binaries-audit.R
│
├── Updates Forgejo issues (3 issues, one per OS family)
└── Writes RDS files to /mnt/cache/packages/
weekly-rebuild-missing-*-*.yaml (14 files)
│
▼
Reads RDS, builds missing packages via bincraft::build_binary_package()
The audit and build workflows are fully independent. Either can be triggered on its own via cron or manually.
Platforms
All current platform/arch combinations:
| Platform | Arch | Image | Codename |
|---|---|---|---|
| ubuntu-2204 | amd64 | reg.devxy.io/rpkgs/build-env-ubuntu:jammy-4.4.3 | jammy |
| ubuntu-2204 | arm64 | reg.devxy.io/rpkgs/build-env-ubuntu:jammy-4.4.3 | jammy |
| ubuntu-2404 | amd64 | reg.devxy.io/rpkgs/build-env-ubuntu:noble-4.4.3 | noble |
| ubuntu-2404 | arm64 | reg.devxy.io/rpkgs/build-env-ubuntu:noble-4.4.3 | noble |
| alpine-321 | amd64 | reg.devxy.io/rpkgs/build-env-alpine:3.21-4.5 | alpine321 |
| alpine-321 | arm64 | reg.devxy.io/rpkgs/build-env-alpine:3.21-4.5 | alpine321 |
| alpine-322 | amd64 | reg.devxy.io/rpkgs/build-env-alpine:3.22-4.5 | alpine322 |
| alpine-322 | arm64 | reg.devxy.io/rpkgs/build-env-alpine:3.22-4.5 | alpine322 |
| alpine-323 | amd64 | reg.devxy.io/rpkgs/build-env-alpine:3.23-4.5 | alpine323 |
| alpine-323 | arm64 | reg.devxy.io/rpkgs/build-env-alpine:3.23-4.5 | alpine323 |
| redhat-8 | amd64 | reg.devxy.io/rpkgs/build-env-redhat:8-4.4.3 | rhel8 |
| redhat-8 | arm64 | reg.devxy.io/rpkgs/build-env-redhat:8-4.4.3 | rhel8 |
| redhat-9 | amd64 | reg.devxy.io/rpkgs/build-env-redhat:9-4.4.3 | rhel9 |
| redhat-9 | arm64 | reg.devxy.io/rpkgs/build-env-redhat:9-4.4.3 | rhel9 |
Component 1: Excluded Packages Config
File: local/excluded-packages.json
A JSON array of objects with package and reason fields:
[
{"package": "RInno", "reason": "windows-only"},
{"package": "KeyboardSimulator", "reason": "windows-only"},
{"package": "doBy", "reason": "hang"},
{"package": "frailtypack", "reason": "hang"},
...
]
This file is the single source of truth for packages that should be skipped. Both the audit script and rebuild workflows read from it.
The existing build-all-versions-*.yaml workflows retain their inline lists for now (migration is out of scope).
Component 2: Audit R Script
File: local/weekly-missing-binaries-audit.R
Environment variables consumed:
PLATFORM— e.g.ubuntu-2204,alpine-321,redhat-9ARCH—amd64orarm64B2_S3_ACCESS_KEY,B2_S3_SECRET_KEY— S3 credentialsPGPASS— PostgreSQL passwordFORGEJO_TOKEN— API token for issue updates
The workflow commands (not the R script) also use:
REPO_RO_TOKEN— forgit clonein the workflow commands
Logic:
- Parse
PLATFORMto derive OS family (Ubuntu,Alpine,Red Hat) and S3 codename (e.g.ubuntu-2204->jammy,redhat-9->rhel9). - Fetch CRAN release packages via
tools::CRAN_package_db()— extractPackageandVersion. - List S3 tarballs at
devxy-rpkgs-binaries/{arch}/{codename}/latest/src/contrib/and parse{name}_{version}.tar.gz. - Find packages where the CRAN release version is missing from S3.
- Read
local/excluded-packages.jsonand remove those packages from the missing list. - Query the
single_buildsDB table: for each missing package+version+platform+arch, check iferror_occurred = TRUE. Split into:- Rebuildable: missing, not excluded, no prior failure for this version
- Known failures: missing, not excluded, but has a recorded failure for this version
- Write the rebuildable package list (names only) to
/mnt/cache/packages/weekly_rebuild_{platform}_{arch}.rds. - Update the Forgejo issue for this OS family.
Issue update logic:
- Issue title:
Missing package binaries for latest version (<OS family>)where OS family isUbuntu,Alpine, orRed Hat. - Search for existing open issue via
GET /api/v1/repos/devxy/build-cran-binaries/issues?type=issues&state=open&q=<url-encoded title>. Match by exact title. - If found, read the existing body, replace the section for this platform/arch, and
PATCHthe issue. - If not found,
POSTa new issue with just this platform/arch section.
Issue body format:
_Last updated: 2026-04-11_
## ubuntu-2204
### amd64 (12 missing, 8 to rebuild)
- ggplot2 (3.5.2)
- dplyr (1.1.5)
- ...
#### Known build failures
- somepkg (1.0.0)
### arm64 (5 missing, 5 to rebuild)
- ...
## ubuntu-2404
### amd64 (3 missing, 3 to rebuild)
- ...
### arm64 (0 missing)
All binaries available.
---
## Excluded packages
doBy (hang), frailtypack (hang), RInno (windows-only), ...
Each audit workflow run updates only its own platform/arch section within the issue. The "Excluded packages" section and "Last updated" timestamp are rewritten on every run.
Section replacement strategy:
The script parses the existing issue body as markdown, finds the ## {platform} + ### {arch} section, replaces it, and writes back the full body.
If the section doesn't exist yet, it's appended under the correct ## {platform} header (or a new one is created).
Component 3: Audit Workflows
Files: 14 files, named weekly-audit-missing-{platform}-{arch}.yaml
Example: .crow/weekly-audit-missing-ubuntu-2204-amd64.yaml
Trigger:
when:
- event: cron
cron: weekly-audit-missing-ubuntu-2204-amd64
- event: manual
evaluate: 'task == "weekly-audit-missing-ubuntu-2204-amd64"'
Step: Lightweight — clones repo, installs bincraft + dependencies, runs the audit R script.
Container: Uses the platform-appropriate build image (needed for correct platform identification), but with minimal resource requests since no building happens.
Resources: ~2Gi memory, 2 CPUs.
Component 4: Rebuild Workflows
Files: 14 files, named weekly-rebuild-missing-{platform}-{arch}.yaml
Example: .crow/weekly-rebuild-missing-ubuntu-2204-amd64.yaml
Trigger:
when:
- event: cron
cron: weekly-rebuild-missing-ubuntu-2204-amd64
- event: manual
evaluate: 'task == "weekly-rebuild-missing-ubuntu-2204-amd64"'
Step:
- Clone repo, install bincraft.
- Read
local/excluded-packages.jsonas a safety net. - Read
/mnt/cache/packages/weekly_rebuild_{platform}_{arch}.rds. If missing or empty, exit 0. - Filter out excluded packages (double-check).
- Iterate and call
bincraft::build_binary_package()for each package withtag_limit = 1L. Same S3/DB parameters as existing build workflows. - Uses
xvfb-run/xwfb-runfor graphical packages (same pattern as existing builds).
Resources: Same as process-updates workflows — 5Gi request, 18Gi limit, 3 CPUs.
Cache volume: Maps ${ARCH}-binaries-r-dep-cache-${PLATFORM}:/mnt/cache (same volumes as existing builds, so the RDS files written by audit are visible).
Secrets Required
All existing secrets are reused:
B2_S3_ACCESS_KEY,B2_S3_SECRET_KEY— S3 accessPGPASS— PostgreSQLREPO_RO_TOKEN— Git cloneGITHUB_PAT— For bincraft GitHub mirror access
New secret needed:
FORGEJO_TOKEN— API token for creating/updating issues on git.devxy.io
Cron Schedule
The audit and rebuild workflows each get their own cron names. The cron schedule itself is configured in the Crow/Woodpecker server, not in the YAML. Intended cadence: once per week (e.g. Sunday morning).
File Inventory
| File | Type | Description |
|---|---|---|
local/excluded-packages.json |
Config | Excluded packages with reasons |
local/weekly-missing-binaries-audit.R |
R script | Audit logic, parameterized by env vars |
.crow/weekly-audit-missing-ubuntu-2204-amd64.yaml |
Workflow | Audit for ubuntu-2204/amd64 |
.crow/weekly-audit-missing-ubuntu-2204-arm64.yaml |
Workflow | Audit for ubuntu-2204/arm64 |
.crow/weekly-audit-missing-ubuntu-2404-amd64.yaml |
Workflow | Audit for ubuntu-2404/amd64 |
.crow/weekly-audit-missing-ubuntu-2404-arm64.yaml |
Workflow | Audit for ubuntu-2404/arm64 |
.crow/weekly-audit-missing-alpine-321-amd64.yaml |
Workflow | Audit for alpine-321/amd64 |
.crow/weekly-audit-missing-alpine-321-arm64.yaml |
Workflow | Audit for alpine-321/arm64 |
.crow/weekly-audit-missing-alpine-322-amd64.yaml |
Workflow | Audit for alpine-322/amd64 |
.crow/weekly-audit-missing-alpine-322-arm64.yaml |
Workflow | Audit for alpine-322/arm64 |
.crow/weekly-audit-missing-alpine-323-amd64.yaml |
Workflow | Audit for alpine-323/amd64 |
.crow/weekly-audit-missing-alpine-323-arm64.yaml |
Workflow | Audit for alpine-323/arm64 |
.crow/weekly-audit-missing-redhat-8-amd64.yaml |
Workflow | Audit for redhat-8/amd64 |
.crow/weekly-audit-missing-redhat-8-arm64.yaml |
Workflow | Audit for redhat-8/arm64 |
.crow/weekly-audit-missing-redhat-9-amd64.yaml |
Workflow | Audit for redhat-9/amd64 |
.crow/weekly-audit-missing-redhat-9-arm64.yaml |
Workflow | Audit for redhat-9/arm64 |
.crow/weekly-rebuild-missing-ubuntu-2204-amd64.yaml |
Workflow | Rebuild for ubuntu-2204/amd64 |
.crow/weekly-rebuild-missing-ubuntu-2204-arm64.yaml |
Workflow | Rebuild for ubuntu-2204/arm64 |
.crow/weekly-rebuild-missing-ubuntu-2404-amd64.yaml |
Workflow | Rebuild for ubuntu-2404/amd64 |
.crow/weekly-rebuild-missing-ubuntu-2404-arm64.yaml |
Workflow | Rebuild for ubuntu-2404/arm64 |
.crow/weekly-rebuild-missing-alpine-321-amd64.yaml |
Workflow | Rebuild for alpine-321/amd64 |
.crow/weekly-rebuild-missing-alpine-321-arm64.yaml |
Workflow | Rebuild for alpine-321/arm64 |
.crow/weekly-rebuild-missing-alpine-322-amd64.yaml |
Workflow | Rebuild for alpine-322/amd64 |
.crow/weekly-rebuild-missing-alpine-322-arm64.yaml |
Workflow | Rebuild for alpine-322/arm64 |
.crow/weekly-rebuild-missing-alpine-323-amd64.yaml |
Workflow | Rebuild for alpine-323/amd64 |
.crow/weekly-rebuild-missing-alpine-323-arm64.yaml |
Workflow | Rebuild for alpine-323/arm64 |
.crow/weekly-rebuild-missing-redhat-8-amd64.yaml |
Workflow | Rebuild for redhat-8/amd64 |
.crow/weekly-rebuild-missing-redhat-8-arm64.yaml |
Workflow | Rebuild for redhat-8/arm64 |
.crow/weekly-rebuild-missing-redhat-9-amd64.yaml |
Workflow | Rebuild for redhat-9/amd64 |
.crow/weekly-rebuild-missing-redhat-9-arm64.yaml |
Workflow | Rebuild for redhat-9/arm64 |
Total: 29 new files (1 JSON config + 1 R script + 14 audit workflows + 14 rebuild workflows + the design doc itself)