-
Notifications
You must be signed in to change notification settings - Fork 53
[REL-8880] Imiller/rel 8880/backmerge integration framework private mirror #115
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
Changes from 250 commits
0d8a83a
554727b
3a0d156
a02a496
0998295
4c5c013
e607cba
41bca35
800b74f
518ab37
ee0dc30
c8fd0ea
e8819d0
1c513e4
990d409
bf2c7d8
e7f7308
f77b49e
1615f08
7e07e85
dbbf258
5c785ab
437d307
17f05f2
174f509
923b4b4
46332c7
cb47481
80977d4
b08d11e
cf5fc01
0004ebe
25da71b
d8e51d3
19c85e8
c9e7944
c7af304
4998dcf
77ff9b6
cc378ca
832c99c
e9a9fae
abea72b
f09c45e
de69d22
01791ad
c3e6715
d586d09
9747e02
82063d7
8399357
4973538
6ebbeb4
0d8d210
37ad082
9d921a6
a2fb143
180b0f1
b8d6565
5231532
467e1d4
9f98ed0
74397f0
216922a
4f0e76e
5db9a78
f694a8a
10fec12
6e5dc85
3135277
9ad896c
b780eb1
ad9a31a
9948edf
d61f5d6
fd95cab
1257859
fd857bc
1a333f8
60f1399
c1bd33a
fb57852
3ca0dce
93cff6a
be2a85e
01be3a0
4ab0b2d
1917db6
b11097d
1d1ff2b
fad85d2
dc1e2a3
2cf1dfc
003597f
d9b87df
aeb3cad
6275b0e
27e6cd7
769a8b8
e5d8bbd
8bcfdc2
ae1db80
f8be2c1
ccf9709
061cb6c
9a0e97a
b4f0001
926a3fa
5839500
1146077
986346a
cb67101
861a601
20c9968
ad00379
b0f6ee3
0842e64
7aed590
e4487e1
63030a3
f209aef
63d5789
14dcbd5
42b688d
855de62
63de845
4fe6a76
7faea1e
0be5381
b3af078
c96c38b
b491810
1223214
10432af
cae92cd
7527549
c609c17
b8a886d
21e89f3
203d1a8
556269f
3f751d9
2957462
59060a9
9877afd
e231e22
8ec7cab
2b6d9b4
5ebc98a
aa86c74
7bdefe8
69b8178
7d99f42
fcf5887
9aa60ee
056292e
f7cccf2
db7093d
0e2c761
0901b97
4793871
51c3c68
726dd32
fc1f0c0
efaa849
c348dae
61b1301
b5dd6a0
775e878
cfe1536
7ed4d33
55849a4
cb61671
867d802
932f188
888d2a1
bd3be6b
afcae62
ede9a2c
8251fc4
4fbd377
814fedd
e84b934
550fffa
8dbbb5c
a0cf0db
dbcfeb8
530f0e9
99b8a4c
18d0dc4
284da34
cee6b5a
add5047
a120363
996554f
c22cb09
96723b7
69fde33
6fe353b
3b3ab08
8c92ff5
8b353e3
9c60786
09a3c19
38ea8fc
1af29ee
e2d2e4a
f61a7dd
b4f2af7
fc6ca9d
0cd31ec
a107c7e
5409b8e
b2c5a1e
d3c74cd
b97f552
479762d
a6002a6
591cde0
879291f
47d921c
9287cba
c97c4db
5d94569
23cd574
da63673
3b8c7e6
f5da733
c799d70
42a4ada
8886d1a
a521b48
0798726
4ea4d58
38ae286
a033572
45785b7
75e148c
22e8b9f
2298bef
c56db72
5de37b7
46e3830
e372c8a
4aea267
6c4fcca
53b5388
c8bcab9
5d8c133
895418f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| name: Dependency Scan | ||
|
|
||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: [main] | ||
|
|
||
| jobs: | ||
| generate-nodejs-sbom: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: launchdarkly/common-actions/init@main | ||
|
|
||
| - name: Generate SBOM | ||
| uses: launchdarkly/common-actions/dependency-scan/generate-sbom@main | ||
| with: | ||
| types: 'nodejs' | ||
|
|
||
| evaluate-policy: | ||
| runs-on: ubuntu-latest | ||
| needs: | ||
| - generate-nodejs-sbom | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Evaluate SBOM Policy | ||
| uses: launchdarkly/common-actions/dependency-scan/evaluate-policy@main | ||
| with: | ||
| artifacts-pattern: bom-* | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,299 @@ | ||
| # Capabilities | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i have genuinely no idea where these came from as they don't appear to have previously been on either public or private repo. but they're great docs
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These were intentionally deleted from this repo to prefer the documentation on our public docs site so we should not reintroduce them here. |
||
|
|
||
| Your integration's `capabilities` describe how it interacts with LaunchDarkly. | ||
|
|
||
| We support three capabilities: | ||
|
|
||
| - [Audit log events hook](#audit-log-events-hook-auditlogeventshook) (`auditLogEventsHook`) | ||
| - [Trigger](#trigger-trigger) (`trigger`) | ||
| - [Reserved custom properties](#reserved-custom-properties-reservedcustomproperties) (`reservedCustomProperties`) | ||
|
|
||
| ## Audit log events hook (`auditLogEventsHook`) | ||
|
|
||
| An audit log events hook is a webhook that LaunchDarkly sends whenever an | ||
| event happens inside of LaunchDarkly. Each of these events | ||
| result in an event being published to LaunchDarkly's audit log. | ||
| You can use this capability to send data to or trigger an event in another service. | ||
|
|
||
| The `auditLogEventsHook` has three properties: | ||
|
|
||
| 1. [`endpoint`](#endpoint): | ||
| Describes the HTTP handler that will receive the webhook. | ||
| 2. [`templates`](#templates): | ||
| A map of template paths relative to your integration's directory. You can use templates to transform the raw audit log events to a format that your integration expects. These templates can be any file type. | ||
| 3. [`defaultPolicy`](#default-policy): | ||
| An array of [LaunchDarkly | ||
| policies](https://docs.launchdarkly.com/home/account-security/custom-roles/policies) that | ||
| act as a filter determining which events to send to your webhook endpoint. | ||
|
|
||
| Here's an example of an audit log events hook capability that subscribes to flag | ||
| events in a LaunchDarkly account: | ||
|
|
||
| ```json | ||
| "capabilities": { | ||
| "auditLogEventsHook": { | ||
| "endpoint": { | ||
| "url": "{{endpointUrl}}", | ||
| "method": "POST", | ||
| "headers": [ | ||
| { | ||
| "name": "Content-Type", | ||
| "value": "application/json" | ||
| }, | ||
| { | ||
| "name": "Authorization", | ||
| "value": "Bearer {{apiToken}}" | ||
| } | ||
| ] | ||
| }, | ||
| "templates": { | ||
| "flag": "templates/flag.json" | ||
| }, | ||
| "defaultPolicy": [ | ||
| { | ||
| "effect": "allow", | ||
| "resources": ["proj/*:env/production:flag/*"], | ||
| "actions": ["*"] | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ### Endpoint | ||
|
|
||
| Every `auditLogEventsHook` capability must specify the endpoint to which LaunchDarkly should send webhook data. This specification must include all appropriate request semantics including the URL, method, and headers. | ||
|
|
||
| In the example | ||
| above, a few of the properties (`endpoint.url` and | ||
| `endpoint.headers[].value`) accept template variables. These template | ||
| variables can reference any `formVariables` you've defined in your manifest. | ||
| The templating language we use is based off of a subset of the | ||
| Handlebars syntax. | ||
|
|
||
| To learn more, read [Handlebars' documentation](https://handlebarsjs.com/). | ||
|
|
||
| There are a few properties that allow you to substitute template variables at | ||
| runtime. The main ones are the `endpoint.url` and the | ||
| `endpoint.headers[].value`. This lets you configure a dynamic endpoint | ||
| based on the `formVariables` your integration collects from the user. Examples follow. | ||
|
|
||
| This example uses the `endpointUrl` form variable as the URL of the endpoint and the `apiToken` as a `Bearer` token in the `Authorization` header: | ||
|
|
||
| ```json | ||
| "endpoint": { | ||
| "url": "{{endpointUrl}}", | ||
| "method": "POST", | ||
| "headers": [ | ||
| { | ||
| "name": "Content-Type", | ||
| "value": "application/json" | ||
| }, | ||
| { | ||
| "name": "Authorization", | ||
| "value": "Bearer {{apiToken}}" | ||
| } | ||
| ] | ||
| }, | ||
| ``` | ||
|
|
||
| This example uses the `apiToken` formVariable as a query parameter on the URL: | ||
|
|
||
| ```json | ||
| "endpoint": { | ||
| "url": "https://example.com/apiToken?={{apiToken}}", | ||
| "method": "POST" | ||
| }, | ||
| ``` | ||
|
|
||
| ### Templates | ||
|
|
||
| Before the `auditLogEventsHook` capability sends the request to the endpoint | ||
| handling your webhook, you can transform the body of the request | ||
| sent to your handler. | ||
|
|
||
| In your manifest, you can specify templates to be executed when webhook events are of kinds `flag`, `project`, and `environment`. Additionally, you can specify a `default` template as a catch-all for any event without a more specific template. A `validation` template is also provided in case you want to provide users with the ability to validate their connection by sending a test event from LaunchDarkly to your service. | ||
|
|
||
| ```json | ||
| "templates": { | ||
| "default": "templates/default.json.hbs", | ||
| "flag": "templates/flag.json.hbs", | ||
| "project": "templates/project.json.hbs", | ||
| "environment": "templates/environment.json.hbs", | ||
| "validation": "templates/default.json.hbs" | ||
| }, | ||
| ``` | ||
|
|
||
| If you don't provide one or more templates, LaunchDarkly | ||
| sends you a default JSON payload that looks like this: | ||
|
|
||
| ```json | ||
| { | ||
| "_links": { | ||
| "canonical": { | ||
| "href": "/api/v2/flags/always-snippet/example-test", | ||
| "type": "application/json" | ||
| }, | ||
| "parent": { | ||
| "href": "/api/v2/auditlog", | ||
| "type": "application/json" | ||
| }, | ||
| "self": { | ||
| "href": "/api/v2/auditlog/5defebd006121dd9f7ea90d0", | ||
| "type": "application/json" | ||
| }, | ||
| "site": { | ||
| "href": "/always-snippet/production/features/example-test", | ||
| "type": "text/html" | ||
| } | ||
| }, | ||
| "_id": "5defebd006121dd9f7ea90d0", | ||
| "_accountId": "", | ||
| "timestamp": { | ||
| "milliseconds": 1580778134028, | ||
| "seconds": 1580778134, | ||
| "rfc3339": "2020-02-04T01:02:14Z" | ||
| }, | ||
| "kind": "flag", | ||
| "name": "Example test", | ||
| "description": "", | ||
| "shortDescription": "", | ||
| "comment": "This is just a test", | ||
| "member": { | ||
| "_links": { | ||
| "parent": { | ||
| "href": "/api/v2/members", | ||
| "type": "application/json" | ||
| }, | ||
| "self": { | ||
| "href": "/api/v2/members/569f514183f2164430000002", | ||
| "type": "application/json" | ||
| } | ||
| }, | ||
| "_id": "569f514183f2164430000002", | ||
| "email": "testing@example.com", | ||
| "firstName": "Henry", | ||
| "lastName": "Barrow" | ||
| }, | ||
| "titleVerb": "", | ||
| "markdownTitle": "[Henrietta Powell](mailto:testing@example.com) turned on the flag [Example test](http://app.launchdarkly/exampledotcom/production/features/example-test) in `Production`", | ||
| "title": "Henrietta Powell turned on the flag Example test in 'Production'", | ||
| "target": { | ||
| "_links": null, | ||
| "name": "" | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| If you choose to provide one or more | ||
| `templates`, | ||
| LaunchDarkly renders your template using the context data above. Your | ||
| template can be any text based format, but you must specify the appropriate | ||
| `Content-Type` header in your `endpoint.headers` property to match the content | ||
| type of your template body. | ||
|
|
||
| We use a basic subset of the Handlebars template syntax to render | ||
| your template. | ||
|
|
||
| To learn more about Handlebars' sysntax, read [Handlebars' Language | ||
| Guide](https://handlebarsjs.com/guide/). | ||
|
|
||
| In addition to the basic language syntax, we support the following [built-in | ||
| helpers](https://handlebarsjs.com/guide/builtin-helpers.html): | ||
|
|
||
| - `if` | ||
| - `unless` | ||
| - `each` | ||
| - `with` | ||
| - `lookup` | ||
|
|
||
| Furthermore, the following custom helpers are supported: | ||
|
|
||
| - `equal` - renders a block if the string version of both arguments are equals | ||
| - `pathEncode` - URL path encodes the string version of the argument | ||
| - `queryEncode` - URL query encodes the string version of the argument | ||
|
|
||
| To test your templates, you can run `npm run preview $INTEGRATION_NAME` or use the [Handlebars | ||
| Sandbox](http://tryhandlebarsjs.com/). | ||
|
|
||
| ### Default policy | ||
|
|
||
| When you configure your integration, customers can specify an array of [LaunchDarkly | ||
| policies](https://docs.launchdarkly.com/home/account-security/custom-roles/policies) filter which events to send to your webhook endpoint. | ||
|
|
||
| To simplify onboarding your integration, you can specify a default policy which follows best practices for your integration's use case. | ||
|
|
||
| Assuming your integration only cares about flag activity, we recommend the following default policy. This policy specifies that LaunchDarkly will notify your integration of all flag activity across production environments from all projects. | ||
|
|
||
| Here is the policy: | ||
|
|
||
| ```json | ||
| "defaultPolicy": [ | ||
| { | ||
| "effect": "allow", | ||
| "resources": ["proj/*:env/production:flag/*"], | ||
| "actions": ["*"] | ||
| } | ||
| ] | ||
| ``` | ||
|
|
||
| ### Validation | ||
|
|
||
| To preview your integration's templates with sample data, run `npm run preview INTEGRATION_NAME`. | ||
|
|
||
| Alternatively, to produce a sample `curl` command, run `npm run curl INTEGRATION_NAME`. This returns data with your integration's service as if it was sent by the audit log event hook capability. | ||
|
|
||
| ## Trigger (`trigger`) | ||
|
|
||
| **At the time of this writing, LaunchDarkly's trigger functionality is only available to customers opted in to an early access program. Email [partnerships@launchdarkly.com](mailto:partnerships@launchdarkly.com) to request access.** | ||
|
|
||
| The trigger capability is used to generate a unique webhook URL that your service can request to generate a user-defined flag change in LaunchDarkly. | ||
|
|
||
| By default, the trigger URL contains a globally unique path parameter to provide security in the form of an [unguessable URL](https://www.schneier.com/blog/archives/2015/07/googles_unguess.html). However, if your service supports additional security settings such as shared secrets when firing webhooks, you can specify those with the optional `auth` object. **Note**: at launch, the `auth` attribute is unsupported and should be omitted. | ||
|
|
||
| The required `documentation` field must be a link to documentation outlining how webhooks should be configured in your service. | ||
|
|
||
| If the integration offers the option to send test events / webhook requests, the optional `testEventNameRegexp` fields allows you to specify regex to match the expected `eventName` value below. This will tell our integration framework not to make any real flag or resource changes associated with matching events. | ||
|
|
||
| If your webhooks' request bodies are non-empty, you can specify the optional `parser` object with one or more of `eventName`, `value`, and `url`. The provided values will flow through LaunchDarkly into the resulting audit log messages when your service invokes a trigger in LaunchDarkly. | ||
|
|
||
| Here is a sample `trigger` capability including all optional properties: | ||
|
|
||
| ```json | ||
| "trigger": { | ||
| "documentation": "https://example.com/configuring-webhooks", | ||
| "auth": { | ||
| "type": "sharedSecret" | ||
| }, | ||
| "parser": { | ||
| "eventName": "/event", | ||
| "value": "/value", | ||
| "url": "/links/self/href" | ||
| }, | ||
| } | ||
| ``` | ||
|
|
||
| **Note**: if an integration only has the trigger capability, the word "trigger" will be added to its name in the LaunchDarkly UI. For this reason, do not include the word "trigger" in the manifest name. See the [generic-trigger manifest](/integrations/generic-trigger/manifest.json) for an example. | ||
|
|
||
| ## Reserved custom properties (`reservedCustomProperties`) | ||
|
|
||
| Custom properties allow you to store data in LaunchDarkly alongside a feature flag. For example, you can use custom properties to indicate flag-level associations with data on your service. If you don't have any flag-level associations or configurations, you don't need to use this capability. | ||
|
|
||
| To learn more, read [Custom properties](https://docs.launchdarkly.com/home/advanced/custom-properties). | ||
|
|
||
| By default, users must specify a custom property name and key when they attach the custom property value to a feature flag. This step introduces the possibility of user error. To prevent this, developers can _reserve_ a custom property for their integration, which makes it much easier for users to correctly add the property's value to feature flags. | ||
|
|
||
| Reserved custom properties are simple to define. Their only requirements are a `name` and `key`. | ||
|
|
||
| After your integration is configured by a user, the custom property starts appearing in the dropdown on the flag's Settings page. | ||
|
|
||
| Here is a sample `reservedCustomProperties` capability: | ||
|
|
||
| ```json | ||
| "reservedCustomProperties": [ | ||
| { | ||
| "name": "Foobar Entities", | ||
| "key": "foobar" | ||
| } | ||
| ], | ||
| ``` | ||
Uh oh!
There was an error while loading. Please reload this page.