-
Notifications
You must be signed in to change notification settings - Fork 0
165 lines (145 loc) · 6.38 KB
/
outbound-bridge.yml
File metadata and controls
165 lines (145 loc) · 6.38 KB
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
# Digital Service Orchestra — Outbound Bridge
# Pushes local ticket changes to Jira when the tickets branch is updated.
name: Outbound Bridge
on:
# Push trigger removed (71fa-c068): GitHub Actions does not detect workflow
# files on orphan branches, so push-to-tickets never fired (all 100 recent
# runs were workflow_dispatch). merge-to-main.sh dispatches explicitly.
workflow_dispatch: {}
concurrency:
group: jira-bridge
cancel-in-progress: false
jobs:
bridge:
name: Push tickets to Jira
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: write
# Skip commits made by the bridge bot itself (echo prevention).
# Fall back to 'dso-bridge[bot]' when BRIDGE_BOT_LOGIN is unset so the
# guard is never silently bypassed (unset var would evaluate to '' and
# always pass, causing an infinite push loop on the tickets branch).
if: github.actor != (vars.BRIDGE_BOT_LOGIN || 'dso-bridge[bot]')
steps:
- name: Checkout main (scripts and plugin code)
uses: actions/checkout@v4
with:
fetch-depth: 1
ref: main
- name: Mount tickets branch as worktree
run: |
git fetch origin tickets --depth=2
rm -rf .tickets-tracker
git worktree add .tickets-tracker tickets
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Cache ACLI binary
id: cache-acli
uses: actions/cache@v4
with:
path: ~/.acli
key: acli-${{ runner.os }}-${{ vars.ACLI_VERSION || 'latest' }}
- name: Validate ACLI version before download
if: steps.cache-acli.outputs.cache-hit != 'true'
run: |
ACLI_VERSION="${{ vars.ACLI_VERSION }}"
if [ -z "$ACLI_VERSION" ] || [ "$ACLI_VERSION" = "latest" ]; then
echo "ERROR: ACLI_VERSION is unset or 'latest' — cannot proceed with download."
echo " Pin ACLI_VERSION to a specific release and set ACLI_SHA256 to its"
echo " expected SHA256 digest before running this workflow."
exit 1
fi
- name: Download ACLI
if: steps.cache-acli.outputs.cache-hit != 'true'
run: |
mkdir -p ~/.acli
# ACLI v1.3+ is a Go binary distributed as tar.gz from acli.atlassian.com.
curl -sSL "https://acli.atlassian.com/linux/${{ vars.ACLI_VERSION }}/acli_${{ vars.ACLI_VERSION }}_linux_amd64.tar.gz" \
-o ~/.acli/acli.tar.gz
- name: Verify ACLI checksum
if: steps.cache-acli.outputs.cache-hit != 'true'
run: |
ACLI_VERSION="${{ vars.ACLI_VERSION }}"
ACLI_SHA256="${{ vars.ACLI_SHA256 }}"
ARTIFACT=~/.acli/acli.tar.gz
if [ -z "$ACLI_VERSION" ] || [ "$ACLI_VERSION" = "latest" ]; then
echo "ERROR: ACLI_VERSION is unset or 'latest' — checksum verification cannot proceed."
echo " Pin ACLI_VERSION to a specific release and set ACLI_SHA256 to its expected"
echo " SHA256 digest before running this workflow."
exit 1
elif [ -z "$ACLI_SHA256" ]; then
COMPUTED_HASH=$(sha256sum "$ARTIFACT" | awk '{print $1}')
echo "WARNING: ACLI_SHA256 is not set. Computed SHA256 of downloaded artifact:"
echo ""
echo " ACLI_SHA256=${COMPUTED_HASH}"
echo ""
echo "Set this value as a GitHub repository variable:"
echo " gh variable set ACLI_SHA256 --body '${COMPUTED_HASH}'"
echo ""
echo "Proceeding WITHOUT checksum verification (first-run bootstrap)."
else
echo "${ACLI_SHA256} ${ARTIFACT}" | sha256sum -c --strict
echo "Checksum verified: ${ARTIFACT}"
fi
- name: Extract ACLI binary
if: steps.cache-acli.outputs.cache-hit != 'true'
run: |
# ACLI v1.3+ is a Go binary in a tar.gz with a version-prefixed directory.
# --strip-components=1 removes the top-level dir (e.g., acli_1.3.14-stable_linux_amd64/).
tar xzf ~/.acli/acli.tar.gz -C ~/.acli/ --strip-components=1
chmod +x ~/.acli/acli
rm -f ~/.acli/acli.tar.gz
echo "Extracted acli binary from tar.gz."
- name: Add ACLI to PATH
run: |
if [ ! -f "$HOME/.acli/acli" ]; then
echo "ERROR: $HOME/.acli/acli not found — download or extraction must have failed." >&2
exit 1
fi
ln -sf "$HOME/.acli/acli" /usr/local/bin/acli
- name: Authenticate ACLI
run: |
echo "$JIRA_API_TOKEN" | acli jira auth login \
--site "$JIRA_URL" \
--email "$JIRA_USER" \
--token
env:
JIRA_URL: ${{ vars.JIRA_URL }}
JIRA_USER: ${{ vars.JIRA_USER }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
- name: Run outbound bridge
id: run-bridge
run: |
python3 plugins/dso/scripts/bridge-outbound.py
env:
JIRA_URL: ${{ vars.JIRA_URL }}
JIRA_USER: ${{ vars.JIRA_USER }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
JIRA_PROJECT: ${{ vars.JIRA_PROJECT }}
BRIDGE_ENV_ID: ${{ vars.BRIDGE_ENV_ID }}
GH_RUN_ID: ${{ github.run_id }}
- name: Commit SYNC events back to tickets branch
run: |
cd .tickets-tracker
if [ -z "$(git status --porcelain)" ]; then
echo "No SYNC events to commit — skipping."
exit 0
fi
# Configure bridge bot identity (not the default github-actions[bot]).
# Values are read from env vars (set via the env: map below) rather than
# interpolated directly into the run: block to prevent expression injection.
git config user.name "${BRIDGE_BOT_NAME}"
git config user.email "${BRIDGE_BOT_EMAIL}"
git add -A
git commit -m "chore: sync SYNC events from Jira bridge [run ${{ github.run_id }}]"
git push origin HEAD:tickets
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRIDGE_BOT_NAME: ${{ vars.BRIDGE_BOT_NAME || 'dso-bridge[bot]' }}
BRIDGE_BOT_EMAIL: ${{ vars.BRIDGE_BOT_EMAIL || 'dso-bridge@users.noreply.github.com' }}
- name: Job timing report
if: always()
run: echo "outbound-bridge completed at $(date -u +%Y-%m-%dT%H:%M:%SZ)"