From 518ff06d9ea1db930bdacc7e6bb1f3bdd5f9ce34 Mon Sep 17 00:00:00 2001 From: Rick van der Staaij <6495166+rick-nu@users.noreply.github.com> Date: Fri, 12 Jul 2024 10:52:24 +0200 Subject: [PATCH] Add BitBucket webhook parser and statuses (#210) * Add BitBucket webhook recordings * Create bitbucket webhook URL * Add Cypress test for bitbucket * Add BitBucket push webhook parser * Setup BitBucket build parser stump * Process BitBucket pipeline builds * Set proper process name and clean up readthedocs status determining * Test succesfull pipeline too * Create bitbucket pull request parser stub * Add BitBucket pull request parser and add documentation * Bump CIMonitor version to 4.14.0 --- README.md | 1 + backend/parser/bitbucket/build.ts | 101 ++++ backend/parser/bitbucket/index.ts | 68 +++ backend/parser/bitbucket/pull-request.ts | 36 ++ backend/parser/bitbucket/push.ts | 41 ++ backend/parser/github/helper.ts | 4 +- backend/parser/github/job.ts | 4 +- backend/parser/gitlab/build.ts | 4 +- backend/parser/gitlab/helper.ts | 6 +- backend/parser/readthedocs.ts | 67 +- backend/router/route/webhook.ts | 33 +- backend/router/route/webhook/bitbucket.ts | 39 ++ backend/status/helper.ts | 4 +- cypress/fixtures/bitbucket/push/1.json | 570 ++++++++++++++++++ cypress/fixtures/bitbucket/push/2.json | 392 ++++++++++++ cypress/fixtures/bitbucket/push/3.json | 187 ++++++ cypress/fixtures/bitbucket/push/4.json | 187 ++++++ cypress/fixtures/bitbucket/push/5.json | 187 ++++++ cypress/fixtures/bitbucket/push/6.json | 187 ++++++ cypress/integration/bitbucket/push.spec.js | 18 + cypress/support/commands.js | 24 +- docs/images/status/bitbucket.png | Bin 0 -> 54119 bytes docs/webhook/bitbucket.md | 15 + .../Statuses/Status/Process/Process.style.tsx | 6 +- .../App/Statuses/Status/Process/Process.tsx | 4 +- mkdocs.yml | 1 + package.json | 2 +- types/bitbucket.ts | 89 +++ types/status.ts | 8 +- 29 files changed, 2202 insertions(+), 83 deletions(-) create mode 100644 backend/parser/bitbucket/build.ts create mode 100644 backend/parser/bitbucket/index.ts create mode 100644 backend/parser/bitbucket/pull-request.ts create mode 100644 backend/parser/bitbucket/push.ts create mode 100644 backend/router/route/webhook/bitbucket.ts create mode 100644 cypress/fixtures/bitbucket/push/1.json create mode 100644 cypress/fixtures/bitbucket/push/2.json create mode 100644 cypress/fixtures/bitbucket/push/3.json create mode 100644 cypress/fixtures/bitbucket/push/4.json create mode 100644 cypress/fixtures/bitbucket/push/5.json create mode 100644 cypress/fixtures/bitbucket/push/6.json create mode 100644 cypress/integration/bitbucket/push.spec.js create mode 100644 docs/images/status/bitbucket.png create mode 100644 docs/webhook/bitbucket.md create mode 100644 types/bitbucket.ts diff --git a/README.md b/README.md index 621d1e18..b7108b45 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ deployments are successful. All in one overview. This is all done via **webhooks - [GitHub](https://cimonitor.readthedocs.io/en/latest/webhook/github/) - [GitLab](https://cimonitor.readthedocs.io/en/latest/webhook/gitlab/) - [Read the Docs](https://cimonitor.readthedocs.io/en/latest/webhook/readthedocs/) +- [BitBucket](https://cimonitor.readthedocs.io/en/latest/webhook/bitbucket/) ## Example diff --git a/backend/parser/bitbucket/build.ts b/backend/parser/bitbucket/build.ts new file mode 100644 index 00000000..7ccc313c --- /dev/null +++ b/backend/parser/bitbucket/build.ts @@ -0,0 +1,101 @@ +import { isOldProcess } from 'backend/status/helper'; +import StatusManager from 'backend/status/manager'; +import { BitBucketBuildState, BitBucketCommitStatusWebhook } from 'types/bitbucket'; +import Status, { Process, State, StepAndStageState } from 'types/status'; + +class BitBucketBuildParser { + parse(id: string, build: BitBucketCommitStatusWebhook): Status { + let status = StatusManager.getStatus(id); + + if (!status) { + status = { + id, + project: `${build.repository.workspace.name} / ${build.repository.name}`, + state: 'info', + source: 'bitbucket', + time: new Date().toUTCString(), + processes: [], + }; + } + + let processes: Process[] = status.processes || []; + + const processId = parseInt(build.commit_status.key); + + if (!processes.find((process) => process.id === processId)) { + if (isOldProcess(status, processId)) { + return null; + } + + processes.push({ + id: processId, + title: build.commit_status.commit.message, + state: 'warning', + stages: [], + time: new Date().toUTCString(), + }); + } + + processes = processes.map((process) => { + if (process.id === processId) { + return this.patchProcess(process, build); + } + + return process; + }); + + const commitUser = build.commit_status.commit.author.user; + return { + ...status, + processes, + username: commitUser.display_name, + userUrl: commitUser.links.html.href, + userImage: commitUser.links.avatar.href, + projectImage: build.repository.links.avatar.href, + sourceUrl: build.repository.links.html.href, + time: new Date().toUTCString(), + }; + } + + patchProcess(process: Process, build: BitBucketCommitStatusWebhook): Process { + return { + ...process, + stages: [ + { + id: 'build', + steps: [], + time: new Date().toUTCString(), + state: this.getStageState(build.commit_status.state), + title: build.commit_status.name, + }, + ], + state: this.getProcessState(build.commit_status.state), + }; + } + + getProcessState(state: BitBucketBuildState): State { + if (state === 'SUCCESSFUL') { + return 'success'; + } + + if (state === 'FAILED') { + return 'error'; + } + + return 'warning'; + } + + getStageState(state: BitBucketBuildState): StepAndStageState { + if (state === 'SUCCESSFUL') { + return 'success'; + } + + if (state === 'FAILED') { + return 'failed'; + } + + return 'running'; + } +} + +export default new BitBucketBuildParser(); diff --git a/backend/parser/bitbucket/index.ts b/backend/parser/bitbucket/index.ts new file mode 100644 index 00000000..2a478ac2 --- /dev/null +++ b/backend/parser/bitbucket/index.ts @@ -0,0 +1,68 @@ +import Slugify from 'backend/parser/slug'; +import { + BitBucketChangeWrapper, + BitBucketCommitStatusWebhook, + BitBucketPullRequestWebhook, + BitBucketPushWebhook, + BitBucketRepository, +} from 'types/bitbucket'; +import Status from 'types/status'; + +import BitBucketBuildParser from './build'; +import BitBucketPullRequestParser from './pull-request'; +import BitBucketPushParser from './push'; + +class BitBucketParser { + getInternalId(repository: BitBucketRepository, branch: string): string { + return `bitbucket-${Slugify(repository.full_name)}-${Slugify(branch)}`; + } + + parsePush(push: BitBucketPushWebhook): Status { + console.log('[parser/bitbucket] Parsing push...'); + + const relevantChange = push.push.changes.find((changes: BitBucketChangeWrapper) => { + if (changes.new) { + return changes.new.type === 'branch' || changes.new.type === 'tag'; + } + + return false; + }); + + if (!relevantChange) { + console.log('[parser/bitbucket] No relevant change of type branch was found. Stopping.'); + return null; + } + + const id = this.getInternalId(push.repository, relevantChange.new.name); + + return BitBucketPushParser.parse(id, push, relevantChange.new); + } + + parseBuild(build: BitBucketCommitStatusWebhook): Status { + console.log('[parser/bitbucket] Parsing build...'); + + if (build.commit_status.refname === null) { + console.log('[parser/bitbucket] Build could not be linked to a branch. Stopping.'); + return null; + } + + if (parseInt(build.commit_status.key) === 0 || isNaN(parseInt(build.commit_status.key))) { + console.log('[parser/bitbucket] Build has an invalid key, should be a build number. Stopping.'); + return null; + } + + const id = this.getInternalId(build.repository, build.commit_status.refname); + + return BitBucketBuildParser.parse(id, build); + } + + parsePullRequest(pr: BitBucketPullRequestWebhook): Status { + console.log('[parser/bitbucket] Parsing pull request...'); + + const id = this.getInternalId(pr.repository, pr.pullrequest.source.branch.name); + + return BitBucketPullRequestParser.parse(id, pr); + } +} + +export default new BitBucketParser(); diff --git a/backend/parser/bitbucket/pull-request.ts b/backend/parser/bitbucket/pull-request.ts new file mode 100644 index 00000000..accd8797 --- /dev/null +++ b/backend/parser/bitbucket/pull-request.ts @@ -0,0 +1,36 @@ +import StatusManager from 'backend/status/manager'; +import { BitBucketPullRequestWebhook } from 'types/bitbucket'; +import Status from 'types/status'; + +class BitBucketPullRequestParser { + parse(id: string, pr: BitBucketPullRequestWebhook): Status { + let status = StatusManager.getStatus(id); + + if (!status) { + status = { + id, + project: `${pr.repository.workspace.name} / ${pr.repository.name}`, + state: 'info', + source: 'bitbucket', + time: new Date().toUTCString(), + processes: [], + }; + } + + const commitUser = pr.actor; + return { + ...status, + branch: pr.pullrequest.source.branch.name, + username: commitUser.display_name, + userUrl: commitUser.links.html.href, + userImage: commitUser.links.avatar.href, + mergeTitle: pr.pullrequest.title, + mergeUrl: pr.pullrequest.links.html.href, + projectImage: pr.repository.links.avatar.href, + sourceUrl: pr.repository.links.html.href, + time: new Date().toUTCString(), + }; + } +} + +export default new BitBucketPullRequestParser(); diff --git a/backend/parser/bitbucket/push.ts b/backend/parser/bitbucket/push.ts new file mode 100644 index 00000000..7bf911af --- /dev/null +++ b/backend/parser/bitbucket/push.ts @@ -0,0 +1,41 @@ +import StatusManager from 'backend/status/manager'; +import { BitBucketChange, BitBucketPushWebhook } from 'types/bitbucket'; +import Status from 'types/status'; + +class BitBucketPushParser { + parse(id: string, push: BitBucketPushWebhook, change: BitBucketChange): Status { + let status = StatusManager.getStatus(id); + + if (!status) { + status = { + id, + project: `${push.repository.workspace.name} / ${push.repository.name}`, + state: 'info', + source: 'bitbucket', + time: new Date().toUTCString(), + processes: [], + }; + + if (change.type === 'branch') { + status.branch = change.name; + } + + if (change.type === 'tag') { + status.tag = change.name; + } + } + + const commitUser = change.target.author.user; + return { + ...status, + username: commitUser.display_name, + userUrl: commitUser.links.html.href, + userImage: commitUser.links.avatar.href, + projectImage: push.repository.links.avatar.href, + sourceUrl: push.repository.links.html.href, + time: new Date().toUTCString(), + }; + } +} + +export default new BitBucketPushParser(); diff --git a/backend/parser/github/helper.ts b/backend/parser/github/helper.ts index ce14b173..06be9811 100644 --- a/backend/parser/github/helper.ts +++ b/backend/parser/github/helper.ts @@ -1,5 +1,5 @@ import { GitHubConclusion, GitHubStatus } from 'types/github'; -import { State, StepState } from 'types/status'; +import { State, StepAndStageState } from 'types/status'; export const getProcessState = (status: GitHubStatus, conclusion: GitHubConclusion): State => { if (conclusion !== null) { @@ -17,7 +17,7 @@ export const getProcessState = (status: GitHubStatus, conclusion: GitHubConclusi return 'info'; }; -export const getStepState = (status: GitHubStatus, conclusion: GitHubConclusion): StepState => { +export const getStepState = (status: GitHubStatus, conclusion: GitHubConclusion): StepAndStageState => { if (conclusion !== null) { if (conclusion === 'failure') { return 'failed'; diff --git a/backend/parser/github/job.ts b/backend/parser/github/job.ts index b9debc53..d664a8b5 100644 --- a/backend/parser/github/job.ts +++ b/backend/parser/github/job.ts @@ -1,7 +1,7 @@ import Slugify from 'backend/parser/slug'; import StatusManager from 'backend/status/manager'; import { GitHubWorkflowJob } from 'types/github'; -import Status, { Process, Stage, Step, StepState } from 'types/status'; +import Status, { Process, Stage, Step, StepAndStageState } from 'types/status'; import { getStepState } from './helper'; @@ -104,7 +104,7 @@ class GitHubJobParser { }; } - getStageState(steps: Step[]): StepState { + getStageState(steps: Step[]): StepAndStageState { if (steps.length === 0) { return 'running'; } diff --git a/backend/parser/gitlab/build.ts b/backend/parser/gitlab/build.ts index 032296d0..6e87cc32 100644 --- a/backend/parser/gitlab/build.ts +++ b/backend/parser/gitlab/build.ts @@ -2,7 +2,7 @@ import Slugify from 'backend/parser/slug'; import { isOldProcess } from 'backend/status/helper'; import StatusManager from 'backend/status/manager'; import { GitLabBuild } from 'types/gitlab'; -import Status, { Process, Stage, Step, StepState } from 'types/status'; +import Status, { Process, Stage, Step, StepAndStageState } from 'types/status'; import { statusToStepState } from './helper'; @@ -147,7 +147,7 @@ class GitLabBuildParser { }; } - determineStageState(steps: Step[]): StepState { + determineStageState(steps: Step[]): StepAndStageState { if (steps.find((step) => ['failed'].includes(step.state))) { return 'failed'; } diff --git a/backend/parser/gitlab/helper.ts b/backend/parser/gitlab/helper.ts index 6a60e90c..b4ea50e3 100644 --- a/backend/parser/gitlab/helper.ts +++ b/backend/parser/gitlab/helper.ts @@ -1,5 +1,5 @@ import { GitLabStatus } from 'types/gitlab'; -import { State, StepState } from 'types/status'; +import { State, StepAndStageState } from 'types/status'; type GitLabStatusMapper = { // eslint-disable-next-line no-unused-vars @@ -19,8 +19,8 @@ export const statusToState = (status: GitLabStatus): State => { return states[status] || 'info'; }; -export const statusToStepState = (status: GitLabStatus, allowFailure: boolean): StepState => { - const states: GitLabStatusMapper = { +export const statusToStepState = (status: GitLabStatus, allowFailure: boolean): StepAndStageState => { + const states: GitLabStatusMapper = { pending: 'pending', running: 'running', created: 'created', diff --git a/backend/parser/readthedocs.ts b/backend/parser/readthedocs.ts index 61ea6621..48f4fa92 100644 --- a/backend/parser/readthedocs.ts +++ b/backend/parser/readthedocs.ts @@ -2,33 +2,9 @@ import Slugify from 'backend/parser/slug'; import { isOldProcess } from 'backend/status/helper'; import StatusManager from 'backend/status/manager'; import ReadTheDocsBuild from 'types/readthedocs'; -import Status, { Process, State, StepState } from 'types/status'; +import Status, { Process, State, StepAndStageState } from 'types/status'; class ReadTheDocsParser { - getState(event: string): State { - if (event === 'build:passed') { - return 'success'; - } - - if (event === 'build:failed') { - return 'error'; - } - - return 'warning'; - } - - getStepState(event: string): StepState { - if (event === 'build:passed') { - return 'success'; - } - - if (event === 'build:failed') { - return 'failed'; - } - - return 'running'; - } - parseBuild(build: ReadTheDocsBuild): Status | null { console.log('[parser/readthedocs] Parsing build...'); @@ -79,23 +55,10 @@ class ReadTheDocsParser { processes, url: build.docs_url, sourceUrl: build.build_url, - state: this.determineState(processes), time: new Date().toUTCString(), }; } - determineState(processes: Process[]): State { - if (processes.find((process) => process.state === 'warning')) { - return 'warning'; - } - - if (processes.find((process) => process.state === 'error')) { - return 'error'; - } - - return 'success'; - } - patchProcess(process: Process, build: ReadTheDocsBuild): Process { return { ...process, @@ -104,13 +67,37 @@ class ReadTheDocsParser { id: 'build', steps: [], time: new Date().toUTCString(), - state: this.getStepState(build.event), + state: this.getStageState(build.event), title: 'Building documentation', }, ], - state: this.getState(build.event), + state: this.getProcessState(build.event), }; } + + getProcessState(event: string): State { + if (event === 'build:passed') { + return 'success'; + } + + if (event === 'build:failed') { + return 'error'; + } + + return 'warning'; + } + + getStageState(event: string): StepAndStageState { + if (event === 'build:passed') { + return 'success'; + } + + if (event === 'build:failed') { + return 'failed'; + } + + return 'running'; + } } export default new ReadTheDocsParser(); diff --git a/backend/router/route/webhook.ts b/backend/router/route/webhook.ts index 3af5c274..5aec574b 100644 --- a/backend/router/route/webhook.ts +++ b/backend/router/route/webhook.ts @@ -2,6 +2,7 @@ import express from 'express'; import FileSystem from 'fs'; import { IncomingHttpHeaders } from 'http'; +import BitBucketRouter from './webhook/bitbucket'; import GitHubRouter from './webhook/github'; import GitLabRouter from './webhook/gitlab'; import ReadTheDocsRouter from './webhook/readthedocs'; @@ -10,29 +11,38 @@ const router = express.Router(); const cleanHeaders = (headers: IncomingHttpHeaders): IncomingHttpHeaders => { const headersToClean = [ - 'x-gitlab-event-uuid', + 'accept', + 'accept-encoding', + 'baggage', 'connection', - 'host', 'content-length', - 'accept', - 'x-real-ip', + 'host', + 'newrelic', + 'sentry-trace', + 'traceparent', + 'tracestate', + 'x-attempt-number', + 'x-b3-parentspanid', + 'x-b3-sampled', + 'x-b3-spanid', + 'x-b3-traceid', 'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-port', 'x-forwarded-proto', 'x-forwarded-scheme', - 'x-scheme', + 'x-forwarded-server', 'x-github-delivery', 'x-github-hook-id', 'x-github-hook-installation-target-id', 'x-github-hook-installation-target-type', + 'x-gitlab-event-uuid', + 'x-hook-uuid', 'x-hub-signature', 'x-hub-signature-256', - 'sentry-trace', - 'baggage', - 'traceparent', - 'tracestate', - 'newrelic', + 'x-real-ip', + 'x-request-uuid', + 'x-scheme', ]; for (let headerToClean of headersToClean) { @@ -82,8 +92,9 @@ router.use((request, response, next) => { next(); }); -router.use('/gitlab', GitLabRouter); +router.use('/bitbucket', BitBucketRouter); router.use('/github', GitHubRouter); +router.use('/gitlab', GitLabRouter); router.use('/readthedocs', ReadTheDocsRouter); export default router; diff --git a/backend/router/route/webhook/bitbucket.ts b/backend/router/route/webhook/bitbucket.ts new file mode 100644 index 00000000..a963602b --- /dev/null +++ b/backend/router/route/webhook/bitbucket.ts @@ -0,0 +1,39 @@ +import express from 'express'; + +import Parser from 'backend/parser/bitbucket'; +import StatusManager from 'backend/status/manager'; +import Status from 'types/status'; + +const router = express.Router(); + +router.post('/', (request, response) => { + console.log('[route/webhook/bitbucket] Webhook received.'); + + const webhookType: string = String(request.headers['x-event-key']); + + let status: Status | null = null; + + switch (webhookType) { + case 'repo:push': + status = Parser.parsePush(request.body); + break; + case 'repo:commit_status_created': + case 'repo:commit_status_updated': + status = Parser.parseBuild(request.body); + break; + case 'pullrequest:created': + case 'pullrequest:updated': + status = Parser.parsePullRequest(request.body); + break; + default: + console.log(`[route/webhook/bitbucket] No parser for webhook type ${webhookType}.`); + } + + if (status !== null) { + StatusManager.setStatus(status); + } + + response.json({ message: 'thanks' }); +}); + +export default router; diff --git a/backend/status/helper.ts b/backend/status/helper.ts index fdada369..dd9b28db 100644 --- a/backend/status/helper.ts +++ b/backend/status/helper.ts @@ -1,4 +1,4 @@ -import Status, { Duration, Process, Stage, State, StepState } from 'types/status'; +import Status, { Duration, Process, Stage, State, StepAndStageState } from 'types/status'; const statusesExpire = 60 * 60 * 24 * 7; // 7 days const statusesTimeout = 60 * 60 * 2; // 2 hours @@ -57,7 +57,7 @@ export const processStatusChanges = (status: Status): Status => { }; }; -const setDuration = (state: StepState | Process['state'], currentDuration?: Duration): Duration => { +const setDuration = (state: StepAndStageState | Process['state'], currentDuration?: Duration): Duration => { if (state === 'running' || state === 'warning') { return { ran: currentDuration?.ran || 0, diff --git a/cypress/fixtures/bitbucket/push/1.json b/cypress/fixtures/bitbucket/push/1.json new file mode 100644 index 00000000..6f8fb741 --- /dev/null +++ b/cypress/fixtures/bitbucket/push/1.json @@ -0,0 +1,570 @@ +{ + "headers": { + "user-agent": "Bitbucket-Webhooks/2.0", + "content-type": "application/json", + "x-event-key": "repo:push" + }, + "body": { + "push": { + "changes": [ + { + "old": null, + "new": { + "name": "feature/XO-466", + "target": { + "type": "commit", + "hash": "0b6c06edfcb49802d7c63ba1b01eabd573c1bade", + "date": "2024-07-10T09:05:08+00:00", + "author": { + "type": "author", + "raw": "Marc <[REDACTED]>", + "user": { + "display_name": "Marc", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/MR-4.png" + }, + "html": { + "href": "https://bitbucket.org/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D/" + } + }, + "type": "user", + "uuid": "{b3d09cea-ea4a-46c1-aef4-eb2904f6820b}", + "account_id": "712020:9d68805c-afe3-47be-ae4e-85c8114c27b7", + "nickname": "Marc" + } + }, + "message": "XO-466: Removed 319 from excluded types\n", + "summary": { + "type": "rendered", + "raw": "XO-466: Removed 319 from excluded types\n", + "markup": "markdown", + "html": "

XO-466: Removed 319 from excluded types

" + }, + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + } + }, + "parents": [ + { + "hash": "a1176fc2a583a0751c67c7b5619e62d61dc9da54", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/a1176fc2a583a0751c67c7b5619e62d61dc9da54" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/a1176fc2a583a0751c67c7b5619e62d61dc9da54" + } + }, + "type": "commit" + } + ], + "rendered": {}, + "properties": {} + }, + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/refs/branches/feature/XO-466" + }, + "commits": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commits/feature/XO-466" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/branch/feature/XO-466" + } + }, + "type": "branch", + "merge_strategies": ["merge_commit", "squash", "fast_forward"], + "default_merge_strategy": "merge_commit" + }, + "truncated": true, + "created": true, + "forced": false, + "closed": false, + "links": { + "commits": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commits?include=0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/branch/feature/XO-466" + } + }, + "commits": [ + { + "type": "commit", + "hash": "0b6c06edfcb49802d7c63ba1b01eabd573c1bade", + "date": "2024-07-10T09:05:08+00:00", + "author": { + "type": "author", + "raw": "Marc <[REDACTED]>", + "user": { + "display_name": "Marc", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/MR-4.png" + }, + "html": { + "href": "https://bitbucket.org/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D/" + } + }, + "type": "user", + "uuid": "{b3d09cea-ea4a-46c1-aef4-eb2904f6820b}", + "account_id": "712020:9d68805c-afe3-47be-ae4e-85c8114c27b7", + "nickname": "Marc" + } + }, + "message": "XO-466: Removed 319 from excluded types\n", + "summary": { + "type": "rendered", + "raw": "XO-466: Removed 319 from excluded types\n", + "markup": "markdown", + "html": "

XO-466: Removed 319 from excluded types

" + }, + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + }, + "diff": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/diff/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + }, + "approve": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/approve" + }, + "comments": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/comments" + }, + "statuses": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/statuses" + }, + "patch": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/patch/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + } + }, + "parents": [ + { + "hash": "a1176fc2a583a0751c67c7b5619e62d61dc9da54", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/a1176fc2a583a0751c67c7b5619e62d61dc9da54" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/a1176fc2a583a0751c67c7b5619e62d61dc9da54" + } + }, + "type": "commit" + } + ], + "rendered": {}, + "properties": {} + }, + { + "type": "commit", + "hash": "a1176fc2a583a0751c67c7b5619e62d61dc9da54", + "date": "2024-07-09T14:39:32+00:00", + "author": { + "type": "author", + "raw": "Pieter [REDACTED] <[REDACTED]>", + "user": { + "display_name": "Pieter [REDACTED]", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7Bf13f3090-4b44-4dbc-bb22-900c559c0c1a%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/PW-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7Bf13f3090-4b44-4dbc-bb22-900c559c0c1a%7D/" + } + }, + "type": "user", + "uuid": "{f13f3090-4b44-4dbc-bb22-900c559c0c1a}", + "account_id": "712020:1874b931-dbea-4196-adbf-a67711461354", + "nickname": "Pieter [REDACTED]" + } + }, + "message": "Merged in feature/XO-372-mock (pull request #435)\n\nFeature/XO-372 mock\n", + "summary": { + "type": "rendered", + "raw": "Merged in feature/XO-372-mock (pull request #435)\n\nFeature/XO-372 mock\n", + "markup": "markdown", + "html": "

Merged in feature/XO-372-mock (pull request #435)

\n

Feature/XO-372 mock

" + }, + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/a1176fc2a583a0751c67c7b5619e62d61dc9da54" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/a1176fc2a583a0751c67c7b5619e62d61dc9da54" + }, + "diff": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/diff/a1176fc2a583a0751c67c7b5619e62d61dc9da54" + }, + "approve": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/a1176fc2a583a0751c67c7b5619e62d61dc9da54/approve" + }, + "comments": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/a1176fc2a583a0751c67c7b5619e62d61dc9da54/comments" + }, + "statuses": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/a1176fc2a583a0751c67c7b5619e62d61dc9da54/statuses" + } + }, + "parents": [ + { + "hash": "a4b653d15af6b3e69720c0a8c6a6c001e7cb018e", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/a4b653d15af6b3e69720c0a8c6a6c001e7cb018e" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/a4b653d15af6b3e69720c0a8c6a6c001e7cb018e" + } + }, + "type": "commit" + }, + { + "hash": "e82e64828d43ecb7e71d8d4adcff860ec35afa2a", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/e82e64828d43ecb7e71d8d4adcff860ec35afa2a" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/e82e64828d43ecb7e71d8d4adcff860ec35afa2a" + } + }, + "type": "commit" + } + ], + "rendered": {}, + "properties": {} + }, + { + "type": "commit", + "hash": "e82e64828d43ecb7e71d8d4adcff860ec35afa2a", + "date": "2024-07-09T13:08:36+00:00", + "author": { + "type": "author", + "raw": "Pieter [REDACTED] <[REDACTED]>", + "user": { + "display_name": "Pieter [REDACTED]", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7Bf13f3090-4b44-4dbc-bb22-900c559c0c1a%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/PW-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7Bf13f3090-4b44-4dbc-bb22-900c559c0c1a%7D/" + } + }, + "type": "user", + "uuid": "{f13f3090-4b44-4dbc-bb22-900c559c0c1a}", + "account_id": "712020:1874b931-dbea-4196-adbf-a67711461354", + "nickname": "Pieter [REDACTED]" + } + }, + "message": "XO-372: Add type definitions to mocks\n", + "summary": { + "type": "rendered", + "raw": "XO-372: Add type definitions to mocks\n", + "markup": "markdown", + "html": "

XO-372: Add type definitions to mocks

" + }, + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/e82e64828d43ecb7e71d8d4adcff860ec35afa2a" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/e82e64828d43ecb7e71d8d4adcff860ec35afa2a" + }, + "diff": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/diff/e82e64828d43ecb7e71d8d4adcff860ec35afa2a" + }, + "approve": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/e82e64828d43ecb7e71d8d4adcff860ec35afa2a/approve" + }, + "comments": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/e82e64828d43ecb7e71d8d4adcff860ec35afa2a/comments" + }, + "statuses": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/e82e64828d43ecb7e71d8d4adcff860ec35afa2a/statuses" + }, + "patch": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/patch/e82e64828d43ecb7e71d8d4adcff860ec35afa2a" + } + }, + "parents": [ + { + "hash": "f7e2bebbc4a60715e9994f1248095abd19e35114", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/f7e2bebbc4a60715e9994f1248095abd19e35114" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/f7e2bebbc4a60715e9994f1248095abd19e35114" + } + }, + "type": "commit" + } + ], + "rendered": {}, + "properties": {} + }, + { + "type": "commit", + "hash": "f7e2bebbc4a60715e9994f1248095abd19e35114", + "date": "2024-07-09T13:03:12+00:00", + "author": { + "type": "author", + "raw": "Pieter [REDACTED] <[REDACTED]>", + "user": { + "display_name": "Pieter [REDACTED]", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7Bf13f3090-4b44-4dbc-bb22-900c559c0c1a%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/PW-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7Bf13f3090-4b44-4dbc-bb22-900c559c0c1a%7D/" + } + }, + "type": "user", + "uuid": "{f13f3090-4b44-4dbc-bb22-900c559c0c1a}", + "account_id": "712020:1874b931-dbea-4196-adbf-a67711461354", + "nickname": "Pieter [REDACTED]" + } + }, + "message": "XO-372: Remove unused lines\n", + "summary": { + "type": "rendered", + "raw": "XO-372: Remove unused lines\n", + "markup": "markdown", + "html": "

XO-372: Remove unused lines

" + }, + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/f7e2bebbc4a60715e9994f1248095abd19e35114" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/f7e2bebbc4a60715e9994f1248095abd19e35114" + }, + "diff": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/diff/f7e2bebbc4a60715e9994f1248095abd19e35114" + }, + "approve": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/f7e2bebbc4a60715e9994f1248095abd19e35114/approve" + }, + "comments": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/f7e2bebbc4a60715e9994f1248095abd19e35114/comments" + }, + "statuses": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/f7e2bebbc4a60715e9994f1248095abd19e35114/statuses" + }, + "patch": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/patch/f7e2bebbc4a60715e9994f1248095abd19e35114" + } + }, + "parents": [ + { + "hash": "1d98d1e873d494dc4f838e032169d1e7b8340e61", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/1d98d1e873d494dc4f838e032169d1e7b8340e61" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/1d98d1e873d494dc4f838e032169d1e7b8340e61" + } + }, + "type": "commit" + } + ], + "rendered": {}, + "properties": {} + }, + { + "type": "commit", + "hash": "1d98d1e873d494dc4f838e032169d1e7b8340e61", + "date": "2024-07-09T13:00:00+00:00", + "author": { + "type": "author", + "raw": "Pieter [REDACTED] <[REDACTED]>", + "user": { + "display_name": "Pieter [REDACTED]", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7Bf13f3090-4b44-4dbc-bb22-900c559c0c1a%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/PW-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7Bf13f3090-4b44-4dbc-bb22-900c559c0c1a%7D/" + } + }, + "type": "user", + "uuid": "{f13f3090-4b44-4dbc-bb22-900c559c0c1a}", + "account_id": "712020:1874b931-dbea-4196-adbf-a67711461354", + "nickname": "Pieter [REDACTED]" + } + }, + "message": "XO-372: Restructure the external service mock\n", + "summary": { + "type": "rendered", + "raw": "XO-372: Restructure the external service mock\n", + "markup": "markdown", + "html": "

XO-372: Restructure the external service mock

" + }, + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/1d98d1e873d494dc4f838e032169d1e7b8340e61" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/1d98d1e873d494dc4f838e032169d1e7b8340e61" + }, + "diff": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/diff/1d98d1e873d494dc4f838e032169d1e7b8340e61" + }, + "approve": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/1d98d1e873d494dc4f838e032169d1e7b8340e61/approve" + }, + "comments": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/1d98d1e873d494dc4f838e032169d1e7b8340e61/comments" + }, + "statuses": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/1d98d1e873d494dc4f838e032169d1e7b8340e61/statuses" + }, + "patch": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/patch/1d98d1e873d494dc4f838e032169d1e7b8340e61" + } + }, + "parents": [ + { + "hash": "4dce6f58402f580afe6b97d8baac4fcef4b8da0f", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/4dce6f58402f580afe6b97d8baac4fcef4b8da0f" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/4dce6f58402f580afe6b97d8baac4fcef4b8da0f" + } + }, + "type": "commit" + } + ], + "rendered": {}, + "properties": {} + } + ] + } + ] + }, + "repository": { + "type": "repository", + "full_name": "groupname/xo", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B05740f13-ee26-40c5-b530-4d204854fea1%7D?ts=3379276" + } + }, + "name": "XO", + "scm": "git", + "website": null, + "owner": { + "display_name": "Development groupname", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/DL-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D/" + } + }, + "type": "user", + "uuid": "{0cd27561-674a-4f88-a54b-593966be7ac9}", + "account_id": "5a6a0877bae36d1ee1890185", + "nickname": "Development groupname" + }, + "workspace": { + "type": "workspace", + "uuid": "{0cd27561-674a-4f88-a54b-593966be7ac9}", + "name": "Development groupname", + "slug": "groupname", + "links": { + "avatar": { + "href": "https://bitbucket.org/workspaces/groupname/avatar/?ts=1677682798" + }, + "html": { + "href": "https://bitbucket.org/groupname/" + }, + "self": { + "href": "https://api.bitbucket.org/2.0/workspaces/groupname" + } + } + }, + "is_private": true, + "project": { + "type": "project", + "key": "PROJ", + "uuid": "{e3a2a754-7d0a-4616-a892-8acd318d7ab1}", + "name": "Software", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/workspaces/groupname/projects/PROJ" + }, + "html": { + "href": "https://bitbucket.org/groupname/workspace/projects/PROJ" + }, + "avatar": { + "href": "https://bitbucket.org/account/user/groupname/projects/PROJ/avatar/32?ts=1593421915" + } + } + }, + "uuid": "{05740f13-ee26-40c5-b530-4d204854fea1}", + "parent": null + }, + "actor": { + "display_name": "Marc", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/MR-4.png" + }, + "html": { + "href": "https://bitbucket.org/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D/" + } + }, + "type": "user", + "uuid": "{b3d09cea-ea4a-46c1-aef4-eb2904f6820b}", + "account_id": "712020:9d68805c-afe3-47be-ae4e-85c8114c27b7", + "nickname": "Marc" + } + } +} diff --git a/cypress/fixtures/bitbucket/push/2.json b/cypress/fixtures/bitbucket/push/2.json new file mode 100644 index 00000000..a928d276 --- /dev/null +++ b/cypress/fixtures/bitbucket/push/2.json @@ -0,0 +1,392 @@ +{ + "headers": { + "user-agent": "Bitbucket-Webhooks/2.0", + "content-type": "application/json", + "x-event-key": "pullrequest:created" + }, + "body": { + "repository": { + "type": "repository", + "full_name": "groupname/xo", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B05740f13-ee26-40c5-b530-4d204854fea1%7D?ts=3379276" + } + }, + "name": "XO", + "scm": "git", + "website": null, + "owner": { + "display_name": "Development groupname", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/DL-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D/" + } + }, + "type": "user", + "uuid": "{0cd27561-674a-4f88-a54b-593966be7ac9}", + "account_id": "5a6a0877bae36d1ee1890185", + "nickname": "Development groupname" + }, + "workspace": { + "type": "workspace", + "uuid": "{0cd27561-674a-4f88-a54b-593966be7ac9}", + "name": "Development groupname", + "slug": "groupname", + "links": { + "avatar": { + "href": "https://bitbucket.org/workspaces/groupname/avatar/?ts=1677682798" + }, + "html": { + "href": "https://bitbucket.org/groupname/" + }, + "self": { + "href": "https://api.bitbucket.org/2.0/workspaces/groupname" + } + } + }, + "is_private": true, + "project": { + "type": "project", + "key": "PROJ", + "uuid": "{e3a2a754-7d0a-4616-a892-8acd318d7ab1}", + "name": "Software", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/workspaces/groupname/projects/PROJ" + }, + "html": { + "href": "https://bitbucket.org/groupname/workspace/projects/PROJ" + }, + "avatar": { + "href": "https://bitbucket.org/account/user/groupname/projects/PROJ/avatar/32?ts=1593421915" + } + } + }, + "uuid": "{05740f13-ee26-40c5-b530-4d204854fea1}", + "parent": null + }, + "actor": { + "display_name": "Marc", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/MR-4.png" + }, + "html": { + "href": "https://bitbucket.org/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D/" + } + }, + "type": "user", + "uuid": "{b3d09cea-ea4a-46c1-aef4-eb2904f6820b}", + "account_id": "712020:9d68805c-afe3-47be-ae4e-85c8114c27b7", + "nickname": "Marc" + }, + "pullrequest": { + "comment_count": 0, + "task_count": 0, + "type": "pullrequest", + "id": 437, + "title": "Draft: XO-466 Wmo319 Create overview", + "description": "TBD", + "rendered": { + "title": { + "type": "rendered", + "raw": "Draft: XO-466 Wmo319 Create overview", + "markup": "markdown", + "html": "

Draft: XO-466 Wmo319 Create overview

" + }, + "description": { + "type": "rendered", + "raw": "TBD", + "markup": "markdown", + "html": "

TBD

" + } + }, + "state": "OPEN", + "merge_commit": null, + "close_source_branch": false, + "closed_by": null, + "author": { + "display_name": "Marc", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/MR-4.png" + }, + "html": { + "href": "https://bitbucket.org/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D/" + } + }, + "type": "user", + "uuid": "{b3d09cea-ea4a-46c1-aef4-eb2904f6820b}", + "account_id": "712020:9d68805c-afe3-47be-ae4e-85c8114c27b7", + "nickname": "Marc" + }, + "reason": "", + "created_on": "2024-07-10T09:06:31.487822+00:00", + "updated_on": "2024-07-10T09:06:32.980951+00:00", + "destination": { + "branch": { + "name": "main" + }, + "commit": { + "hash": "a1176fc2a583", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/a1176fc2a583" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/a1176fc2a583" + } + }, + "type": "commit" + }, + "repository": { + "type": "repository", + "full_name": "groupname/xo", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B05740f13-ee26-40c5-b530-4d204854fea1%7D?ts=3379276" + } + }, + "name": "XO", + "uuid": "{05740f13-ee26-40c5-b530-4d204854fea1}" + } + }, + "source": { + "branch": { + "name": "feature/XO-466" + }, + "commit": { + "hash": "0b6c06edfcb4", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb4" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/0b6c06edfcb4" + } + }, + "type": "commit" + }, + "repository": { + "type": "repository", + "full_name": "groupname/xo", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B05740f13-ee26-40c5-b530-4d204854fea1%7D?ts=3379276" + } + }, + "name": "XO", + "uuid": "{05740f13-ee26-40c5-b530-4d204854fea1}" + } + }, + "reviewers": [ + { + "display_name": "Pieter [REDACTED]", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7Bf13f3090-4b44-4dbc-bb22-900c559c0c1a%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/PW-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7Bf13f3090-4b44-4dbc-bb22-900c559c0c1a%7D/" + } + }, + "type": "user", + "uuid": "{f13f3090-4b44-4dbc-bb22-900c559c0c1a}", + "account_id": "712020:1874b931-dbea-4196-adbf-a67711461354", + "nickname": "Pieter [REDACTED]" + }, + { + "display_name": "Nick", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B439374be-ee4d-411c-b153-0b768303ac74%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/N-5.png" + }, + "html": { + "href": "https://bitbucket.org/%7B439374be-ee4d-411c-b153-0b768303ac74%7D/" + } + }, + "type": "user", + "uuid": "{439374be-ee4d-411c-b153-0b768303ac74}", + "account_id": "712020:343fef7f-3815-42cb-bd8f-f22fd8d6676d", + "nickname": "Nick" + }, + { + "display_name": "Björn [REDACTED]", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B99927a7f-57e1-457d-92f4-4be1a4af9137%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/BS-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7B99927a7f-57e1-457d-92f4-4be1a4af9137%7D/" + } + }, + "type": "user", + "uuid": "{99927a7f-57e1-457d-92f4-4be1a4af9137}", + "account_id": "712020:d6d2db88-8e9d-4e8d-a275-93829ee8c7eb", + "nickname": "Björn [REDACTED]" + } + ], + "participants": [ + { + "type": "participant", + "user": { + "display_name": "Björn [REDACTED]", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B99927a7f-57e1-457d-92f4-4be1a4af9137%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/BS-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7B99927a7f-57e1-457d-92f4-4be1a4af9137%7D/" + } + }, + "type": "user", + "uuid": "{99927a7f-57e1-457d-92f4-4be1a4af9137}", + "account_id": "712020:d6d2db88-8e9d-4e8d-a275-93829ee8c7eb", + "nickname": "Björn [REDACTED]" + }, + "role": "REVIEWER", + "approved": false, + "state": null, + "participated_on": null + }, + { + "type": "participant", + "user": { + "display_name": "Pieter [REDACTED]", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7Bf13f3090-4b44-4dbc-bb22-900c559c0c1a%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/PW-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7Bf13f3090-4b44-4dbc-bb22-900c559c0c1a%7D/" + } + }, + "type": "user", + "uuid": "{f13f3090-4b44-4dbc-bb22-900c559c0c1a}", + "account_id": "712020:1874b931-dbea-4196-adbf-a67711461354", + "nickname": "Pieter [REDACTED]" + }, + "role": "REVIEWER", + "approved": false, + "state": null, + "participated_on": null + }, + { + "type": "participant", + "user": { + "display_name": "Nick", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B439374be-ee4d-411c-b153-0b768303ac74%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/N-5.png" + }, + "html": { + "href": "https://bitbucket.org/%7B439374be-ee4d-411c-b153-0b768303ac74%7D/" + } + }, + "type": "user", + "uuid": "{439374be-ee4d-411c-b153-0b768303ac74}", + "account_id": "712020:343fef7f-3815-42cb-bd8f-f22fd8d6676d", + "nickname": "Nick" + }, + "role": "REVIEWER", + "approved": false, + "state": null, + "participated_on": null + } + ], + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/pullrequests/437" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/pull-requests/437" + }, + "commits": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/pullrequests/437/commits" + }, + "approve": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/pullrequests/437/approve" + }, + "request-changes": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/pullrequests/437/request-changes" + }, + "diff": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/diff/groupname/xo:0b6c06edfcb4%0Da1176fc2a583?from_pullrequest_id=437&topic=true&exclude_files=97a77efb-65a7-42d5-b48a-5c13c78fdadf" + }, + "diffstat": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/diffstat/groupname/xo:0b6c06edfcb4%0Da1176fc2a583?from_pullrequest_id=437&topic=true&exclude_files=97a77efb-65a7-42d5-b48a-5c13c78fdadf" + }, + "comments": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/pullrequests/437/comments" + }, + "activity": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/pullrequests/437/activity" + }, + "merge": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/pullrequests/437/merge" + }, + "decline": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/pullrequests/437/decline" + }, + "statuses": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/pullrequests/437/statuses" + } + }, + "summary": { + "type": "rendered", + "raw": "TBD", + "markup": "markdown", + "html": "

TBD

" + } + } + } +} diff --git a/cypress/fixtures/bitbucket/push/3.json b/cypress/fixtures/bitbucket/push/3.json new file mode 100644 index 00000000..cda6d72e --- /dev/null +++ b/cypress/fixtures/bitbucket/push/3.json @@ -0,0 +1,187 @@ +{ + "headers": { + "user-agent": "Bitbucket-Webhooks/2.0", + "content-type": "application/json", + "x-event-key": "repo:commit_status_created" + }, + "body": { + "repository": { + "type": "repository", + "full_name": "groupname/xo", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B05740f13-ee26-40c5-b530-4d204854fea1%7D?ts=3379276" + } + }, + "name": "XO", + "scm": "git", + "website": null, + "owner": { + "display_name": "Development groupname", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/DL-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D/" + } + }, + "type": "user", + "uuid": "{0cd27561-674a-4f88-a54b-593966be7ac9}", + "account_id": "5a6a0877bae36d1ee1890185", + "nickname": "Development groupname" + }, + "workspace": { + "type": "workspace", + "uuid": "{0cd27561-674a-4f88-a54b-593966be7ac9}", + "name": "Development groupname", + "slug": "groupname", + "links": { + "avatar": { + "href": "https://bitbucket.org/workspaces/groupname/avatar/?ts=1677682798" + }, + "html": { + "href": "https://bitbucket.org/groupname/" + }, + "self": { + "href": "https://api.bitbucket.org/2.0/workspaces/groupname" + } + } + }, + "is_private": true, + "project": { + "type": "project", + "key": "PROJ", + "uuid": "{e3a2a754-7d0a-4616-a892-8acd318d7ab1}", + "name": "Software", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/workspaces/groupname/projects/PROJ" + }, + "html": { + "href": "https://bitbucket.org/groupname/workspace/projects/PROJ" + }, + "avatar": { + "href": "https://bitbucket.org/account/user/groupname/projects/PROJ/avatar/32?ts=1593421915" + } + } + }, + "uuid": "{05740f13-ee26-40c5-b530-4d204854fea1}", + "parent": null + }, + "actor": { + "display_name": "Development groupname", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/DL-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D/" + } + }, + "type": "user", + "uuid": "{0cd27561-674a-4f88-a54b-593966be7ac9}", + "account_id": "5a6a0877bae36d1ee1890185", + "nickname": "Development groupname" + }, + "commit_status": { + "key": "606642714", + "type": "build", + "state": "INPROGRESS", + "name": "Pipeline #3506 for Pull Request #437", + "refname": "feature/XO-466", + "commit": { + "type": "commit", + "hash": "0b6c06edfcb49802d7c63ba1b01eabd573c1bade", + "date": "2024-07-10T09:05:08+00:00", + "author": { + "type": "author", + "raw": "Marc <[REDACTED]>", + "user": { + "display_name": "Marc", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/MR-4.png" + }, + "html": { + "href": "https://bitbucket.org/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D/" + } + }, + "type": "user", + "uuid": "{b3d09cea-ea4a-46c1-aef4-eb2904f6820b}", + "account_id": "712020:9d68805c-afe3-47be-ae4e-85c8114c27b7", + "nickname": "Marc" + } + }, + "message": "XO-466: Removed 319 from excluded types\n", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + }, + "diff": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/diff/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + }, + "approve": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/approve" + }, + "comments": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/comments" + }, + "statuses": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/statuses" + }, + "patch": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/patch/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + } + } + }, + "url": "https://bitbucket.org/groupname/xo/addon/pipelines/home#!/results/3506", + "repository": { + "type": "repository", + "full_name": "groupname/xo", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B05740f13-ee26-40c5-b530-4d204854fea1%7D?ts=3379276" + } + }, + "name": "XO", + "uuid": "{05740f13-ee26-40c5-b530-4d204854fea1}" + }, + "description": "", + "created_on": "2024-07-10T09:06:37.643706+00:00", + "updated_on": "2024-07-10T09:06:37.643718+00:00", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/statuses/build/606642714" + }, + "commit": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + } + } + } + } +} diff --git a/cypress/fixtures/bitbucket/push/4.json b/cypress/fixtures/bitbucket/push/4.json new file mode 100644 index 00000000..1507f38e --- /dev/null +++ b/cypress/fixtures/bitbucket/push/4.json @@ -0,0 +1,187 @@ +{ + "headers": { + "user-agent": "Bitbucket-Webhooks/2.0", + "content-type": "application/json", + "x-event-key": "repo:commit_status_updated" + }, + "body": { + "repository": { + "type": "repository", + "full_name": "groupname/xo", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B05740f13-ee26-40c5-b530-4d204854fea1%7D?ts=3379276" + } + }, + "name": "XO", + "scm": "git", + "website": null, + "owner": { + "display_name": "Development groupname", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/DL-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D/" + } + }, + "type": "user", + "uuid": "{0cd27561-674a-4f88-a54b-593966be7ac9}", + "account_id": "5a6a0877bae36d1ee1890185", + "nickname": "Development groupname" + }, + "workspace": { + "type": "workspace", + "uuid": "{0cd27561-674a-4f88-a54b-593966be7ac9}", + "name": "Development groupname", + "slug": "groupname", + "links": { + "avatar": { + "href": "https://bitbucket.org/workspaces/groupname/avatar/?ts=1677682798" + }, + "html": { + "href": "https://bitbucket.org/groupname/" + }, + "self": { + "href": "https://api.bitbucket.org/2.0/workspaces/groupname" + } + } + }, + "is_private": true, + "project": { + "type": "project", + "key": "PROJ", + "uuid": "{e3a2a754-7d0a-4616-a892-8acd318d7ab1}", + "name": "Software", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/workspaces/groupname/projects/PROJ" + }, + "html": { + "href": "https://bitbucket.org/groupname/workspace/projects/PROJ" + }, + "avatar": { + "href": "https://bitbucket.org/account/user/groupname/projects/PROJ/avatar/32?ts=1593421915" + } + } + }, + "uuid": "{05740f13-ee26-40c5-b530-4d204854fea1}", + "parent": null + }, + "actor": { + "display_name": "Development groupname", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/DL-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D/" + } + }, + "type": "user", + "uuid": "{0cd27561-674a-4f88-a54b-593966be7ac9}", + "account_id": "5a6a0877bae36d1ee1890185", + "nickname": "Development groupname" + }, + "commit_status": { + "key": "606642714", + "type": "build", + "state": "FAILED", + "name": "Pipeline #3506 for Pull Request #437", + "refname": "feature/XO-466", + "commit": { + "type": "commit", + "hash": "0b6c06edfcb49802d7c63ba1b01eabd573c1bade", + "date": "2024-07-10T09:05:08+00:00", + "author": { + "type": "author", + "raw": "Marc <[REDACTED]>", + "user": { + "display_name": "Marc", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/MR-4.png" + }, + "html": { + "href": "https://bitbucket.org/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D/" + } + }, + "type": "user", + "uuid": "{b3d09cea-ea4a-46c1-aef4-eb2904f6820b}", + "account_id": "712020:9d68805c-afe3-47be-ae4e-85c8114c27b7", + "nickname": "Marc" + } + }, + "message": "XO-466: Removed 319 from excluded types\n", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + }, + "diff": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/diff/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + }, + "approve": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/approve" + }, + "comments": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/comments" + }, + "statuses": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/statuses" + }, + "patch": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/patch/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + } + } + }, + "url": "https://bitbucket.org/groupname/xo/addon/pipelines/home#!/results/3506", + "repository": { + "type": "repository", + "full_name": "groupname/xo", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B05740f13-ee26-40c5-b530-4d204854fea1%7D?ts=3379276" + } + }, + "name": "XO", + "uuid": "{05740f13-ee26-40c5-b530-4d204854fea1}" + }, + "description": "", + "created_on": "2024-07-10T09:06:37.643706+00:00", + "updated_on": "2024-07-10T09:14:31.026080+00:00", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/statuses/build/606642714" + }, + "commit": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + } + } + } + } +} diff --git a/cypress/fixtures/bitbucket/push/5.json b/cypress/fixtures/bitbucket/push/5.json new file mode 100644 index 00000000..8456021b --- /dev/null +++ b/cypress/fixtures/bitbucket/push/5.json @@ -0,0 +1,187 @@ +{ + "headers": { + "user-agent": "Bitbucket-Webhooks/2.0", + "content-type": "application/json", + "x-event-key": "repo:commit_status_created" + }, + "body": { + "repository": { + "type": "repository", + "full_name": "groupname/xo", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B05740f13-ee26-40c5-b530-4d204854fea1%7D?ts=3379276" + } + }, + "name": "XO", + "scm": "git", + "website": null, + "owner": { + "display_name": "Development groupname", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/DL-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D/" + } + }, + "type": "user", + "uuid": "{0cd27561-674a-4f88-a54b-593966be7ac9}", + "account_id": "5a6a0877bae36d1ee1890185", + "nickname": "Development groupname" + }, + "workspace": { + "type": "workspace", + "uuid": "{0cd27561-674a-4f88-a54b-593966be7ac9}", + "name": "Development groupname", + "slug": "groupname", + "links": { + "avatar": { + "href": "https://bitbucket.org/workspaces/groupname/avatar/?ts=1677682798" + }, + "html": { + "href": "https://bitbucket.org/groupname/" + }, + "self": { + "href": "https://api.bitbucket.org/2.0/workspaces/groupname" + } + } + }, + "is_private": true, + "project": { + "type": "project", + "key": "PROJ", + "uuid": "{e3a2a754-7d0a-4616-a892-8acd318d7ab1}", + "name": "Software", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/workspaces/groupname/projects/PROJ" + }, + "html": { + "href": "https://bitbucket.org/groupname/workspace/projects/PROJ" + }, + "avatar": { + "href": "https://bitbucket.org/account/user/groupname/projects/PROJ/avatar/32?ts=1593421915" + } + } + }, + "uuid": "{05740f13-ee26-40c5-b530-4d204854fea1}", + "parent": null + }, + "actor": { + "display_name": "Development groupname", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/DL-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D/" + } + }, + "type": "user", + "uuid": "{0cd27561-674a-4f88-a54b-593966be7ac9}", + "account_id": "5a6a0877bae36d1ee1890185", + "nickname": "Development groupname" + }, + "commit_status": { + "key": "606642715", + "type": "build", + "state": "INPROGRESS", + "name": "Pipeline #3507 for Pull Request #437", + "refname": "feature/XO-466", + "commit": { + "type": "commit", + "hash": "0b6c06edfcb49802d7c63ba1b01eabd573c1bade", + "date": "2024-07-10T09:05:08+00:00", + "author": { + "type": "author", + "raw": "Marc <[REDACTED]>", + "user": { + "display_name": "Marc", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/MR-4.png" + }, + "html": { + "href": "https://bitbucket.org/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D/" + } + }, + "type": "user", + "uuid": "{b3d09cea-ea4a-46c1-aef4-eb2904f6820b}", + "account_id": "712020:9d68805c-afe3-47be-ae4e-85c8114c27b7", + "nickname": "Marc" + } + }, + "message": "XO-466: Removed 319 from excluded types\n", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + }, + "diff": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/diff/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + }, + "approve": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/approve" + }, + "comments": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/comments" + }, + "statuses": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/statuses" + }, + "patch": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/patch/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + } + } + }, + "url": "https://bitbucket.org/groupname/xo/addon/pipelines/home#!/results/3506", + "repository": { + "type": "repository", + "full_name": "groupname/xo", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B05740f13-ee26-40c5-b530-4d204854fea1%7D?ts=3379276" + } + }, + "name": "XO", + "uuid": "{05740f13-ee26-40c5-b530-4d204854fea1}" + }, + "description": "", + "created_on": "2024-07-10T09:06:37.643706+00:00", + "updated_on": "2024-07-10T09:06:37.643718+00:00", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/statuses/build/606642714" + }, + "commit": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + } + } + } + } +} diff --git a/cypress/fixtures/bitbucket/push/6.json b/cypress/fixtures/bitbucket/push/6.json new file mode 100644 index 00000000..c2ed16f1 --- /dev/null +++ b/cypress/fixtures/bitbucket/push/6.json @@ -0,0 +1,187 @@ +{ + "headers": { + "user-agent": "Bitbucket-Webhooks/2.0", + "content-type": "application/json", + "x-event-key": "repo:commit_status_updated" + }, + "body": { + "repository": { + "type": "repository", + "full_name": "groupname/xo", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B05740f13-ee26-40c5-b530-4d204854fea1%7D?ts=3379276" + } + }, + "name": "XO", + "scm": "git", + "website": null, + "owner": { + "display_name": "Development groupname", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/DL-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D/" + } + }, + "type": "user", + "uuid": "{0cd27561-674a-4f88-a54b-593966be7ac9}", + "account_id": "5a6a0877bae36d1ee1890185", + "nickname": "Development groupname" + }, + "workspace": { + "type": "workspace", + "uuid": "{0cd27561-674a-4f88-a54b-593966be7ac9}", + "name": "Development groupname", + "slug": "groupname", + "links": { + "avatar": { + "href": "https://bitbucket.org/workspaces/groupname/avatar/?ts=1677682798" + }, + "html": { + "href": "https://bitbucket.org/groupname/" + }, + "self": { + "href": "https://api.bitbucket.org/2.0/workspaces/groupname" + } + } + }, + "is_private": true, + "project": { + "type": "project", + "key": "PROJ", + "uuid": "{e3a2a754-7d0a-4616-a892-8acd318d7ab1}", + "name": "Software", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/workspaces/groupname/projects/PROJ" + }, + "html": { + "href": "https://bitbucket.org/groupname/workspace/projects/PROJ" + }, + "avatar": { + "href": "https://bitbucket.org/account/user/groupname/projects/PROJ/avatar/32?ts=1593421915" + } + } + }, + "uuid": "{05740f13-ee26-40c5-b530-4d204854fea1}", + "parent": null + }, + "actor": { + "display_name": "Development groupname", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/DL-3.png" + }, + "html": { + "href": "https://bitbucket.org/%7B0cd27561-674a-4f88-a54b-593966be7ac9%7D/" + } + }, + "type": "user", + "uuid": "{0cd27561-674a-4f88-a54b-593966be7ac9}", + "account_id": "5a6a0877bae36d1ee1890185", + "nickname": "Development groupname" + }, + "commit_status": { + "key": "606642715", + "type": "build", + "state": "SUCCESSFUL", + "name": "Pipeline #3507 for Pull Request #437", + "refname": "feature/XO-466", + "commit": { + "type": "commit", + "hash": "0b6c06edfcb49802d7c63ba1b01eabd573c1bade", + "date": "2024-07-10T09:05:08+00:00", + "author": { + "type": "author", + "raw": "Marc <[REDACTED]>", + "user": { + "display_name": "Marc", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D" + }, + "avatar": { + "href": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/initials/MR-4.png" + }, + "html": { + "href": "https://bitbucket.org/%7Bb3d09cea-ea4a-46c1-aef4-eb2904f6820b%7D/" + } + }, + "type": "user", + "uuid": "{b3d09cea-ea4a-46c1-aef4-eb2904f6820b}", + "account_id": "712020:9d68805c-afe3-47be-ae4e-85c8114c27b7", + "nickname": "Marc" + } + }, + "message": "XO-466: Removed 319 from excluded types\n", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo/commits/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + }, + "diff": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/diff/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + }, + "approve": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/approve" + }, + "comments": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/comments" + }, + "statuses": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/statuses" + }, + "patch": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/patch/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + } + } + }, + "url": "https://bitbucket.org/groupname/xo/addon/pipelines/home#!/results/3506", + "repository": { + "type": "repository", + "full_name": "groupname/xo", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo" + }, + "html": { + "href": "https://bitbucket.org/groupname/xo" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B05740f13-ee26-40c5-b530-4d204854fea1%7D?ts=3379276" + } + }, + "name": "XO", + "uuid": "{05740f13-ee26-40c5-b530-4d204854fea1}" + }, + "description": "", + "created_on": "2024-07-10T09:06:37.643706+00:00", + "updated_on": "2024-07-10T09:14:31.026080+00:00", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade/statuses/build/606642714" + }, + "commit": { + "href": "https://api.bitbucket.org/2.0/repositories/groupname/xo/commit/0b6c06edfcb49802d7c63ba1b01eabd573c1bade" + } + } + } + } +} diff --git a/cypress/integration/bitbucket/push.spec.js b/cypress/integration/bitbucket/push.spec.js new file mode 100644 index 00000000..559880bc --- /dev/null +++ b/cypress/integration/bitbucket/push.spec.js @@ -0,0 +1,18 @@ +/// + +context('A running BitBucket push', () => { + it('opens the CIMonitor dashboard', () => { + cy.visit('/'); + }); + + it('pushes a BitBucket branch', () => { + for (let count = 1; count <= 6; count++) { + if (count > 1) { + cy.wait(1000); + } + cy.bitbucket(`push/${count}`); + } + + cy.wait(2000); + }); +}); diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 075ac915..f22e75dc 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -5,21 +5,23 @@ // *********************************************** const fireFixture = (service, file) => { - cy.fixture(`${service}/${file}`).then((fixture) => { - cy.request({ - url: `webhook/${service}`, - method: 'POST', - body: fixture.body, - headers: { - ...fixture.headers, - 'x-dont-persist': true, - }, - }); - }); + cy.fixture(`${service}/${file}`).then((fixture) => { + cy.request({ + url: `webhook/${service}`, + method: 'POST', + body: fixture.body, + headers: { + ...fixture.headers, + 'x-dont-persist': true, + }, + }); + }); }; Cypress.Commands.add('github', (file) => fireFixture('github', file)); Cypress.Commands.add('gitlab', (file) => fireFixture('gitlab', file)); +Cypress.Commands.add('bitbucket', (file) => fireFixture('bitbucket', file)); + Cypress.Commands.add('readthedocs', (file) => fireFixture('readthedocs', file)); diff --git a/docs/images/status/bitbucket.png b/docs/images/status/bitbucket.png new file mode 100644 index 0000000000000000000000000000000000000000..92511a71512374c914a299961bb97c7f9fd24158 GIT binary patch literal 54119 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
  • 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 `; type StepProps = { - state: StepState; + state: StepAndStageState; processState: State; }; diff --git a/frontend/App/Statuses/Status/Process/Process.tsx b/frontend/App/Statuses/Status/Process/Process.tsx index 42b4511f..5b539fe1 100644 --- a/frontend/App/Statuses/Status/Process/Process.tsx +++ b/frontend/App/Statuses/Status/Process/Process.tsx @@ -6,9 +6,9 @@ import RunTime from '/frontend/App/Statuses/Status/RunTime'; import Icon from '/frontend/components/Icon'; import useSetting from '/frontend/hooks/useSetting'; -import { Process as ProcessType, Stage as StageType, State, Step as StepType, StepState } from '/types/status'; +import { Process as ProcessType, Stage as StageType, State, Step as StepType, StepAndStageState } from '/types/status'; -const getStateIcon = (state: StepState, processState: State = 'warning') => { +const getStateIcon = (state: StepAndStageState, processState: State = 'warning') => { const icons = { running: 'autorenew', success: 'done', diff --git a/mkdocs.yml b/mkdocs.yml index d116d82f..cc4e71a4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -20,6 +20,7 @@ nav: - GitHub: webhook/github.md - GitLab: webhook/gitlab.md - Read the docs: webhook/readthedocs.md + - BitBucket: webhook/bitbucket.md - Modules: modules.md - Module: - GPIO: module/gpio.md diff --git a/package.json b/package.json index 57029a75..30650ff9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cimonitor", - "version": "4.13.1", + "version": "4.14.0", "description": "Monitors all your projects CI automatically", "repository": "git@github.com:FuturePortal/CIMonitor.git", "license": "MIT", diff --git a/types/bitbucket.ts b/types/bitbucket.ts new file mode 100644 index 00000000..cef987e0 --- /dev/null +++ b/types/bitbucket.ts @@ -0,0 +1,89 @@ +export type BitBucketRepository = { + name: string; + full_name: string; + links: { + avatar: { + href: string; + }; + html: { + href: string; + }; + }; + workspace: { + name: string; + }; +}; + +export type BitBucketUser = { + display_name: string; + links: { + avatar: { + href: string; + }; + html: { + href: string; + }; + }; +}; + +export type BitBucketBuildState = 'INPROGRESS' | 'FAILED' | 'SUCCESSFUL'; + +export type BitBucketChange = { + name: string; // branch/tag name + type: 'branch' | 'tag' | unknown; + target: { + message: string; // commit message + author: { + user: BitBucketUser; + }; + }; +}; + +export type BitBucketChangeWrapper = { + old: BitBucketChange | null; + new: BitBucketChange; +}; + +export type BitBucketPushWebhook = { + push: { + changes: BitBucketChangeWrapper[]; + }; + repository: BitBucketRepository; + actor: BitBucketUser; +}; + +export type BitBucketCommitStatusWebhook = { + commit_status: { + key: string; + type: 'build' | unknown; + state: BitBucketBuildState; + name: string; + refname: string | null; // branch name + commit: { + message: string; + author: { + user: BitBucketUser; + }; + }; + }; + repository: BitBucketRepository; + actor: BitBucketUser; +}; + +export type BitBucketPullRequestWebhook = { + pullrequest: { + title: string; + source: { + branch: { + name: string; + }; + }; + links: { + html: { + href: string; + }; + }; + }; + repository: BitBucketRepository; + actor: BitBucketUser; +}; diff --git a/types/status.ts b/types/status.ts index 3b7d45bc..98c6b93b 100644 --- a/types/status.ts +++ b/types/status.ts @@ -1,6 +1,6 @@ export type State = 'info' | 'warning' | 'error' | 'success'; -export type StepState = +export type StepAndStageState = | 'created' | 'pending' | 'running' @@ -19,7 +19,7 @@ export type Duration = { export type Step = { id: string; title: string; - state: StepState; + state: StepAndStageState; time: string; duration?: Duration; }; @@ -27,7 +27,7 @@ export type Step = { export type Stage = { id: string; title?: string; - state: StepState; + state: StepAndStageState; steps: Step[]; time: string; duration?: Duration; @@ -48,7 +48,7 @@ export type Status = { state: State; processes: Process[]; time: string; - source: 'github' | 'gitlab' | 'readthedocs'; + source: 'github' | 'gitlab' | 'readthedocs' | 'bitbucket'; sourceUrl?: string; url?: string; branch?: string;