mirror of
https://github.com/ansible/awx.git
synced 2026-06-22 15:17:44 -02:30
fix: use GPG-signed commits in spec sync workflow
Switch from unsigned GitHub API commits to GPG-signed git commits
using the aap-api-bot GPG key (OPENAPI_SPEC_SYNC_GPG_PRIVATE_KEY).
The aap-openapi-specs repo requires signed commits via org ruleset.
The previous API-based approach didn't sign commits because GitHub
only auto-signs API commits for GitHub App tokens, not user PATs.
This matches the pattern used by EDA and Gateway teams for their
spec sync workflows.
Also fixes template injection risk by using env vars instead of
direct ${{ }} expansion in shell context.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
207 lines
7.5 KiB
YAML
207 lines
7.5 KiB
YAML
# Sync OpenAPI Spec on Merge
|
|
#
|
|
# This workflow runs when code is merged to the devel branch.
|
|
# It runs the dev environment to generate the OpenAPI spec, then syncs it to
|
|
# the central spec repository.
|
|
#
|
|
# FLOW: PR merged → push to branch → dev environment runs → spec synced to central repo
|
|
#
|
|
# NOTE: This is an inlined version for testing with private forks.
|
|
# Production version will use a reusable workflow from the org repos.
|
|
name: Sync OpenAPI Spec on Merge
|
|
env:
|
|
LC_ALL: "C.UTF-8"
|
|
DEV_DOCKER_OWNER: ${{ github.repository_owner }}
|
|
on:
|
|
push:
|
|
branches:
|
|
- devel
|
|
- 'stable-2.[6-9]'
|
|
- 'stable-2.[1-9][0-9]'
|
|
workflow_dispatch: # Allow manual triggering for testing
|
|
jobs:
|
|
sync-openapi-spec:
|
|
if: |
|
|
github.event_name == 'workflow_dispatch' ||
|
|
(github.repository == 'ansible/awx' && (github.ref_name == 'devel' || startsWith(github.ref_name, 'feature_'))) ||
|
|
(github.repository == 'ansible/tower' && (startsWith(github.ref_name, 'stable-') || startsWith(github.ref_name, 'release_')))
|
|
name: Sync OpenAPI spec to central repo
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
packages: write
|
|
contents: read
|
|
steps:
|
|
- name: Checkout Controller repository
|
|
uses: actions/checkout@v4
|
|
with:
|
|
show-progress: false
|
|
|
|
- name: Build awx_devel image to use for schema gen
|
|
uses: ./.github/actions/awx_devel_image
|
|
with:
|
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
private-github-key: ${{ secrets.PRIVATE_GITHUB_KEY }}
|
|
|
|
- name: Generate API Schema
|
|
env:
|
|
REF_NAME: ${{ github.ref_name }}
|
|
BASE_REF: ${{ github.base_ref }}
|
|
run: |
|
|
DEV_DOCKER_TAG_BASE=ghcr.io/${OWNER_LC} \
|
|
COMPOSE_TAG=${BASE_REF:-${REF_NAME}} \
|
|
docker run -u $(id -u) --rm -v ${{ github.workspace }}:/awx_devel/:Z \
|
|
--workdir=/awx_devel `make print-DEVEL_IMAGE_NAME` /start_tests.sh genschema
|
|
|
|
- name: Verify spec file exists
|
|
run: |
|
|
SPEC_FILE="./schema.json"
|
|
if [ ! -f "$SPEC_FILE" ]; then
|
|
echo "❌ Spec file not found at $SPEC_FILE"
|
|
echo "Contents of workspace:"
|
|
ls -la .
|
|
exit 1
|
|
fi
|
|
echo "✅ Found spec file at $SPEC_FILE"
|
|
|
|
- name: Checkout spec repo
|
|
id: checkout_spec_repo
|
|
continue-on-error: true
|
|
uses: actions/checkout@v4
|
|
with:
|
|
repository: ansible-automation-platform/aap-openapi-specs
|
|
ref: ${{ github.ref_name }}
|
|
path: spec-repo
|
|
token: ${{ secrets.OPENAPI_SPEC_SYNC_TOKEN }}
|
|
|
|
- name: Fail if branch doesn't exist
|
|
if: steps.checkout_spec_repo.outcome == 'failure'
|
|
env:
|
|
REF_NAME: ${{ github.ref_name }}
|
|
run: |
|
|
echo "##[error]❌ Branch '${REF_NAME}' does not exist in the central spec repository."
|
|
echo "##[error]Expected branch: ${REF_NAME}"
|
|
echo "##[error]This branch must be created in the spec repo before specs can be synced."
|
|
exit 1
|
|
|
|
- name: Compare specs
|
|
id: compare
|
|
run: |
|
|
COMPONENT_SPEC="./schema.json"
|
|
SPEC_REPO_FILE="spec-repo/controller.json"
|
|
|
|
# Check if spec file exists in spec repo
|
|
if [ ! -f "$SPEC_REPO_FILE" ]; then
|
|
echo "Spec file doesn't exist in spec repo - will create new file"
|
|
echo "has_diff=true" >> $GITHUB_OUTPUT
|
|
echo "is_new_file=true" >> $GITHUB_OUTPUT
|
|
else
|
|
# Compare files
|
|
if diff -q "$COMPONENT_SPEC" "$SPEC_REPO_FILE" > /dev/null; then
|
|
echo "✅ No differences found - specs are identical"
|
|
echo "has_diff=false" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "📝 Differences found - spec has changed"
|
|
echo "has_diff=true" >> $GITHUB_OUTPUT
|
|
echo "is_new_file=false" >> $GITHUB_OUTPUT
|
|
fi
|
|
fi
|
|
|
|
- name: Update spec file
|
|
if: steps.compare.outputs.has_diff == 'true'
|
|
run: |
|
|
cp "./schema.json" "spec-repo/controller.json"
|
|
echo "✅ Updated spec-repo/controller.json"
|
|
|
|
- name: Create PR in spec repo
|
|
if: steps.compare.outputs.has_diff == 'true'
|
|
working-directory: spec-repo
|
|
env:
|
|
GH_TOKEN: ${{ secrets.OPENAPI_SPEC_SYNC_TOKEN }}
|
|
GPG_PRIVATE_KEY: ${{ secrets.OPENAPI_SPEC_SYNC_GPG_PRIVATE_KEY }}
|
|
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
|
SPEC_REPO: ansible-automation-platform/aap-openapi-specs
|
|
REF_NAME: ${{ github.ref_name }}
|
|
GITHUB_SHA_FULL: ${{ github.sha }}
|
|
GITHUB_REPO: ${{ github.repository }}
|
|
IS_NEW_FILE: ${{ steps.compare.outputs.is_new_file }}
|
|
run: |
|
|
# Import GPG key and configure git for signed commits
|
|
echo "$GPG_PRIVATE_KEY" | gpg --batch --import 2>/dev/null
|
|
GPG_KEY_ID=$(gpg --list-secret-keys --keyid-format long 2>/dev/null | grep sec | head -1 | awk '{print $2}' | cut -d'/' -f2)
|
|
if [ -z "$GPG_KEY_ID" ]; then
|
|
echo "❌ Failed to import GPG key or extract key ID"
|
|
exit 1
|
|
fi
|
|
git config user.name "aap-api-bot"
|
|
git config user.email "aap-api-bot@redhat.com"
|
|
git config commit.gpgsign true
|
|
git config user.signingkey "$GPG_KEY_ID"
|
|
|
|
# Configure git to use the token for push
|
|
git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${SPEC_REPO}.git"
|
|
|
|
SHORT_SHA="${GITHUB_SHA_FULL:0:7}"
|
|
BRANCH_NAME="update-Controller-${REF_NAME}-${SHORT_SHA}"
|
|
|
|
git checkout -b "$BRANCH_NAME"
|
|
|
|
# Add and commit changes
|
|
git add "controller.json"
|
|
|
|
if [ "${IS_NEW_FILE}" == "true" ]; then
|
|
COMMIT_MSG="Add Controller OpenAPI spec for ${REF_NAME}"
|
|
else
|
|
COMMIT_MSG="Update Controller OpenAPI spec for ${REF_NAME}"
|
|
fi
|
|
|
|
git commit -m "${COMMIT_MSG}
|
|
|
|
Synced from ${GITHUB_REPO}@${GITHUB_SHA_FULL}
|
|
Source branch: ${REF_NAME}
|
|
|
|
Co-Authored-By: github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
|
|
|
|
# Push branch
|
|
git push origin "$BRANCH_NAME"
|
|
|
|
# Create PR
|
|
PR_TITLE="[${REF_NAME}] Update Controller spec from merged commit"
|
|
PR_BODY="## Summary
|
|
Automated OpenAPI spec sync from component repository merge.
|
|
|
|
**Source:** ${GITHUB_REPO}@${GITHUB_SHA_FULL}
|
|
**Branch:** \`${REF_NAME}\`
|
|
**Component:** \`Controller\`
|
|
**Spec File:** \`controller.json\`
|
|
|
|
## Changes
|
|
$(if [ "${IS_NEW_FILE}" == "true" ]; then echo "- 🆕 New spec file created"; else echo "- 📝 Spec file updated with latest changes"; fi)
|
|
|
|
## Source Commit
|
|
\`\`\`
|
|
${COMMIT_MESSAGE}
|
|
\`\`\`
|
|
|
|
---
|
|
🤖 This PR was automatically generated by the OpenAPI spec sync workflow."
|
|
|
|
gh pr create \
|
|
--repo "${SPEC_REPO}" \
|
|
--title "$PR_TITLE" \
|
|
--body "$PR_BODY" \
|
|
--base "${REF_NAME}" \
|
|
--head "$BRANCH_NAME"
|
|
|
|
echo "✅ Created PR in spec repo"
|
|
|
|
- name: Report results
|
|
if: always()
|
|
env:
|
|
HAS_DIFF: ${{ steps.compare.outputs.has_diff }}
|
|
run: |
|
|
if [ "${HAS_DIFF}" == "true" ]; then
|
|
echo "📝 Spec sync completed - PR created in spec repo"
|
|
else
|
|
echo "✅ Spec sync completed - no changes needed"
|
|
fi
|