Skip to content

Mirror Artifacts

Mirror Artifacts #569

name: Mirror Artifacts
# Mirrors GitHub Releases, GHCR images, Flatpak bundles, and RPM packages
# from Interested-Deving-1896 to OSP and OOC mirror orgs.
#
# Runs:
# - Hourly at :00 (reconciliation — catches any missed releases)
# - On workflow_dispatch with optional repo/tag inputs
on:
schedule:
- cron: "10 * * * *" # Hourly at :10 — offset from mirror-releases (:00)
workflow_dispatch:
inputs:
upstream_repo:
description: "Specific repo to mirror (leave blank for all)"
required: false
default: ""
release_tag:
description: "Specific release tag to mirror (leave blank for all)"
required: false
default: ""
dry_run:
description: "Dry run — skip uploads and pushes"
type: boolean
required: false
default: false
force:
description: "Force re-mirror even if tag already exists at destination"
type: boolean
required: false
default: false
permissions:
contents: read
packages: write # needed for GHCR push
# ── Rate limits ──────────────────────────────────────────────────────────────
# GitHub REST API (SYNC_TOKEN): 5 000 req/hr primary limit.
# Sub-scripts (mirror-releases.sh, mirror-ghcr.sh, etc.) retry HTTP 403/429
# up to 3 times with X-RateLimit-Reset sleep.
# GHCR (ghcr.io): Docker push/pull rate limits apply per authenticated user.
# mirror-ghcr.sh retries HTTP 403/429 on the GitHub packages API.
# Docker daemon push errors are not retried — re-run the workflow manually.
# PyPI: no rate limit on uploads; trusted publishing (OIDC) is used.
# Flatpak/RPM repos: no API rate limits — written to gh-pages via git push.
concurrency:
group: mirror-artifacts
cancel-in-progress: false
jobs:
mirror:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install dependencies
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq createrepo-c flatpak ostree jq
- name: Mirror artifacts
env:
GH_TOKEN: ${{ secrets.SYNC_TOKEN }}
UPSTREAM_OWNER: Interested-Deving-1896
OSP_ORG: OpenOS-Project-OSP
OOC_ORG: OpenOS-Project-Ecosystem-OOC
UPSTREAM_REPO: ${{ inputs.upstream_repo }}
RELEASE_TAG: ${{ inputs.release_tag }}
DRY_RUN: ${{ inputs.dry_run || 'false' }}
FORCE: ${{ inputs.force || 'false' }}
run: |
if [[ -z "${GH_TOKEN}" ]]; then
echo "SYNC_TOKEN not configured — skipping."
exit 0
fi
bash scripts/mirror-artifacts.sh
- name: Write summary
if: always()
env:
JOB_STATUS: ${{ job.status }}
INPUTS_JSON: ${{ toJSON(inputs) }}
run: bash scripts/write-summary.sh