-
Notifications
You must be signed in to change notification settings - Fork 1
202 lines (183 loc) · 8.55 KB
/
Copy pathbeta.yml
File metadata and controls
202 lines (183 loc) · 8.55 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
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
name: Build Beta
on:
pull_request:
branches:
- release
jobs:
build:
runs-on: ubuntu-latest
if: github.event.pull_request.user.login != 'dependabot[bot]'
permissions:
contents: write
packages: write
pull-requests: write
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 200
- name: Print build name
run: echo "$GITHUB_ACTOR is building '$GITHUB_REPOSITORY' (commit $GITHUB_SHA)"
- name: Set up Python
id: setup-python
uses: actions/setup-python@v5
with:
python-version: "3.12.12"
- name: Cache dependencies
uses: actions/cache@v4
with:
path: |
~/.cache/pip
~/.local/share/virtualenvs
key: ${{ runner.os }}-python-${{ steps.setup-python.outputs.python-version }}-dependency-cache
- name: Install dependencies
run: |
pip install --no-cache-dir pipenv
pipenv install --dev
- name: Lint checks
run: pipenv run pre-commit run --all-files --show-diff-on-failure
- name: Test the service
env:
BUILD_QUALITY: "BETA"
LOG_LEVEL: "trace"
run: pipenv run pytest -v
- name: Build Docker image
run: docker build . --file Dockerfile --tag the-agent
- name: Auth for GitHub's Container Registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.actor }}" --password-stdin
- name: Tag Docker image
run: |
VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
echo "Tagging images with version '$VERSION'..."
docker tag the-agent ghcr.io/$GITHUB_REPOSITORY:"$VERSION".beta
docker tag the-agent ghcr.io/$GITHUB_REPOSITORY:latest_beta
docker tag the-agent appifyhub/the-agent:"$VERSION".beta
docker tag the-agent appifyhub/the-agent:latest_beta
- name: Publish Docker images to GitHub
run: |
VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
echo "Publishing images with version '$VERSION'..."
docker push ghcr.io/$GITHUB_REPOSITORY:"$VERSION".beta
docker push ghcr.io/$GITHUB_REPOSITORY:latest_beta
- name: Publish Docker images to DockerHub
id: docker_publish
env:
USER: ${{ secrets.DOCKER_HUB_USER }}
TOKEN: ${{ secrets.DOCKER_HUB_TOKEN }}
run: |
VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
docker login docker.io -u $USER -p $TOKEN
echo "Publishing images with version '$VERSION'..."
docker push appifyhub/the-agent:"$VERSION".beta
docker push appifyhub/the-agent:latest_beta
echo ::set-output name=the_agent_version::"$VERSION"
- name: Comment build information
env:
GITHUB_SHA: ${{ env.GITHUB_SHA }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_RUN_ID: ${{ env.GITHUB_RUN_ID }}
GITHUB_REPOSITORY: ${{ env.GITHUB_REPOSITORY }}
GITHUB_SERVER_URL: ${{ env.GITHUB_SERVER_URL }}
PR_NUMBER: ${{ github.event.number }}
VERSION: ${{ steps.docker_publish.outputs.the_agent_version }}
DOCKER_IMG: "docker pull appifyhub/the-agent"
run: |
NL=$'\n'
CODE='```'
DOCKER_VERSIONED="$DOCKER_IMG:$VERSION.beta"
DOCKER_LATEST="# Valid until a new build${NL}${DOCKER_IMG}:latest_beta"
CODE_BLOCK="${CODE}shell${NL}${DOCKER_LATEST}${NL}${DOCKER_VERSIONED}${NL}${CODE}"
JOB="[${GITHUB_RUN_ID}](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID})"
NOTIFICATION="Build ${JOB} complete for ${GITHUB_SHA}.${NL}${NL}${CODE_BLOCK}${NL}"
gh pr comment "$PR_NUMBER" -b "$NOTIFICATION"
- name: Publish to GitHub Releases
id: publish_github_release
env:
ARTIFACT: "the-agent"
BUILD_QUALITY: "BETA"
VERSION: ${{ steps.docker_publish.outputs.the_agent_version }}
GITHUB_SHA: ${{ env.GITHUB_SHA }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY: ${{ env.GITHUB_REPOSITORY }}
run: pipenv run python tools/publish_github_release.py
- name: Wait for the service to go live
env:
HEALTH_ENDPOINT: ${{ secrets.HEALTH_ENDPOINT_STAGING }}
EXPECTED_VERSION: ${{ steps.publish_github_release.outputs.release_version }} # stored in Python
run: |
INTERVAL=15
DURATION_MINUTES=12
ATTEMPTS=$(( (DURATION_MINUTES * 60) / INTERVAL ))
echo "Waiting for health endpoint to report version: $EXPECTED_VERSION"
echo "Polling every $INTERVAL seconds for $DURATION_MINUTES minutes ($ATTEMPTS attempts)"
for ((i=1;i<=ATTEMPTS;i++)); do
RESPONSE=$(curl -s "$HEALTH_ENDPOINT" || true)
VERSION=$(echo "$RESPONSE" | grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' | head -n1 | sed 's/.*: *"\([^"]*\)".*/\1/')
if [[ "$VERSION" == "$EXPECTED_VERSION" ]]; then
echo "Health endpoint version matches: $VERSION"
exit 0
fi
echo "Attempt $i/$ATTEMPTS: version is '$VERSION', waiting..."
sleep $INTERVAL
done
echo "Waited full $DURATION_MINUTES minutes. Version did not match. Continuing."
exit 0
- name: Notify of release
id: notify_release
env:
NOTIFICATION_AUTH_KEY: ${{ secrets.NOTIFICATION_AUTH_KEY_STAGING }}
NOTIFICATION_ENDPOINT: ${{ secrets.NOTIFICATION_URL_STAGING }}
RELEASE_OUTPUT_B64: ${{ steps.publish_github_release.outputs.release_output_b64 }} # stored in Python
run: |
INTERVAL=15
MAX_ATTEMPTS=20
echo "Notifying release endpoint with retry support"
echo "Will retry every $INTERVAL seconds for up to $MAX_ATTEMPTS attempts if needed"
for ((i=1;i<=MAX_ATTEMPTS;i++)); do
echo "Attempt $i/$MAX_ATTEMPTS: sending notification..."
SUMMARY_RESPONSE=$(curl -X POST \
-L "$NOTIFICATION_ENDPOINT" \
-H "X-API-Key: $NOTIFICATION_AUTH_KEY" \
-H "Content-Type: application/json" \
-d "{\"release_output_b64\": \"$RELEASE_OUTPUT_B64\"}" \
-s || true)
if ! echo "$SUMMARY_RESPONSE" | jq empty 2>/dev/null; then
echo "Warning: non-JSON response on attempt $i/$MAX_ATTEMPTS (raw): $SUMMARY_RESPONSE"
sleep $INTERVAL
continue
fi
SHOULD_RETRY=$(echo "$SUMMARY_RESPONSE" | jq -r '.should_retry // false')
if [[ "$SHOULD_RETRY" != "true" ]]; then
echo "Notification successful (should_retry = $SHOULD_RETRY)"
SUMMARY=$(echo "$SUMMARY_RESPONSE" | jq -r '.summary // ""')
SUMMARY_B64=$(printf "%s" "$SUMMARY" | base64 -w 0)
echo "summary_b64=$SUMMARY_B64" >> $GITHUB_OUTPUT
exit 0
fi
echo "Instance not ready yet (should_retry = true), waiting $INTERVAL seconds..."
sleep $INTERVAL
done
echo "Reached maximum attempts ($MAX_ATTEMPTS). Last response:"
echo "$SUMMARY_RESPONSE"
echo "Continuing without summary."
exit 0
- name: Update GitHub Release with summary
if: steps.notify_release.outputs.summary_b64 != ''
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY: ${{ env.GITHUB_REPOSITORY }}
RELEASE_TAG: ${{ steps.publish_github_release.outputs.release_tag }} # stored in Python
SUMMARY_B64: ${{ steps.notify_release.outputs.summary_b64 }} # stored in the task above
run: |
SUMMARY=$(echo "$SUMMARY_B64" | base64 --decode)
echo "$SUMMARY" > summary.txt
gh release edit "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" --notes-file summary.txt
- name: Update PR with summary
if: steps.notify_release.outputs.summary_b64 != '' && github.event.number
env:
PR_NUMBER: ${{ github.event.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SUMMARY_B64: ${{ steps.notify_release.outputs.summary_b64 }} # stored in the task above
run: |
SUMMARY=$(echo "$SUMMARY_B64" | base64 --decode)
echo "$SUMMARY" > summary.txt
gh pr edit "$PR_NUMBER" --body-file summary.txt