Last active
June 19, 2019 17:53
-
-
Save thesurlydev/b58a6618f6175e7e802f22b9a4977886 to your computer and use it in GitHub Desktop.
CodeBuild and GH webhook goodness
This file contains hidden or 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 com.amazonaws.services.lambda.runtime.Context | |
import com.seekret.arch.customresources.model.RequestBody | |
import org.kohsuke.github.GHEvent | |
import org.kohsuke.github.GitHub | |
import software.amazon.awssdk.services.codebuild.CodeBuildClient | |
import software.amazon.awssdk.services.codebuild.model.CreateWebhookRequest | |
import software.amazon.awssdk.services.codebuild.model.CreateWebhookResponse | |
import software.amazon.awssdk.services.codebuild.model.DeleteWebhookRequest | |
import software.amazon.awssdk.services.codebuild.model.ResourceAlreadyExistsException | |
import software.amazon.awssdk.services.codebuild.model.WebhookFilter | |
import software.amazon.awssdk.services.codebuild.model.WebhookFilterType | |
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient | |
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest | |
import java.lang.IllegalStateException | |
@Suppress("unused") | |
class CodeBuildWebhookHandler : AbstractCustomResourceHandler() { | |
override fun doCreate(request: RequestBody, context: Context) { | |
val client = CodeBuildClient.create() | |
val projectName = request.tryGetStringProperty("ProjectName") | |
val webhookFilters = listOf( | |
WebhookFilter.builder().type(WebhookFilterType.EVENT).pattern("PUSH").build() | |
) | |
val createWebhookRequest = CreateWebhookRequest.builder() | |
.projectName(projectName) | |
.filterGroups(webhookFilters) | |
.build() | |
val createWebhookResponse: CreateWebhookResponse = try { | |
client.createWebhook(createWebhookRequest) | |
} catch (ae: ResourceAlreadyExistsException) { | |
return sendFailedResponse(request, context, "Webhook already exists!") | |
} | |
val successful = createWebhookResponse.sdkHttpResponse().isSuccessful | |
when { | |
successful -> { | |
// call GitHub to create webhook with payloadUrl and secret | |
val webhook = createWebhookResponse.webhook() | |
val hookPayloadUrl = webhook.payloadUrl() | |
val hookSecret = webhook.secret() | |
createHook(request, hookPayloadUrl, hookSecret) | |
sendSuccessResponse(request, context, "Created Webhook") | |
} | |
else -> sendFailedResponse(request, context, "Error creating Webhook") | |
} | |
} | |
override fun doDelete(request: RequestBody, context: Context) { | |
val projectName = request.resourceProperties["ProjectName"] as String | |
val deleteWebhookRequest = DeleteWebhookRequest.builder().projectName(projectName).build() | |
val deleteWebhookResponse = CodeBuildClient.create().deleteWebhook(deleteWebhookRequest) | |
if (deleteWebhookResponse.sdkHttpResponse().isSuccessful) { | |
sendSuccessResponse(request, context, "Deleted Webhook") | |
} else { | |
sendFailedResponse(request, context, "Error deleting Webhook") | |
} | |
} | |
override fun doUpdate(request: RequestBody, context: Context) { | |
sendSuccessResponse(request, context, "Not implemented") | |
} | |
private fun createHook(request: RequestBody, hookPayloadUrl: String, hookSecret: String) { | |
log("Creating webhook") | |
val gitHubUser = request.tryGetStringProperty("GitHubUser") | |
val gitHubRepo = request.tryGetStringProperty("GitHubRepo") | |
val gitHubPersonalAccessTokenSecretId = request.tryGetStringProperty("GitHubPersonalAccessTokenSecretId") | |
val gitHubEndpoint = request.tryGetStringProperty("GitHubEndpoint") | |
// get GitHub personal access token from Secrets Manager | |
val sm = SecretsManagerClient.create() | |
val getSecretValueRequest = GetSecretValueRequest.builder().secretId(gitHubPersonalAccessTokenSecretId).build() | |
val getSecretValueResponse = sm.getSecretValue(getSecretValueRequest) | |
val sdkHttpResponse = getSecretValueResponse.sdkHttpResponse() | |
val gitHubPersonalAccessToken = if (sdkHttpResponse.isSuccessful) { | |
getSecretValueResponse.secretString() | |
} else { | |
throw IllegalStateException("Error getting GitHub personal access token from secretId: $gitHubPersonalAccessTokenSecretId; ${sdkHttpResponse.statusText()}") | |
} | |
log("Successfully retrieved GH personal access token") | |
val gh: GitHub = GitHub.connectToEnterpriseWithOAuth(gitHubEndpoint, gitHubUser, gitHubPersonalAccessToken) | |
val repo = gh.myself.getRepository(gitHubRepo) | |
val conf = mapOf( | |
"url" to hookPayloadUrl, | |
"content_type" to "json", | |
"secret" to hookSecret | |
) | |
val events = listOf(GHEvent.PUSH) | |
repo.createHook("web", conf, events, true) | |
log("Webhook creation successful") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment