Last active
September 26, 2023 10:02
-
-
Save dgellow/5f6ad9c616b7b0859941f99e42681e95 to your computer and use it in GitHub Desktop.
Pulumi dynamic provider to set/update the Webhook config of a GitHub App
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as pulumi from '@pulumi/pulumi'; | |
import { Octokit } from '@octokit/core'; | |
import { AppAuthentication, createAppAuth } from '@octokit/auth-app'; | |
export interface ConfigurationResourceInputs { | |
appId: pulumi.Input<string>; | |
privateKey: pulumi.Input<string>; | |
clientId: pulumi.Input<string>; | |
clientSecret: pulumi.Input<string>; | |
url: pulumi.Input<string>; | |
secret: pulumi.Input<string>; | |
contentType?: pulumi.Input<string> | undefined; | |
} | |
export class Configuration extends pulumi.dynamic.Resource { | |
public readonly appId!: pulumi.Output<pulumi.ID>; | |
public readonly privateKey!: pulumi.Output<string>; | |
public readonly clientId!: pulumi.Output<string>; | |
public readonly clientSecret!: pulumi.Output<string>; | |
public readonly url!: pulumi.Output<string>; | |
public readonly secret!: pulumi.Output<string>; | |
public readonly contentType!: pulumi.Output<string>; | |
constructor(name: string, args: ConfigurationResourceInputs, opts?: pulumi.CustomResourceOptions) { | |
super(new ConfigurationProvider(), name, args, opts, 'github-app', 'Configuration'); | |
} | |
} | |
interface ConfigurationInputs { | |
appId: string; | |
privateKey: string; | |
clientId: string; | |
clientSecret: string; | |
url: string; | |
secret: string; | |
contentType?: string | undefined; | |
} | |
export interface ConfigurationOutputs extends Omit<ConfigurationInputs, 'url' | 'secret'> { | |
url?: string | undefined; | |
secret?: string | undefined; | |
} | |
export class ConfigurationProvider implements pulumi.dynamic.ResourceProvider { | |
async auth({ | |
appId, | |
privateKey, | |
clientId, | |
clientSecret, | |
}: Pick< | |
ConfigurationInputs, | |
'appId' | 'clientId' | 'clientSecret' | 'privateKey' | |
>): Promise<AppAuthentication> { | |
const auth = createAppAuth({ | |
appId: appId, | |
privateKey: privateKey, | |
clientId: clientId, | |
clientSecret: clientSecret, | |
}); | |
return await auth({ type: 'app' }); | |
} | |
async create(inputs: ConfigurationInputs): Promise<pulumi.dynamic.CreateResult> { | |
const auth = await this.auth(inputs); | |
const octokit = new Octokit({ auth: auth.token }); | |
try { | |
const { data } = await octokit.request('PATCH /app/hook/config', { | |
data: JSON.stringify({ | |
url: inputs.url, | |
secret: inputs.secret, | |
insecure_ssl: '0', | |
content_type: inputs.contentType || 'json', | |
}), | |
}); | |
return { | |
id: inputs.appId, | |
outs: { | |
appId: inputs.appId, | |
privateKey: inputs.privateKey, | |
clientId: inputs.clientId, | |
clientSecret: inputs.clientSecret, | |
url: data.url, | |
secret: data.secret, | |
contentType: data.content_type, | |
}, | |
}; | |
} catch (err) { | |
await pulumi.log.error(`${JSON.stringify(err, null, 2)}`); | |
throw new Error('Failed to set github app webhook config'); | |
} | |
} | |
async diff( | |
id: pulumi.ID, | |
olds: ConfigurationOutputs, | |
news: ConfigurationInputs, | |
): Promise<pulumi.dynamic.DiffResult> { | |
let changes: boolean = false; | |
let replaces: string[] = []; | |
let keys = Object.keys(news) as Array<Extract<keyof typeof news, string>>; | |
for (const key of keys) { | |
if (JSON.stringify(olds[key]) !== JSON.stringify(news[key])) { | |
changes = true; | |
if (key === 'appId' || key === 'privateKey' || key === 'clientId' || key === 'clientSecret') { | |
replaces.push(key); | |
} | |
} | |
} | |
return { changes, replaces }; | |
} | |
async update( | |
id: pulumi.ID, | |
_olds: ConfigurationOutputs, | |
news: ConfigurationInputs, | |
): Promise<pulumi.dynamic.UpdateResult> { | |
const auth = await this.auth(news); | |
const octokit = new Octokit({ auth: auth.token }); | |
try { | |
const { data } = await octokit.request('PATCH /app/hook/config', { | |
data: JSON.stringify({ | |
url: news.url, | |
secret: news.secret, | |
insecure_ssl: '0', | |
content_type: news.contentType || 'json', | |
}), | |
}); | |
return { | |
outs: { | |
appId: id, | |
privateKey: news.privateKey, | |
clientId: news.clientId, | |
clientSecret: news.clientSecret, | |
url: data.url, | |
secret: data.secret, | |
contentType: data.content_type, | |
}, | |
}; | |
} catch (err) { | |
await pulumi.log.error(`${JSON.stringify(err, null, 2)}`); | |
throw new Error('Failed to set github app webhook config'); | |
} | |
} | |
async read(id: pulumi.ID, props?: ConfigurationOutputs): Promise<pulumi.dynamic.ReadResult> { | |
if (!props) { | |
throw new Error('Props undefined'); | |
} | |
const auth = await this.auth({ ...props, appId: id }); | |
const octokit = new Octokit({ auth: auth.token }); | |
try { | |
const { data } = await octokit.request('GET /app/hook/config'); | |
return { | |
id, | |
props: { | |
appId: id, | |
privateKey: props.privateKey, | |
clientId: props.clientId, | |
clientSecret: props.clientSecret, | |
url: data.url, | |
secret: data.secret, | |
contentType: data.content_type, | |
}, | |
}; | |
} catch (err) { | |
await pulumi.log.error(`${JSON.stringify(err, null, 2)}`); | |
throw new Error('Failed to set github app webhook config'); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment