diff --git a/cli/samples/restler/running-against-raft/replay.json b/cli/samples/restler/running-against-raft/replay.json index 7fe0b207..e089207c 100644 --- a/cli/samples/restler/running-against-raft/replay.json +++ b/cli/samples/restler/running-against-raft/replay.json @@ -1,7 +1,4 @@ { - "swaggerLocation" : { - "FilePath" : "" - }, "readOnlyFileShareMounts": [ { "FileShareName": "{jobId}", diff --git a/docs/images/LogicApps/LogicApp.png b/docs/images/LogicApps/LogicApp.png new file mode 100644 index 00000000..d47e72f6 Binary files /dev/null and b/docs/images/LogicApps/LogicApp.png differ diff --git a/docs/images/LogicApps/LogicApp_0_1.png b/docs/images/LogicApps/LogicApp_0_1.png new file mode 100644 index 00000000..493ec48d Binary files /dev/null and b/docs/images/LogicApps/LogicApp_0_1.png differ diff --git a/docs/images/LogicApps/LogicApp_0_2.png b/docs/images/LogicApps/LogicApp_0_2.png new file mode 100644 index 00000000..aac1b36b Binary files /dev/null and b/docs/images/LogicApps/LogicApp_0_2.png differ diff --git a/docs/images/LogicApps/LogicApp_1.png b/docs/images/LogicApps/LogicApp_1.png new file mode 100644 index 00000000..cd4b5f47 Binary files /dev/null and b/docs/images/LogicApps/LogicApp_1.png differ diff --git a/docs/images/LogicApps/LogicApp_10.png b/docs/images/LogicApps/LogicApp_10.png new file mode 100644 index 00000000..3e76523a Binary files /dev/null and b/docs/images/LogicApps/LogicApp_10.png differ diff --git a/docs/images/LogicApps/LogicApp_11.png b/docs/images/LogicApps/LogicApp_11.png new file mode 100644 index 00000000..42e87eee Binary files /dev/null and b/docs/images/LogicApps/LogicApp_11.png differ diff --git a/docs/images/LogicApps/LogicApp_11_1.png b/docs/images/LogicApps/LogicApp_11_1.png new file mode 100644 index 00000000..ee738c77 Binary files /dev/null and b/docs/images/LogicApps/LogicApp_11_1.png differ diff --git a/docs/images/LogicApps/LogicApp_12.png b/docs/images/LogicApps/LogicApp_12.png new file mode 100644 index 00000000..4c0cfde2 Binary files /dev/null and b/docs/images/LogicApps/LogicApp_12.png differ diff --git a/docs/images/LogicApps/LogicApp_13.png b/docs/images/LogicApps/LogicApp_13.png new file mode 100644 index 00000000..412f1317 Binary files /dev/null and b/docs/images/LogicApps/LogicApp_13.png differ diff --git a/docs/images/LogicApps/LogicApp_2.png b/docs/images/LogicApps/LogicApp_2.png new file mode 100644 index 00000000..636e253a Binary files /dev/null and b/docs/images/LogicApps/LogicApp_2.png differ diff --git a/docs/images/LogicApps/LogicApp_3.png b/docs/images/LogicApps/LogicApp_3.png new file mode 100644 index 00000000..d1cd0d4b Binary files /dev/null and b/docs/images/LogicApps/LogicApp_3.png differ diff --git a/docs/images/LogicApps/LogicApp_4.png b/docs/images/LogicApps/LogicApp_4.png new file mode 100644 index 00000000..e162da7d Binary files /dev/null and b/docs/images/LogicApps/LogicApp_4.png differ diff --git a/docs/images/LogicApps/LogicApp_4_1.png b/docs/images/LogicApps/LogicApp_4_1.png new file mode 100644 index 00000000..b59c204c Binary files /dev/null and b/docs/images/LogicApps/LogicApp_4_1.png differ diff --git a/docs/images/LogicApps/LogicApp_5.png b/docs/images/LogicApps/LogicApp_5.png new file mode 100644 index 00000000..aa996be9 Binary files /dev/null and b/docs/images/LogicApps/LogicApp_5.png differ diff --git a/docs/images/LogicApps/LogicApp_6.png b/docs/images/LogicApps/LogicApp_6.png new file mode 100644 index 00000000..adad724f Binary files /dev/null and b/docs/images/LogicApps/LogicApp_6.png differ diff --git a/docs/images/LogicApps/LogicApp_7.png b/docs/images/LogicApps/LogicApp_7.png new file mode 100644 index 00000000..2fc711ee Binary files /dev/null and b/docs/images/LogicApps/LogicApp_7.png differ diff --git a/docs/images/LogicApps/LogicApp_8.png b/docs/images/LogicApps/LogicApp_8.png new file mode 100644 index 00000000..1ee7c0f6 Binary files /dev/null and b/docs/images/LogicApps/LogicApp_8.png differ diff --git a/docs/images/LogicApps/LogicApp_9.png b/docs/images/LogicApps/LogicApp_9.png new file mode 100644 index 00000000..ffcb8b54 Binary files /dev/null and b/docs/images/LogicApps/LogicApp_9.png differ diff --git a/docs/index.md b/docs/index.md index 31673305..d59f3d93 100644 --- a/docs/index.md +++ b/docs/index.md @@ -6,6 +6,7 @@ * How to [Onboard a Tool](how-to-onboard-a-tool.md) * How to configure [Webhooks](how-to-configure-webhooks.md) * How to [submit a job](how-to-submit-a-job.md) +* How to [handle webhooks with a Logic App](logicApps/github-email.md) * Using the RAFT [command line](cli-reference.md) * REST API * [Swagger](sdk/swagger.md) diff --git a/docs/logicApps/github-email.md b/docs/logicApps/github-email.md new file mode 100644 index 00000000..368132bb --- /dev/null +++ b/docs/logicApps/github-email.md @@ -0,0 +1,178 @@ +# Consuming webhooks with a logic app + +This tutorial demonstrates how you can consume webhooks generated by RAFT to +create github issues and send e-mail by using a [Logic App.](https://docs.microsoft.com/en-us/azure/logic-apps) + +[Hundreds of connectors](https://docs.microsoft.com/en-us/azure/connectors/apis-list) + are available for use in your logic app. In this tutorial, we are only demonstrating the +use of two. + + +## Step One: Use the Azure Portal to create a Logic App + +If you're unsure how to create a blank logic app, +see this [Quickstart guide.](https://docs.microsoft.com/en-us/azure/logic-apps/quickstart-create-first-logic-app-workflow) + +Open the logic app designer view, in the following steps we will add connectors and +code. + +## Step Two: Add Http Hander + +Search for **http**. +![Logic App](../images/LogicApps/LogicApp_0_1.png) + +Click on **Request**, then select **When a HTTP request is received** trigger. +![Logic App](../images/LogicApps/LogicApp_0_2.png) + +Then click on the **Use sample payload to generate schema** link. +![Logic App](../images/LogicApps/LogicApp_2.png) + +We will use the JSON snippet below to create the schema. You can use any valid JSON for this purpose. +The JSON we provide here, is an example of the BugFound body generated from RAFT's BugFound webhook. + +```json +[ + { + "Id":"37d90124-02f0-48f9-b3f7-a9c7295c04a5", + "EventType":"BugFound", + "Subject":"BugFound", + "Data":{ + "Tool":"RESTler", + "JobId":"3191249c-5a57-4f6c-9ef8-876574de6e2d", + "AgentName":"0-RESTler-123", + "Metadata":{ + "branch":"wizbangFeature" + }, + "BugDetails":{ + "bugBucket":"main500_1.txt", + "experiment":"experiment_123", + "jobId":"3191249c-5a57-4f6c-9ef8-876574de6e2d", + "outputFolder":"my_test_results" + } + }, + "DataVersion":"1.0", + "metadataVersion":"1", + "EventTime":"2020-11-04T18:35:54.3784505Z", + "Topic":"eventĀ gridĀ topic" + } +] +``` + +Paste the JSON into the schema window and click **Done.** +When you click **Save**, the HTTP POST URL will be generated. +You will use this URL when you register a Webhook with RAFT as the `--url` parameter. + +![Logic App](../images/LogicApps/LogicApp_3.png) + +## Step Three: Create a webhook + +Using the RAFT CLI run the following command to create a webhook for the BugFound event. +Use the Url from the previous step as the `--url` parameter in the command. + +``` +python raft.py webhook create --name MyWebhook --event BugFound --url "https://prod-19.westus2.logic.azure.com:443/workflows/01697c5f..." +``` + +Now you can execute the following command to send webhook test data to your logic app: + +``` +python raft.py webhook test --event BugFound --name MyWebhook +``` + +This will show up in Runs history. You may need to refresh the window for the data to appear. + +![Logic App](../images/LogicApps/LogicApp_4.png) + + +When you run a job that can generate bugs (for example RESTLer Test or Fuzz), +use **MyWebhook** as the webhook name in your job configuration. + +```json + "webhook": { + "name": "MyWebhook", + "metadata": {} + } +``` + +## Step Four: Creating a Github issue + +Click **Edit** to go back to Logic App designer + +![Logic App](../images/LogicApps/LogicApp_4_1.png) + + +Click on the **New Step** button + +![Logic App](../images/LogicApps/LogicApp_5.png) + +Search for GitHub and under the **Actions** tab, select **Create an issue** + +![Logic App](../images/LogicApps/LogicApp_6.png) + +Populate the fields for **Repository Owner** and **Repository Name**. +Add a dynamic content value to your issue. For example, we have added **Subject** to the title. +When you do this the Logic App will wrap the **Issue** with **For each**, which makes it easy to +iterate over the array data in the schema. + +![Logic App](../images/LogicApps/LogicApp_7.png) + +Then click **Code view** button to see the auto-generated code. We will be modifying this code +with the samples below. + + - Find the **body** object + - Replace the **title** key and value using the content below +``` +"title": "Found by RAFT with @{items('For_each')?['Data']?['Tool']}" +``` + + - Add a **body** key and value using the content below. +``` +"body" : "**Job ID**: @{items('For_each')?['Data']?['BugDetails']?['JobId']}\n@{if(equals(toLower(items('For_each')?['Data']?['Tool']), 'restler'), concat('**RESTler job definition replay tool-coinfiguration**\n','Mount results file share that contains RESTler bug data:\n','```json\n','\"readOnlyFileShareMounts\": [\n',' {\n',' \"FileShareName\":\"',items('For_each')?['Data']?['BugDetails']?['jobId'],'\",\n',' \"MountPath\": \"/job-run\"\n',' }\n',' ]\n','```\n','Task tool-configuration (used in tasks array)\n','```json\n','\"toolConfiguration\": {\n',' \"task\": \"Replay\",\n',' \"runConfiguration\": {\n',' \"inputFolderPath\":\"','/job-run/',items('For_each')?['Data']?['BugDetails']?['outputFolder'],'/RestlerResults/',items('For_each')?['Data']?['BugDetails']?['experiment'],'/bug_buckets\"\n',' },\n',' \"replayConfiguration\": {\n',' \"bugBuckets\": [\"', items('For_each')?['Data']?['BugDetails']?['bugBucket'],'\"]\n',' }\n','}\n','```\n' ), '' )}" +``` + +You end up with the code for the Create_an_issue step that looks like this: + +![Logic App](../images/LogicApps/LogicApp_8.png) + +Save your logic app and re-run this command to test the webhook. This will create a new issue +in your github repo. + +``` +python raft.py webhook test --event BugFound --name MyWebhook +``` + +Now look at the issues in your github repo, you should see the following. +![Logic App](../images/LogicApps/LogicApp_9.png) + +## Step Five: Sending email with a link to the issue +Next let's add a connector to send e-mail using Outlook. We will create +email body content that contains a link to the newly opened issue in github: + +In the Logic App Designer click the **Add An Action** button. +![Logic App](../images/LogicApps/LogicApp_11_1.png) + +Search for **Outlook.com** or **Office 365 Outlook** and create the **Send an e-mail(V2)** Action +![Logic App](../images/LogicApps/LogicApp_10.png) + + +After you add the action, fill in the **To**, **Subject**, and **Body** fields. The **Body** we will +replace with the code below when we edit the item in the **Code view**. +Notice we used the dynamic field **Title** for the Subject field. This is the github issue title. + +![Logic App](../images/LogicApps/LogicApp_11.png) + + +Click on **Code view** and find the section "Send_an_email_(V2)". Replace the "Body" with the code below. + +```json +"Body" : "

@{body('Create_an_issue')['title']} #@{body('Create_an_issue')['number']}

Created: @{body('Create_an_issue')?['created_at']}

Link@{body('Create_an_issue')?['html_url']}

", +``` + +Your code should look like this: +![Logic App](../images/LogicApps/LogicApp_12.png) + + +Save your changes and re-run the webhook test. A new issue will be opened in github and you will receive +an e-mail with a link to the new github issue. + +![Logic App](../images/LogicApps/LogicApp_13.png) \ No newline at end of file diff --git a/src/APIService/ApiService/Controllers/Webhook.fs b/src/APIService/ApiService/Controllers/Webhook.fs index bc9dddfa..2705ce24 100644 --- a/src/APIService/ApiService/Controllers/Webhook.fs +++ b/src/APIService/ApiService/Controllers/Webhook.fs @@ -399,7 +399,14 @@ type webhooksController(configuration : IConfiguration, telemetryClient : Teleme JobId = jobId AgentName = "1" Metadata = None - BugDetails = Some(Map.empty.Add("Experiment", "experiment23").Add("BugBucket", "main_driver_500_1.txt")) + BugDetails = + Some( + Map.empty + .Add("Experiment", "experiment23") + .Add("BugBucket", "main_driver_500_1.txt") + .Add("jobId", jobId) + .Add("outputFolder", "my_results") + ) } log.Info "Setting JobStatus webhook in webhooks table" ["name", webhookName; "event", eventName; "jobId", sprintf "%A" jobId] let entity = Raft.StorageEntities.JobWebhookEntity(jobId, webhookName) :> TableEntity