@@ -189,13 +189,33 @@ jobs:
189189 body: body,
190190 });
191191
192+ - name : Parse preview links from PR body
193+ id : preview-links
194+ uses : actions/github-script@v7
195+ with :
196+ script : |
197+ const prBody = context.payload.pull_request.body || '';
198+
199+ // Parse <!-- preview-link: tasks=N --> from PR body
200+ const tasksMatch = prBody.match(/<!--\s*preview-link:\s*tasks=(\d+)\s*-->/i);
201+ if (tasksMatch) {
202+ const tasksPrNum = tasksMatch[1];
203+ core.setOutput('tasks-pr', tasksPrNum);
204+ console.log(`Found linked tasks preview: PR #${tasksPrNum}`);
205+ } else {
206+ core.setOutput('tasks-pr', '');
207+ console.log('No linked tasks preview found in PR body');
208+ }
209+
192210 - name : Deploy to preview host
193211 env :
194212 SSH_PRIVATE_KEY : ${{ secrets.PREVIEW_DEPLOY_SSH_KEY }}
195213 PREVIEW_HOST : ${{ secrets.PREVIEW_HOST }}
196214 PREVIEW_USER : ${{ secrets.PREVIEW_USER || 'opencouncil' }}
197215 STORE_PATH : ${{ steps.store-path.outputs.path }}
198216 HAS_MIGRATIONS : ${{ needs.check-migrations.outputs.has-migrations }}
217+ LINKED_TASKS_PR : ${{ steps.preview-links.outputs.tasks-pr }}
218+ PREVIEW_TASKS_API_KEY : ${{ secrets.PREVIEW_TASKS_API_KEY }}
199219 run : |
200220 set -euo pipefail
201221
@@ -221,6 +241,19 @@ jobs:
221241
222242 # The droplet pulls the build from Cachix automatically (configured as a substituter).
223243 # Just SSH in and create the preview — nix-store --realise is called by the create script.
244+
245+ # Write per-preview env overrides BEFORE create (so service picks them up on first start)
246+ if [ -n "${LINKED_TASKS_PR:-}" ]; then
247+ echo "🔗 Linking to tasks preview PR #$LINKED_TASKS_PR"
248+ TASKS_URL="https://pr-${LINKED_TASKS_PR}.tasks.opencouncil.gr"
249+ $SSH_CMD "mkdir -p /var/lib/opencouncil-previews/pr-$PR_NUM && cat > /var/lib/opencouncil-previews/pr-$PR_NUM/.env.local <<EOF
250+ # Linked tasks preview (from PR body: <!-- preview-link: tasks=$LINKED_TASKS_PR -->)
251+ TASK_API_URL=$TASKS_URL
252+ TASK_API_KEY=${PREVIEW_TASKS_API_KEY:-}
253+ EOF
254+ chmod 600 /var/lib/opencouncil-previews/pr-$PR_NUM/.env.local"
255+ fi
256+
224257 echo "Creating/updating preview instance..."
225258 $SSH_CMD "sudo opencouncil-preview-create '$PR_NUM' '$STORE_PATH' $DEPLOY_FLAGS"
226259
@@ -233,6 +266,9 @@ jobs:
233266 else
234267 echo "Database : Shared staging" >> $GITHUB_STEP_SUMMARY
235268 fi
269+ if [ -n "${LINKED_TASKS_PR:-}" ]; then
270+ echo "Tasks API : https://pr-${LINKED_TASKS_PR}.tasks.opencouncil.gr" >> $GITHUB_STEP_SUMMARY
271+ fi
236272
237273 - name : Health check
238274 id : health-check
@@ -263,6 +299,7 @@ jobs:
263299 const healthStatus = '${{ steps.health-check.outputs.status }}';
264300 const logsUrl = context.serverUrl + '/' + context.repo.owner + '/' + context.repo.repo + '/actions/runs/' + context.runId;
265301 const hasMigrations = '${{ needs.check-migrations.outputs.has-migrations }}' === 'true';
302+ const linkedTasksPr = '${{ steps.preview-links.outputs.tasks-pr }}';
266303
267304 const dbNote = hasMigrations
268305 ? '*This preview uses an **isolated database** with seed data (migrations were applied).*'
@@ -271,8 +308,13 @@ jobs:
271308 let body = '## 🚀 Preview deployment ready!\n\n'
272309 + '**Preview URL:** ' + previewUrl + '\n'
273310 + '**Commit:** `' + commitSha + '`\n'
274- + '**Database:** ' + (hasMigrations ? 'Isolated (PostGIS 3.3.5, seed data)' : 'Shared staging') + '\n\n'
275- + 'The preview will be automatically updated when you push new commits.\n'
311+ + '**Database:** ' + (hasMigrations ? 'Isolated (PostGIS 3.3.5, seed data)' : 'Shared staging') + '\n';
312+
313+ if (linkedTasksPr) {
314+ body += '**Tasks API:** https://pr-' + linkedTasksPr + '.tasks.opencouncil.gr\n';
315+ }
316+
317+ body += '\nThe preview will be automatically updated when you push new commits.\n'
276318 + 'It will be destroyed when this PR is closed or merged.\n\n';
277319
278320 if (healthStatus === 'unhealthy') {
0 commit comments