-
-
Notifications
You must be signed in to change notification settings - Fork 307
feat: sync secrets workflow for sibling repositories #825
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | |||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,81 @@ | |||||||||||||||||||||||||||||
| name: Sync Secrets to Repositories | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| on: | |||||||||||||||||||||||||||||
| workflow_dispatch: | |||||||||||||||||||||||||||||
| inputs: | |||||||||||||||||||||||||||||
| target_repo: | |||||||||||||||||||||||||||||
| description: 'Target repository (org/repo format)' | |||||||||||||||||||||||||||||
| required: true | |||||||||||||||||||||||||||||
| default: 'game-ci/orchestrator' | |||||||||||||||||||||||||||||
| type: choice | |||||||||||||||||||||||||||||
| options: | |||||||||||||||||||||||||||||
| - game-ci/orchestrator | |||||||||||||||||||||||||||||
| - game-ci/cli | |||||||||||||||||||||||||||||
| dry_run: | |||||||||||||||||||||||||||||
| description: 'Dry run (list secrets to sync without writing)' | |||||||||||||||||||||||||||||
| required: false | |||||||||||||||||||||||||||||
| default: false | |||||||||||||||||||||||||||||
| type: boolean | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| jobs: | |||||||||||||||||||||||||||||
| sync-secrets: | |||||||||||||||||||||||||||||
| name: Sync secrets to ${{ inputs.target_repo }} | |||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | |||||||||||||||||||||||||||||
| steps: | |||||||||||||||||||||||||||||
| - name: Sync secrets | |||||||||||||||||||||||||||||
| env: | |||||||||||||||||||||||||||||
| GH_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} | |||||||||||||||||||||||||||||
| TARGET_REPO: ${{ inputs.target_repo }} | |||||||||||||||||||||||||||||
| DRY_RUN: ${{ inputs.dry_run }} | |||||||||||||||||||||||||||||
| # Secrets to sync — values come from repo + org secrets available here | |||||||||||||||||||||||||||||
| SECRET_UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} | |||||||||||||||||||||||||||||
| SECRET_UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} | |||||||||||||||||||||||||||||
| SECRET_UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} | |||||||||||||||||||||||||||||
| SECRET_GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} | |||||||||||||||||||||||||||||
| SECRET_LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }} | |||||||||||||||||||||||||||||
| SECRET_GOOGLE_SERVICE_ACCOUNT_EMAIL: ${{ secrets.GOOGLE_SERVICE_ACCOUNT_EMAIL }} | |||||||||||||||||||||||||||||
| SECRET_GOOGLE_SERVICE_ACCOUNT_KEY: ${{ secrets.GOOGLE_SERVICE_ACCOUNT_KEY }} | |||||||||||||||||||||||||||||
| SECRET_CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |||||||||||||||||||||||||||||
|
Comment on lines
+31
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cd /tmp && git ls-files | grep -E "\.github/workflows/" | head -20Repository: game-ci/unity-builder Length of output: 133 🏁 Script executed: cat -n .github/workflows/sync-secrets.yml | head -60Repository: game-ci/unity-builder Length of output: 2698 🏁 Script executed: cat -n .github/workflows/build-tests-windows.yml | grep -i "unity_license" -A 2 -B 2Repository: game-ci/unity-builder Length of output: 826 🏁 Script executed: cat .github/workflows/orchestrator-integrity.yml | grep -E "AWS_ACCESS_KEY_ID|AWS_SECRET_ACCESS_KEY" -A 2 -B 2Repository: game-ci/unity-builder Length of output: 4497 🏁 Script executed: cat .github/workflows/orchestrator-integrity.yml | grep -E "secrets\." -i | head -20Repository: game-ci/unity-builder Length of output: 1172 🏁 Script executed: rg "secrets\.AWS_" .github/workflows/ -A 1 -B 1Repository: game-ci/unity-builder Length of output: 436 🏁 Script executed: cat .github/workflows/orchestrator-async-checks.yml | grep -A 10 -B 10 "AWS_ACCESS_KEY_ID.*secrets"Repository: game-ci/unity-builder Length of output: 830 🏁 Script executed: cat -n .github/workflows/sync-secrets.yml | tail -30Repository: game-ci/unity-builder Length of output: 1239 Add UNITY_LICENSE to the secrets allowlist for sync. The mapping omits Note: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are not referenced as actual secrets in the workflows—they are hardcoded test values (in orchestrator-integrity.yml) or commented out (in orchestrator-async-checks.yml), so they should not be added to the sync allowlist. Suggested patch SECRET_UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
+ SECRET_UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
SECRET_GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} "UNITY_SERIAL:SECRET_UNITY_SERIAL"
+ "UNITY_LICENSE:SECRET_UNITY_LICENSE"
"GIT_PRIVATE_TOKEN:SECRET_GIT_PRIVATE_TOKEN"🤖 Prompt for AI Agents |
|||||||||||||||||||||||||||||
| run: | | |||||||||||||||||||||||||||||
| SECRETS=( | |||||||||||||||||||||||||||||
| "UNITY_EMAIL:SECRET_UNITY_EMAIL" | |||||||||||||||||||||||||||||
| "UNITY_PASSWORD:SECRET_UNITY_PASSWORD" | |||||||||||||||||||||||||||||
| "UNITY_SERIAL:SECRET_UNITY_SERIAL" | |||||||||||||||||||||||||||||
| "GIT_PRIVATE_TOKEN:SECRET_GIT_PRIVATE_TOKEN" | |||||||||||||||||||||||||||||
| "LOCALSTACK_AUTH_TOKEN:SECRET_LOCALSTACK_AUTH_TOKEN" | |||||||||||||||||||||||||||||
| "GOOGLE_SERVICE_ACCOUNT_EMAIL:SECRET_GOOGLE_SERVICE_ACCOUNT_EMAIL" | |||||||||||||||||||||||||||||
| "GOOGLE_SERVICE_ACCOUNT_KEY:SECRET_GOOGLE_SERVICE_ACCOUNT_KEY" | |||||||||||||||||||||||||||||
| "CODECOV_TOKEN:SECRET_CODECOV_TOKEN" | |||||||||||||||||||||||||||||
| ) | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| synced=0 | |||||||||||||||||||||||||||||
| skipped=0 | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| for entry in "${SECRETS[@]}"; do | |||||||||||||||||||||||||||||
| name="${entry%%:*}" | |||||||||||||||||||||||||||||
| env_var="${entry##*:}" | |||||||||||||||||||||||||||||
| value="${!env_var}" | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| if [ -z "$value" ]; then | |||||||||||||||||||||||||||||
| echo "⏭ SKIP: $name (not available in this repo's context)" | |||||||||||||||||||||||||||||
| skipped=$((skipped + 1)) | |||||||||||||||||||||||||||||
| continue | |||||||||||||||||||||||||||||
| fi | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| if [ "$DRY_RUN" = "true" ]; then | |||||||||||||||||||||||||||||
| echo "🔍 DRY RUN: would sync $name → $TARGET_REPO" | |||||||||||||||||||||||||||||
| else | |||||||||||||||||||||||||||||
| echo "$value" | gh secret set "$name" -R "$TARGET_REPO" --body - | |||||||||||||||||||||||||||||
| echo "✅ SYNCED: $name → $TARGET_REPO" | |||||||||||||||||||||||||||||
| fi | |||||||||||||||||||||||||||||
| synced=$((synced + 1)) | |||||||||||||||||||||||||||||
| done | |||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| echo "" | |||||||||||||||||||||||||||||
| echo "=== Summary ===" | |||||||||||||||||||||||||||||
| echo "Synced: $synced" | |||||||||||||||||||||||||||||
| echo "Skipped (not available): $skipped" | |||||||||||||||||||||||||||||
| echo "Target: $TARGET_REPO" | |||||||||||||||||||||||||||||
| if [ "$DRY_RUN" = "true" ]; then | |||||||||||||||||||||||||||||
| echo "Mode: DRY RUN (no secrets were written)" | |||||||||||||||||||||||||||||
| fi | |||||||||||||||||||||||||||||
|
Comment on lines
+22
to
+81
Check warningCode scanning / CodeQL Workflow does not contain permissions Medium
Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {}
Copilot AutofixAI 5 days ago In general, the fix is to add an explicit The single best way to fix this without affecting existing behavior is to add a Concretely, in sync-secrets:
name: Sync secrets to ${{ inputs.target_repo }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Sync secrets
...No new imports or libraries are needed, as this is purely a YAML configuration change.
Suggested changeset
1
.github/workflows/sync-secrets.yml
Copilot is powered by AI and may make mistakes. Always verify output.
Refresh and try again.
|
|||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: game-ci/unity-builder
Length of output: 3535
🏁 Script executed:
Repository: game-ci/unity-builder
Length of output: 49
🏁 Script executed:
Repository: game-ci/unity-builder
Length of output: 547
🏁 Script executed:
Repository: game-ci/unity-builder
Length of output: 67
🏁 Script executed:
Repository: game-ci/unity-builder
Length of output: 195
🏁 Script executed:
grep -A 2 "^permissions:" .github/workflows/integrity-check.yml .github/workflows/orchestrator-async-checks.yml .github/workflows/orchestrator-integrity.ymlRepository: game-ci/unity-builder
Length of output: 585
🏁 Script executed:
Repository: game-ci/unity-builder
Length of output: 178
Add explicit workflow permissions (least privilege).
The workflow lacks an explicit
permissionsblock, leaving defaultGITHUB_TOKENpermissions implicit. While this workflow uses an explicitGH_TOKENforgh secret set, the default token should still be restricted to follow least-privilege principle and align with the repository's existing security pattern (other workflows declare explicit permissions).Suggested patch
name: Sync Secrets to Repositories on: workflow_dispatch: + inputs:🤖 Prompt for AI Agents