Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .github/actions/slack-post/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Post Slack Message
description: Post a Block Kit message to a Slack channel via chat.postMessage

inputs:
channel:
description: Slack channel to post to (e.g. '#agentic-service-alerts')
required: true
header:
description: Header text for the message (also used as fallback text)
required: true
content:
description: JSON array of Block Kit blocks for the message body
required: true

runs:
using: composite
steps:
- name: Post to Slack
shell: bash
env:
SLACK_CHANNEL: ${{ inputs.channel }}
SLACK_HEADER: ${{ inputs.header }}
SLACK_CONTENT: ${{ inputs.content }}
GITHUB_REPO: ${{ github.repository }}
GITHUB_SERVER: ${{ github.server_url }}
GITHUB_RUN: ${{ github.run_id }}
run: |
if [ -z "$SLACK_TOKEN" ]; then
echo "::error::SLACK_TOKEN environment variable is not set"
exit 1
fi

if ! echo "$SLACK_CONTENT" | jq -e 'type == "array"' > /dev/null 2>&1; then
echo "::error::content input must be a valid JSON array"
exit 1
fi

TIMESTAMP=$(date +%s)
TIMESTAMP_FMT=$(date -u +%Y-%m-%dT%H:%M:%SZ)

PAYLOAD=$(jq -n \
--arg channel "$SLACK_CHANNEL" \
--arg header "$SLACK_HEADER" \
--arg repo "$GITHUB_REPO" \
--arg server "$GITHUB_SERVER" \
--arg run_id "$GITHUB_RUN" \
--argjson content "$SLACK_CONTENT" \
--argjson ts "$TIMESTAMP" \
--arg ts_fmt "$TIMESTAMP_FMT" \
'{
channel: $channel,
text: $header,
blocks: (
[
{type: "header", text: {type: "plain_text", text: $header}},
{type: "context", elements: [{type: "mrkdwn", text: "<\($server)/\($repo)|\($repo)> | <\($server)/\($repo)/actions/runs/\($run_id)|Run #\($run_id)>"}]}
]
+ $content
+ [
{type: "context", elements: [{type: "mrkdwn", text: "Posted at <!date^\($ts)^{date_num} {time_secs}|\($ts_fmt)>"}]}
]
)
}')

RESPONSE=$(curl -s -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_TOKEN" \
-H "Content-Type: application/json" \
-d "$PAYLOAD")

if [ "$(echo "$RESPONSE" | jq -r '.ok')" != "true" ]; then
echo "::error::Slack API error: $(echo "$RESPONSE" | jq -r '.error')"
exit 1
fi
36 changes: 20 additions & 16 deletions .github/workflows/drift-detection.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ jobs:
steps:
- uses: actions/checkout@v6

- uses: scope3data/actions/node/install@node/install/v1
- uses: actions/setup-node@v6
with:
node-version-file: '.nvmrc'
cache: 'npm'

- name: Install dependencies
run: npm ci --no-audit --no-fund --ignore-scripts

- name: Run drift detection
id: drift
Expand Down Expand Up @@ -49,30 +55,28 @@ jobs:

- name: Alert on drift
if: steps.drift.outputs.exit_code == '1'
uses: ./.github/actions/slack-post
env:
SLACK_TOKEN: ${{ secrets.SLACK_NOTIF_BOT_TOKEN }}
uses: scope3data/actions/slack/post@slack/post/v2
with:
channel: '#agentic-service-alerts'
header: 'SDK API Drift Detected'
content: |
[
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*${{ steps.parse.outputs.total }} endpoint(s) out of sync*\n\n*skill.md vs spec:*\n• Missing from skill.md: ${{ steps.parse.outputs.skill_missing }}\n• Extra in skill.md: ${{ steps.parse.outputs.skill_extra }}\n\n*SDK vs spec:*\n• Missing from SDK: ${{ steps.parse.outputs.sdk_missing }}\n• Extra in SDK: ${{ steps.parse.outputs.sdk_extra }}"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View full report>"
}
}
{"type": "section", "text": {"type": "mrkdwn", "text": "*${{ steps.parse.outputs.total }} endpoint(s) out of sync*\n\n*skill.md vs spec:*\n• Missing from skill.md: ${{ steps.parse.outputs.skill_missing }}\n• Extra in skill.md: ${{ steps.parse.outputs.skill_extra }}\n\n*SDK vs spec:*\n• Missing from SDK: ${{ steps.parse.outputs.sdk_missing }}\n• Extra in SDK: ${{ steps.parse.outputs.sdk_extra }}"}},
{"type": "section", "text": {"type": "mrkdwn", "text": "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View full report>"}}
]

- name: Notify on failure
if: failure()
uses: ./.github/actions/slack-post
env:
SLACK_TOKEN: ${{ secrets.SLACK_NOTIF_BOT_TOKEN }}
with:
channel: '#agentic-service-alerts'
header: 'API Drift Detection Failed'
content: '[{"type": "section", "text": {"type": "mrkdwn", "text": "The drift detection workflow failed. <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View run>"}}]'

regenerate:
name: Regenerate Schemas
needs: detect-drift
Expand Down
36 changes: 20 additions & 16 deletions .github/workflows/regenerate-schemas.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ jobs:
with:
token: ${{ steps.app-token.outputs.token }}

- uses: scope3data/actions/node/install@node/install/v1
- uses: actions/setup-node@v6
with:
node-version-file: '.nvmrc'
cache: 'npm'

- name: Install dependencies
run: npm ci --no-audit --no-fund --ignore-scripts

- name: Regenerate schemas
run: npm run generate-schemas
Expand Down Expand Up @@ -81,26 +87,24 @@ jobs:

- name: Notify Slack
if: steps.create-pr.outputs.pr_url
uses: ./.github/actions/slack-post
env:
SLACK_TOKEN: ${{ secrets.SLACK_NOTIF_BOT_TOKEN }}
uses: scope3data/actions/slack/post@slack/post/v2
with:
channel: '#agentic-service-alerts'
header: 'SDK Schemas Regenerated'
content: |
[
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "A PR has been created to update Zod schemas from the latest OpenAPI specification."
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "<${{ steps.create-pr.outputs.pr_url }}|View Pull Request>"
}
}
{"type": "section", "text": {"type": "mrkdwn", "text": "A PR has been created to update Zod schemas from the latest OpenAPI specification."}},
{"type": "section", "text": {"type": "mrkdwn", "text": "<${{ steps.create-pr.outputs.pr_url }}|View Pull Request>"}}
]

- name: Notify on failure
if: failure()
uses: ./.github/actions/slack-post
env:
SLACK_TOKEN: ${{ secrets.SLACK_NOTIF_BOT_TOKEN }}
with:
channel: '#agentic-service-alerts'
header: 'Schema Regeneration Failed'
content: '[{"type": "section", "text": {"type": "mrkdwn", "text": "The schema regeneration workflow failed. <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View run>"}}]'
10 changes: 10 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,13 @@ jobs:
title: 'chore: version packages'
env:
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}

- name: Notify on failure
if: failure()
uses: ./.github/actions/slack-post
env:
SLACK_TOKEN: ${{ secrets.SLACK_NOTIF_BOT_TOKEN }}
with:
channel: '#agentic-service-alerts'
header: 'Release Failed'
content: '[{"type": "section", "text": {"type": "mrkdwn", "text": "The release workflow failed. <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View run>"}}]'