mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: adopt markdownlint and markdown-table-formatter for *.md (#15831)
Co-authored-by: Edward Angert <EdwardAngert@users.noreply.github.com>
This commit is contained in:
co-authored by
Edward Angert
parent
08463c27d8
commit
94f5d52fdc
@@ -64,7 +64,7 @@ You can modify the notification delivery behavior using the following server
|
||||
flags.
|
||||
|
||||
| Required | CLI | Env | Type | Description | Default |
|
||||
| :------: | ----------------------------------- | --------------------------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
|:--------:|-------------------------------------|-----------------------------------------|------------|-----------------------------------------------------------------------------------------------------------------------|---------|
|
||||
| ✔️ | `--notifications-dispatch-timeout` | `CODER_NOTIFICATIONS_DISPATCH_TIMEOUT` | `duration` | How long to wait while a notification is being sent before giving up. | 1m |
|
||||
| ✔️ | `--notifications-method` | `CODER_NOTIFICATIONS_METHOD` | `string` | Which delivery method to use (available options: 'smtp', 'webhook'). See [Delivery Methods](#delivery-methods) below. | smtp |
|
||||
| -️ | `--notifications-max-send-attempts` | `CODER_NOTIFICATIONS_MAX_SEND_ATTEMPTS` | `int` | The upper limit of attempts to send a notification. | 5 |
|
||||
@@ -90,15 +90,15 @@ existing one.
|
||||
**Server Settings:**
|
||||
|
||||
| Required | CLI | Env | Type | Description | Default |
|
||||
| :------: | ------------------- | ----------------------- | -------- | ----------------------------------------- | --------- |
|
||||
|:--------:|---------------------|-------------------------|----------|-------------------------------------------|-----------|
|
||||
| ✔️ | `--email-from` | `CODER_EMAIL_FROM` | `string` | The sender's address to use. | |
|
||||
| ✔️ | `--email-smarthost` | `CODER_EMAIL_SMARTHOST` | `string` | The SMTP relay to send messages |
|
||||
| ✔️ | `--email-smarthost` | `CODER_EMAIL_SMARTHOST` | `string` | The SMTP relay to send messages | |
|
||||
| ✔️ | `--email-hello` | `CODER_EMAIL_HELLO` | `string` | The hostname identifying the SMTP server. | localhost |
|
||||
|
||||
**Authentication Settings:**
|
||||
|
||||
| Required | CLI | Env | Type | Description |
|
||||
| :------: | ---------------------------- | -------------------------------- | -------- | ------------------------------------------------------------------------- |
|
||||
|:--------:|------------------------------|----------------------------------|----------|---------------------------------------------------------------------------|
|
||||
| - | `--email-auth-username` | `CODER_EMAIL_AUTH_USERNAME` | `string` | Username to use with PLAIN/LOGIN authentication. |
|
||||
| - | `--email-auth-password` | `CODER_EMAIL_AUTH_PASSWORD` | `string` | Password to use with PLAIN/LOGIN authentication. |
|
||||
| - | `--email-auth-password-file` | `CODER_EMAIL_AUTH_PASSWORD_FILE` | `string` | File from which to load password for use with PLAIN/LOGIN authentication. |
|
||||
@@ -106,14 +106,14 @@ existing one.
|
||||
|
||||
**TLS Settings:**
|
||||
|
||||
| Required | CLI | Env | Type | Description | Default |
|
||||
| :------: | --------------------------- | ----------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| - | `--email-force-tls` | `CODER_EMAIL_FORCE_TLS` | `bool` | Force a TLS connection to the configured SMTP smarthost. If port 465 is used, TLS will be forced. See https://datatracker.ietf.org/doc/html/rfc8314#section-3.3. | false |
|
||||
| - | `--email-tls-starttls` | `CODER_EMAIL_TLS_STARTTLS` | `bool` | Enable STARTTLS to upgrade insecure SMTP connections using TLS. Ignored if `CODER_NOTIFICATIONS_EMAIL_FORCE_TLS` is set. | false |
|
||||
| - | `--email-tls-skip-verify` | `CODER_EMAIL_TLS_SKIPVERIFY` | `bool` | Skip verification of the target server's certificate (**insecure**). | false |
|
||||
| - | `--email-tls-server-name` | `CODER_EMAIL_TLS_SERVERNAME` | `string` | Server name to verify against the target certificate. | |
|
||||
| - | `--email-tls-cert-file` | `CODER_EMAIL_TLS_CERTFILE` | `string` | Certificate file to use. | |
|
||||
| - | `--email-tls-cert-key-file` | `CODER_EMAIL_TLS_CERTKEYFILE` | `string` | Certificate key file to use. | |
|
||||
| Required | CLI | Env | Type | Description | Default |
|
||||
|:--------:|-----------------------------|-------------------------------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|
|
||||
| - | `--email-force-tls` | `CODER_EMAIL_FORCE_TLS` | `bool` | Force a TLS connection to the configured SMTP smarthost. If port 465 is used, TLS will be forced. See <https://datatracker.ietf.org/doc/html/rfc8314#section-3.3>. | false |
|
||||
| - | `--email-tls-starttls` | `CODER_EMAIL_TLS_STARTTLS` | `bool` | Enable STARTTLS to upgrade insecure SMTP connections using TLS. Ignored if `CODER_NOTIFICATIONS_EMAIL_FORCE_TLS` is set. | false |
|
||||
| - | `--email-tls-skip-verify` | `CODER_EMAIL_TLS_SKIPVERIFY` | `bool` | Skip verification of the target server's certificate (**insecure**). | false |
|
||||
| - | `--email-tls-server-name` | `CODER_EMAIL_TLS_SERVERNAME` | `string` | Server name to verify against the target certificate. | |
|
||||
| - | `--email-tls-cert-file` | `CODER_EMAIL_TLS_CERTFILE` | `string` | Certificate file to use. | |
|
||||
| - | `--email-tls-cert-key-file` | `CODER_EMAIL_TLS_CERTKEYFILE` | `string` | Certificate key file to use. | |
|
||||
|
||||
**NOTE:** you _MUST_ use `CODER_EMAIL_FORCE_TLS` if your smarthost supports TLS
|
||||
on a port other than `465`.
|
||||
@@ -123,9 +123,11 @@ on a port other than `465`.
|
||||
After setting the required fields above:
|
||||
|
||||
1. Create an [App Password](https://myaccount.google.com/apppasswords) using the
|
||||
account you wish to send from
|
||||
2. Set the following configuration options:
|
||||
```
|
||||
account you wish to send from.
|
||||
|
||||
1. Set the following configuration options:
|
||||
|
||||
```text
|
||||
CODER_EMAIL_SMARTHOST=smtp.gmail.com:465
|
||||
CODER_EMAIL_AUTH_USERNAME=<user>@<domain>
|
||||
CODER_EMAIL_AUTH_PASSWORD="<app password created above>"
|
||||
@@ -140,8 +142,9 @@ for more options.
|
||||
After setting the required fields above:
|
||||
|
||||
1. Setup an account on Microsoft 365 or outlook.com
|
||||
2. Set the following configuration options:
|
||||
```
|
||||
1. Set the following configuration options:
|
||||
|
||||
```text
|
||||
CODER_EMAIL_SMARTHOST=smtp-mail.outlook.com:587
|
||||
CODER_EMAIL_TLS_STARTTLS=true
|
||||
CODER_EMAIL_AUTH_USERNAME=<user>@<domain>
|
||||
@@ -161,40 +164,40 @@ systems.
|
||||
**Settings**:
|
||||
|
||||
| Required | CLI | Env | Type | Description |
|
||||
| :------: | ---------------------------------- | -------------------------------------- | ----- | --------------------------------------- |
|
||||
|:--------:|------------------------------------|----------------------------------------|-------|-----------------------------------------|
|
||||
| ✔️ | `--notifications-webhook-endpoint` | `CODER_NOTIFICATIONS_WEBHOOK_ENDPOINT` | `url` | The endpoint to which to send webhooks. |
|
||||
|
||||
Here is an example payload for Coder's webhook notification:
|
||||
|
||||
```json
|
||||
{
|
||||
"_version": "1.0",
|
||||
"msg_id": "88750cad-77d4-4663-8bc0-f46855f5019b",
|
||||
"payload": {
|
||||
"_version": "1.0",
|
||||
"notification_name": "Workspace Deleted",
|
||||
"user_id": "4ac34fcb-8155-44d5-8301-e3cd46e88b35",
|
||||
"user_email": "danny@coder.com",
|
||||
"user_name": "danny",
|
||||
"user_username": "danny",
|
||||
"actions": [
|
||||
{
|
||||
"label": "View workspaces",
|
||||
"url": "https://et23ntkhpueak.pit-1.try.coder.app/workspaces"
|
||||
},
|
||||
{
|
||||
"label": "View templates",
|
||||
"url": "https://et23ntkhpueak.pit-1.try.coder.app/templates"
|
||||
}
|
||||
],
|
||||
"labels": {
|
||||
"initiator": "danny",
|
||||
"name": "my-workspace",
|
||||
"reason": "initiated by user"
|
||||
}
|
||||
},
|
||||
"title": "Workspace \"my-workspace\" deleted",
|
||||
"body": "Hi danny\n\nYour workspace my-workspace was deleted.\nThe specified reason was \"initiated by user (danny)\"."
|
||||
"_version": "1.0",
|
||||
"msg_id": "88750cad-77d4-4663-8bc0-f46855f5019b",
|
||||
"payload": {
|
||||
"_version": "1.0",
|
||||
"notification_name": "Workspace Deleted",
|
||||
"user_id": "4ac34fcb-8155-44d5-8301-e3cd46e88b35",
|
||||
"user_email": "danny@coder.com",
|
||||
"user_name": "danny",
|
||||
"user_username": "danny",
|
||||
"actions": [
|
||||
{
|
||||
"label": "View workspaces",
|
||||
"url": "https://et23ntkhpueak.pit-1.try.coder.app/workspaces"
|
||||
},
|
||||
{
|
||||
"label": "View templates",
|
||||
"url": "https://et23ntkhpueak.pit-1.try.coder.app/templates"
|
||||
}
|
||||
],
|
||||
"labels": {
|
||||
"initiator": "danny",
|
||||
"name": "my-workspace",
|
||||
"reason": "initiated by user"
|
||||
}
|
||||
},
|
||||
"title": "Workspace \"my-workspace\" deleted",
|
||||
"body": "Hi danny\n\nYour workspace my-workspace was deleted.\nThe specified reason was \"initiated by user (danny)\"."
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ To integrate Slack with Coder, follow these steps to create a Slack application:
|
||||
|
||||
3. Under "OAuth & Permissions", add the following OAuth scopes:
|
||||
|
||||
- `chat:write`: To send messages as the app.
|
||||
- `users:read`: To find the user details.
|
||||
- `users:read.email`: To find user emails.
|
||||
- `chat:write`: To send messages as the app.
|
||||
- `users:read`: To find the user details.
|
||||
- `users:read.email`: To find user emails.
|
||||
|
||||
4. Install the app to your workspace and note down the **Bot User OAuth Token**
|
||||
from the "OAuth & Permissions" section.
|
||||
@@ -52,128 +52,128 @@ To build the server to receive webhooks and interact with Slack:
|
||||
|
||||
1. Initialize your project by running:
|
||||
|
||||
```bash
|
||||
npm init -y
|
||||
```
|
||||
```bash
|
||||
npm init -y
|
||||
```
|
||||
|
||||
2. Install the Bolt library:
|
||||
|
||||
```bash
|
||||
npm install @slack/bolt
|
||||
```
|
||||
```bash
|
||||
npm install @slack/bolt
|
||||
```
|
||||
|
||||
3. Create and edit the `app.js` file. Below is an example of the basic
|
||||
structure:
|
||||
|
||||
```js
|
||||
const { App, LogLevel, ExpressReceiver } = require("@slack/bolt");
|
||||
const bodyParser = require("body-parser");
|
||||
```js
|
||||
const { App, LogLevel, ExpressReceiver } = require("@slack/bolt");
|
||||
const bodyParser = require("body-parser");
|
||||
|
||||
const port = process.env.PORT || 6000;
|
||||
const port = process.env.PORT || 6000;
|
||||
|
||||
// Create a Bolt Receiver
|
||||
const receiver = new ExpressReceiver({
|
||||
signingSecret: process.env.SLACK_SIGNING_SECRET,
|
||||
});
|
||||
receiver.router.use(bodyParser.json());
|
||||
// Create a Bolt Receiver
|
||||
const receiver = new ExpressReceiver({
|
||||
signingSecret: process.env.SLACK_SIGNING_SECRET,
|
||||
});
|
||||
receiver.router.use(bodyParser.json());
|
||||
|
||||
// Create the Bolt App, using the receiver
|
||||
const app = new App({
|
||||
token: process.env.SLACK_BOT_TOKEN,
|
||||
logLevel: LogLevel.DEBUG,
|
||||
receiver,
|
||||
});
|
||||
// Create the Bolt App, using the receiver
|
||||
const app = new App({
|
||||
token: process.env.SLACK_BOT_TOKEN,
|
||||
logLevel: LogLevel.DEBUG,
|
||||
receiver,
|
||||
});
|
||||
|
||||
receiver.router.post("/v1/webhook", async (req, res) => {
|
||||
try {
|
||||
if (!req.body) {
|
||||
return res.status(400).send("Error: request body is missing");
|
||||
}
|
||||
receiver.router.post("/v1/webhook", async (req, res) => {
|
||||
try {
|
||||
if (!req.body) {
|
||||
return res.status(400).send("Error: request body is missing");
|
||||
}
|
||||
|
||||
const { title, body } = req.body;
|
||||
if (!title || !body) {
|
||||
return res.status(400).send('Error: missing fields: "title", or "body"');
|
||||
}
|
||||
const { title, body } = req.body;
|
||||
if (!title || !body) {
|
||||
return res.status(400).send('Error: missing fields: "title", or "body"');
|
||||
}
|
||||
|
||||
const payload = req.body.payload;
|
||||
if (!payload) {
|
||||
return res.status(400).send('Error: missing "payload" field');
|
||||
}
|
||||
const payload = req.body.payload;
|
||||
if (!payload) {
|
||||
return res.status(400).send('Error: missing "payload" field');
|
||||
}
|
||||
|
||||
const { user_email, actions } = payload;
|
||||
if (!user_email || !actions) {
|
||||
return res
|
||||
.status(400)
|
||||
.send('Error: missing fields: "user_email", "actions"');
|
||||
}
|
||||
const { user_email, actions } = payload;
|
||||
if (!user_email || !actions) {
|
||||
return res
|
||||
.status(400)
|
||||
.send('Error: missing fields: "user_email", "actions"');
|
||||
}
|
||||
|
||||
// Get the user ID using Slack API
|
||||
const userByEmail = await app.client.users.lookupByEmail({
|
||||
email: user_email,
|
||||
});
|
||||
// Get the user ID using Slack API
|
||||
const userByEmail = await app.client.users.lookupByEmail({
|
||||
email: user_email,
|
||||
});
|
||||
|
||||
const slackMessage = {
|
||||
channel: userByEmail.user.id,
|
||||
text: body,
|
||||
blocks: [
|
||||
{
|
||||
type: "header",
|
||||
text: { type: "plain_text", text: title },
|
||||
},
|
||||
{
|
||||
type: "section",
|
||||
text: { type: "mrkdwn", text: body },
|
||||
},
|
||||
],
|
||||
};
|
||||
const slackMessage = {
|
||||
channel: userByEmail.user.id,
|
||||
text: body,
|
||||
blocks: [
|
||||
{
|
||||
type: "header",
|
||||
text: { type: "plain_text", text: title },
|
||||
},
|
||||
{
|
||||
type: "section",
|
||||
text: { type: "mrkdwn", text: body },
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// Add action buttons if they exist
|
||||
if (actions && actions.length > 0) {
|
||||
slackMessage.blocks.push({
|
||||
type: "actions",
|
||||
elements: actions.map((action) => ({
|
||||
type: "button",
|
||||
text: { type: "plain_text", text: action.label },
|
||||
url: action.url,
|
||||
})),
|
||||
});
|
||||
}
|
||||
// Add action buttons if they exist
|
||||
if (actions && actions.length > 0) {
|
||||
slackMessage.blocks.push({
|
||||
type: "actions",
|
||||
elements: actions.map((action) => ({
|
||||
type: "button",
|
||||
text: { type: "plain_text", text: action.label },
|
||||
url: action.url,
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
// Post message to the user on Slack
|
||||
await app.client.chat.postMessage(slackMessage);
|
||||
// Post message to the user on Slack
|
||||
await app.client.chat.postMessage(slackMessage);
|
||||
|
||||
res.status(204).send();
|
||||
} catch (error) {
|
||||
console.error("Error sending message:", error);
|
||||
res.status(500).send();
|
||||
}
|
||||
});
|
||||
res.status(204).send();
|
||||
} catch (error) {
|
||||
console.error("Error sending message:", error);
|
||||
res.status(500).send();
|
||||
}
|
||||
});
|
||||
|
||||
// Acknowledge clicks on link_button, otherwise Slack UI
|
||||
// complains about missing events.
|
||||
app.action("button_click", async ({ body, ack, say }) => {
|
||||
await ack(); // no specific action needed
|
||||
});
|
||||
// Acknowledge clicks on link_button, otherwise Slack UI
|
||||
// complains about missing events.
|
||||
app.action("button_click", async ({ body, ack, say }) => {
|
||||
await ack(); // no specific action needed
|
||||
});
|
||||
|
||||
// Start the Bolt app
|
||||
(async () => {
|
||||
await app.start(port);
|
||||
console.log("⚡️ Coder Slack bot is running!");
|
||||
})();
|
||||
```
|
||||
// Start the Bolt app
|
||||
(async () => {
|
||||
await app.start(port);
|
||||
console.log("⚡️ Coder Slack bot is running!");
|
||||
})();
|
||||
```
|
||||
|
||||
3. Set environment variables to identify the Slack app:
|
||||
4. Set environment variables to identify the Slack app:
|
||||
|
||||
```bash
|
||||
export SLACK_BOT_TOKEN=xoxb-...
|
||||
export SLACK_SIGNING_SECRET=0da4b...
|
||||
```
|
||||
```bash
|
||||
export SLACK_BOT_TOKEN=xoxb-...
|
||||
export SLACK_SIGNING_SECRET=0da4b...
|
||||
```
|
||||
|
||||
4. Start the web application by running:
|
||||
5. Start the web application by running:
|
||||
|
||||
```bash
|
||||
node app.js
|
||||
```
|
||||
```bash
|
||||
node app.js
|
||||
```
|
||||
|
||||
## Enable Interactivity in Slack
|
||||
|
||||
|
||||
@@ -21,115 +21,115 @@ following:
|
||||
|
||||
The process of setting up a Teams workflow consists of three key steps:
|
||||
|
||||
1. Configure the Webhook Trigger.
|
||||
1. Configure the Webhook Trigger.
|
||||
|
||||
Begin by configuring the trigger: **"When a Teams webhook request is
|
||||
received"**.
|
||||
Begin by configuring the trigger: **"When a Teams webhook request is
|
||||
received"**.
|
||||
|
||||
Ensure the trigger access level is set to **"Anyone"**.
|
||||
Ensure the trigger access level is set to **"Anyone"**.
|
||||
|
||||
2. Setup the JSON Parsing Action.
|
||||
1. Setup the JSON Parsing Action.
|
||||
|
||||
Next, add the **"Parse JSON"** action, linking the content to the **"Body"**
|
||||
of the received webhook request. Use the following schema to parse the
|
||||
notification payload:
|
||||
Add the **"Parse JSON"** action, linking the content to the **"Body"** of the
|
||||
received webhook request. Use the following schema to parse the notification
|
||||
payload:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_version": {
|
||||
"type": "string"
|
||||
},
|
||||
"payload": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_version": {
|
||||
"type": "string"
|
||||
},
|
||||
"user_email": {
|
||||
"type": "string"
|
||||
},
|
||||
"actions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"label": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["label", "url"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"body": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
```json
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_version": {
|
||||
"type": "string"
|
||||
},
|
||||
"payload": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_version": {
|
||||
"type": "string"
|
||||
},
|
||||
"user_email": {
|
||||
"type": "string"
|
||||
},
|
||||
"actions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"label": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["label", "url"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"body": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This action parses the notification's title, body, and the recipient's email
|
||||
address.
|
||||
This action parses the notification's title, body, and the recipient's email
|
||||
address.
|
||||
|
||||
3. Configure the Adaptive Card Action.
|
||||
1. Configure the Adaptive Card Action.
|
||||
|
||||
Finally, set up the **"Post Adaptive Card in a chat or channel"** action
|
||||
with the following recommended settings:
|
||||
Finally, set up the **"Post Adaptive Card in a chat or channel"** action with
|
||||
the following recommended settings:
|
||||
|
||||
**Post as**: Flow Bot
|
||||
**Post as**: Flow Bot
|
||||
|
||||
**Post in**: Chat with Flow Bot
|
||||
**Post in**: Chat with Flow Bot
|
||||
|
||||
**Recipient**: `user_email`
|
||||
**Recipient**: `user_email`
|
||||
|
||||
Use the following _Adaptive Card_ template:
|
||||
Use the following _Adaptive Card_ template:
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://adaptivecards.io/schemas/adaptive-card.json",
|
||||
"type": "AdaptiveCard",
|
||||
"version": "1.0",
|
||||
"body": [
|
||||
{
|
||||
"type": "Image",
|
||||
"url": "https://coder.com/coder-logo-horizontal.png",
|
||||
"height": "40px",
|
||||
"altText": "Coder",
|
||||
"horizontalAlignment": "center"
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": "**@{replace(body('Parse_JSON')?['title'], '"', '\"')}**"
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": "@{replace(body('Parse_JSON')?['body'], '"', '\"')}",
|
||||
"wrap": true
|
||||
},
|
||||
{
|
||||
"type": "ActionSet",
|
||||
"actions": [@{replace(replace(join(body('Parse_JSON')?['payload']?['actions'], ','), '{', '{"type": "Action.OpenUrl",'), '"label"', '"title"')}]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
```json
|
||||
{
|
||||
"$schema": "https://adaptivecards.io/schemas/adaptive-card.json",
|
||||
"type": "AdaptiveCard",
|
||||
"version": "1.0",
|
||||
"body": [
|
||||
{
|
||||
"type": "Image",
|
||||
"url": "https://coder.com/coder-logo-horizontal.png",
|
||||
"height": "40px",
|
||||
"altText": "Coder",
|
||||
"horizontalAlignment": "center"
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": "**@{replace(body('Parse_JSON')?['title'], '"', '\"')}**"
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": "@{replace(body('Parse_JSON')?['body'], '"', '\"')}",
|
||||
"wrap": true
|
||||
},
|
||||
{
|
||||
"type": "ActionSet",
|
||||
"actions": [@{replace(replace(join(body('Parse_JSON')?['payload']?['actions'], ','), '{', '{"type": "Action.OpenUrl",'), '"label"', '"title"')}]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
_Notice_: The Coder `actions` format differs from the `ActionSet` schema, so
|
||||
its properties need to be modified: include `Action.OpenUrl` type, rename
|
||||
`label` to `title`. Unfortunately, there is no straightforward solution for
|
||||
`for-each` pattern.
|
||||
_Notice_: The Coder `actions` format differs from the `ActionSet` schema, so
|
||||
its properties need to be modified: include `Action.OpenUrl` type, rename
|
||||
`label` to `title`. Unfortunately, there is no straightforward solution for
|
||||
`for-each` pattern.
|
||||
|
||||
Feel free to customize the payload to modify the logo, notification title,
|
||||
or body content to suit your needs.
|
||||
Feel free to customize the payload to modify the logo, notification title, or
|
||||
body content to suit your needs.
|
||||
|
||||
## Enable Webhook Integration
|
||||
|
||||
|
||||
Reference in New Issue
Block a user