fastlane-plugin-teams_card 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +46 -4
- data/lib/fastlane/plugin/teams_card/actions/teams_card_action.rb +104 -110
- data/lib/fastlane/plugin/teams_card/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b229f7cfb58d0bc2158d0b16b61952554e78266cdffdb37aa7db2fa12a9c1ce
|
4
|
+
data.tar.gz: 03c0faf12e34721112ed176a827e0c181e5b304e95a56100653042cabc323380
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 04c5e5f5e5bc2a3ef2ca16aa8068dff16035fa6cfdb9e40f2f960d4498b9dac15c5f2fed33d03a044cf584cf9963dc715edfba97f8460fd3c6b6665e882f5b0b
|
7
|
+
data.tar.gz: 3b8f8b94e0b882f658214b9ade5495c2deb7be4471d01807a707f20c65513b0549fff1987ebcd27771ba193b56ae9ce166ff74196f12e9d2e264317aed30bee5
|
data/README.md
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
# teams_card plugin
|
1
|
+
# Microsoft Teams fastlane teams_card plugin via Workflow
|
2
2
|
|
3
3
|
[](https://rubygems.org/gems/fastlane-plugin-teams_card)
|
4
4
|
|
5
|
+
> ⚠️ Note: This plugin utilizes the latest **Workflows** app (rather than the [now-retired Office connectors](https://devblogs.microsoft.com/microsoft365dev/retirement-of-office-365-connectors-within-microsoft-teams/) used in other plugins)
|
6
|
+
|
5
7
|
## Getting Started
|
6
8
|
|
7
9
|
This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-teams_card`, add it to your project by running:
|
@@ -57,6 +59,32 @@ This code give the following message:
|
|
57
59
|
|
58
60
|
<img src="screenshots/1.png">
|
59
61
|
|
62
|
+
### Custom Adaptive cards
|
63
|
+
|
64
|
+
You can fully customize your cards by providing a custom JSON for AdaptiveCard. Look at the [templates and information on how to customize cards](https://adaptivecards.io/samples/). Note that MS Teams cannot display the latest versions of the schema!
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
teams_card(
|
68
|
+
workflow_url: "https://your.logic.azure.com:443/workflows/1234567890",
|
69
|
+
custom_card: {
|
70
|
+
"type" => "AdaptiveCard",
|
71
|
+
"body" => [
|
72
|
+
{
|
73
|
+
"type" => "TextBlock",
|
74
|
+
"text" => "Custom message content!",
|
75
|
+
"wrap" => true
|
76
|
+
}
|
77
|
+
],
|
78
|
+
"$schema" => "http://adaptivecards.io/schemas/adaptive-card.json",
|
79
|
+
"version" => "1.2"
|
80
|
+
}
|
81
|
+
)
|
82
|
+
```
|
83
|
+
|
84
|
+
This code give the following message:
|
85
|
+
|
86
|
+
<img src="screenshots/2.png">
|
87
|
+
|
60
88
|
### Help
|
61
89
|
|
62
90
|
Once installed, information and help for an action can be printed out with this command:
|
@@ -69,12 +97,13 @@ fastlane action teams_card
|
|
69
97
|
|
70
98
|
| Key | Description | Env Var(s) | Default |
|
71
99
|
|-------------|----------------------------------------------------|---------------------------|---------|
|
72
|
-
| `title` |
|
73
|
-
| `image` |
|
74
|
-
| `image_title` |
|
100
|
+
| `title` | Optional title | `TEAMS_MESSAGE_TITLE` | |
|
101
|
+
| `image` | Optional image on your activity (project logo, company logo, etc.) | `TEAMS_MESSAGE_IMAGE` | |
|
102
|
+
| `image_title` | Optional title next to your image | `TEAMS_MESSAGE_IMAGE_TITLE` | |
|
75
103
|
| `text` | The message you want to display | `TEAMS_MESSAGE_TEXT` | |
|
76
104
|
| `facts` | Optional facts (assigned to, due date, status, branch, environment, etc.) | `TEAMS_MESSAGE_FACTS` | `[]` |
|
77
105
|
| `open_url` | Optional URL for a button at the bottom of the card | `TEAMS_MESSAGE_OPEN_URL` | |
|
106
|
+
| `custom_card` | Optional JSON to fully customize your card. | `TEAMS_MESSAGE_CUSTOM_CARD` | |
|
78
107
|
| `workflow_url` | The URL of the incoming Webhook you created in Workflows app | `TEAMS_MESSAGE_WORKFLOW_URL` | |
|
79
108
|
|
80
109
|
|
@@ -84,6 +113,19 @@ Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plu
|
|
84
113
|
|
85
114
|
**Note to author:** Please set up a sample project to make it easy for users to explore what your plugin does. Provide everything that is necessary to try out the plugin in this project (including a sample Xcode/Android project if necessary)
|
86
115
|
|
116
|
+
## Run tests for this plugin
|
117
|
+
|
118
|
+
To run both the tests, and code style validation, run
|
119
|
+
|
120
|
+
```
|
121
|
+
rake
|
122
|
+
```
|
123
|
+
|
124
|
+
To automatically fix many of the styling issues, use
|
125
|
+
```
|
126
|
+
rubocop -a
|
127
|
+
```
|
128
|
+
|
87
129
|
## Issues and Feedback
|
88
130
|
|
89
131
|
For any other issues and feedback about this plugin, please submit it to this repository.
|
@@ -6,91 +6,119 @@ module Fastlane
|
|
6
6
|
module Actions
|
7
7
|
class TeamsCardAction < Action
|
8
8
|
def self.run(params)
|
9
|
+
payload = build_payload(params)
|
10
|
+
send_message(params[:workflow_url], payload)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Build the payload for the Teams message
|
14
|
+
def self.build_payload(params)
|
15
|
+
# Use custom card if provided, otherwise build the card dynamically
|
16
|
+
content = params[:custom_card] || {
|
17
|
+
"type" => "AdaptiveCard",
|
18
|
+
"body" => build_card_body(params),
|
19
|
+
"$schema" => "http://adaptivecards.io/schemas/adaptive-card.json",
|
20
|
+
"version" => "1.2"
|
21
|
+
}
|
22
|
+
|
9
23
|
payload = {
|
10
24
|
"type" => "message",
|
11
25
|
"attachments" => [{
|
12
26
|
"contentType" => "application/vnd.microsoft.card.adaptive",
|
13
27
|
"contentUrl" => nil,
|
14
|
-
"content" =>
|
15
|
-
"type" => "AdaptiveCard",
|
16
|
-
"body" => [
|
17
|
-
{
|
18
|
-
"type" => "TextBlock",
|
19
|
-
"text" => params[:text],
|
20
|
-
"wrap" => true
|
21
|
-
},
|
22
|
-
{
|
23
|
-
"type" => "FactSet",
|
24
|
-
"facts" => params[:facts]
|
25
|
-
}
|
26
|
-
],
|
27
|
-
"$schema" => "http://adaptivecards.io/schemas/adaptive-card.json",
|
28
|
-
"version" => "1.2"
|
29
|
-
}
|
28
|
+
"content" => content
|
30
29
|
}]
|
31
30
|
}
|
32
31
|
|
33
|
-
|
34
|
-
|
32
|
+
add_actions_to_payload(payload, params[:open_url]) if params[:open_url]
|
33
|
+
payload
|
34
|
+
end
|
35
|
+
|
36
|
+
# Construct the body of the Adaptive Card
|
37
|
+
def self.build_card_body(params)
|
38
|
+
body = [
|
39
|
+
build_text_block(params[:text]),
|
40
|
+
build_fact_set(params[:facts])
|
41
|
+
]
|
42
|
+
|
43
|
+
body.unshift(build_image_column_set(params[:image], params[:image_title])) if params[:image] || params[:image_title]
|
44
|
+
body.unshift(build_title_block(params[:title])) if params[:title]
|
45
|
+
body
|
46
|
+
end
|
47
|
+
|
48
|
+
# Create a text block for the card
|
49
|
+
def self.build_text_block(text)
|
50
|
+
{
|
51
|
+
"type" => "TextBlock",
|
52
|
+
"text" => text,
|
53
|
+
"wrap" => true
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
# Create a fact set for the card
|
58
|
+
def self.build_fact_set(facts)
|
59
|
+
{
|
60
|
+
"type" => "FactSet",
|
61
|
+
"facts" => facts
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
# Create an image and title column set for the card
|
66
|
+
def self.build_image_column_set(image, image_title)
|
67
|
+
{
|
68
|
+
"type" => "ColumnSet",
|
69
|
+
"columns" => [
|
35
70
|
{
|
36
|
-
"type" => "
|
37
|
-
"
|
71
|
+
"type" => "Column",
|
72
|
+
"items" => [
|
38
73
|
{
|
39
|
-
"type" => "
|
40
|
-
"
|
41
|
-
|
42
|
-
|
43
|
-
"style" => "Person",
|
44
|
-
"url" => params[:image],
|
45
|
-
"size" => "Small"
|
46
|
-
}
|
47
|
-
],
|
48
|
-
"width" => "auto"
|
49
|
-
},
|
50
|
-
{
|
51
|
-
"type" => "Column",
|
52
|
-
"items" => [
|
53
|
-
{
|
54
|
-
"type" => "TextBlock",
|
55
|
-
"weight" => "Bolder",
|
56
|
-
"text" => params[:image_title],
|
57
|
-
"wrap" => true
|
58
|
-
}
|
59
|
-
],
|
60
|
-
"width" => "stretch",
|
61
|
-
"horizontalAlignment" => "Left",
|
62
|
-
"verticalContentAlignment" => "Center"
|
74
|
+
"type" => "Image",
|
75
|
+
"style" => "Person",
|
76
|
+
"url" => image,
|
77
|
+
"size" => "Small"
|
63
78
|
}
|
64
|
-
]
|
65
|
-
|
66
|
-
|
67
|
-
end
|
68
|
-
|
69
|
-
if params[:title]
|
70
|
-
payload["attachments"][0]["content"]["body"].unshift(
|
71
|
-
{
|
72
|
-
"type" => "TextBlock",
|
73
|
-
"size" => "large",
|
74
|
-
"weight" => "bolder",
|
75
|
-
"text" => params[:title],
|
76
|
-
"wrap" => true
|
77
|
-
}
|
78
|
-
)
|
79
|
-
end
|
80
|
-
|
81
|
-
if params[:open_url]
|
82
|
-
payload["attachments"][0]["content"]["actions"] = [
|
79
|
+
],
|
80
|
+
"width" => "auto"
|
81
|
+
},
|
83
82
|
{
|
84
|
-
"type" => "
|
85
|
-
"
|
86
|
-
|
83
|
+
"type" => "Column",
|
84
|
+
"items" => [
|
85
|
+
{
|
86
|
+
"type" => "TextBlock",
|
87
|
+
"weight" => "Bolder",
|
88
|
+
"text" => image_title,
|
89
|
+
"wrap" => true
|
90
|
+
}
|
91
|
+
],
|
92
|
+
"width" => "stretch",
|
93
|
+
"horizontalAlignment" => "Left",
|
94
|
+
"verticalContentAlignment" => "Center"
|
87
95
|
}
|
88
96
|
]
|
89
|
-
|
97
|
+
}
|
98
|
+
end
|
90
99
|
|
91
|
-
|
100
|
+
# Create a title block for the card
|
101
|
+
def self.build_title_block(title)
|
102
|
+
{
|
103
|
+
"type" => "TextBlock",
|
104
|
+
"size" => "large",
|
105
|
+
"weight" => "bolder",
|
106
|
+
"text" => title,
|
107
|
+
"wrap" => true
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
# Add actions to the payload if needed
|
112
|
+
def self.add_actions_to_payload(payload, open_url)
|
113
|
+
payload["attachments"][0]["content"]["actions"] ||= []
|
114
|
+
payload["attachments"][0]["content"]["actions"] << {
|
115
|
+
"type" => "Action.OpenUrl",
|
116
|
+
"title" => "Open",
|
117
|
+
"url" => open_url
|
118
|
+
}
|
92
119
|
end
|
93
120
|
|
121
|
+
# Send the message to the Teams Webhook URL
|
94
122
|
def self.send_message(url, payload)
|
95
123
|
require 'net/http'
|
96
124
|
require 'uri'
|
@@ -104,6 +132,7 @@ module Fastlane
|
|
104
132
|
is_message_success(response)
|
105
133
|
end
|
106
134
|
|
135
|
+
# Check if the message was successfully posted
|
107
136
|
def self.is_message_success(response)
|
108
137
|
if response.code.to_i == 202
|
109
138
|
UI.message("🔔 The card was posted successfully.")
|
@@ -147,6 +176,12 @@ module Fastlane
|
|
147
176
|
description: "Optional url for a button at bottom of card",
|
148
177
|
optional: true),
|
149
178
|
|
179
|
+
FastlaneCore::ConfigItem.new(key: :custom_card,
|
180
|
+
env_name: "TEAMS_MESSAGE_CUSTOM_CARD",
|
181
|
+
description: "Custom Adaptive Card JSON object",
|
182
|
+
optional: true,
|
183
|
+
type: Hash),
|
184
|
+
|
150
185
|
FastlaneCore::ConfigItem.new(key: :workflow_url,
|
151
186
|
env_name: "TEAMS_MESSAGE_TEAMS_URL",
|
152
187
|
sensitive: true,
|
@@ -158,48 +193,7 @@ module Fastlane
|
|
158
193
|
]
|
159
194
|
end
|
160
195
|
|
161
|
-
|
162
|
-
[
|
163
|
-
'teams_card(
|
164
|
-
workflow_url: "https://your.logic.azure.com:443/workflows/1234567890",
|
165
|
-
title: "Notification Title",
|
166
|
-
text: "A new release is ready for testing!",
|
167
|
-
image: "https://raw.githubusercontent.com/fastlane/boarding/master/app/assets/images/fastlane.png",
|
168
|
-
image_title: "Fastlane",
|
169
|
-
open_url: "https://beta.itunes.apple.com/v1/app/_YOUR_APP_ID_",
|
170
|
-
facts: [
|
171
|
-
{
|
172
|
-
"title" => "Environment",
|
173
|
-
"value" => "Staging"
|
174
|
-
},
|
175
|
-
{
|
176
|
-
"title" => "Release",
|
177
|
-
"value" => "1.0.3"
|
178
|
-
}
|
179
|
-
]
|
180
|
-
)'
|
181
|
-
]
|
182
|
-
end
|
183
|
-
|
184
|
-
def self.description
|
185
|
-
"Easily send a message to a Microsoft Teams channel or group chat through the Power Automate Webhook connector"
|
186
|
-
end
|
187
|
-
|
188
|
-
def self.details
|
189
|
-
"Send a message to a specific channel, group chat or chat on your Microsoft Teams organization via a Workflow of Power Automate"
|
190
|
-
end
|
191
|
-
|
192
|
-
def self.authors
|
193
|
-
["Kondamon"]
|
194
|
-
end
|
195
|
-
|
196
|
-
def self.return_value
|
197
|
-
# If your method provides a return value, you can describe here what it does
|
198
|
-
end
|
199
|
-
|
200
|
-
def self.is_supported?(platform)
|
201
|
-
true
|
202
|
-
end
|
196
|
+
# Rest of the methods...
|
203
197
|
end
|
204
198
|
end
|
205
199
|
end
|