Skip to content
Closed
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
174 changes: 174 additions & 0 deletions .github/workflows/sync-upstream-cli.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# Reusable workflow for syncing CLI reference YAML from upstream repositories.
#
# Upstream repos call this after generating their CLI reference YAML files.
# The workflow copies the YAML to data/cli/<folder>/ and opens a PR.
#
# Uses the same input names as validate-upstream.yml so upstream repos
# can share the generate step and swap validate/sync based on trigger.
#
# Auth: uses a GitHub App (docker-docs-sync) installed on docker/docs.
# The calling workflow mints a short-lived token and passes it as a secret.
# App credentials are stored as org secrets (DOCS_SYNC_APP_ID, DOCS_SYNC_APP_PRIVATE_KEY).
#
# Example caller (e.g., in docker/buildx .github/workflows/docs-release.yml):
#
# jobs:
# docs-yaml:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v5
# - run: make generate-yaml-docs
# - uses: actions/upload-artifact@v4
# with:
# name: cli-yaml
# path: docs/yaml/*.yaml
#
# # Mint a short-lived token from the GitHub App
# token:
# runs-on: ubuntu-latest
# outputs:
# token: ${{ steps.app.outputs.token }}
# steps:
# - uses: actions/create-github-app-token@v2
# id: app
# with:
# app-id: ${{ vars.DOCS_SYNC_APP_ID }}
# private-key: ${{ secrets.DOCS_SYNC_APP_PRIVATE_KEY }}
# owner: docker
# repositories: docs
#
# # On PR — validate that docs still build
# validate:
# needs: docs-yaml
# uses: docker/docs/.github/workflows/validate-upstream.yml@main
# with:
# module-name: docker/buildx
# data-files-id: cli-yaml
# data-files-folder: buildx
#
# # On release — sync to docker/docs
# sync:
# needs: [docs-yaml, token]
# uses: docker/docs/.github/workflows/sync-upstream-cli.yml@main
# with:
# data-files-id: cli-yaml
# data-files-folder: buildx
# version: ${{ github.ref_name }}
# secrets:
# token: ${{ needs.token.outputs.token }}

name: sync-upstream-cli

on:
workflow_call:
inputs:
data-files-folder:
description: "Subfolder under data/cli/ (e.g., buildx, compose, model). Same as validate-upstream."
required: true
type: string
data-files-id:
description: "Name of the uploaded artifact containing YAML reference files. Same as validate-upstream."
required: true
type: string
version:
description: "Version string for commit message and PR title (e.g., v0.33.0)"
required: true
type: string
secrets:
token:
description: "GitHub token with contents:write and pull-requests:write on docker/docs"
required: true

jobs:
sync:
runs-on: ubuntu-24.04
env:
BRANCH: "bot/sync-${{ inputs.data-files-folder }}-cli"
steps:
- name: Checkout docker/docs
uses: actions/checkout@v5
with:
repository: docker/docs
token: ${{ secrets.token }}
fetch-depth: 0

- name: Download data files
uses: actions/download-artifact@v4
with:
name: ${{ inputs.data-files-id }}
path: /tmp/cli-data

- name: Copy data files
run: |
mkdir -p "data/cli/${{ inputs.data-files-folder }}"
rm -f "data/cli/${{ inputs.data-files-folder }}"/*.yaml
cp /tmp/cli-data/*.yaml "data/cli/${{ inputs.data-files-folder }}/"

- name: Check for changes
id: diff
run: |
git add "data/cli/${{ inputs.data-files-folder }}/"
if git diff --cached --quiet; then
echo "changes=false" >> "$GITHUB_OUTPUT"
echo "No changes detected" >> "$GITHUB_STEP_SUMMARY"
else
echo "changes=true" >> "$GITHUB_OUTPUT"
echo '```' >> "$GITHUB_STEP_SUMMARY"
git diff --cached --stat >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
fi

- name: Commit and push
if: steps.diff.outputs.changes == 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git checkout -b "$BRANCH"
git commit -m "cli(${{ inputs.data-files-folder }}): sync docs ${{ inputs.version }}"
git push -u origin "$BRANCH" --force

- name: Create or update PR
if: steps.diff.outputs.changes == 'true'
env:
GH_TOKEN: ${{ secrets.token }}
run: |
TITLE="cli(${{ inputs.data-files-folder }}): sync docs ${{ inputs.version }}"

EXISTING=$(gh pr list --repo docker/docs --state open \
--head "$BRANCH" --json url --jq '.[0].url // empty')

if [ -n "$EXISTING" ]; then
echo "Updating existing PR: $EXISTING" >> "$GITHUB_STEP_SUMMARY"
gh pr edit "$EXISTING" --repo docker/docs \
--title "$TITLE" \
--body "$(cat <<EOF
## Summary

Automated sync of CLI reference docs.

| | |
|---|---|
| **Tool** | \`${{ inputs.data-files-folder }}\` |
| **Version** | \`${{ inputs.version }}\` |
| **Source** | ${{ github.repository }}@\`$(echo ${{ github.sha }} | head -c 12)\` |
EOF
)"
else
echo "Creating new PR" >> "$GITHUB_STEP_SUMMARY"
gh pr create --repo docker/docs \
--title "$TITLE" \
--base main \
--head "$BRANCH" \
--body "$(cat <<EOF
## Summary

Automated sync of CLI reference docs.

| | |
|---|---|
| **Tool** | \`${{ inputs.data-files-folder }}\` |
| **Version** | \`${{ inputs.version }}\` |
| **Source** | ${{ github.repository }}@\`$(echo ${{ github.sha }} | head -c 12)\` |
EOF
)"
fi