argoproj / argoproj/notifications-engine
[slack] Support new Block Kit blocks in notification templates
- Dominant language
- Go
- Stars
- 334
- Forks
- 217
- PR merge metrics
- No merged PRs in 30d
Description
The Slack service pins `github.com/slack-go/slack` at `v0.16.0`. Block Kit types added since then (e.g. `table`, `markdown`) aren't in `Blocks.UnmarshalJSON`'s type switch, so they fall through to `UnknownBlock`, which only keeps `type`/`block_id` and drops everything else.
The block is then re-marshaled as a bare `{"type":"table"}` and Slack's API rejects the whole payload with `invalid_blocks`/`invalid_attachments`, whether the block was placed under `slack.blocks` or `slack.attachments`.
From a user perspective, this feels like a wrongly formatted template on its end when in reality it's the client that silently strips the block's content.
## Reproduction
Save the following file as `main.go` in a new folder. It unmarshals a `section` block alongside a `table` and a `markdown` block (similarly to how it's done in [`slack.go`](https://github.com/argoproj/notifications-engine/blob/master/pkg/services/slack.go#L155-L163)), then re-marshals them as is currently done by the Slack client (see [`chat.go`](https://github.com/slack-go/slack/blob/v0.27.0/chat.go#L397-L403)):
```go
// main.go
package main
import (
"encoding/json"
"fmt"
"github.com/slack-go/slack"
)
func main() {
input := `[
{"type": "section", "text": {"type": "mrkdwn", "text": "hello"}},
{"type": "table", "rows": [[{"type": "raw_text", "text": "a"}]]},
{"type": "markdown", "text": "**bold**"}
]`
var blocks slack.Blocks
json.Unmarshal([]byte(input), &blocks)
for i, b := range blocks.BlockSet {
fmt.Printf("block[%d]: %T (%s)\n", i, b, b.BlockType())
}
out, _ := json.Marshal(blocks)
fmt.Println(string(out))
}
```
Initialize this folder as a Go module, fetch the currently pinned `slack-go` version and run `main.go`:
```text
$ go mod init repo
$ go get github.com/slack-go/slack@v0.16.0
$ go run main.go
block[0]: *slack.SectionBlock (section)
block[1]: *slack.UnknownBlock (table)
block[2]: *slack.UnknownBlock (markdown)
[{"type":"section","text":{"type":"mrkdwn","text":"hello"}},{"type":"table"},{"type":"markdown"}]
```
Re-run the same test after updating `slack-go` to `v0.27.0`:
```text
$ go get github.com/slack-go/slack@v0.27.0
$ go run main.go
[{"type":"section","text":{"type":"mrkdwn","text":"hello"}},{"type":"table","rows":[[{"type":"raw_text","text":"a"}]]},{"type":"markdown","text":"**bold**"}]
```
## Proposed fix
Bump `github.com/slack-go/slack` in `go.mod` to a current release to support those newly added blocks.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with go.mod and the Slack integration in pkg/services/slack.go, then run the provided main.go reproduction using the pinned dependency. Verify that table and markdown blocks retain their fields when unmarshaled and re-marshaled, including when used in Slack blocks or attachments.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 82/100