From 4ad44817c10d2771ace9f600ae6b11d2b5d80ae3 Mon Sep 17 00:00:00 2001 From: Glenn Terjesen Date: Tue, 14 Apr 2026 09:09:42 +0200 Subject: [PATCH 1/4] fix: use composite actions for slack --- .github/actions/post/action.yml | 77 ++++++++++++++++++++++++++++++++ .github/actions/react/action.yml | 30 +++++++++++++ .github/workflows/post.yml | 54 +++------------------- .github/workflows/react.yml | 12 ++--- 4 files changed, 118 insertions(+), 55 deletions(-) create mode 100644 .github/actions/post/action.yml create mode 100644 .github/actions/react/action.yml diff --git a/.github/actions/post/action.yml b/.github/actions/post/action.yml new file mode 100644 index 0000000..3837925 --- /dev/null +++ b/.github/actions/post/action.yml @@ -0,0 +1,77 @@ +name: Entur/Slack/Post +description: Post a message to Slack + +inputs: + channel_id: + description: "Slack channel ID" + required: true + message: + description: "Plain text message" + required: false + default: "Default slack message" + blocks: + description: "Slack Block Kit JSON blocks" + required: false + thread_ts: + description: "Post as threaded reply to this message timestamp" + required: false + token: + description: "Slack bot token" + required: true + +outputs: + message_ts: + description: "Slack message timestamp (unique message ID)" + value: ${{ steps.capture-ts.outputs.message_ts }} + +runs: + using: composite + steps: + - id: set-env + shell: bash + env: + INPUT_CHANNEL: ${{ inputs.channel_id }} + INPUT_MESSAGE: ${{ inputs.message }} + INPUT_BLOCKS: ${{ inputs.blocks }} + INPUT_THREAD_TS: ${{ inputs.thread_ts }} + run: | + echo "GHA_SLACK_POST_CHANNEL=$INPUT_CHANNEL" >> $GITHUB_ENV + echo 'GHA_SLACK_POST_MESSAGE<> $GITHUB_ENV + echo "$INPUT_MESSAGE" >> $GITHUB_ENV + echo 'GHA_SLACK_EOM_DELIMITER' >> $GITHUB_ENV + if [ -n "$INPUT_BLOCKS" ]; then + echo "$INPUT_BLOCKS" | jq . > /dev/null 2>&1 || { echo "::error::blocks input is not valid JSON"; exit 1; } + fi + echo 'GHA_SLACK_POST_BLOCKS<> $GITHUB_ENV + echo "$INPUT_BLOCKS" >> $GITHUB_ENV + echo 'GHA_SLACK_EOB_DELIMITER' >> $GITHUB_ENV + echo "GHA_SLACK_POST_THREAD_TS=$INPUT_THREAD_TS" >> $GITHUB_ENV + - id: build-payload + shell: bash + env: + CHANNEL: ${{ env.GHA_SLACK_POST_CHANNEL }} + TEXT: ${{ env.GHA_SLACK_POST_MESSAGE }} + BLOCKS: ${{ env.GHA_SLACK_POST_BLOCKS }} + THREAD_TS: ${{ env.GHA_SLACK_POST_THREAD_TS }} + run: | + PAYLOAD=$(jq -n \ + --arg channel "$CHANNEL" \ + --arg text "$TEXT" \ + --arg thread_ts "$THREAD_TS" \ + '{channel: $channel, text: $text} + (if $thread_ts != "" then {thread_ts: $thread_ts} else {} end)') + if [ -n "$BLOCKS" ]; then + PAYLOAD=$(echo "$PAYLOAD" | jq --argjson blocks "$BLOCKS" '. + {blocks: $blocks}') + fi + echo "payload<> $GITHUB_OUTPUT + echo "$PAYLOAD" >> $GITHUB_OUTPUT + echo "GHA_SLACK_PAYLOAD_DELIMITER" >> $GITHUB_OUTPUT + - id: slack-post + uses: slackapi/slack-github-action@v3.0.1 + with: + method: chat.postMessage + token: ${{ inputs.token }} + payload: ${{ steps.build-payload.outputs.payload }} + - id: capture-ts + shell: bash + run: | + echo "message_ts=${{ steps.slack-post.outputs.ts }}" >> $GITHUB_OUTPUT diff --git a/.github/actions/react/action.yml b/.github/actions/react/action.yml new file mode 100644 index 0000000..4066690 --- /dev/null +++ b/.github/actions/react/action.yml @@ -0,0 +1,30 @@ +name: Entur/Slack/React +description: Add a reaction to a Slack message + +inputs: + channel_id: + description: "Slack channel ID" + required: true + message_ts: + description: "Message timestamp to react to" + required: true + emoji: + description: "Emoji name without colons" + required: true + token: + description: "Slack bot token" + required: true + +runs: + using: composite + steps: + - id: slack-react + uses: slackapi/slack-github-action@v3.0.1 + with: + method: reactions.add + token: ${{ inputs.token }} + errors: true + payload: | + channel: "${{ inputs.channel_id }}" + timestamp: "${{ inputs.message_ts }}" + name: "${{ inputs.emoji }}" diff --git a/.github/workflows/post.yml b/.github/workflows/post.yml index 9c7ee5b..dc9f701 100644 --- a/.github/workflows/post.yml +++ b/.github/workflows/post.yml @@ -35,53 +35,13 @@ jobs: permissions: contents: read outputs: - message_ts: ${{ steps.capture-ts.outputs.message_ts }} + message_ts: ${{ steps.post.outputs.message_ts }} steps: - - id: set-env - shell: bash - env: - INPUT_CHANNEL: ${{ inputs.channel_id }} - INPUT_MESSAGE: ${{ inputs.message }} - INPUT_BLOCKS: ${{ inputs.blocks }} - INPUT_THREAD_TS: ${{ inputs.thread_ts }} - run: | - echo "GHA_SLACK_POST_CHANNEL=$INPUT_CHANNEL" >> $GITHUB_ENV - echo 'GHA_SLACK_POST_MESSAGE<> $GITHUB_ENV - echo "$INPUT_MESSAGE" >> $GITHUB_ENV - echo 'GHA_SLACK_EOM_DELIMITER' >> $GITHUB_ENV - if [ -n "$INPUT_BLOCKS" ]; then - echo "$INPUT_BLOCKS" | jq . > /dev/null 2>&1 || { echo "::error::blocks input is not valid JSON"; exit 1; } - fi - echo 'GHA_SLACK_POST_BLOCKS<> $GITHUB_ENV - echo "$INPUT_BLOCKS" >> $GITHUB_ENV - echo 'GHA_SLACK_EOB_DELIMITER' >> $GITHUB_ENV - echo "GHA_SLACK_POST_THREAD_TS=$INPUT_THREAD_TS" >> $GITHUB_ENV - - id: build-payload - shell: bash - env: - CHANNEL: ${{ env.GHA_SLACK_POST_CHANNEL }} - TEXT: ${{ env.GHA_SLACK_POST_MESSAGE }} - BLOCKS: ${{ env.GHA_SLACK_POST_BLOCKS }} - THREAD_TS: ${{ env.GHA_SLACK_POST_THREAD_TS }} - run: | - PAYLOAD=$(jq -n \ - --arg channel "$CHANNEL" \ - --arg text "$TEXT" \ - --arg thread_ts "$THREAD_TS" \ - '{channel: $channel, text: $text} + (if $thread_ts != "" then {thread_ts: $thread_ts} else {} end)') - if [ -n "$BLOCKS" ]; then - PAYLOAD=$(echo "$PAYLOAD" | jq --argjson blocks "$BLOCKS" '. + {blocks: $blocks}') - fi - echo "payload<> $GITHUB_OUTPUT - echo "$PAYLOAD" >> $GITHUB_OUTPUT - echo "GHA_SLACK_PAYLOAD_DELIMITER" >> $GITHUB_OUTPUT - - id: slack-post - uses: slackapi/slack-github-action@v3.0.1 + - id: post + uses: ./.github/actions/post with: - method: chat.postMessage + channel_id: ${{ inputs.channel_id }} + message: ${{ inputs.message }} + blocks: ${{ inputs.blocks }} + thread_ts: ${{ inputs.thread_ts }} token: ${{ secrets.SLACK_BOT_TOKEN }} - payload: ${{ steps.build-payload.outputs.payload }} - - id: capture-ts - shell: bash - run: | - echo "message_ts=${{ steps.slack-post.outputs.ts }}" >> $GITHUB_OUTPUT diff --git a/.github/workflows/react.yml b/.github/workflows/react.yml index f98a331..dfeaa66 100644 --- a/.github/workflows/react.yml +++ b/.github/workflows/react.yml @@ -26,13 +26,9 @@ jobs: permissions: contents: read steps: - - id: slack-react - uses: slackapi/slack-github-action@v3.0.1 + - uses: ./.github/actions/react with: - method: reactions.add + channel_id: ${{ inputs.channel_id }} + message_ts: ${{ inputs.message_ts }} + emoji: ${{ inputs.emoji }} token: ${{ secrets.SLACK_BOT_TOKEN }} - errors: true - payload: | - channel: "${{ inputs.channel_id }}" - timestamp: "${{ inputs.message_ts }}" - name: "${{ inputs.emoji }}" From eb3cdb93cb019af813dcb25112bebfeceae193cf Mon Sep 17 00:00:00 2001 From: Glenn Terjesen Date: Tue, 14 Apr 2026 09:15:47 +0200 Subject: [PATCH 2/4] fix: checkout before ci test --- .github/workflows/post.yml | 1 + .github/workflows/react.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/post.yml b/.github/workflows/post.yml index dc9f701..0a063b5 100644 --- a/.github/workflows/post.yml +++ b/.github/workflows/post.yml @@ -37,6 +37,7 @@ jobs: outputs: message_ts: ${{ steps.post.outputs.message_ts }} steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - id: post uses: ./.github/actions/post with: diff --git a/.github/workflows/react.yml b/.github/workflows/react.yml index dfeaa66..595a59e 100644 --- a/.github/workflows/react.yml +++ b/.github/workflows/react.yml @@ -26,6 +26,7 @@ jobs: permissions: contents: read steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: ./.github/actions/react with: channel_id: ${{ inputs.channel_id }} From 348ade058e716bdb3ee9a8f53ec2757b7e5fbeed Mon Sep 17 00:00:00 2001 From: Glenn-Terjesen Date: Tue, 14 Apr 2026 07:16:26 +0000 Subject: [PATCH 3/4] docs: Update workflow documentation --- README-react.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/README-react.md b/README-react.md index 5be938a..4a3d70b 100644 --- a/README-react.md +++ b/README-react.md @@ -54,19 +54,17 @@ jobs: -| INPUT | TYPE | REQUIRED | DEFAULT | DESCRIPTION | -| ----------------------------------------------------------------------------- | ------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| [channel_id](#input_channel_id) | string | true | | Slack channel ID where the
message was posted | -| [emoji](#input_emoji) | string | true | | Emoji name to react with (without colons). Common examples:
- `white_check_mark` ✅ success / done
- `x` ❌ failure
- `rocket` 🚀 deployment / release
- `eyes` 👀 reviewing / taking a look
- `tada` 🎉 celebration
- `warning` ⚠️ warning
- `thumbsup` 👍 approval | -| [message_ts](#input_message_ts) | string | true | | Slack message timestamp (unique message ID) to
react to | -| [timeout_minutes](#input_timeout_minutes) | number | false | `5` | Job timeout in minutes | +| INPUT | TYPE | REQUIRED | DEFAULT | DESCRIPTION | +|-------------------------------------------------------------------------------|--------|----------|---------|--------------------------------------------------------------| +| [channel_id](#input_channel_id) | string | true | | Slack channel ID where the
message was posted | +| [emoji](#input_emoji) | string | true | | Emoji name to react with
(without colons) | +| [message_ts](#input_message_ts) | string | true | | Slack message timestamp (unique message ID) to
react to | +| [timeout_minutes](#input_timeout_minutes) | number | false | `5` | Job timeout in minutes | ## Outputs - No outputs. - From 15fccab48d702fa0d33b05af2de48debaa8c6e4f Mon Sep 17 00:00:00 2001 From: Glenn Terjesen Date: Tue, 14 Apr 2026 09:58:31 +0200 Subject: [PATCH 4/4] fix: dependabot pr's --- .github/workflows/{cd.yml => cd.yaml} | 0 .github/workflows/{ci.yml => ci.yaml} | 12 +++++------- .github/workflows/dependabot-pr.yaml | 20 ++++++++++++++++++++ 3 files changed, 25 insertions(+), 7 deletions(-) rename .github/workflows/{cd.yml => cd.yaml} (100%) rename .github/workflows/{ci.yml => ci.yaml} (90%) create mode 100644 .github/workflows/dependabot-pr.yaml diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yaml similarity index 100% rename from .github/workflows/cd.yml rename to .github/workflows/cd.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yaml similarity index 90% rename from .github/workflows/ci.yml rename to .github/workflows/ci.yaml index b004a72..e9b660f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yaml @@ -1,12 +1,10 @@ name: Entur/Slack/CI on: - push: - branches: - - main + workflow_call: pull_request: - pull_request_review: - types: [submitted] + branches: [main] + types: [opened, synchronize, reopened, edited] # on PR edit, rerun jobs: verify-pr: @@ -15,7 +13,7 @@ jobs: uses: entur/gha-meta/.github/workflows/verify-pr.yml@v1 test-post-message: - if: github.actor != 'dependabot[bot]' || (github.event_name == 'pull_request_review' && github.event.review.state == 'approved') + if: github.actor != 'dependabot[bot]' uses: ./.github/workflows/post.yml with: channel_id: "C01AVRY6Q23" # notify-plattform @@ -23,7 +21,7 @@ jobs: secrets: inherit test-post-message-with-blocks: - if: github.actor != 'dependabot[bot]' || (github.event_name == 'pull_request_review' && github.event.review.state == 'approved') + if: github.actor != 'dependabot[bot]' uses: ./.github/workflows/post.yml with: channel_id: "C01AVRY6Q23" # notify-plattform diff --git a/.github/workflows/dependabot-pr.yaml b/.github/workflows/dependabot-pr.yaml new file mode 100644 index 0000000..5a40bbf --- /dev/null +++ b/.github/workflows/dependabot-pr.yaml @@ -0,0 +1,20 @@ +# Dependabot pull request workflow +# +# Dependabot PRs do not receive repository secrets by default. +# This workflow adds an approval gate so secrets are only exposed after a human has reviewed and approved the PR. +# You can use workflow_dispatch to test the workflow before enabling the approval flow. + +name: on-pull_request_review-submitted + +on: + pull_request_review: + types: [submitted] + +permissions: + contents: read + +jobs: + ci: + if: github.event.review.state == 'approved' && github.event.pull_request.user.login == 'dependabot[bot]' + uses: ./.github/workflows/ci.yaml + secrets: inherit \ No newline at end of file