Configuration

This page explains the concepts and options available to configure Flowie. If you are just getting started, you can skip this page and come back later.

Flowie utilizes configuration as code using JavaScript/TypeScript to define it.

Configuration is defined via Flowie settings pages, which can be accessed from the repository or workspace settings.

A typical configuration looks like this:

ts
import {configure} from "flowie.app"
 
import {
merge,
draftPullRequest,
noChangesRequested,
noUnresolvedTasks,
minimumBuilds,
minimumApprovals,
} from "flowie.app/plugins"
 
configure({
plugins: [
merge({
allow: ["Team leaders"],
}),
draftPullRequest(),
// Basic checks
noChangesRequested(),
noUnresolvedTasks(),
minimumBuilds(1),
minimumApprovals(2),
],
})

Scopes

The configurations can be defined at repository level or workspace level. The workspace configuration is inherited by all repositories in the workspace, and can be overridden by the repository configuration.

Plugins

Plugins are defined using the plugins property. They provide high level and common workflows by leveraging Flowie functionalities such as labels and checks combined.

Check the Plugins section of the documentation to find more about the plugins available.

Rules and conditions

Rules and conditions allow you to define different configurations based on the context of the pull request.

Examples:

  • Define a condition to use a different plugin configuration based on the target branch.
ts
import {configure} from "flowie.app"
import {draftPullRequest} from "flowie.app/plugins"
import {target} from "flowie.app/conditions"
 
configure({
plugins: [
// run only when target is main, using plugin default options
draftPullRequest([target("main")]),
],
})
  • Run with different options for different branches.
ts
import {configure} from "flowie.app"
import {draftPullRequest} from "flowie.app/plugins"
import {target} from "flowie.app/conditions"
 
configure({
plugins: [
draftPullRequest(
[target("main"), {draftOnCreate: true}],
[target(/feature.*/), {draftOnCreate: false}]
),
],
})
  • With a catch-all clause.
ts
import {configure} from "flowie.app"
import {draftPullRequest} from "flowie.app/plugins"
import {target, otherwise} from "flowie.app/conditions"
 
configure({
plugins: [
draftPullRequest(
[target("main"), {draftOnCreate: true}],
[target(/feature.*/), {draftOnCreate: false}],
[otherwise, {draftOnCreate: false, title: "A different title"}]
),
],
})

Rules

A Rule is a tuple that defines a Condition and a configuration value for the plugin, which is used when the condition is matched. You can define multiple rules for the same plugin; if no rule is matched, the plugin will not be applied.

A rule is defined as follows:

[condition, configuration]

multiple rules use the following syntax:

[condition, configuration], [condition, configuration], ...

if the plugin has a default configuration, you can omit it:

[condition], [condition, configuration], ...

ts
import {configure} from "flowie.app"
import {draftPullRequest} from "flowie.app/plugins"
import {target} from "flowie.app/conditions"
 
configure({
plugins: [
draftPullRequest(
// Condition Configuration
// | |
// v v
[target("main"), {draftOnCreate: true}], // <-------- Rule 1
[target(/feature.*/), {draftOnCreate: false}] // <--- Rule 2
/*... more rules...
^--- If none of the conditions are matched,
the plugin will not be applied.
*/
),
],
})

Conditions

Condition is a function that takes a context and returns a value. The most common conditions are built-in and can be imported from flowie.app/conditions.

Combining conditions

You can combine conditions logically:

ts
import {labels, target, source, not} from "flowie.app/conditions"
 
labels.has("Ready to merge").and(target("main"))
labels.has("Ready to merge").or(source("main"))
labels.hasAny("Ready to merge", "WIP").and.not(target("main"))
 
// Reuse
const readyMain = labels.has("Ready to merge").and(target("main"))
 
// Negation
not(labels.has("Ready to merge"))
not(readyMain)

Branch restrictions

The branch.restrictions property allows customizing or disabling the branch permissions managed by Flowie in order to implement some of its features.

By default, when restrictions are enabled, Flowie will protect branches based on the branching model defined on Bitbucket. It will protect production, main and release branches, by only allowing pull request merge through Flowie, and no write, push, create, rewrite or delete. It also removes any extraneous configuration.

If you wish to keep other branch restrictions, or modify the default behavior your can use branch.restrictions:

ts
import {configure} from "flowie.app"
 
configure({
branches: {
restrictions: {
/*
It accepts a branch pattern or the branch types from the
branching model that are prefixed: release, feature,
hotfix and bugfix
*/
"main": {
// Let CI group write to the branch
pushGroups: ["CI"],
},
"release": {
// Alternatively, use "Everybody" special value to allow any user
// with write access
pushGroups: "Everybody",
},
"feature": {
// Enable reset for changes
resetRequestedChanges: true,
// Premium Bitbucket only features
// resetApprovals: true
// resetApprovalsKeepIfNoChanges: true
},
// A custom rule, outside the branching model
"my-branch-prefix/*": {
pushGroups: ["Developers"],
allowDeleting: true,
allowRewriting: true,
},
},
},
})

Or can completely disable it by setting restrictions to false.

Create branches

Typically, you will want to allow admins or scripts to create new branches under protected prefixes. For instance, creating new releases.

ts
import {configure} from "flowie.app"
 
configure({
branches: {
restrictions: {
release: {
// Give permission to the Administrators group
// to create new branches, e.g.,
// release/1.0, release/2.0, and so on.
pushGroups: ["Administrators", "CI"],
},
},
},
})

Editor support

The script setting pages have support for auto-completion and validation using the Monaco editor. This is the same editor used in VS Code. Learn more about the editor features here.

Editor example

Why JavaScript?

Instead of inventing a new configuration language, Flowie leverages JavaScript/TypeScript to configure the workflow. This allows you to use the full power of a programming language to configure your workflow, which is especially useful for complex workflows and when using conditionals. Also, it can re-use all the tooling and knowledge already available.

This is a similar concept of tools like AWS CDK, Pulumi and CDK for Terraform.

You are not required to know JavaScript, as most of the configurations should be really simple, however, if you require mode advanced or custom configurations, you will probably benefit from it.