diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index f945ba9..fd2c091 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -37,7 +37,7 @@ jobs: run: | sam build --use-container sam local invoke WDLParsingFunction -e events/event.json &> output.txt - grep "statusCode\":200" output.txt + grep "statusCode\": 200" output.txt - name: Test Nextflow parsing with SAM CLI build (no invoke) working-directory: ./nextflow-parsing # SAM build also runs the Java tests diff --git a/upsertGitHubTag/deployment/index.js b/upsertGitHubTag/deployment/index.js index beccd3e..bffad7b 100644 --- a/upsertGitHubTag/deployment/index.js +++ b/upsertGitHubTag/deployment/index.js @@ -3,8 +3,8 @@ const url = require("url"); const https = require("https"); const crypto = require("crypto"); -const qs = require("querystring"); const LAMBDA_USER_AGENT = "DockstoreLambda (NodeJs)"; +const DELIVERY_ID_HEADER = "X-GitHub-Delivery"; // Verification function to check if it is actually GitHub who is POSTing here const verifyGitHub = (req, payload) => { @@ -26,16 +26,17 @@ const verifyGitHub = (req, payload) => { }; // Makes a POST request to the given path -function postEndpoint(path, postBody, callback) { +function postEndpoint(path, postBody, deliveryId, callback) { console.log("POST " + path); - console.log(qs.stringify(postBody)); + console.log(postBody); const options = url.parse(path); options.method = "POST"; options.headers = { - "Content-Type": "application/x-www-form-urlencoded", + "Content-Type": "application/json", Authorization: "Bearer " + process.env.DOCKSTORE_TOKEN, "User-Agent": LAMBDA_USER_AGENT, + "X-GitHub-Delivery": deliveryId, }; const req = https.request(options, (res) => { @@ -63,7 +64,7 @@ function postEndpoint(path, postBody, callback) { }); return res; }); - req.write(qs.stringify(postBody)); + req.write(JSON.stringify(postBody)); req.end(); } @@ -73,7 +74,7 @@ function deleteEndpoint( repository, reference, username, - installationId, + deliveryId, callback ) { console.log("DELETE " + path); @@ -82,13 +83,13 @@ function deleteEndpoint( urlWithParams.searchParams.append("gitReference", reference); urlWithParams.searchParams.append("repository", repository); urlWithParams.searchParams.append("username", username); - urlWithParams.searchParams.append("installationId", installationId); const options = url.parse(urlWithParams.href); options.method = "DELETE"; options.headers = { Authorization: "Bearer " + process.env.DOCKSTORE_TOKEN, "User-Agent": LAMBDA_USER_AGENT, + "X-GitHub-Delivery": deliveryId, }; const req = https.request(options, (res) => { @@ -110,38 +111,6 @@ function deleteEndpoint( req.end(); } -/** - * Handles github apps payload parsing for the 'installation_repositories' event type and creates a JSON to call the post endpoint. - * Currently, if the payload's action is not 'added', we return null, as we don't want to call the endpoint. - * - * @param body - JSON payload body - * @returns {null|{repositories: *, installationId: string, username: *}} - */ -function handleInstallationRepositoriesEvent(body) { - // Currently ignoring repository removal events, only calling the endpoint if we are adding a repository. - if (body.action === "added") { - console.log("Valid installation event"); - const username = body.sender.login; - const installationId = body.installation.id; - const repositoriesAdded = body.repositories_added; - const repositories = []; - repositoriesAdded.forEach((repo) => { - repositories.push(repo.full_name); - }); - - return { - installationId: installationId, - username: username, - repositories: repositories.join(","), - }; - } else { - console.log( - 'installation_repositories event ignored "' + body.action + '" action' - ); - return null; - } -} - // Performs an action based on the event type (action) function processEvent(event, callback) { // Usually returns array of records, however it is fixed to only return 1 record @@ -174,19 +143,39 @@ function processEvent(event, callback) { var path = process.env.API_URL; - // Handle installation events + var deliveryId; + if (requestBody[DELIVERY_ID_HEADER]) { + deliveryId = requestBody[DELIVERY_ID_HEADER]; + } else { + // TODO: remove this after 1.15. + // This was added because there's a small period of time during the 1.15 deploy where the header isn't available + console.log( + "Could not retrieve X-GitHub-Delivery header, generating a random UUID" + ); + deliveryId = crypto.randomUUID(); + } + + console.log("X-GitHub-Delivery: " + deliveryId); var githubEventType = requestBody["X-GitHub-Event"]; + // Handle installation events if (githubEventType === "installation_repositories") { - const pushPostBody = handleInstallationRepositoriesEvent(body); - path += "workflows/github/install"; + // Currently ignoring repository removal events, only calling the endpoint if we are adding a repository. + if (body.action === "added") { + console.log("Valid installation event"); + path += "workflows/github/install"; + const repositoriesAdded = body.repositories_added; + const repositories = repositoriesAdded.map((repo) => repo.full_name); - if (pushPostBody != null) { - postEndpoint(path, pushPostBody, (response) => { + postEndpoint(path, body, deliveryId, (response) => { const successMessage = "The GitHub app was successfully installed on repositories " + - pushPostBody.repositories; + repositories; handleCallback(response, successMessage, callback); }); + } else { + console.log( + 'installation_repositories event ignored "' + body.action + '" action' + ); } } else if (githubEventType === "push") { /** @@ -212,20 +201,11 @@ function processEvent(event, callback) { if (!body.deleted) { console.log("Valid push event"); const repository = body.repository.full_name; - const username = body.sender.login; const gitReference = body.ref; - const installationId = body.installation.id; - - const pushPostBody = { - gitReference: gitReference, - installationId: installationId, - repository: repository, - username: username, - }; path += "workflows/github/release"; - postEndpoint(path, pushPostBody, (response) => { + postEndpoint(path, body, deliveryId, (response) => { const successMessage = "The associated entries on Dockstore for repository " + repository + @@ -239,7 +219,6 @@ function processEvent(event, callback) { const repository = body.repository.full_name; const gitReference = body.ref; const username = body.sender.login; - const installationId = body.installation.id; path += "workflows/github"; @@ -248,7 +227,7 @@ function processEvent(event, callback) { repository, gitReference, username, - installationId, + deliveryId, (response) => { const successMessage = "The associated versions on Dockstore for repository " + @@ -294,10 +273,6 @@ function handleCallback(response, successMessage, callback) { } } -module.exports = { - handleInstallationRepositoriesEvent, -}; - module.exports.handler = (event, context, callback) => { processEvent(event, callback); }; diff --git a/upsertGitHubTag/deployment/index.spec.js b/upsertGitHubTag/deployment/index.spec.js deleted file mode 100644 index b3750f0..0000000 --- a/upsertGitHubTag/deployment/index.spec.js +++ /dev/null @@ -1,51 +0,0 @@ -const lambda = require("./index.js"); - -describe("installation_repositories event handling", function () { - it("should return null for random input", function () { - const postBody = lambda.handleInstallationRepositoriesEvent("fake body"); - expect(postBody).toEqual(null); - }); - - it("should return valid post body", function () { - const repositories_added = [ - { full_name: "repo1" }, - { full_name: "repo2" }, - { full_name: "repo3" }, - ]; - const fake_payload_body = { - action: "added", - sender: { login: "myinfo" }, - installation: { id: "123456" }, - repositories_added: repositories_added, - }; - const postBody = - lambda.handleInstallationRepositoriesEvent(fake_payload_body); - - expect(postBody.installationId).toEqual("123456"); - expect(postBody.username).toEqual("myinfo"); - - // there should be three repositories - const repos = postBody.repositories.split(","); - expect(repos.length).toEqual(3); - expect(repos[0]).toEqual("repo1"); - expect(repos[1]).toEqual("repo2"); - expect(repos[2]).toEqual("repo3"); - }); - - it("should return null for removed action", function () { - const repositories_added = [ - { full_name: "repo1" }, - { full_name: "repo2" }, - { full_name: "repo3" }, - ]; - const fake_payload_body = { - action: "removed", - sender: { login: "myinfo" }, - installation: { id: "123456" }, - repositories_added: repositories_added, - }; - const postBody = - lambda.handleInstallationRepositoriesEvent(fake_payload_body); - expect(postBody).toEqual(null); - }); -}); diff --git a/upsertGitHubTag/template.yaml b/upsertGitHubTag/template.yaml index 51db8a1..bd20fb1 100644 --- a/upsertGitHubTag/template.yaml +++ b/upsertGitHubTag/template.yaml @@ -16,7 +16,7 @@ Resources: Properties: CodeUri: deployment/ Handler: index.handler - Runtime: nodejs12.x + Runtime: nodejs18.x Environment: Variables: SECRET_TOKEN: !Ref SecretToken