Snap-in developmentTutorials

Snap-in triggered by an external source

Introduction

In this tutorial, you’ll learn how to create a snap-in that responds to an external source, particularly GitHub. The objective is to seamlessly integrate commit comments from GitHub into the DevRev platform.

Background context

  1. Understanding webhooks in GitHub: Explore the fundamentals of webhooks and learn how to incorporate them into the GitHub repository. Gain insights into the mechanisms of triggering events and handling notifications.

  2. Extracting information from external payload: Delve into the external payload generated by GitHub and comprehend the process of extracting relevant information. Understand the structure and content of the payload to facilitate seamless integration with DevRev.

  3. Encoding SHA-256 in the header with secret: Learn the technique of encoding SHA-256 in the header using a secret key. Learn the security measures involved in ensuring the integrity and authenticity of data transmitted via webhooks from GitHub to DevRev.

Installation guide

If you did not follow the getting started tutorial then follow these steps to authenticate and initialize the snap-in TypeScript template:

$devrev profiles authenticate -o <dev-org-slug> -u <youremail@yourdomain.com>
$devrev snap_in_version init

Trigger

The main trigger for this snap-in is an external webhook, which necessitates registration within GitHub. This ensures that the relevant payloads are dispatched to our designated endpoint.

Action

The primary action involves a straightforward process of examining our commit messages and displaying them on the discussion tab of the specified Product section. The configuration for this action can be customized through the input parameters of the snap-in.

Creating the snap-in

Updating the manifest

To outline the structure of the snap-in, the initial step is to define key attributes in the snap-in’s manifest. Begin by specifying the name, description, and account display name for the snap-in.

1version: "2"
2
3name: GitHub Commit Tracker
4description:
5 Reflects commits that happen on GitHub in DevRev posting to timeline of a
6 product part.
7
8service_account:
9 display_name: "GitHub-Commit Bot"

Configuration

To enhance the flexibility and adaptability of the snap-in, configurable inputs need to be incorporated. In this instance, organization-level inputs are introduced to specify the product part for which comments should be added. This configuration allows users to customize the behavior of the snap-in by providing a meaningful description of the product part where comments are intended to be added.

1inputs:
2 organization:
3 - name: part_id
4 field_type: id
5 default_value: don:core:dvrv-us-1:devo/XXXXXXX:product/1
6 is_required: true
7 id_type:
8 - product
9 description: The default part on which to post commits.
10 ui:
11 display_name: The part on which to post commits.

Event source

To establish the event source from which the snap-in will receive events, the flow-custom-webhook event is introduced. This event source serves as the conduit for receiving relevant events.

1event_sources:
2 organization:
3 - name: github-app-source
4 type: flow-custom-webhook
5 description: Event coming from Github app.
6 config:
7 policy: |
8 package rego
9 signature := crypto.hmac.sha256(base64.decode(input.request.body_raw), input.parameters.secret)
10 expected_header := sprintf("sha256=%v", [signature])
11 signature_header_name:= "X-Hub-Signature-256"
12 status_code = 200 {
13 input.request.headers[signature_header_name] == expected_header
14 } else = 401 {
15 true
16 }
17 output = {"event": body, "event_key": event_key} {
18 status_code == 200
19 body := input.request.body
20 event_key := "github-event"
21 } else = {"response": response} {
22 response := {"status_code": status_code}
23 }
24 parameters:
25 secret: SECRET_TOKEN
26 setup_instructions:
27 "Please copy the source URL from here: \n\nURL: `{{
28 source.trigger_url }}` \n\nSecret:
29 `{{source.config.parameters.secret}}`."

Here, in the configuration, two crucial tasks are primarily addressed:

  1. Extracting request body for consumption: The configuration is designed to retrieve the body from the incoming request and forward it to the event, facilitating seamless consumption by the handler function. This ensures that the relevant data from the request is accessible for further processing.

  2. Authentication of requests: The configuration plays a pivotal role in authenticating incoming requests by validating the signature present in the header. This validation process involves comparing the signature in the header with the one sent by GitHub along with its request body. Detailed setup instructions are provided within the snap-in screen, allowing users to copy the URL and Secret. Subsequently, users can employ this information when creating the webhook on GitHub. During webhook creation, users can specify the events for which they intend to subscribe, with a focus on the events pertinent to this snap-in: push.

Functions and automations

With the foundational configurations in place, the next step involves defining the functions and automations that orchestrate the core logic of the snap-in. These automations serve as the bridge between triggers and functions, ensuring a seamless execution flow when specific events are detected.

1functions:
2 - name: github_handler
3 description: Function to reflect Github activities on DevRev.
4
5automations:
6 - name: github-commit-tracker
7 source: github-app-source
8 event_types:
9 - custom:github-event
10 function: github_handler

Function logic

Having established the manifest that outlines the overall logic of the snap-in, the subsequent step involves defining the function logic responsible for handling the business logic. The initial point of focus is understanding the payload structure of the event, which can be gleaned from the GitHub webhook event.

Once acquainted with the payload structure, the function logic can be crafted to extract pertinent information and utilize the DevRev SDK for creating timeline entries on the relevant object.

This involves a multi-step process:

  1. Payload structure exploration: Refer to the GitHub webhook event documentation to gain insights into the structure of the payload.

  2. Information extraction: Derive essential information from the payload, discerning details crucial for the subsequent actions.

  3. DevRev SDK integration: Utilize the DevRev SDK to create timeline entries on the appropriate object, ensuring seamless integration with the DevRev platform.

By adhering to this process, the function logic is poised to effectively handle the business logic, responding dynamically to incoming events and enriching the object timeline in DevRev.

1// Handles the event from GitHub
2async function handleEvent(event: any) {
3 // Extract necessary information from the event
4 const token = event.context.secrets.service_account_token;
5 const endpoint = event.execution_metadata.devrev_endpoint;
6
7 // Set up the DevRev SDK with the extracted information
8 const devrevSDK = client.setup({
9 endpoint: endpoint,
10 token: token,
11 });
12
13 // Extract the part ID and commits from the event
14 const partID = event.input_data.global_values.part_id;
15 const commits = event.payload.commits;
16
17 // Iterate through commits and append the commit message to the body of the comment
18 let bodyComment = "";
19 for (const commit of commits) {
20 bodyComment += commit.message + "\n";
21 }
22
23 // Prepare the body for creating a timeline comment
24 const body = {
25 body: bodyComment,
26 object: partID,
27 type: "timeline_comment",
28 };
29
30 // Create a timeline comment using the DevRev SDK
31 const response = await devrevSDK.timelineEntriesCreate(body as any);
32
33 // Return the response from the DevRev API
34 return response;
35}

Deploying the snap-in to your organization

Upon completion and validation of the code changes, the subsequent crucial step involves deploying the snap-in to your organization. Execute the following steps for a seamless deployment:

  1. Navigate to the code folder in your project directory.

  2. Run the following commands sequentially to build, package, and generate the necessary artifacts:

    $npm install
    >npm run build
    >npm run package
  3. Following this, proceed to create your snap-in package and version as described in the previous steps.

  4. During the installation of the snap-in, crucial inputs such as the product part description need to be provided. Additionally, it’s imperative to register the webhook in GitHub during this process.

Resources

The final snap-in code and manifest can be found here.