-
Notifications
You must be signed in to change notification settings - Fork 0
222 lines (208 loc) · 8.13 KB
/
ansible-cicd.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
---
name: Ansible CI/CD
on:
pull_request:
types:
- opened
- synchronize
- reopened
- closed
branches:
- main
paths:
- "ansible/host_vars/**"
workflow_dispatch:
inputs:
host:
description: "Host to run Ansible against"
required: true
type: choice
options:
- "authentik"
- "cicd"
- "healthchecks"
- "monitoring"
- "vault"
dry_run:
description: "Dry run"
required: true
type: boolean
default: true
workflow_call:
inputs:
host:
description: "Host to run Ansible against"
required: true
type: string
dry_run:
description: "Dry run"
required: true
type: boolean
default: true
env:
TAILSCALE_VERSION: 1.44.0
PYTHON_VERSION: 3.11
jobs:
setup:
runs-on: ubuntu-latest
outputs:
host: ${{ steps.set-host.outputs.host }}
dry_run: ${{ steps.set-dry-run.outputs.dry_run }}
steps:
- name: Checkout (pull_request)
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
if: github.event_name == 'pull_request'
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Checkout (workflow_dispatch || push)
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
if: github.event_name != 'pull_request'
- name: Fetch main branch
run: git fetch origin main
- name: Set host
id: set-host
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "host=${{ github.event.inputs.host }}" >> $GITHUB_OUTPUT
elif [ "${{ github.event_name }}" == "pull_request" ]; then
# Get list of subdirectories in ansible/host_vars that have changed vs PR base SHA
CHANGED_HOSTS=$(git diff --name-only ${{ github.event.pull_request.base.sha }} | grep -oP 'ansible/host_vars/\K[^/]+')
# Set host to list of changed hosts, using , as a delimiter
echo "host=$(echo $CHANGED_HOSTS | tr ' ' ',')" >> $GITHUB_OUTPUT
else
echo "Unknown event name: ${{ github.event_name }}"
exit 1
fi
- name: Set dry run (workflow_dispatch)
id: set-dry-run
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "dry_run=${{ github.event.inputs.dry_run }}" >> $GITHUB_OUTPUT
elif [ "${{ github.event_name }}" == "pull_request" ]; then
if [ "${{ github.event.pull_request.merged }}" == "true" ]; then
echo "dry_run=false" >> $GITHUB_OUTPUT
else
echo "dry_run=true" >> $GITHUB_OUTPUT
fi
else
echo "Unknown event name: ${{ github.event_name }}"
exit 1
fi
- name: Summary
run: |
echo "# Inputs Summary" >> $GITHUB_STEP_SUMMARY
echo "| Input | Value |" >> $GITHUB_STEP_SUMMARY
echo "| --- | --- |" >> $GITHUB_STEP_SUMMARY
echo "| host | ${{ steps.set-host.outputs.host }} |" >> $GITHUB_STEP_SUMMARY
echo "| dry_run | ${{ steps.set-dry-run.outputs.dry_run }} |" >> $GITHUB_STEP_SUMMARY
ansible:
runs-on: ubuntu-latest
needs: setup
env:
ANSIBLE_ROLES_PATH: ${{ github.workspace }}/ansible/roles
ANSIBLE_COLLECTIONS_PATH: ${{ github.workspace }}/ansible/collections
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
# Configure 1Password Service Account
- name: Configure 1Password Service Account
uses: 1Password/load-secrets-action/configure@581a835fb51b8e7ec56b71cf2ffddd7e68bb25e0 # v2
with:
service-account-token: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
# Fetch TAILSCALE_OAUTH_CLIENT_ID and TAILSCALE_OAUTH_CLIENT_SECRET
# from 1Password using load-secrets-action
- name: Fetch Tailscale Secrets
uses: 1Password/load-secrets-action@581a835fb51b8e7ec56b71cf2ffddd7e68bb25e0 # v2
id: fetch-tailscale-secrets
with:
export-env: false
env:
OAUTH_CLIENT_ID: op://Infrastructure/tailscale/github_actions/oauth_client_id
OAUTH_CLIENT_SECRET: op://Infrastructure/tailscale/github_actions/oauth_client_secret
- name: Setup Tailscale
uses: tailscale/github-action@4e4c49acaa9818630ce0bd7a564372c17e33fb4d # v2
with:
version: ${{ env.TAILSCALE_VERSION }}
oauth-client-id: ${{ steps.fetch-tailscale-secrets.outputs.OAUTH_CLIENT_ID }}
oauth-secret: ${{ steps.fetch-tailscale-secrets.outputs.OAUTH_CLIENT_SECRET }}
tags: tag:cicd
- name: Disallow DNS configuration from Tailscale admin panel
run: sudo tailscale set --accept-dns=false
- name: Setup Taskfile
uses: arduino/setup-task@v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Python
uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: pip
- name: Cache Ansible Roles
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4
with:
path: ${{ env.ANSIBLE_ROLES_PATH }}
key: ${{ runner.os }}-ansible-roles-${{ hashFiles('ansible/requirements.yml') }}
- name: Cache Ansible Collections
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4
with:
path: ${{ env.ANSIBLE_COLLECTIONS_PATH }}
key: ${{ runner.os }}-ansible-collections-${{ hashFiles('ansible/requirements.yml') }}
- name: Setup CICD
run: task setup-cicd
# Fetch ANSIBLE_VAULT_PASSWORD from 1Password using load-secrets-action
- name: Fetch Ansible Vault Password
uses: 1Password/load-secrets-action@581a835fb51b8e7ec56b71cf2ffddd7e68bb25e0 # v2
id: fetch-ansible-vault-password
with:
export-env: false
env:
ANSIBLE_VAULT_PASSWORD: op://Infrastructure/ansible/vault/password
# Loop through hosts
- name: Run Ansible
env:
ANSIBLE_VAULT_PASSWORD: ${{ steps.fetch-ansible-vault-password.outputs.ANSIBLE_VAULT_PASSWORD }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "# Ansible CICD Summary" >> $GITHUB_STEP_SUMMARY
echo "Job: [${{ github.job }}]($GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY
echo "| Host | Status |" >> $GITHUB_STEP_SUMMARY
echo "| --- | --- |" >> $GITHUB_STEP_SUMMARY
FINAL_STATUS=0
# Create list of hosts to run Ansible for, splitting on ,
HOSTS=$(echo ${{ needs.setup.outputs.host }} | tr ',' ' ')
for host in $HOSTS; do
STATUS_EMOJI=""
if ! ansible --list-hosts all | grep -q $host; then
echo "$host is not an available host, skipping"
continue
fi
echo ::group::Pinging $host
HOST=$host task ansible-ping
STATUS_PING=$?
echo ::endgroup::
if [ $STATUS_PING -ne 0 ]; then
STATUS_EMOJI=":warning:"
echo "$host is unreachable, skipping"
else
echo ::group::Running Ansible for $host
HOST=$host DRY_RUN=${{ needs.setup.outputs.dry_run }} task ansible
STATUS=$?
echo ::endgroup::
if [ $STATUS -ne 0 ]; then
FINAL_STATUS=$STATUS
fi
if [ $STATUS -eq 0 ]; then
STATUS_EMOJI=":white_check_mark:"
else
STATUS_EMOJI=":x:"
fi
fi
echo "| $host | $STATUS_EMOJI |" >> $GITHUB_STEP_SUMMARY
done
if [ "${{ github.event_name }}" == "pull_request" ]; then
gh pr comment ${{ github.event.pull_request.number }} --body "$(cat $GITHUB_STEP_SUMMARY)"
fi
exit $FINAL_STATUS
- name: Tailscale Logout
if: always()
run: sudo tailscale logout