Skip to content

Commit b29f2e3

Browse files
CI: Add CI/CD pipeline and test with gtm/healthcare demos
1 parent 9dddf74 commit b29f2e3

File tree

3 files changed

+284
-18
lines changed

3 files changed

+284
-18
lines changed

.github/workflows/create-build.yml

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
name: Create PromptQL Build
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
paths:
7+
- "demos/**"
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout code
15+
uses: actions/checkout@v4
16+
17+
- name: Detect all changed demos
18+
id: demo-setup
19+
run: |
20+
# Fetch the base branch to compare against
21+
git fetch origin ${{ github.base_ref }}
22+
23+
# Get changed files between base and current branch
24+
CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}..HEAD)
25+
CHANGED_DEMOS=$(echo "$CHANGED_FILES" | grep '^demos/' | cut -d'/' -f2 | sort -u)
26+
27+
if [ -z "$CHANGED_DEMOS" ]; then
28+
echo "No demo changes detected"
29+
exit 1
30+
fi
31+
32+
echo "demos<<EOF" >> $GITHUB_OUTPUT
33+
echo "$CHANGED_DEMOS" >> $GITHUB_OUTPUT
34+
echo "EOF" >> $GITHUB_OUTPUT
35+
36+
- name: Load secrets from 1Password
37+
uses: 1password/load-secrets-action@v1
38+
with:
39+
export-env: true
40+
env:
41+
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
42+
43+
- name: Install DDN CLI
44+
run: |
45+
curl -L https://graphql-engine-cdn.hasura.io/ddn/cli/v4/get.sh | bash
46+
echo "$HOME/.local/bin" >> $GITHUB_PATH
47+
48+
- name: Verify DDN CLI installation
49+
run: ddn --version
50+
51+
- name: Build all changed demos
52+
id: build
53+
run: |
54+
BUILDS_JSON="[]"
55+
56+
while IFS= read -r demo; do
57+
echo "Building demo: $demo"
58+
59+
# Load secrets for this specific demo from 1Password
60+
case $demo in
61+
gtm)
62+
HASURA_DDN_PAT=$(op read "op://Product ACT/axiom_gtm/ddn-service-account")
63+
JWT_SECRET=$(op read "op://Product ACT/axiom_gtm/JWT_SECRET")
64+
OPERATIONS_AUTH_JDBC_URL=$(op read "op://Product ACT/axiom_gtm/OPERATIONS_AUTH_JDBC_URL")
65+
REVOPS_CLARI_JDBC_URL=$(op read "op://Product ACT/axiom_gtm/REVOPS_CLARI_JDBC_URL")
66+
REVOPS_SALESFORCE_JDBC_URL=$(op read "op://Product ACT/axiom_gtm/REVOPS_SALESFORCE_JDBC_URL")
67+
;;
68+
healthcare)
69+
HASURA_DDN_PAT=$(op read "op://Product ACT/axiom_healthcare/ddn-service-account")
70+
JWT_SECRET=$(op read "op://Product ACT/axiom_healthcare/JWT_SECRET")
71+
PATIENT_OPS_OPERATIONS_JDBC_URL=$(op read "op://Product ACT/axiom_healthcare/PATIENT_OPS_OPERATIONS_JDBC_URL")
72+
PATIENT_OPS_PATIENTS_JDBC_URL=$(op read "op://Product ACT/axiom_healthcare/PATIENT_OPS_PATIENTS_JDBC_URL")
73+
REFERENCE_REFERENCE_JDBC_URL=$(op read "op://Product ACT/axiom_healthcare/REFERENCE_REFERENCE_JDBC_URL")
74+
;;
75+
*)
76+
echo "Unknown demo: $demo"
77+
continue
78+
;;
79+
esac
80+
81+
cd demos/$demo
82+
ddn auth login --pat "$HASURA_DDN_PAT"
83+
84+
# Create .env.cloud file
85+
case $demo in
86+
gtm)
87+
cat > .env.cloud << EOF
88+
JWT_SECRET=$JWT_SECRET
89+
OPERATIONS_AUTH_JDBC_URL=$OPERATIONS_AUTH_JDBC_URL
90+
REVOPS_CLARI_JDBC_URL=$REVOPS_CLARI_JDBC_URL
91+
REVOPS_SALESFORCE_JDBC_URL=$REVOPS_SALESFORCE_JDBC_URL
92+
EOF
93+
;;
94+
healthcare)
95+
cat > .env.cloud << EOF
96+
JWT_SECRET=$JWT_SECRET
97+
PATIENT_OPS_OPERATIONS_JDBC_URL=$PATIENT_OPS_OPERATIONS_JDBC_URL
98+
PATIENT_OPS_PATIENTS_JDBC_URL=$PATIENT_OPS_PATIENTS_JDBC_URL
99+
REFERENCE_REFERENCE_JDBC_URL=$REFERENCE_REFERENCE_JDBC_URL
100+
EOF
101+
;;
102+
esac
103+
104+
# Build this demo
105+
BUILD_OUTPUT=$(ddn supergraph build create --out json -d "PR #${{ github.event.number }}: ${{ github.event.pull_request.title }} ($demo)")
106+
107+
# Add demo name to build output and append to array
108+
BUILD_WITH_DEMO=$(echo "$BUILD_OUTPUT" | jq ". + {\"demo\": \"$demo\"}")
109+
BUILDS_JSON=$(echo "$BUILDS_JSON" | jq ". += [$BUILD_WITH_DEMO]")
110+
111+
cd ../..
112+
done <<< "${{ steps.demo-setup.outputs.demos }}"
113+
114+
echo "builds_output<<EOF" >> $GITHUB_OUTPUT
115+
echo "$BUILDS_JSON" >> $GITHUB_OUTPUT
116+
echo "EOF" >> $GITHUB_OUTPUT
117+
118+
- name: Comment on PR
119+
if: always()
120+
uses: actions/github-script@v7
121+
with:
122+
script: |
123+
const builds = JSON.parse(`${{ steps.build.outputs.builds_output }}`);
124+
125+
let comment = `## 🚀 PromptQL Builds Complete\n\n`;
126+
127+
builds.forEach(build => {
128+
comment += `### ${build.demo.toUpperCase()} Demo\n`;
129+
comment += `**Build Version:** \`${build.build_version || 'N/A'}\`\n`;
130+
comment += `**Project:** \`${build.project_name || 'pql-docs'}\`\n`;
131+
comment += `**PromptQL Playground:** ${build.promptql_url ? `[Open Playground](${build.promptql_url})` : 'N/A'}\n`;
132+
if (build.description) {
133+
comment += `**Description:** ${build.description}\n`;
134+
}
135+
comment += `\n`;
136+
});
137+
138+
// Find and update existing comment logic...
139+
const comments = await github.rest.issues.listComments({
140+
issue_number: context.issue.number,
141+
owner: context.repo.owner,
142+
repo: context.repo.repo,
143+
});
144+
145+
const existingComment = comments.data.find(comment =>
146+
comment.body.includes('🚀 PromptQL Build Complete')
147+
);
148+
149+
if (existingComment) {
150+
// Update existing comment
151+
await github.rest.issues.updateComment({
152+
comment_id: existingComment.id,
153+
owner: context.repo.owner,
154+
repo: context.repo.repo,
155+
body: comment
156+
});
157+
} else {
158+
// Create new comment
159+
await github.rest.issues.createComment({
160+
issue_number: context.issue.number,
161+
owner: context.repo.owner,
162+
repo: context.repo.repo,
163+
body: comment
164+
});
165+
}
166+
167+
- name: Notify Slack
168+
if: always()
169+
uses: actions/github-script@v7
170+
env:
171+
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
172+
SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }}
173+
with:
174+
script: |
175+
const buildOutput = JSON.parse(`${{ steps.build.outputs.build_output }}`);
176+
177+
console.log('Environment check:');
178+
console.log('SLACK_BOT_TOKEN exists:', !!process.env.SLACK_BOT_TOKEN);
179+
console.log('SLACK_CHANNEL_ID:', process.env.SLACK_CHANNEL_ID);
180+
181+
const slackMessage = `🚀 *PromptQL Build Complete*
182+
183+
*Build Version:* \`${buildOutput.build_version || 'N/A'}\`
184+
*Project:* \`${buildOutput.project_name || 'pql-docs'}\`
185+
*PromptQL Playground:* ${buildOutput.promptql_url ? buildOutput.promptql_url : 'N/A'}
186+
187+
${buildOutput.description ? `*Description:* ${buildOutput.description}` : ''}`;
188+
189+
// Check if thread exists in PR metadata
190+
const comments = await github.rest.issues.listComments({
191+
issue_number: context.issue.number,
192+
owner: context.repo.owner,
193+
repo: context.repo.repo,
194+
});
195+
196+
let threadTs = null;
197+
const threadComment = comments.data.find(comment =>
198+
comment.body.includes('<!-- slack-thread-ts:')
199+
);
200+
201+
if (threadComment) {
202+
const match = threadComment.body.match(/<!-- slack-thread-ts:([^-]+) -->/);
203+
threadTs = match ? match[1] : null;
204+
console.log('Found existing thread:', threadTs);
205+
}
206+
207+
if (!threadTs) {
208+
console.log('Creating new Slack thread...');
209+
const prAuthor = context.payload.pull_request.user.login;
210+
const prTitle = context.payload.pull_request.title;
211+
const prNumber = context.payload.pull_request.number;
212+
213+
const initialMessage = `@${prAuthor} opened a PR »\n\n#${prNumber} ${prTitle}`;
214+
215+
const response = await fetch('https://slack.com/api/chat.postMessage', {
216+
method: 'POST',
217+
headers: {
218+
'Authorization': `Bearer ${process.env.SLACK_BOT_TOKEN}`,
219+
'Content-Type': 'application/json',
220+
},
221+
body: JSON.stringify({
222+
channel: process.env.SLACK_CHANNEL_ID,
223+
text: initialMessage,
224+
}),
225+
});
226+
227+
const slackData = await response.json();
228+
console.log('Slack thread response:', JSON.stringify(slackData, null, 2));
229+
230+
if (!slackData.ok) {
231+
console.error('Failed to create Slack thread:', slackData.error);
232+
return;
233+
}
234+
235+
threadTs = slackData.ts;
236+
237+
// Store thread timestamp in PR comment
238+
await github.rest.issues.createComment({
239+
issue_number: context.issue.number,
240+
owner: context.repo.owner,
241+
repo: context.repo.repo,
242+
body: `<!-- slack-thread-ts:${threadTs} -->`
243+
});
244+
}
245+
246+
// Only post to thread if we have a valid threadTs
247+
if (threadTs) {
248+
console.log('Posting build info to thread:', threadTs);
249+
const buildResponse = await fetch('https://slack.com/api/chat.postMessage', {
250+
method: 'POST',
251+
headers: {
252+
'Authorization': `Bearer ${process.env.SLACK_BOT_TOKEN}`,
253+
'Content-Type': 'application/json',
254+
},
255+
body: JSON.stringify({
256+
channel: process.env.SLACK_CHANNEL_ID,
257+
thread_ts: threadTs,
258+
text: slackMessage,
259+
}),
260+
});
261+
262+
const buildData = await buildResponse.json();
263+
console.log('Slack build response:', JSON.stringify(buildData, null, 2));
264+
265+
if (!buildData.ok) {
266+
console.error('Failed to post build info:', buildData.error);
267+
}
268+
} else {
269+
console.error('No valid thread timestamp available');
270+
}

demos/gtm/.hasura/context.yaml

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,14 @@ definition:
99
subgraph: ../revops/subgraph.yaml
1010
localEnvFile: ../.env
1111
cloudEnvFile: ../.env.cloud
12-
sandbox-gtm:
13-
project: sandbox-gtm
14-
supergraph: ../supergraph.yaml
15-
subgraph: ../revops/subgraph.yaml
16-
localEnvFile: ../.env
17-
cloudEnvFile: ../.env.cloud
1812
scripts:
1913
docker-start:
20-
bash: HASURA_DDN_PAT=$(ddn auth print-access-token) PROMPTQL_SECRET_KEY=$(ddn auth print-promptql-secret-key) docker compose -f compose.yaml --env-file .env up --build --pull always
21-
powershell: $Env:HASURA_DDN_PAT = ddn auth print-access-token; $Env:PROMPTQL_SECRET_KEY = ddn auth print-promptql-secret-key; docker compose -f compose.yaml --env-file .env up --build --pull always
14+
bash:
15+
HASURA_DDN_PAT=$(ddn auth print-access-token) PROMPTQL_SECRET_KEY=$(ddn auth print-promptql-secret-key) docker
16+
compose -f compose.yaml --env-file .env up --build --pull always
17+
powershell:
18+
$Env:HASURA_DDN_PAT = ddn auth print-access-token; $Env:PROMPTQL_SECRET_KEY = ddn auth
19+
print-promptql-secret-key; docker compose -f compose.yaml --env-file .env up --build --pull always
2220
dataset-up:
2321
bash: ../../scripts/ddn-run/dataset-up.sh gtm
2422
powershell: ../../scripts/ddn-run/dataset-up.ps1 gtm
@@ -28,4 +26,4 @@ definition:
2826
jwt-gen:
2927
bash: node ../../scripts/jwt/jwt.mjs
3028
powershell: node ../../scripts/jwt/jwt.mjs
31-
promptQL: true
29+
promptQL: true

demos/healthcare/.hasura/context.yaml

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,14 @@ definition:
99
subgraph: ../patient_ops/subgraph.yaml
1010
localEnvFile: ../.env
1111
cloudEnvFile: ../.env.cloud
12-
sandbox-healthcare:
13-
project: sandbox-healthcare
14-
supergraph: ../supergraph.yaml
15-
subgraph: ../patient_ops/subgraph.yaml
16-
localEnvFile: ../.env
17-
cloudEnvFile: ../.env.cloud
1812
scripts:
1913
docker-start:
20-
bash: HASURA_DDN_PAT=$(ddn auth print-access-token) PROMPTQL_SECRET_KEY=$(ddn auth print-promptql-secret-key) docker compose -f compose.yaml --env-file .env up --build --pull always
21-
powershell: $Env:HASURA_DDN_PAT = ddn auth print-access-token; $Env:PROMPTQL_SECRET_KEY = ddn auth print-promptql-secret-key; docker compose -f compose.yaml --env-file .env up --build --pull always
14+
bash:
15+
HASURA_DDN_PAT=$(ddn auth print-access-token) PROMPTQL_SECRET_KEY=$(ddn auth print-promptql-secret-key) docker
16+
compose -f compose.yaml --env-file .env up --build --pull always
17+
powershell:
18+
$Env:HASURA_DDN_PAT = ddn auth print-access-token; $Env:PROMPTQL_SECRET_KEY = ddn auth
19+
print-promptql-secret-key; docker compose -f compose.yaml --env-file .env up --build --pull always
2220
dataset-up:
2321
bash: ../../scripts/ddn-run/dataset-up.sh healthcare
2422
powershell: ../../scripts/ddn-run/dataset-up.ps1 healthcare
@@ -28,4 +26,4 @@ definition:
2826
jwt-gen:
2927
bash: node ../../scripts/jwt/jwt.mjs
3028
powershell: node ../../scripts/jwt/jwt.mjs
31-
promptQL: true
29+
promptQL: true

0 commit comments

Comments
 (0)