Skip to content

Instantly share code, notes, and snippets.

@ceejbot
Last active April 4, 2024 03:08
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ceejbot/30bfd493c5796db9c38d1323afdb2b65 to your computer and use it in GitHub Desktop.
Save ceejbot/30bfd493c5796db9c38d1323afdb2b65 to your computer and use it in GitHub Desktop.
an example of a github action that updates other repo actions & secrets on a push
name: deploy service tar
on:
push:
branches:
- 'deploy/*'
jobs:
update:
name: Update target service Github deploy workflows
runs-on: ubuntu-latest
env:
TOPIC: 'YOUR-TAG-HERE'
ORG: 'YOUR-ORG-HERE'
USERNAME: 'YOUR-GIT-USERNAME-HERE'
AWS_DEFAULT_REGION: 'us-west-2'
steps:
- name: capture target from branch
run: |
echo "::set-env name=REPO_TARGET::$(echo $GITHUB_REF | sed -n "s/refs\/heads\/deploy\/\(.\+\)/\1/p")"
- uses: actions/checkout@v2
- run: |
echo "::set-env name=GIT_HASH::$(git rev-parse --short HEAD)"
- name: create slack script
run: |
cat <<EOF > slack
#!/bin/bash
curl -X POST --data-urlencode "payload={\"channel\": \"#deploys\", \"username\": \"deployomat-9000\", \"text\": \"\$1\", \"icon_emoji\": \":robot_face:\"}" ${{ secrets.SLACK_DEPLOYS_CHANNEL }} >/dev/null
EOF
chmod +x slack
sudo mv slack /usr/local/bin
- run: |
utterance="<https://github.com/$GITHUB_REPOSITORY/commit/$GIT_HASH|"'`'"$GITHUB_REPOSITORY@$GIT_HASH"'`'"> → "'`'$REPO_TARGET'`'
echo "::set-env name=SLACK_STRING::$utterance"
- name: fetch target repos
run: |
repos=$(curl -sL -H "Accept: application/vnd.github.mercy-preview+json" -H "Authorization: token ${{secrets.GH_TOKEN}}" "https://api.github.com/search/repositories?q=org:${ORG}+topic:${TOPIC}&per_page=200" | jq -r '.items[].full_name')
# on the next two lines we capture the result to prevent early exit.
repos=$(echo "$repos" | grep -v ogdotnet | grep -v action-deploys) || result=$?
if [ $REPO_TARGET != "all" ]; then
repos=$(echo "$repos" | grep $REPO_TARGET) || result=$?
fi
# we then handle the errors here in order to emit a useful message with context.
if [ -z "$repos" ]; then
echo "Found no repos (requested repos=${REPO_TARGET}), bailing."
slack ":bangbang: $SLACK_STRING failed to identify any repo targets using \`$REPO_TARGET\`. Do the repos exist and have the $TOPIC topic applied?"
exit 1
fi
echo "::set-env name=REPOS::$repos"
- name: cache octosecret
id: cache-octosecret
uses: actions/cache@v1
with:
path: /usr/bin/octosecret
key: ${{ runner.os }}-octosecret
- name: download octosecret
if: steps.cache-octosecret.outputs.cache-hit != 'true'
run: |
sudo curl -sL https://github.com/ceejbot/octosecret/releases/download/v0.1.0/octosecret_linux_x64 -o /usr/bin/octosecret
sudo chmod +x /usr/bin/octosecret
- name: for each repo, check out the repo
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: |
# fetch secrets
original_message=$(git log HEAD --pretty='%s' -1)
outgoing_message="Updating github action via $GITHUB_REPOSITORY @ $GIT_HASH:"
outgoing_message=$(echo -e $outgoing_message "\n\n" $original_message)
echo $outgoing_message
workflow=$(cat data/deploy.yml)
git config --global user.name "$(git log HEAD --pretty='%aN')"
git config --global user.email "$(git log HEAD --pretty='%aE')"
mkdir ~/repos
cd ~/repos
secrets=$(aws secretsmanager get-secret-value --secret-id action_deploys_secrets | jq -r '.SecretString')
secret_names=$(jq -r 'keys[]' <<< "$secrets")
for repo in $REPOS; do
git clone https://$USERNAME:${{ secrets.GH_TOKEN }}@github.com/$repo workingdir
cd workingdir
# update secrets first
key_data=$(curl -s -H "Accept: application/vnd.github.mercy-preview+json" -H "Authorization: token ${{ secrets.GH_TOKEN }}" 'https://api.github.com/repos/'"$repo"'/actions/secrets/public-key')
key_id=$(jq -r '.key_id' <<< "$key_data")
key_b64=$(jq -r '.key' <<< "$key_data")
for secret_name in $secret_names; do
secret_value=$(jq -r ".$secret_name" <<< "$secrets")
encrypted_value=$(printf "%s" "$secret_value" | octosecret "$key_b64")
result=0; curl -sf \
-X PUT \
-d '{"encrypted_value": "'"$encrypted_value"'", "key_id": "'"$key_id"'""}' \
-H "Accept: application/vnd.github.mercy-preview+json" \
-H "Content-Type: application/json" \
-H "Authorization: token ${{ secrets.GH_TOKEN }}" \
'https://api.github.com/repos/'"$repo"'/actions/secrets/'"$secret_name" || result=$?
if [ $result -ne 0 ]; then
slack ":fire: $SLACK_STRING failed update $secret_name for $repo. *Stopping.* See <https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID|the run>."
exit 1
fi
done
slack ":github: $SLACK_STRING \`$repo\` secrets updated."
# now update the deploy workflow
cat <<< "$workflow" > .github/workflows/deploy.yml
git add .github/workflows/deploy.yml
if [ -z "$(git status --short)" ]; then
slack ":fast_forward: $SLACK_STRING \`$repo\` deploy action already up to date."
continue
fi
git commit -m "$outgoing_message"
result=0; git push || result=$?
if [ $result -ne 0 ]; then
slack ":fire: $SLACK_STRING failed to push an update to $repo. *Stopping.* See <https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID|the run>."
exit 1
fi
new_commit=$(git rev-parse --short HEAD)
slack ":github: $SLACK_STRING \`$repo\` deploy action updated. See <https://github.com/$repo/commit/$new_commit|\`$new_commit\`>."
cd ..
rm -rf workingdir
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment