jenkinsci / slack-plugin

A Jenkins plugin for posting notifications to a Slack channel
https://plugins.jenkins.io/slack/
672 stars 413 forks source link

SlackUploadFile for channel threads are not working after latest update. #966

Closed raghavanrrs closed 1 month ago

timja commented 1 month ago

Please provide more information on how to reproduce, your slack plugin version, your build log from when running the upload and system logs.

Have you added the new required scopes: https://github.com/jenkinsci/slack-plugin/releases/tag/711.v41060f587001

raghavanrrs commented 1 month ago

Please provide more information on how to reproduce, your slack plugin version, your build log from when running the upload and system logs.

Have you added the new required scopes: https://github.com/jenkinsci/slack-plugin/releases/tag/711.v41060f587001

Issue: Unable to upload files to User channel (userID resolved from commits) threads, but can able to upload files to Group channels in a thread Slack plugin version: 714.v62ffe7c796cd

Jenkins version: Jenkins 2.454 Build Log: [Pipeline] slackUploadFile ERROR: Failed uploading file to slack, channel not found: :1715237120.817939

Method: slackUploadFile(channel: "${env.userId}" + ":" + slackUserResponse.ts , filePath: "changelog.txt", initialComment: "<@$userId> Detailed summary of changes for Build ${env.BUILD_NUMBER}.")

Bot Permissions: chat:write chat:write.customize chat:write.public files:write incoming-webhook channels:read groups:read files:read users:read users:read.email

timja commented 1 month ago

Hi, apologies for this.

It appears this was an unintentional feature that Slack wasn't aware of

https://github.com/slackapi/python-slack-sdk/issues/1326#issuecomment-1424986841

I've tested the workaround they suggested in https://github.com/jenkinsci/slack-plugin/pull/967 It will work after a minor change I made to fallback to try what the user passed in if it can't be found in the channel ID cache.

You will need to adapt your code to message a user first then user the channel ID from the response, (see the updated docs in the PR)

ctrongminh commented 1 month ago

Hi @timja , Could you please help to share your bot testing API scope permission ?

I'm using the below code as the testing in https://github.com/jenkinsci/slack-plugin/pull/967, but got the error channel_not_found

def slackResponse = slackSend channel: 'U05052SAR54', message: 'Hey', sendAsText: true slackUploadFile filePath: "*.txt", channel: slackResponse.channelId

Slack upload may have failed. Response: {"ok":false,"error":"channel_not_found"}

Please note: I already modified the channel ID before posting, Thank you.

timja commented 1 month ago

That Hey message successfully sent a message to the users private channel?

My testing bot has the config from the manifest here: https://github.com/jenkinsci/slack-plugin#creating-your-app

ctrongminh commented 1 month ago

Hi @timja ,

Yes, the "Hey" is successfully sent to Slackbot of the user, and then the it timeouts for the slackUploadFile command (5-6 minutes).

With the file.upload V1, we received the "Hey" in Slackbot, and the files are sent in the Jenkins app (you can see in the image, there are Slackbot and Jenkins app, which is separated, not as one),

Screen Shot 2024-05-13 at 22 21 28

Full error message for the slackUploadFile command

Using dirname=/var/lib/jenkins/workspace/test and includeMask=*.txt
Adding file /var/lib/jenkins/workspace/test/test.txt
ERROR: Failed uploading file to slack
Slack upload may have failed. Response: {"ok":false,"error":"channel_not_found"}
Failed to complete uploading file to Slack

Slack plugin version: 715.v1cfed1b_9c63c

timja commented 1 month ago

can you print the channel ID I think it should start with a D? after slackSend and before uploading the file

something like:

echo slackResponse.id

or

sh "echo $slackResponse.id"

ctrongminh commented 1 month ago

yes, the slackResponse.channelId output to the ID which starts with D, for the user, it starts with U. I even input the channelId to the slackUploadFile but still, got the channel_not_found

def slackResponse = slackSend channel: 'U05052SAR54', message: 'Hey', sendAsText: true
slackUploadFile filePath: "*.txt", channel: 'D050861H9N1'
timja commented 1 month ago

Hi @timja ,

With the file.upload V1, we received the "Hey" in Slackbot, and the files are sent in the Jenkins app (you can see in the image, there are Slackbot and Jenkins app, which is separated, not as one),

Try change it to this:

def slackResponse = slackSend channel: 'U05052SAR54', message: 'Hey', sendAsText: true, botUser: true
slackUploadFile filePath: "*.txt", channel: slackResponse.id
raghavanrrs commented 1 month ago

Hi @timja , With the file.upload V1, we received the "Hey" in Slackbot, and the files are sent in the Jenkins app (you can see in the image, there are Slackbot and Jenkins app, which is separated, not as one),

Try change it to this:

def slackResponse = slackSend channel: 'U05052SAR54', message: 'Hey', sendAsText: true, botUser: true
slackUploadFile filePath: "*.txt", channel: slackResponse.id

throws error:

Also: org.jenkinsci.plugins.workflow.actions.ErrorAction$ErrorId: dbab4939-33b7-4f42-a386-a34075775b95 groovy.lang.MissingPropertyException: No such field found: field jenkins.plugins.slack.workflow.SlackResponse id

Also how to print slackResponse in user friendly format??

timja commented 1 month ago

ah sorry channelId.

def slackResponse = slackSend channel: 'U05052SAR54', message: 'Hey', sendAsText: true, botUser: true
slackUploadFile filePath: "*.txt", channel: slackResponse.channelId
ctrongminh commented 1 month ago

Hi @timja ,

I think I found the root cause,

In our case, when we use slackSend to send message to the user, the chat is sent from SlackBot to the user, which results to the channel Id of the SlackBot.

However, for the slackUploadFile to work, we need to input the channel Id of the Jenkins Apps for that user. I tested it by manually inputting the Jenkins App Channel Id, for my user to the slackUploadFile.

With the checkbox "Custom slack app bot user", message will be sent to SlackBot. However, if we uncheck, the connection will fail

image
timja commented 1 month ago

If you send as custom slack app bot user then it should come from the app not slackbot.

That's what I was trying to test in the last sample I sent to see if explicitly setting it to true makes it work.

ctrongminh commented 1 month ago

thank you, let me try it with flag, I miss that,

"botUser: true"

ctrongminh commented 1 month ago

it still failed at slackUploadFile step with setting "botUser: true" at the slackSend, as the slackResponse.channelId resolved to the SlackBot's channel Id.

In the description of "Custom slack app bot user", it says the chat will be sent as @slackbot.

"If the notification will be sent to a user via direct message, the default integration sends it via @slackbot, use this option if you want to send messages via a bot user"

MatthewBooth commented 1 month ago

I'm having a similar issue here, but instead of a user, I'm using a thread posted in a channel, using: slackResponse.threadId as the channel: value.

The response is the same:

Slack upload may have failed. Response: {"ok":false,"error":"channel_not_found"}
10:40:37  Failed to complete uploading file to Slack
raghavanrrs commented 1 month ago

I'm having a similar issue here, but instead of a user, I'm using a thread posted in a channel, using: slackResponse.threadId as the channel: value.

The response is the same:

Slack upload may have failed. Response: {"ok":false,"error":"channel_not_found"}
10:40:37  Failed to complete uploading file to Slack

for Reply to a channel thread we are using slackResponse.ts which works in our case.

MatthewBooth commented 1 month ago

I'm having a similar issue here, but instead of a user, I'm using a thread posted in a channel, using: slackResponse.threadId as the channel: value. The response is the same:

Slack upload may have failed. Response: {"ok":false,"error":"channel_not_found"}
10:40:37  Failed to complete uploading file to Slack

for Reply to a channel thread we are using slackResponse.ts which works in our case.

Thanks, I'll try that. We mostly upload into threads.

Sorry to jump in on your issue, but it seems quite related.

I actually just tried this

sh("echo hey > file.txt")
slackUploadFile(filePath: 'file.txt', channel: 'cloud-engineering')

Straight into a channel and the result is:

[Pipeline] sh
 + echo hey
[Pipeline] slackUploadFile
ERROR: Failed uploading file to slack
[Pipeline] }

EDIT:

This also didn't work:

sh("echo hey > file.txt")
def slackResponse = slackSend(channel: "cloud-engineering", message: "Here is the primary message")
slackSend(channel: slackResponse.threadId, message: "Thread reply #1")
slackSend(channel: slackResponse.threadId, message: "Thread reply #2")
slackUploadFile(filePath: 'file.txt', channel: slackResponse.ts)

Which results in:

[Pipeline] sh
 + echo hey
 [Pipeline] slackSend
 Slack Send Pipeline step running, values are - baseUrl: <empty>, teamDomain: SNIP, channel: cloud-engineering, color: <empty>, botUser: true, tokenCredentialId: SNIP, notifyCommitters: false, iconEmoji: <empty>, username: <empty>, timestamp: <empty>
 [Pipeline] slackSend
 Slack Send Pipeline step running, values are - baseUrl: <empty>, teamDomain: SNIP, channel: C01RT3GFUV6:1715681693.932169, color: <empty>, botUser: true, tokenCredentialId: SNIP, notifyCommitters: false, iconEmoji: <empty>, username: <empty>, timestamp: <empty>
 [Pipeline] slackSend
 Slack Send Pipeline step running, values are - baseUrl: <empty>, teamDomain: SNIP, channel: C01RT3GFUV6:1715681693.932169, color: <empty>, botUser: true, tokenCredentialId: SNIP, notifyCommitters: false, iconEmoji: <empty>, username: <empty>, timestamp: <empty>
 [Pipeline] slackUploadFile
 ERROR: Failed uploading file to slack

image

timja commented 1 month ago

For threads this works for me:

  sh "echo hey > blah.txt"
  def slackResponse = slackSend channel: '#jenkins-slack-plugin-testing', message: "hello"

  slackUploadFile channel: "#jenkins-slack-plugin-testing:${slackResponse.ts}", filePath: 'blah.txt', initialComment: '*Full changes*:'
timja commented 1 month ago

Which is documented here: https://github.com/jenkinsci/slack-plugin#threads-support

MatthewBooth commented 1 month ago

Still no joy :/

This resulted in a channel not found message:

def slackResponse = slackSend(channel: "cloud-engineering", message: "Here is the primary message")
slackSend(channel: slackResponse.threadId, message: "Thread reply #1")
slackSend(channel: slackResponse.threadId, message: "Thread reply #2")
slackUploadFile(filePath: 'file.txt', channel: "cloud-engineering:" + slackResponse.ts)
 + echo hey
 [Pipeline] slackSend
 Slack Send Pipeline step running, values are - baseUrl: <empty>, teamDomain: SNIP, channel: cloud-engineering, color: <empty>, botUser: true, tokenCredentialId: SNIP, notifyCommitters: false, iconEmoji: <empty>, username: <empty>, timestamp: <empty>
 [Pipeline] slackSend
 Slack Send Pipeline step running, values are - baseUrl: <empty>, teamDomain: SNIP, channel: C01RT3GFUV6:1715683388.219919, color: <empty>, botUser: true, tokenCredentialId: SNIP, notifyCommitters: false, iconEmoji: <empty>, username: <empty>, timestamp: <empty>
 [Pipeline] slackSend
 Slack Send Pipeline step running, values are - baseUrl: <empty>, teamDomain: SNIP, channel: C01RT3GFUV6:1715683388.219919, color: <empty>, botUser: true, tokenCredentialId: SNIP, notifyCommitters: false, iconEmoji: <empty>, username: <empty>, timestamp: <empty>
 [Pipeline] slackUploadFile
 Using dirname=/home/ec2-user/workspace/TestJenkinsSandbox and includeMask=file.txt
 Adding file /home/ec2-user/workspace/TestJenkinsSandbox/file.txt
 ERROR: Failed uploading file to slack
 Slack upload may have failed. Response: {"ok":false,"error":"channel_not_found"}
 Failed to complete uploading file to Slack

I also tried threadId instead of ts, which just produced:

 ERROR: Failed uploading file to slack
timja commented 1 month ago

Can you show an example that matches what I sent?

  slackUploadFile channel: "#your-channel:${slackResponse.ts}", filePath: 'blah.txt', initialComment: '*Full changes*:'
MatthewBooth commented 1 month ago

Sure :)

sh("echo hey > blah.txt")

def slackResponse = slackSend(channel: "cloud-engineering", message: "Here is the primary message")
slackSend(channel: slackResponse.threadId, message: "Thread reply #1")
slackSend(channel: slackResponse.threadId, message: "Thread reply #2")

slackUploadFile channel: "#cloud-engineering:${slackResponse.ts}", filePath: 'blah.txt', initialComment: '*Full changes*:'
[Pipeline] sh
 + echo hey
 [Pipeline] slackSend
 Slack Send Pipeline step running, values are - baseUrl: <empty>, teamDomain: SNIP, channel: cloud-engineering, color: <empty>, botUser: true, tokenCredentialId: SNIP, notifyCommitters: false, iconEmoji: <empty>, username: <empty>, timestamp: <empty>
 [Pipeline] slackSend
 Slack Send Pipeline step running, values are - baseUrl: <empty>, teamDomain: SNIP, channel: C01RT3GFUV6:1715684261.131669, color: <empty>, botUser: true, tokenCredentialId: SNIP, notifyCommitters: false, iconEmoji: <empty>, username: <empty>, timestamp: <empty>
 [Pipeline] slackSend
 Slack Send Pipeline step running, values are - baseUrl: <empty>, teamDomain: SNIP, channel: C01RT3GFUV6:1715684261.131669, color: <empty>, botUser: true, tokenCredentialId: SNIP, notifyCommitters: false, iconEmoji: <empty>, username: <empty>, timestamp: <empty>
 [Pipeline] slackUploadFile
 Using dirname=/home/ec2-user/workspace/TestJenkinsSandbox and includeMask=blah.txt
 Adding file /home/ec2-user/workspace/TestJenkinsSandbox/blah.txt
 ERROR: Failed uploading file to slack
 [Pipeline] }

 [Pipeline] // ansiColor
 [Pipeline] }
 Slack upload may have failed. Response: {"ok":false,"error":"channel_not_found"}
 Failed to complete uploading file to Slack

Apologies, I haven't mentioned yet, but I'm using 715.v1cfed1b_9c63c with the plugin and 2.440.3 with Jenkins.

timja commented 1 month ago

There doesn't happen to be anything useful in the system logs?

MatthewBooth commented 1 month ago

There doesn't happen to be anything useful in the system logs?

Ahh, ha!

Couldn't convert channel name to ID in Slack: {"needed":"channels:read,groups:read,mpim:read,im:read","provided":"chat:write,files:write,reactions:write,users:read,users:read.email","ok":false,"error":"missing_scope"}
timja commented 1 month ago

hmm damn, I tried to make sure those logs all made it into the build log, =/.

MatthewBooth commented 1 month ago

hmm damn, I tried to make sure those logs all made it into the build log, =/.

No worries, I feel silly that I didn't think of that myself! I've updated the scopes on the bot user/app and will try again.

It makes sense now, as even a file upload to a channel was also failing.

EDIT:

Yep, that's working now. Thanks @raghavanrrs and @timja

raghavanrrs commented 1 month ago

@timja how to print the slacksend response in user-friendly. As currently we are getting only the hashed values.

timja commented 1 month ago

sh "echo $slackResponse.channelId $slackResponse.ts"

or sh "echo $slackResponse.threadId"