Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retirement of Office 365 connectors within Microsoft Teams #355

Open
yogeshpsp opened this issue Jul 9, 2024 · 62 comments
Open

Retirement of Office 365 connectors within Microsoft Teams #355

yogeshpsp opened this issue Jul 9, 2024 · 62 comments

Comments

@yogeshpsp
Copy link

What feature do you want to see added?

Micorosft has announced that office 365 connector will expire on August 2024. Will this affect the office 365 connector jenkins plugin as well.
https://devblogs.microsoft.com/microsoft365dev/retirement-of-office-365-connectors-within-microsoft-teams/

Upstream changes

No response

Are you interested in contributing this feature?

No response

@PrismaComputer
Copy link

A fix for the problem will be available in time?

@wjones38
Copy link

wjones38 commented Jul 15, 2024

This plugin can continue to be used if you translate the data it sends on power automate into Microsofts "adaptive card" format. See the comment from Damian E here: https://gitlab.com/gitlab-org/gitlab/-/issues/471344 for the template I used that got this working for me.

The biggest issue I ran into is that this plugin looks for a 200 response and Power Automate does not give 200 responses, it gives 202 responses. I opened an issue to address this here: #356

@PrismaComputer
Copy link

PrismaComputer commented Jul 16, 2024

Folks, don't get me wrong, I know it's for free and open source. But please try to see it from the Admin side, who's just a user from this point of view. It's not the aim of the user to translate anything from this plugin into whatever. Especially if the webservice isn't giving the expected response code anyway. Adjustments have to be made anyway. I think the aim should be to have one checkbox in plugin configuration to trigger the usage of another data format and expecting another response code.

@wjones38
Copy link

@PrismaComputer What you proposed would be nice, but the very simple addition of a 202 response code can be easily done in the short time window that Microsoft has given. Long term I wholeheartedly agree but, to be completely honest, right now I just need something that holds my team over until that long term solution is finished.

@damianszczepanik
Copy link
Member

This plugin can continue to be used if you translate the data it sends on power automate into Microsofts "adaptive card" format. See the comment from Damian E here: https://gitlab.com/gitlab-org/gitlab/-/issues/471344 for the template I used that got this working for me.

Can be used but you need to user Power Automate and implement the workflow which will consume requests from this plugin. Is that correct?

@wjones38
Copy link

@damianszczepanik yes, that is correct. Its not probably the nicest solution ever but it gets the job done.

@damianszczepanik
Copy link
Member

@damianszczepanik yes, that is correct. Its not probably the nicest solution ever but it gets the job done.

Agree. Then this plugin will work as pure curl with POST method and the adaptive cards with filled subject/text as the body of this request.

@PrismaComputer
Copy link

PrismaComputer commented Jul 17, 2024

@damianszczepanik
Agree. Then this plugin will work as pure curl with POST method and the adaptive cards with filled subject/text as the body of this request.

As far as I can see, at the moment no adaptive cards are used. But for PowerAutomate adaptive cards are mandatory. This is at least my information, maybe I'm wrong. And it's not only the card definition itself. In opposite to “the old method” the card's JSON must be wrapped into "attachments": [] beside the “type”: “message”.

If I'm correct, just solving the 202 problem alone won't do the trick.

So, may I kindly ask where to edit the card's template? I did not find anything in Jenkins directory. But maybe I've overseen something.

@jimmygoogle
Copy link

This plugin can continue to be used if you translate the data it sends on power automate into Microsofts "adaptive card" format. See the comment from Damian E here: https://gitlab.com/gitlab-org/gitlab/-/issues/471344 for the template I used that got this working for me.

Can be used but you need to user Power Automate and implement the workflow which will consume requests from this plugin. Is that correct?

Unfortunately, you need a premium license to be able to use "When an http request is received", which would allow you to take the current payload Jenkins plugin sends and transform it to an adaptive card to post to a Teams channel. The "When a Teams webhook request is received" trigger does not require a premium license but it expects an adaptive card payload.

@damianszczepanik
Copy link
Member

Can you clarify which one is where? This is not clear to me what is the difference or which one will work after office 365 retirement

@jimmygoogle
Copy link

Both webhooks will work as they are in the workflow setup (https://make.powerautomate.com/). The "When an http request is received" webhook allows you to supply the payload of the webhook that Microsoft will send. The "When a Teams webhook request is received" webhook expects a payload with a specific structure.

@wjones38
Copy link

Both webhooks will work as they are in the workflow setup (https://make.powerautomate.com/). The "When an http request is received" webhook allows you to supply the payload of the webhook that Microsoft will send. The "When a Teams webhook request is received" webhook expects a payload with a specific structure.

@jimmygoogle have you tested using the "When a Teams webhook request is received" and received errors when sending a format that doesn't match? I have been able to send whatever payload I want to that trigger and it has been working. Not sure if maybe I just managed to find a loop hole on accident or what.

@jimmygoogle
Copy link

Both webhooks will work as they are in the workflow setup (https://make.powerautomate.com/). The "When an http request is received" webhook allows you to supply the payload of the webhook that Microsoft will send. The "When a Teams webhook request is received" webhook expects a payload with a specific structure.

@jimmygoogle have you tested using the "When a Teams webhook request is received" and received errors when sending a format that doesn't match? I have been able to send whatever payload I want to that trigger and it has been working. Not sure if maybe I just managed to find a loop hole on accident or what.

Yes I have tried that webhook and I get "Action 'Send_each_adaptive_card' failed: The execution of template action 'Send_each_adaptive_card' failed: the result of the evaluation of 'foreach' expression '@triggerOutputs()?['body']?['attachments']' is of type 'Null'. The result must be a valid array."

@PrismaComputer
Copy link

PrismaComputer commented Jul 18, 2024

Yes I have tried that webhook and I get "Action 'Send_each_adaptive_card' failed: The execution of template action 'Send_each_adaptive_card' failed: the result of the evaluation of 'foreach' expression '@triggerOutputs()?['body']?['attachments']' is of type 'Null'. The result must be a valid array."

I completely agree.

That is the trigger which Teams will set up automatically if you click the drop-in replacement link (which, unfortunately, does not create a drop-in replacement) in the warning. Additionally, this is the trigger which you can set up manually without PowerAutomate Premium:

image

This trigger expects:

  • An adaptive card format, which is significantly different from the old Teams Card.
  • Colours only as "default, dark, light, accent, good, warning, attention". No RGB values are allowed anymore.
  • The card wrapped into "attachments": [] beside the “type”: “message”.

Otherwise, as you wrote, the error appears:

"Action 'Send_each_adaptive_card' failed: The execution of template action 'Send_each_adaptive_card' failed: the result of the evaluation of 'foreach' expression '@triggerOutputs()?['body']?['attachments']' is of type 'Null'. The result must be a valid array."

@wjones38
Copy link

@PrismaComputer @jimmygoogle sounds to me like you guys just need to iterate over something that exists, not the attachments. Change the "send each adaptive card" to look for just the body.

Screenshot 2024-07-18 at 9 42 50 AM

@PrismaComputer
Copy link

PrismaComputer commented Jul 18, 2024

“Everyone” using Teams Integration will encounter this problem. It is difficult to imagine that “everyone” will be able to resolve this using Power Automate. Previously, the solution involved simply copying and pasting a generated URL into the plugin. This meant that webhooks were utilized by users and companies without any extensive knowledge of automation.

@wjones38 , I understand that it is not your companies fault, but we cannot change the reality.

Could you please confirm whether the “old” MessageCard generated by the plugin will continue to work, or if an additional transformation of the card into adaptive-card is necessary, such as in Power Automate?

Additionally, do we have a timeline for the 202 fix?

@jimmygoogle
Copy link

“Everyone” using Teams Integration will encounter this problem. It is difficult to imagine that “everyone” will be able to resolve this using Power Automate. Previously, the solution involved simply copying and pasting a generated URL into the plugin. This meant that webhooks were utilized by users and companies without any extensive knowledge of automation.

@wjones38 , I understand that it is not your companies fault, but we cannot change the reality.

Could you please confirm whether the “old” MessageCard generated by the plugin will continue to work, or if an additional transformation of the card into adaptive-card is necessary, such as in Power Automate?

Additionally, do we have a timeline for the 202 fix?

The 202 fix was merged. According to Microsoft, the notifications as they are right now will stop working in September. The solution is to move to something in workflows.

@wjones38
Copy link

Could you please confirm whether the “old” MessageCard generated by the plugin will continue to work, or if an additional transformation of the card into adaptive-card is necessary, such as in Power Automate?

You need to do some transformation in power automate and I can't guarantee it will be easy. The web UI is clunky and generally hard to understand but it is possible. If you change the foreach command to look only at the request body, then you can use the same general template that I used:

This plugin can continue to be used if you translate the data it sends on power automate into Microsofts "adaptive card" format. See the comment from Damian E here: https://gitlab.com/gitlab-org/gitlab/-/issues/471344 for the template I used that got this working for me.

This should get you most of the way. After that you will just need to look up how to style adaptive cards and plug in the variables from your payload into the adaptive card JSON.

@PrismaComputer
Copy link

From what I have observed, it should be possible to export the automation. Would it not be a good idea if someone with a fully functional (not theoretically working) solution shares their anonymised export here?

@jimmygoogle
Copy link

jimmygoogle commented Jul 18, 2024

From what I have observed, it should be possible to export the automation. Would it not be a good idea if someone with a fully functional (not theoretically working) solution shares their anonymised export here?

@wjones38 got me on the right path and I got this working in Jenkins even with the 202 status returned. I setup a workflow based on the payload that Jenkins sends to the webhook. You can tell the payload after you build the workflow and test and it via Jenkins, Postman, etc.

card

For me, the Jenkins payload looks something like this so this helped me build my adaptive card. I don't see all of the facts that used to be there, I am still looking into that.

  "summary": "branch » master: Build #1",
  "themeColor": "3479BF",
  "sections": [
    {
      "markdown": true,
      "facts": [
        {
          "name": "Status",
          "value": "Success"
        }
      ],
      "activityTitle": "Notification from branch » master",
      "activitySubtitle": "some text here"
    }
  ],
  "potentialAction": []
}

Inside the Post card in chat or channel settings, I used this adaptive card JSON. This is what worked for me and my setup. You might be able to copy/paste it or you might need to adapt it to your situation.

   "type": "AdaptiveCard",
   "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
   "version": "1.4",
   "msteams": {
      "width": "Full"
   },
   "body": [
      {
         "type": "TextBlock",
         "size": "Large",
         "weight": "Bolder",
         "text": "@{replace(triggerBody().sections[0].activityTitle, '\', '\\')}"
      },
      {
         "type": "ColumnSet",
         "columns": [
            {
               "type": "Column",
               "width": "stretch",
               "items": [
                  {
                     "type": "TextBlock",
                     "weight": "Bolder",
                     "text": "@{triggerBody().sections[0].activitySubtitle}",
                     "wrap": true
                  },
                  {
                     "type": "TextBlock",
                     "text": "@{triggerBody().summary}",
                     "wrap": true
                  },
                  {
                     "type": "TextBlock",
                     "text": "Status: @{triggerBody().sections[0].facts[0].value}",
                     "wrap": true
                  }
               ]
            }
         ]
      }
   ]
}

The workflow run history will show you successes, failures and it will show you exactly what was sent. Clicking into the run history for a given request is extremely useful.
run-history

@PrismaComputer
Copy link

PrismaComputer commented Jul 19, 2024

I don't see all of the facts that used to be there, I am still looking into that.

Thank you for the information. I am beginning to understand the approach and objective. Although my opinion remains that it is not the administrator's responsibility to fit a square peg into a round hole, the plugin requires fixing.

Nevertheless, thank you. I shall wait until all questions (regarding why you do not see all the facts) are answered. Perhaps by then, the plugin will have been improved. If not, we can still resort to more drastic measures. I look forward to your investigation, @jimmygoogle. Thank you very much.

@jimmygoogle
Copy link

I don't see all of the facts that used to be there, I am still looking into that.

Thank you for the information. I am beginning to understand the approach and objective. Although my opinion remains that it is not the administrator's responsibility to fit a square peg into a round hole, the plugin requires fixing.

Nevertheless, thank you. I shall wait until all questions (regarding why you do not see all the facts) are answered. Perhaps by then, the plugin will have been improved. If not, we can still resort to more drastic measures. I look forward to your investigation, @jimmygoogle. Thank you very much.

I am not sure I am going to figure out why the facts are missing or even if they are missing at all. All I know is I dont have the same information in the webhook payload that diplayed previously for us. That might be a configuration thing on our end for all I know. I currently have a working solution so unless the plugin is updated, I am probably going to leave it as is.

@fafl245
Copy link

fafl245 commented Jul 22, 2024

From what I have observed, it should be possible to export the automation. Would it not be a good idea if someone with a fully functional (not theoretically working) solution shares their anonymised export here?

@wjones38 got me on the right path and I got this working in Jenkins even with the 202 status returned. I setup a workflow based on the payload that Jenkins sends to the webhook. You can tell the payload after you build the workflow and test and it via Jenkins, Postman, etc.

card

For me, the Jenkins payload looks something like this so this helped me build my adaptive card. I don't see all of the facts that used to be there, I am still looking into that.

  "summary": "branch » master: Build #1",
  "themeColor": "3479BF",
  "sections": [
    {
      "markdown": true,
      "facts": [
        {
          "name": "Status",
          "value": "Success"
        }
      ],
      "activityTitle": "Notification from branch » master",
      "activitySubtitle": "some text here"
    }
  ],
  "potentialAction": []
}

Inside the Post card in chat or channel settings, I used this adaptive card JSON. This is what worked for me and my setup. You might be able to copy/paste it or you might need to adapt it to your situation.

   "type": "AdaptiveCard",
   "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
   "version": "1.4",
   "msteams": {
      "width": "Full"
   },
   "body": [
      {
         "type": "TextBlock",
         "size": "Large",
         "weight": "Bolder",
         "text": "@{replace(triggerBody().sections[0].activityTitle, '\', '\\')}"
      },
      {
         "type": "ColumnSet",
         "columns": [
            {
               "type": "Column",
               "width": "stretch",
               "items": [
                  {
                     "type": "TextBlock",
                     "weight": "Bolder",
                     "text": "@{triggerBody().sections[0].activitySubtitle}",
                     "wrap": true
                  },
                  {
                     "type": "TextBlock",
                     "text": "@{triggerBody().summary}",
                     "wrap": true
                  },
                  {
                     "type": "TextBlock",
                     "text": "Status: @{triggerBody().sections[0].facts[0].value}",
                     "wrap": true
                  }
               ]
            }
         ]
      }
   ]
}

The workflow run history will show you successes, failures and it will show you exactly what was sent. Clicking into the run history for a given request is extremely useful. run-history

Hello @jimmygoogle,
when I try to copy and paste your code to my flow in "code view" it says: "cannot edit in read-only" editor. What can I do?
Thank you!

@PrismaComputer
Copy link

And this is, why we need an urgent fix of this plugin.

@jimmygoogle
Copy link

And this is, why we need an urgent fix of this plugin.

Even if/when the plugin is fixed you are still going to need setup a workflow. The readonly option is because you are using one of the precanned flows. You need to build your flow using the 2 steps from above.

@PrismaComputer
Copy link

@jimmygoogle : No, I disagree.

If the plugin were fixed (or better: given an option to use a different card and expect another return code), there would be no need to set up, tweak, program, modify, or manually handle flows. Within Teams, there's a "fix-it" link embedded in the depreciation warning. If you click this link, a new flow is created automatically—a precanned one, as you call it. This will be done within Teams without requiring any deeper knowledge of Power Automate, and without revealing that this is Power Automate at all.

This is how Microsoft anticipates this problem to be resolved. And this is what the typical admin will do and expect to work.
As I wrote at the beginning, the topic here is not the reason for all this. The reason is, Microsoft is disregarding its users. However, the solution should not be to send the users back to Microsoft with their issues.

Of course, you can ask me, why should the developers of this plugin think this way?
Answer:
First of all, they decided to develop this plugin knowing it is Microsoft-related, with all its downsides.
And second, perhaps they want to perform better than Microsoft?

@jimmygoogle
Copy link

This is an open source plugin, no one has responsibilities to fix anything. I took a day and learned how Power Automate worked and got a solution working for our situation. We use Team notifications for all sorts of things so it was in our best interest to learn about it and address it.

The crux of the problem here is that the notification is expecting an adaptive card but the payload coming from Jenkins is a message card. The easiest thing to do for us was to pass in an adaptive card template with the parts of the payload coming in from Jenkins.

@meiswjn
Copy link

meiswjn commented Jul 23, 2024

This is an open source plugin, no one has responsibilities to fix anything.

And to add on that: while nobody is responsible, everyone is invited. If this is a great painpoint for you, the easiest way may be to provide a PR @PrismaComputer.

@meiswjn
Copy link

meiswjn commented Jul 23, 2024

Inside the Post card in chat or channel settings, I used this adaptive card JSON. This is what worked for me and my setup. You might be able to copy/paste it or you might need to adapt it to your situation.

   "type": "AdaptiveCard",
   "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
   "version": "1.4",
   "msteams": {
      "width": "Full"
   },
   "body": [
      {
         "type": "TextBlock",
         "size": "Large",
         "weight": "Bolder",
         "text": "@{replace(triggerBody().sections[0].activityTitle, '\', '\\')}"
      },
      {
         "type": "ColumnSet",
         "columns": [
            {
               "type": "Column",
               "width": "stretch",
               "items": [
                  {
                     "type": "TextBlock",
                     "weight": "Bolder",
                     "text": "@{triggerBody().sections[0].activitySubtitle}",
                     "wrap": true
                  },
                  {
                     "type": "TextBlock",
                     "text": "@{triggerBody().summary}",
                     "wrap": true
                  },
                  {
                     "type": "TextBlock",
                     "text": "Status: @{triggerBody().sections[0].facts[0].value}",
                     "wrap": true
                  }
               ]
            }
         ]
      }
   ]
}

Note that a curly bracket { is missing at the beginning. Apart from that, it works perfectly. Thanks for sharing!

@SoftpymesJuan-Camilo-C
Copy link

I've been working this way, if you're interested take a look here: #353 (comment)

@mbxsuite
Copy link

mbxsuite commented Jul 24, 2024

OK, I had a look into Card.java and how it is used. If I got it right, the Card object is build by createCompletedCard and other methods and directly turned into Json just before sending it to the remote. So the object structure defines the json request.

Then the Card class might need one or two new siblings for the AdaptiveCard and HtmlMessage format.

The new Workflow does not support ConnectorCards (Card.java) anymore, but AdaptiveCards and "Messages". I personally find AdaptiveCards "nice", but way too bloated. "Messages" on the other hand can contain HTML, but do not get wrapped with an extra border, space and footer message like this "AdaptiveCard":
grafik

I played around and came up with these basic message jsons. You are able to test the Workflow with via curl --url <triggerurlwithauth> -XPOST -d @sample.json -H "Content-Type: application/json"

x payload Teams-Workflow Definition
Message {"message":"Surely someone thought <b>HTML</b> is way <sub>more</sub> <i>convenient</i>, than Markdown."} "When a Teams webhook request is received" -> "Post message in a chat or channel" -> Parameters: Message: triggerBody().message
single AdaptiveCard {"$schema":"http://adaptivecards.io/schemas/adaptive-card.json", "type":"AdaptiveCard","version":"1.4", "body":[{"type":"Container","style":"warning","items":[ {"type":"TextBlock","text":"default","weight":"Bolder", "size":"Medium","color":"default"}]}]} "When a Teams webhook request is received" -> "Post to a channel when a webhook request is received" -> Parametes: Adaptive Card: triggerBody()
multiple AdaptiveCards {"attachments":[{"contentType":"text/json","content":{ "$schema":"http://adaptivecards.io/schemas/adaptive-card.json", "type":"AdaptiveCard","version":"1.4", "body":[{"type":"Container","items":[ {"type":"TextBlock","text":"card1", "weight":"Bolder","size":"Medium","color":"warning"}]}]}}, {"contentType":"text/json","content":{ "$schema":"http://adaptivecards.io/schemas/adaptive-card.json", "type":"AdaptiveCard","version":"1.4", "body":[{"type":"Container","items":[ {"type":"TextBlock","text":"card2", "weight":"Bolder","size":"Medium","color":"attention"}]}]}}]} "When a Teams webhook request is received" -> "Send each adaptive card" -> Parameters: "Select an output from previous steps": triggerBody()?['body']?['attachments'] && "Post to a channel when a webhook request is received" -> Parametes: Adaptive Card: item()?['content']

The 1st and 2nd workflow variants are pretty straight forward in Java code (compared to the current implementation) and on the Workflow side.
The 3rd workflow gets somehow the default, if you fiddle around in the UI for the first time. I currently don't see the requirement to send multiple cards into one Channel.
Yes, that is beyond this plugins scope, but I think this should also be documented here, in case this plugin will get an option to choose the desired message format.

The possibly supportable elements of an adaptive card can be found here.

@yogeshpsp
Copy link
Author

yogeshpsp commented Jul 25, 2024

image
Deadline got extended till Dec 2025 for existing connectors

@RobEvans875
Copy link

Last week I got this working with Power Automate using its "when a Teams webhook request is received" >>> "Post card in a chat or a channel". I used the adaptive card i think @jimmygoogle posted above here and editted it to suit what I needed. This also involved changing the old teams webhook with Power Automates new webhook for nearly every job I have setup in Jenkins.

What I noticed was that I was receiving 3 identical notifications in the Teams channel for every job being completed. I seen this morning that the plugin was updated here so I installed it. That has resolved the 3 notificiations issues and I am only receiving 1 as expected now.

@PrismaComputer
Copy link

PrismaComputer commented Jul 25, 2024

image Deadline got extended till Dec 2025 for existing connectors

Yes, I have already noticed that the deprecation warning in Teams has been removed. It appears that the appropriate individuals utilized their support plans and connections with Microsoft to prevent this from happening. Much ado about nothing.

…but changes nothing and gives the developers time to implement the user-friendly way.

@myronu
Copy link

myronu commented Jul 25, 2024

Just so nobody else runs into this, I found that viewing Workflows in Teams you do not see the body of the request that was sent, however, the PowerAutomate website, https://make.powerautomate.com, does show the body. After looking at the responses we were receiving for both success and failure, and other examples found here and elsewhere, I was able to build an adaptive card that works well for our needs.

@abc21086999
Copy link

Hi guys, I just found a temporary workround for this issue.

First, after Jenkins job is finished and send request to the webhook url, it's payload will be parsed into headers and body:
Xnip2024-07-26_16-53-32
You can check this in the Power Automate, here is the body part, it's in a json format:

{
  "summary": "Jenkins » Regression Test » Your Tasks",
  "themeColor": "3479BF",
  "sections": [
    {
      "markdown": true,
      "facts": [
        {
          "name": "Status",
          "value": "Started"
        },
        {
          "name": "Remarks",
          "value": "Started by user Muffin."
        }
      ],
      "activityTitle": "Notification from Jenkins » Regression Test » Your Tasks",
      "activitySubtitle": "Latest status of build #1"
    }
  ],
  "potentialAction": [
    {
      "@context": "http://schema.org",
      "@type": "ViewAction",
      "name": "View Build",
      "target": [
        "https://url_to_your_job"
      ]
    }
  ]
}

And since we are going to let the Workflow bot sent card into the chat, we have to tell the bot what kind of information we want him to write into the card. Microsoft is using something called Adaptive Card for this, so you might need to search for how to make an adaptive card.

Here is the Adaptive card I use:

{
    "type": "AdaptiveCard",
    "body": [
        {
            "type": "TextBlock",
            "size": "Large",
            "weight": "Bolder",
            "text": "@{triggerBody().sections[0].activityTitle}"
        },
        {
            "type": "ColumnSet",
            "columns": [
                {
                    "type": "Column",
                    "width": "stretch",
                    "items": [
                        {
                            "type": "TextBlock",
                            "text": "@{triggerBody().summary}",
                            "wrap": true
                        },
                        {
                            "type": "TextBlock",
                            "weight": "Bolder",
                            "text": "Status: @{triggerBody().sections[0].facts[0].value}",
                            "wrap": true
                        },
                        {
                            "type": "TextBlock",
                            "text": "Remarks: @{triggerBody().sections[0].facts[1].value}",
                            "wrap": true
                        }
                    ]
                }
            ]
        }
    ],
    "actions": [
        {
            "type": "Action.OpenUrl",
            "title": "Link",
            "url": "@{triggerBody().potentialAction[0].target[0]}"
        }
    ],
    "msteams": {
        "width": "Full"
    },
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "version": "1.4"
}

Anything you need to take out from the body of Jenkins body, you need to use trigger.Body(), for the rest of the features about Adaptive card like how to make the words bigger, you can check at apadtive card's website.

Note: setting adaptive card's version to 1.5 will cause error, causing the workflow bot unable to show message in chat

@claudia-ca
Copy link

I wanted to share my 2 cents, since I've been trying to make the switch to a workflow too and eventually got it to work though it took quite a bit of trial and error. Things I've noticed:

  • You have to write out the json of the Facts yourself in order to get (all of) them to show correctly in the posted card. Add a Foreach loop in your workflow and for each item in the facts, use Compose to create a title&value json pair from the name&value of the fact and add it to an Array variable. In your adaptive card you can then add the array as dynamic content for the facts.
  • Watch out for escaped characters in the input of your webhook. At least in the activityTitle I've noticed characters having been escaped (single backslash), which subsequently breaks the json in your card if you use it directly.
  • The potentialAction element is not always part of the input message, e.g. in case of Success or BackToNormal, there won't be a link. If you use "triggerBody().potentialAction[0]" in the Action.OpenUrl, this will break the workflow with a null ref in these cases. You could add an isVisible property so the button is not always present but that brings me to the next point:
  • If your team uses the MS Teams app on mobile, make sure to compare your posts on mobile to desktop. They seem to behave differently, e.g. colors/images rendering on desktop but not on mobile, layout differences, visibility property hides more elements on mobile than on desktop, etc.
  • Lastly, if you see the "...used a Workflow template to send this card" message under your post, make a copy of your workflow with SaveAs and continue with that one (see this link).

Our post now look like this:
image

The adaptive card:

    "type": "AdaptiveCard",
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "version": "1.4",
    "msteams": {  
        "width": "Full"
    },
    "body": [
        {
            "type": "ColumnSet",
            "columns": [
                {
                    "type": "Column",
                    "width": "5px",
                    "items": [
                        {
                            "type": "Container",
                            "backgroundImage": {
                                "url": "@{variables('imgUrl')}",
                                "fillMode": "RepeatVertically"
                            },
                            "height": "stretch",
                            "minHeight": "5px"
                        }
                    ]
                },
                {
                    "type": "Column",
                    "width": "stretch",
                    "items": [
                        {
                            "type": "TextBlock",
                            "text": "@{variables('activityTitle')}",
                            "weight": "bolder",
                            "wrap": true
                        },
                        {
                            "type": "TextBlock",
                            "wrap": true,
                            "separator": true,
                            "text": "@{body('Parse_JSON')?['sections'][0]['activitySubtitle']}"
                        }
                    ]
                }
            ]
        },
        {
            "type": "Container",
            "items": [
                {
                    "type": "FactSet",
                    "separator": true,
                    "facts": @{variables('factlist')}
                }
            ]
        },
        {
            "type": "Container",
            "items": [
                {
                    "type": "ActionSet",
                    "actions": [
                        {
                            "type": "Action.OpenUrl",
                            "title": "@{body('Parse_JSON')?['potentialAction'][0]['name']}",
                            "url": "@{body('Parse_JSON')?['potentialAction'][0]['target'][0]}"
                        }
                    ]
                }
            ]
        }
    ]
}

Here's a clip with the whole workflow, in case someone perhaps finds it useful:
2024-07-26_17-24-42

I created the image data uri's with the help of this link.

@sebracs
Copy link

sebracs commented Jul 26, 2024

I also managed to setup a somewhat generic converter Workflow based on @jimmygoogle 's original example:

{
   "type": "AdaptiveCard",
   "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
   "version": "1.4",
   "msteams": {
      "width": "Full"
   },
   "body": [
      {
         "type": "TextBlock",
         "size": "Large",
         "weight": "Bolder",
         "text": "@{replace(triggerBody().sections[0].activityTitle, '\', '\\')}"
      },
      {
         "type": "ColumnSet",
         "columns": [
            {
               "type": "Column",
               "width": "stretch",
               "items": [
                  {
                     "type": "TextBlock",
                     "weight": "Bolder",
                     "text": "@{triggerBody().sections[0].activitySubtitle}",
                     "wrap": true
                  },
                  {
                     "type": "TextBlock",
                     "text": "@{triggerBody().summary}",
                     "wrap": true
                  },
                  {
                     "type": "TextBlock",
                     "text": "Status: @{triggerBody().sections[0].facts[0].value}",
                     "wrap": true
                  }
               ]
            }
         ]
      }
   ]
}

by adding "Apply to all" loops and Compose data operations:
image

image

You can also get a colored stripe back by adding a background image that is just a single color and repeating it vertically or horizontally only.

Here is the Adaptive Card template json:

{
    "type": "AdaptiveCard",
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "version": "1.4",
    "verticalContentAlignment": "Center",
    "msteams": {
       "width": "Full"
    },
    "backgroundImage": {
        "url": "data:image/gif;base64,R0lGODlhCAABAIABAAD/AAacDywAAAAACAABAAACA4RvBQA7",
        "fillMode": "RepeatVertically"
    },
    "body": [
        {
            "type": "ColumnSet",
            "columns": [
                {
                    "type": "Column",
                    "items": [
                        {
                            "type": "Image",
                            "style": "Person",
                            "url": "https://www.jenkins.io/images/logos/jenkins/jenkins.png",
                            "altText": "Jenkins",
                            "size": "Small"
                        }
                    ],
                    "width": "auto"
                },
                {
                    "type": "Column",
                    "items": [
                        {
                            "type": "TextBlock",
                            "size": "Medium",
                            "weight": "Bolder",
                            "text": "@{replace(triggerBody().sections[0].activityTitle, '\', '\\')}",
                            "color": "@{triggerBody().themeColor}",
                            "style": "heading",
                            "wrap": true
                        }
                    ],
                    "width": "stretch"
                }
            ]
        },
        {
            "type": "TextBlock",
            "text": "@{triggerBody().sections[0].activitySubtitle}",
            "wrap": true
        },
        {
            "type": "FactSet",
            "facts":  @{variables('myfilter')}
        }
    ],
    "actions": @{variables('myactions')}
}

@karannnn-exe
Copy link

@manuelwallrapp
Copy link

We can only support @PrismaComputer, there is a fix necessary in this plugin. We want to send as effortless Teams Notifications as we did so far. That is very possible if the Plugin gets updated. Everything stays simple and lean and the users just need to update their Teams Notification URL to a Teams workflow webhook.

@mehroz377
Copy link

@manuelwallrapp absolutely correct.

@kikmon
Copy link

kikmon commented Aug 1, 2024

Thanks for the PR, hopefully it will allow us to proceed with the migration in a smooth and elegant way.
When can we expect it to be merged ? I don't see much activity from reviewers

@sebracs
Copy link

sebracs commented Aug 7, 2024

I created the image data uri's with the help of this link.

@claudia-ca Do you know if there is any way to do this hex-color to base64 gif conversion using PowerAutomate? There seem to be string, binary and base64 conversion functions, but no way to get binary string from a hex.

@PrismaComputer
Copy link

PrismaComputer commented Aug 8, 2024

As I expect that this issue will be resolved by the developers of this plugin and not by each individual user in a slightly different way each time, this message is more for the developers than for the users:

image

Red: I'm interested in whether this can be changed to “Jenkins” instead of “UserXY via Workflows”. However, I fear this can only (and nearly) be solved by creating a user named Jenkins.

Magenta: How can we have the task name here instead of “Card”?

Orange: How can we remove this completely unnecessary comment?

@markush81
Copy link
Contributor

markush81 commented Aug 8, 2024

@PrismaComputer
Copy link

PrismaComputer commented Aug 8, 2024

Red: This can be somewhat resolved by the Admin, for example, by using a Workflow owner named “Jenkins”.
Magenta: I hope this is a misunderstanding. This should not be up to “me” (as you wrote “you”. Who is “you”?).
Orange: This remains up to Microsoft but is truly a minor issue.

@markush81
Copy link
Contributor

Magenta: I hope this is a misunderstanding. This should not be up to “me” (as you wrote “you”. Who is “you”?).

You = the one creating the Jenkins Job.

@markush81
Copy link
Contributor

markush81 commented Aug 8, 2024

Red: This can be somewhat resolved by the Admin, for example, by using a Workflow owner named “Jenkins”.

Yep, if your company policy allows to have an owner which is not a human. But you're right my answer wasn't correct.

@PrismaComputer
Copy link

@markush81, regarding magenta:
Of course, this is configured through Jenkins' job name. My picture was produced with a CURL command, not with a fixed plugin. However, I expect this to be handled by the plugin in the future.

To prevent further confusion, has your pull request (thanks for that) been merged and released? Is there something to test and see? I apologize for the seemingly obvious question; this information could undoubtedly be found here on GitHub.

@markush81
Copy link
Contributor

markush81 commented Aug 8, 2024

@PrismaComputer no, it is not merged/released.

If you're "fearless" you could use my local built version from here https://github.com/markush81/office-365-connector-plugin/releases/tag/alpha and install the hpi manually. Or built the PR or from the fork the branch o365-adaptivecards yourself.

@sebracs
Copy link

sebracs commented Aug 12, 2024

image

Orange: How can we remove this completely unnecessary comment?

@PrismaComputer You can remove the Template reference by exporting and important the Workflow. Via Power Automate export to zip and import (only via Website https://make.powerautomate.com/ -> My flows -> select -> Export -> Package (.zip)) works for sure. Maybe copying inside Power Automate also works, but I have not tried it. Of course you can also get this by creating a new Flow from scratch (without starting from a template)

@KIuliia
Copy link

KIuliia commented Aug 19, 2024

Last week I got this working with Power Automate using its "when a Teams webhook request is received" >>> "Post card in a chat or a channel". I used the adaptive card i think @jimmygoogle posted above here and editted it to suit what I needed. This also involved changing the old teams webhook with Power Automates new webhook for nearly every job I have setup in Jenkins.

What I noticed was that I was receiving 3 identical notifications in the Teams channel for every job being completed. I seen this morning that the plugin was updated here so I installed it. That has resolved the 3 notificiations issues and I am only receiving 1 as expected now.

I have the same issue - notification is sent 3 times. can you please explain what you mean by updated the plugin? we have installed it last week and we have this issue.

@myronu
Copy link

myronu commented Aug 19, 2024

I have the same issue - notification is sent 3 times. can you please explain what you mean by updated the plugin? we have installed it last week and we have this issue.

Just update to the latest version of the plugin. That is the one thing they did fix.

@damianszczepanik
Copy link
Member

Did you use office-365-connector-plugin to post message from Jenkins using old card format or you have created new payload with adaptive card?

@FrankReisenhofer
Copy link

Just one remark from my side:

The new approach with using PowerAutomate has a critical security concern:

The new endpoint is "public", which means anyone that knows the endpoint can trigger workflow in user context without user authentication.

@ViliusS
Copy link

ViliusS commented Oct 17, 2024

Just one remark from my side:

The new approach with using PowerAutomate has a critical security concern:

The new endpoint is "public", which means anyone that knows the endpoint can trigger workflow in user context without user authentication.

It is the same for Incoming Webhook or Jenkins connectors. Their endpoints are public too, however Power Automate Workflows has an advantage, you can actually set who can trigger the flow through exposed URL.

Image

Of course, setting it to anything except Anyone won't work with Jenkins, as it doesn't use any user to post to the URL. The only way to have a protected URL moving forward is to develop custom Power Automate connectors with Microsoft Entra App integration.

@damianszczepanik
Copy link
Member

I'm not sure what is the right way to authenticate with Power Automate and without this knowledge this is hard to implement proper credential support

@ViliusS
Copy link

ViliusS commented Oct 24, 2024

Just FYI, if somebody wants to implement authentication with Power Automate it is done via Microsoft Entra ID App using OAuth https://learn.microsoft.com/en-us/power-automate/oauth-authentication?tabs=classic-designer .

  1. Create Entra ID App with appropriate permissions.
  2. Configure Power Automate endpoint to only accept trigger from authenticated users.
    Then:
  3. Initiate OAuth 2.0 Authorization Grant flow from Jenkins.
  4. Get and store access/refresh tokens in Jenkins.
  5. Send authorization in Bearer token to Power Automate endpoint.
  6. Refresh token when necessary.

Instructions how to configure Entra ID App is here https://forwardforever.com/using-oauth-authentication-for-http-request-triggers-in-power-automate/ .

Though I do feel like such kind of authentication is a little bit overkill for such trivial task as webhook trigger. Especially considering that Power Automate workflows for Team webhooks are user based, which means that it requires interactive OAuth authentication every time refresh token expires.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests