- Install Go
brew install go(on macOS) - Install the latest Bitrise CLI - it's a single binary command line tool
- Run
bitrise setupjust to be sure everything's prepared cdinto a directory where you have yourbitrise.yml, and run:bitrise :workflow-editor
That's all. The Workflow Editor is now part of the Bitrise CLI core plugins, so you don't have to install it manually.
To upgrade to the latest version of the Workflow Editor run:
bitrise plugin update workflow-editor
Join the Workflow Editor's discussion at: https://discuss.bitrise.io/t/workflow-editor-v2-open-source-offline-workflow-editor/39
The client is a Vite build and needs node and npm. The local executable is written in Go, so you need a Go
toolchain too. One command installs both sides' dependencies and builds them:
bitrise run setupgo install
npm start # start both the local plugin api and the Vite dev server- In your browser, you can reach the Workflow Editor on
localhost:4000/{version}. Be aware that you usually have to wait a while until dev server starts up (then refresh) - By default, the Workflow Editor will open the
test_bitrise.ymlfrom integration folder (used for integration testing). Please do not commit this file if you have any changes with it (e2e tests would fail).
If you would like to run the Workflow Editor in website mode, you have to run the dedicated npm command:
npm run start:website # starts WFE in website modeYou also have to make sure that the Monolith is already running before you try to execute the command above (otherwise
every request to http://localhost:3000 will be handled by the WFE).
start:website defaults to PUBLIC_URL_ROOT=/workflow_editor, so the HTML emits asset URLs that route through the
monolith's /workflow_editor/* asset proxy. Point the monolith at your local WFE by setting the env var below (no
controller-source edits needed):
- if you run the monolith directly (umbrella repo):
BITRISE_WORKFLOW_EDITOR_URL=http://localhost:4000/workflow_editor - if you run the monolith in docker (
web-dev-env):BITRISE_WORKFLOW_EDITOR_URL=http://host.docker.internal:4000/workflow_editor(orhttp://workflow-editor:4000/workflow_editorwhen both run on the same compose network)
Once the above is set, the Workflow Editor is reachable in the monolith
on localhost:3000/app/{slug}/workflow_editor.
If you want the browser to fetch assets directly from the WFE dev server (skipping the monolith proxy — faster, but only works when the browser is on the same host as Vite, so not for remote dev boxes), override the prefix:
PUBLIC_URL_ROOT=http://localhost:4000 npm run start:websiteIn that case set BITRISE_WORKFLOW_EDITOR_URL=http://localhost:4000 (no trailing path) in the monolith.
If you pull/rebase across a release commit (one that bumps the version in both package.json and
version/version.go), restart the WFE — don't just rely on Vite's hot-reload. Vite picks up the new version from
package.json and starts serving at the new /{version}/ path, but go run main.go keeps running its already-compiled
binary with the old version.VERSION constant. The two then disagree on the route prefix and requests 404 (which
surfaces in the monolith as OpenURI::HTTPError 404 from WorkflowController#content).
npm test # Jest unit tests
npm test -- --testPathPattern="path/to" # a subset
npm run storybook # component workshop on :6006
npx tsc --noEmit # nothing else type-checks, including CIJest runs in the node environment by default; a test that renders a hook or a component needs an
@jest-environment jsdom docblock at the top of the file.
npm run test:smoke is a post-deploy Playwright check, not a local one. It signs into a deployed app and needs
SMOKE_TEST_APP_ID, SMOKE_TEST_USER_NAME, SMOKE_TEST_USER_PASSWORD and NPM_PACKAGE_VERSION.
You can create an ld.local.json file in the project root to override the LaunchDarkly flags.
Example ld.local.json content:
{
"enable-nice-feature": true,
"key-of-the-feature-flag": "local value of the feature flag"
}This project is using squash & merge model, feel free to have as many commits as you like but at the end the work will end up on master as a single commit.
- TypeScript and React throughout. The AngularJS migration finished in May 2025 and there is no legacy tier left.
- New UI work uses
@bitrise/bitkit-v2(Chakra v3).@bitrise/bitkit(Chakra v2) is legacy — port v1 components to v2 in any file you already touch. - Nothing type-checks unless you run
npx tsc --noEmit, so run it before calling a typed change done. - Four ESLint rules encode architectural boundaries rather than style. If
npm run lintfails onno-restricted-syntaxorno-restricted-imports, you crossed a boundary — see CLAUDE.md.
Working on this codebase with an AI agent? CLAUDE.md is the entry point, and docs/decisions.md explains the parts that look odd on purpose.
- Unit tests are required for every new feature
- Consider writing React Testing Library component tests
- Services get a YAML round-trip test: seed the store, call the service, compare the emitted YAML.
Every master commit is released to an S3 bucket and Bitrise will integrate it with the website manually (CD is planned
when test coverage and confidence is increasing with the editor). If you wanna do a plugin release as well you need to
tag the PRs with #plugin wherever in the PR title (like: "new feature #plugin").
If new release requires Bitrise CLI to be updated, in bitrise-plugin.yml change min_version requirement of
the bitrise tool to the required CLI version.
- In bitrise.yml, create a workflow e. g.
test-release - From the
create-releaseworkflow, copy-paste the GitHub release and Create Discuss topic steps. - In the GitHub release step, remove the
files_to_uploadinput, set the$NEW_RELEASE_VERSIONeverywhere to something arbitrary, same for thebody, and most importantly setdraft: 'yes' - In the Create Discuss topic step, change the
DISCUSS_CHANGELOG_CATEGORY_IDto the ID of one our discuss.bitrise.io's internal channels' ID (you can find an ID using the Discourse API with a cURL request) so that it is only visible to us; also change thetitleand therawparameter to something arbitrary. - After the test release process, don't forget to delete the draft release and the internal changelog topic.