ppg:devel:19: switch pg_tde source to percona/pg_tde main, add build … #6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Sync to OBS (main) | |
| # Runs whenever a push to main touches any file under root/. | |
| # Syncs the full package tree to OBS (releases/ directories are excluded from | |
| # sync push traversal), then creates git tags from any release.yaml files | |
| # that changed since the last successful run to trigger obs-release.yml. | |
| # | |
| # Two-job debounce design: the `sync` job serializes on its own concurrency | |
| # group and is never cancelled mid-upload, so back-to-back pushes queue up | |
| # short sync runs instead of waiting behind a multi-hour build poll. The | |
| # `poll` job runs in a cancel-superseding group so a newer push's poll | |
| # replaces an older run's poll (the OBS badge, version lists and release | |
| # tags are derived from the last *successful* run's SHA, so whichever poll | |
| # survives covers the superseded runs' ranges too). | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - 'root/**' | |
| - '!root/README.md' | |
| workflow_dispatch: {} | |
| jobs: | |
| sync: | |
| name: percona-obs sync push | |
| runs-on: ubuntu-latest | |
| container: ghcr.io/${{ github.repository_owner }}/obs-tools:latest | |
| # Serialize syncs; never cancel a sync mid-upload. | |
| concurrency: | |
| group: sync-main-sync | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| packages: read | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| # Full history is required: sync push reads git log to detect | |
| # per-package changes since the last OBS sync commit SHA. | |
| fetch-depth: 0 | |
| token: ${{ secrets.GH_PAT }} | |
| # Packages synced before the migration to percona/obs-packaging carry | |
| # OBS sync comments whose SHAs come from the legacy repo's history and | |
| # do not resolve in this clone, which forces --skip-unchanged off the | |
| # cheap git gate into services + upload comparison for every such | |
| # package. Fetch the legacy history so those SHAs resolve; drop this | |
| # step once all packages have been re-synced with percona SHAs. | |
| - name: Fetch legacy repo history (pre-migration sync SHAs) | |
| run: | | |
| git fetch https://github.com/rjd15372/percona-obs-packaging.git \ | |
| 'refs/heads/*:refs/remotes/legacy/*' \ | |
| || echo "::warning::legacy repo unreachable; sync falls back to content checks" | |
| # Persists the content-addressed .cache/ tree across runs, split in | |
| # two entries: | |
| # | |
| # deps — download_url, cargo_vendor and Phase 2 manual-service | |
| # outputs (crates, go tarballs, vendor tarballs): small and | |
| # stable across commits. Also carries the sync_state | |
| # manifest used by --skip-unchanged. | |
| # scm — Phase 1 obs_scm outputs: multi-GB source archives keyed by | |
| # upstream HEAD, churning on every upstream advance. | |
| # | |
| # Splitting keeps the small, highly-reusable deps cache from being | |
| # evicted out of the repo's 10 GB Actions cache quota by churn in the | |
| # much larger scm tree. Without any cache, every main sync would | |
| # regenerate vendor tarballs with new file mtimes and needlessly | |
| # re-upload them. Entries are content-addressed so a partial hit via | |
| # restore-keys is always safe: unused SHA-keyed subdirs are ignored. | |
| - name: Restore percona-obs deps cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| .cache/download_url | |
| .cache/cargo_vendor | |
| .cache/services | |
| .cache/sync_state | |
| key: percona-obs-deps-${{ runner.os }}-${{ github.sha }} | |
| restore-keys: | | |
| percona-obs-deps-${{ runner.os }}- | |
| - name: Restore percona-obs scm cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: .cache/obs_scm | |
| key: percona-obs-scm-${{ runner.os }}-${{ github.sha }} | |
| restore-keys: | | |
| percona-obs-scm-${{ runner.os }}- | |
| - uses: ./.github/actions/obs-setup | |
| with: | |
| obs-apiurl: ${{ vars.OBS_APIURL }} | |
| obs-user: ${{ vars.OBS_USER }} | |
| obs-password: ${{ secrets.OBS_PASSWORD }} | |
| - name: Create percona-obs profile | |
| env: | |
| OBS_APIURL: ${{ vars.OBS_APIURL }} | |
| OBS_ROOTPRJ: ${{ vars.OBS_ROOTPRJ }} | |
| run: | | |
| venv/bin/python -m percona_obs \ | |
| -A "$OBS_APIURL" \ | |
| -R "$OBS_ROOTPRJ" \ | |
| -e "REMOTE_OBS_ORG_INTERCONNECT:" \ | |
| -e "PERCONA_OBS_PACKAGING_BRANCH:main" \ | |
| -e "PERCONA_OBS_PACKAGING_REPO:${{ github.server_url }}/${{ github.repository }}.git" \ | |
| profile create main | |
| # releases/ directories are excluded from sync push traversal (each | |
| # root/*/releases/<name>/ contains a release.yaml marker that prevents | |
| # find_projects/find_packages from descending), so release commits are | |
| # synced normally but produce no OBS changes. | |
| # The report JSON scopes the poll job to the packages this run touched; | |
| # remove any stale report first (self-hosted runners reuse /tmp). | |
| - name: Sync to OBS | |
| run: | | |
| rm -f /tmp/sync-report.json | |
| venv/bin/python -m percona_obs --verbose -P main sync push \ | |
| --no-scm-validate --skip-unchanged --report-json /tmp/sync-report.json | |
| # Drop cache entries not used by any run in the last 7 days so the | |
| # .cache/ tree saved by actions/cache stops growing monotonically. | |
| # Entry mtimes are bumped on every cache hit, so age == unused-for. | |
| # Runs even when the sync fails: pruning only removes stale entries. | |
| - name: Prune stale cache entries | |
| if: always() | |
| env: | |
| PYTHONPATH: ${{ github.workspace }} | |
| run: venv/bin/python .github/scripts/prune_obs_cache.py | |
| # Hand the report to the poll job. Only uploaded on success: poll | |
| # only runs after a successful sync, so an always() upload is not | |
| # needed. | |
| - name: Upload sync report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: sync-report | |
| path: /tmp/sync-report.json | |
| retention-days: 1 | |
| poll: | |
| name: Wait for OBS builds | |
| needs: sync | |
| runs-on: ubuntu-latest | |
| container: ghcr.io/${{ github.repository_owner }}/obs-tools:latest | |
| timeout-minutes: 360 | |
| # Newest poll wins: a newer push's poll supersedes (cancels) older polls. | |
| concurrency: | |
| group: sync-main-poll | |
| cancel-in-progress: true | |
| permissions: | |
| # Required to push the badge JSON to the badges branch. | |
| contents: write | |
| # Required to query sibling workflow runs (gh api .../actions/...). | |
| actions: read | |
| packages: read | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| # Full history is required to git-diff release.yaml files against | |
| # the last-successful base SHA; GH_PAT is required to push tags. | |
| fetch-depth: 0 | |
| token: ${{ secrets.GH_PAT }} | |
| - uses: ./.github/actions/obs-setup | |
| with: | |
| obs-apiurl: ${{ vars.OBS_APIURL }} | |
| obs-user: ${{ vars.OBS_USER }} | |
| obs-password: ${{ secrets.OBS_PASSWORD }} | |
| - name: Download sync report | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: sync-report | |
| path: /tmp | |
| # A superseded (cancelled) poll never runs the version-lists / release | |
| # -tags steps below, so the surviving run must cover the cancelled | |
| # runs' ranges too. Diffing from the head SHA of the last SUCCESSFUL | |
| # sync-main run does exactly that (and tag creation already tolerates | |
| # existing tags). Fall back to github.event.before (empty for | |
| # workflow_dispatch), then to the all-zeros SHA. | |
| - name: Compute last-successful base SHA | |
| id: base | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| LAST_GOOD=$(gh api \ | |
| "repos/$GITHUB_REPOSITORY/actions/workflows/sync-main.yml/runs?branch=main&status=success&per_page=1" \ | |
| --jq '.workflow_runs[0].head_sha // empty' || true) | |
| BASE="${LAST_GOOD:-${{ github.event.before }}}" | |
| BASE="${BASE:-0000000000000000000000000000000000000000}" | |
| echo "sha=${BASE}" >> "$GITHUB_OUTPUT" | |
| echo "Diff base: ${BASE}" | |
| # Poll OBS until all builds reach a terminal state. Fails the job if | |
| # any build fails, is broken, or is unresolvable. The sync report | |
| # scopes polling to the packages the sync job actually touched. | |
| - name: Poll OBS build status | |
| id: poll | |
| env: | |
| OBS_APIURL: ${{ vars.OBS_APIURL }} | |
| OBS_ROOTPRJ: ${{ vars.OBS_ROOTPRJ }} | |
| OBS_SYNC_REPORT: /tmp/sync-report.json | |
| PYTHONPATH: ${{ github.workspace }} | |
| run: venv/bin/python .github/scripts/poll_obs_builds.py | |
| # Update docs/versions/<dist>.md for each distribution project touched | |
| # since the last successful run, and refresh the README "## Development | |
| # Projects" section. Only runs when OBS builds all succeed. | |
| # Disabled: this step git-pushes regenerated docs/versions/*.md and | |
| # README.md directly to main, which is blocked once main is protected | |
| # against direct pushes. Re-enable (restore the poll-outcome guard) once | |
| # a PR-based or badges-branch publishing path is in place. | |
| - name: Update version lists | |
| if: false | |
| env: | |
| GITHUB_EVENT_BEFORE: ${{ steps.base.outputs.sha }} | |
| OBS_WEB_URL: ${{ vars.OBS_WEB_URL }} | |
| OBS_ROOTPRJ: ${{ vars.OBS_ROOTPRJ }} | |
| PYTHONPATH: ${{ github.workspace }} | |
| run: venv/bin/python .github/scripts/update_version_lists.py | |
| # After builds succeed, detect any release.yaml files changed since the | |
| # last successful run and create git tags from their latest releases: | |
| # entries. The tag (e.g. ppg/17.9-1) triggers obs-release.yml. | |
| - name: Create release tags | |
| if: steps.poll.outcome == 'success' | |
| env: | |
| GH_TOKEN: ${{ secrets.GH_PAT }} | |
| run: | | |
| CHANGED=$(git diff --name-only "${{ steps.base.outputs.sha }}" "$GITHUB_SHA" \ | |
| -- 'root/*/releases/*/release.yaml' 2>/dev/null || true) | |
| for release_file in $CHANGED; do | |
| [ -f "$release_file" ] || continue | |
| TAG=$(venv/bin/python3 -c \ | |
| "import yaml,sys; d=yaml.safe_load(open(sys.argv[1])); r=d.get('releases',[]); print(r[-1] if r else d.get('revision',''))" \ | |
| "$release_file" 2>/dev/null) | |
| [ -z "$TAG" ] && continue | |
| echo "Creating tag ${TAG} → $GITHUB_SHA" | |
| gh api "repos/$GITHUB_REPOSITORY/git/refs" \ | |
| -X POST \ | |
| -f "ref=refs/tags/${TAG}" \ | |
| -f "sha=$GITHUB_SHA" || echo "Tag ${TAG} already exists, skipping" | |
| done | |
| # Push the badge JSON to the orphan `badges` branch so it can be | |
| # embedded in README.md via a shields.io endpoint badge. | |
| # Runs even when the poll step fails so the badge always reflects the | |
| # latest build outcome. | |
| - name: Publish OBS build badge | |
| if: always() | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| [ -f /tmp/obs-build-badge.json ] || exit 0 | |
| BADGE=$(base64 -w0 /tmp/obs-build-badge.json) | |
| FILE_SHA=$(gh api \ | |
| "repos/$GITHUB_REPOSITORY/contents/obs-build-badge.json?ref=badges" \ | |
| --jq '.sha' 2>/dev/null || echo "") | |
| if [ -n "$FILE_SHA" ]; then | |
| gh api "repos/$GITHUB_REPOSITORY/contents/obs-build-badge.json" \ | |
| -X PUT \ | |
| -f message="ci: update OBS build badge" \ | |
| -f content="$BADGE" \ | |
| -f branch=badges \ | |
| -f sha="$FILE_SHA" | |
| else | |
| gh api "repos/$GITHUB_REPOSITORY/contents/obs-build-badge.json" \ | |
| -X PUT \ | |
| -f message="ci: update OBS build badge" \ | |
| -f content="$BADGE" \ | |
| -f branch=badges | |
| fi |