CI plugin

The Bitbucket Cloud CI plugin provides greater control over when CI runs. It offers the following advantages:

  • Use conditions to define which CIs run and when they are triggered
  • Trigger builds using different event types (e.g., source and/or destination PR branch updates)
  • Specific granular event for code changes only, avoid triggers on non-relevant PR changes
  • Skip builds for conflicted pull requests
  • Trigger multiple builds from a single event
  • Fully compatible with existing CI integrations or any webhook-based CI provider
    (e.g., Jenkins , CircleCI, Azure Pipelines , Snyk, Bitrise , etc.)
import {const configure: (config: Config | (() => Config)) => voidconfigure} from "flowie.app"
import {const ci: OptionsPlugin<CiPluginOptions, false>
@ignore
ci
} from "flowie.app/plugins"
function configure(config: Config | (() => Config)): voidconfigure({ Config.plugins?: PluginDef<unknown>[] | undefinedplugins: [ function ci(options: CiPluginOptions): PluginDef<CiPluginOptions> (+2 overloads)
@ignore
ci
({
webhook?: RegExp | undefinedwebhook: /jenkins/, trigger?: (RunTriggerEvent | "source_updated")[] | undefinedtrigger: ["source_updated", "destination_updated"], }), ], })

How webhook matching works

This plugin triggers existing repository webhooks whose URLs match your webhook regex.

function ci(options: CiPluginOptions): PluginDef<CiPluginOptions> (+2 overloads)
@ignore
ci
({
webhook?: RegExp | undefinedwebhook: /my-ci.example.com/, })

If webhook is not provided, Flowie uses a default matcher:

  • /jenkins|circleci|dev.azure.com|snyk.io|bitrise.io|buildkite.com|travis-ci.com|semaphoreci.com|teamcity/

Trigger events

The trigger option defines when CI webhooks run.

function ci(options: CiPluginOptions): PluginDef<CiPluginOptions> (+2 overloads)
@ignore
ci
({
webhook?: RegExp | undefinedwebhook: /jenkins/, trigger?: (RunTriggerEvent | "source_updated")[] | undefinedtrigger: ["source_new_updated", "destination_updated"], })

Supported trigger events:

  • created
  • source_updated
  • source_updated_diff
  • source_new_updated
  • destination_updated
  • fulfilled
  • merge_cascade_conflict
  • label events (for example, label:added:{name:'Env',value:'Staging'})

For the complete trigger type reference, see RunTriggerEvent.

If trigger is omitted, Flowie uses source_updated.

Bitbucket default event

Bitbucket’s updated pull request update webhook triggers builds when the title, description, reviewers, destination branch name, and delete branch options are changed. This limitation is tracked in BCLOUD-21184.

Flowie mitigates this by letting you configure granular trigger events.

Conflict behavior

By default, CI webhooks are not triggered when the pull request has conflicts.

Set skipConflict: false to trigger CI even when conflicts exist:

function ci(options: CiPluginOptions): PluginDef<CiPluginOptions> (+2 overloads)
@ignore
ci
({
webhook?: RegExp | undefinedwebhook: /jenkins/, trigger?: (RunTriggerEvent | "source_updated")[] | undefinedtrigger: ["source_updated_diff"], skipConflict?: boolean | undefinedskipConflict: false, })

Triggering CI based on conditions

Use conditions to apply different CI rules based on branch, labels, or changeset.

import {const configure: (config: Config | (() => Config)) => voidconfigure} from "flowie.app"
import {const ci: OptionsPlugin<CiPluginOptions, false>
@ignore
ci
} from "flowie.app/plugins"
import {function target(...branches: Array<string | RegExp> & NonEmptyArray): ChainableConditiontarget, const labels: Labelslabels} from "flowie.app/conditions" function configure(config: Config | (() => Config)): voidconfigure({ Config.plugins?: PluginDef<unknown>[] | undefinedplugins: [ function ci(...rules: Rules<CiPluginOptions | undefined>): PluginDef<CiPluginOptions> (+2 overloads)
@ignore
ci
([
function target(...branches: Array<string | RegExp> & NonEmptyArray): ChainableConditiontarget("main").ChainableCondition.and: (also: Condition<boolean>) => ChainableConditionand(const labels: Labelslabels.Labels.has(label: string | LabelRef): ChainableCondition (+1 overload)has("CI ready")), { webhook?: RegExp | undefinedwebhook: /jenkins|circleci/, trigger?: (RunTriggerEvent | "source_updated")[] | undefinedtrigger: ["source_new_updated", "destination_updated"], }, ]), ], })

You can define multiple conditional CI rules:

import {const configure: (config: Config | (() => Config)) => voidconfigure} from "flowie.app"
import {const ci: OptionsPlugin<CiPluginOptions, false>
@ignore
ci
} from "flowie.app/plugins"
import {function source(...branches: Array<string | RegExp> & NonEmptyArray): ChainableConditionsource, function otherwise(): trueotherwise} from "flowie.app/conditions" function configure(config: Config | (() => Config)): voidconfigure({ Config.plugins?: PluginDef<unknown>[] | undefinedplugins: [ function ci(...rules: Rules<CiPluginOptions | undefined>): PluginDef<CiPluginOptions> (+2 overloads)
@ignore
ci
(
[ function source(...branches: Array<string | RegExp> & NonEmptyArray): ChainableConditionsource(/^hotfix\/.*/), { webhook?: RegExp | undefinedwebhook: /jenkins.*quickTests=true/, trigger?: (RunTriggerEvent | "source_updated")[] | undefinedtrigger: ["source_new_updated"], }, ], [ function otherwise(): trueotherwise, { webhook?: RegExp | undefinedwebhook: /jenkins.*quickTests=false/, trigger?: (RunTriggerEvent | "source_updated")[] | undefinedtrigger: ["source_new_updated"], }, ] ), ], })

In the example above, it creates an emergency path for hotfixes by running only a minimal set of tests instead of the full test suite, so fixes can be deployed faster. For all other branches, it triggers Jenkins with quickTests=false, which runs the full suite.

Triggering multiple CI webhooks

You can trigger multiple webhook groups with a single plugin declaration:

import {const configure: (config: Config | (() => Config)) => voidconfigure} from "flowie.app"
import {const ci: OptionsPlugin<CiPluginOptions, false>
@ignore
ci
} from "flowie.app/plugins"
function configure(config: Config | (() => Config)): voidconfigure({ Config.plugins?: PluginDef<unknown>[] | undefinedplugins: [ function ci(options: CiPluginOptions): PluginDef<CiPluginOptions> (+2 overloads)
@ignore
ci
([
{ webhook?: RegExp | undefinedwebhook: /circleci/, trigger?: (RunTriggerEvent | "source_updated")[] | undefinedtrigger: [ "created", "source_updated_diff", // Trigger when the destination branch is updated "destination_updated", ], }, { webhook?: RegExp | undefinedwebhook: /snyk/, // Trigger security scans only on code changes trigger?: (RunTriggerEvent | "source_updated")[] | undefinedtrigger: ["source_updated_diff"], }, ]), ], })
Further reference
BCLOUD-21184