ci: add Bitbucket Pipelines mirror of the GitLab release pipeline#55
Conversation
Adds bitbucket-pipelines.yml as a third implementation of ci/pipeline.yml, deep-mirroring .gitlab-ci.yml via the same provider-neutral ci/scripts/*.mjs: - CI layer (push/PR): parallel validate (lint, compliance, non-blocking audit, gitleaks secret-scan) -> build -> xvfb Electron smoke test. - Release layer (v* tags): package:linux (dist + CycloneDX SBOM + verify-signing, per-OS artifact staging) -> secure (SHA256SUMS) -> release-notes -> GitHub Release CO-PUBLISH (pinned gh CLI, idempotent create-or-clobber, --prerelease on hyphen tags) -> optional token-guarded Bitbucket Downloads upload. - custom: manual dry-run (package+secure, no publish) and sync-github (--force-with-lease only, per-invocation http.extraheader). Shared scripts now also resolve Bitbucket's env (BITBUCKET_TAG / BITBUCKET_COMMIT) alongside GitLab/GitHub, and check-manifest link-checks the new docs/ci/bitbucket-pipelines.md guide. GitLab remains the single source of truth and sole GitLab-Release publisher; secrets stay in SECURED repository variables (GITHUB_TOKEN, optional BITBUCKET_ACCESS_TOKEN) — never in YAML. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Review Summary
This PR successfully adds Bitbucket Pipelines as a third CI/CD implementation, maintaining consistency with the existing GitLab and GitHub Actions setup. The implementation follows the canonical pipeline specification and properly handles provider-specific environment variables.
Critical Issue Found
One security vulnerability was identified that must be fixed before merge:
- Line 282 in bitbucket-pipelines.yml: The use of
printfwith the GitHub token exposes it in process listings. Replace withecho -npiped to base64 to avoid this exposure.
Strengths
- Consistent implementation across all three CI providers using shared scripts
- Proper documentation added (bitbucket-pipelines.md)
- Correct environment variable handling for Bitbucket (
BITBUCKET_TAG,BITBUCKET_COMMIT) - Security-conscious design with secured variables and
--force-with-lease - Idempotent release co-publishing logic
Recommendations
Address the security issue in line 282, then this PR is ready to merge.
You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.
| - | | ||
| set -eu | ||
| : "${GITHUB_TOKEN:?GITHUB_TOKEN must be set as a SECURED repository variable}" | ||
| AUTH="Authorization: Basic $(printf 'x-access-token:%s' "$GITHUB_TOKEN" | base64 -w0)" |
There was a problem hiding this comment.
🛑 Security Vulnerability: The GitHub token is exposed in the command string during base64 encoding, which could leak it into process listings, logs, or shell history. Use a safer method that avoids command substitution with the token.1
| AUTH="Authorization: Basic $(printf 'x-access-token:%s' "$GITHUB_TOKEN" | base64 -w0)" | |
| AUTH="Authorization: Basic $(echo -n "x-access-token:$GITHUB_TOKEN" | base64 -w0)" |
Footnotes
-
CWE-200: Exposure of Sensitive Information to an Unauthorized Actor - https://cwe.mitre.org/data/definitions/200.html ↩
📝 WalkthroughWalkthroughAdds a new Bitbucket Pipelines configuration mirroring the existing GitLab CI pipeline, updates provider-neutral CI scripts (apply-tag-version, check-manifest, check-tag-unique) to recognize Bitbucket environment variables, and updates CLAUDE.md, ci/pipeline.yml, and docs/ci to document Bitbucket support. ChangesBitbucket Pipelines Integration
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
bitbucket-pipelines.yml (1)
78-78: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winPin the mutable CI inputs here.
zricethezav/gitleaks:latest,curlimages/curl:latest,npx --yes@cyclonedx/cyclonedx-npm``, and theghtarball download all depend on mutable upstream artifacts. Pin image digests/package versions and verify the archive before these release-adjacent steps run.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@bitbucket-pipelines.yml` at line 78, The CI job currently uses mutable upstream inputs, so pin the external artifacts used by the pipeline step: replace the `zricethezav/gitleaks:latest` image in the bitbucket pipeline, and also lock down the related `curlimages/curl:latest`, `npx --yes `@cyclonedx/cyclonedx-npm``, and `gh` tarball download references elsewhere in the pipeline. Update the affected pipeline definitions and scripts to use fixed digests or versions, and add archive verification for the downloaded release artifacts before the release-adjacent steps execute.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@bitbucket-pipelines.yml`:
- Around line 146-151: The release staging step in the pipeline is swallowing
missing-artifact/copy failures, which can leave dist/ empty before checksums and
signing run. Update the shell block that creates dist and copies from
artifacts/*/* so it fails fast when no installers are staged or the copy fails,
then only proceed to make-checksums.mjs and verify-signing.mjs after a
successful copy; use the existing dist staging step as the place to enforce
this.
- Around line 285-288: The push step in the Bitbucket pipeline currently falls
back to main when BITBUCKET_BRANCH is unset, which can send a detached HEAD to
the GitHub main branch. Update the branch resolution logic in the push block to
require an explicit branch context and fail fast with a clear error if
BITBUCKET_BRANCH is empty, then use that validated branch for the git push in
the pipeline step that performs the github remote push.
In `@docs/ci/README.md`:
- Around line 5-9: The README wording in the CI overview overstates artifact
parity across GitLab CI, GitHub Actions, and Bitbucket Pipelines; update the
description in the CI intro to qualify that only the shared validate/build/test
logic is identical, or explicitly note that Bitbucket’s release packaging
artifacts differ. Use the existing CI overview paragraph and the references to
ci/scripts as the place to adjust the claim so it stays accurate without
implying all providers produce identical artifacts.
---
Nitpick comments:
In `@bitbucket-pipelines.yml`:
- Line 78: The CI job currently uses mutable upstream inputs, so pin the
external artifacts used by the pipeline step: replace the
`zricethezav/gitleaks:latest` image in the bitbucket pipeline, and also lock
down the related `curlimages/curl:latest`, `npx --yes `@cyclonedx/cyclonedx-npm``,
and `gh` tarball download references elsewhere in the pipeline. Update the
affected pipeline definitions and scripts to use fixed digests or versions, and
add archive verification for the downloaded release artifacts before the
release-adjacent steps execute.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0decb323-75e5-4557-8615-b74c990732b1
📒 Files selected for processing (8)
CLAUDE.mdbitbucket-pipelines.ymlci/pipeline.ymlci/scripts/apply-tag-version.mjsci/scripts/check-manifest.mjsci/scripts/check-tag-unique.mjsdocs/ci/README.mddocs/ci/bitbucket-pipelines.md
| - | | ||
| mkdir -p dist | ||
| cp -r artifacts/*/* dist/ 2>/dev/null || true | ||
| ls -la dist | ||
| - node ci/scripts/make-checksums.mjs dist dist/SHA256SUMS | ||
| - node ci/scripts/verify-signing.mjs dist |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Fail before checksumming an empty release payload.
Line 148 masks missing artifacts and copy errors, so dist/ can be checksummed/signed without the staged installers.
Proposed fix
mkdir -p dist
- cp -r artifacts/*/* dist/ 2>/dev/null || true
+ if [ ! -d artifacts ] || ! find artifacts -mindepth 2 -maxdepth 2 -type f -print -quit | grep -q .; then
+ echo "[secure] no staged artifacts found under artifacts/*/*"
+ exit 1
+ fi
+ find artifacts -mindepth 2 -maxdepth 2 -type f -exec cp {} dist/ \;
ls -la dist📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - | | |
| mkdir -p dist | |
| cp -r artifacts/*/* dist/ 2>/dev/null || true | |
| ls -la dist | |
| - node ci/scripts/make-checksums.mjs dist dist/SHA256SUMS | |
| - node ci/scripts/verify-signing.mjs dist | |
| - | | |
| mkdir -p dist | |
| if [ ! -d artifacts ] || ! find artifacts -mindepth 2 -maxdepth 2 -type f -print -quit | grep -q .; then | |
| echo "[secure] no staged artifacts found under artifacts/*/*" | |
| exit 1 | |
| fi | |
| find artifacts -mindepth 2 -maxdepth 2 -type f -exec cp {} dist/ \; | |
| ls -la dist | |
| - node ci/scripts/make-checksums.mjs dist dist/SHA256SUMS | |
| - node ci/scripts/verify-signing.mjs dist |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@bitbucket-pipelines.yml` around lines 146 - 151, The release staging step in
the pipeline is swallowing missing-artifact/copy failures, which can leave dist/
empty before checksums and signing run. Update the shell block that creates dist
and copies from artifacts/*/* so it fails fast when no installers are staged or
the copy fails, then only proceed to make-checksums.mjs and verify-signing.mjs
after a successful copy; use the existing dist staging step as the place to
enforce this.
| BRANCH="${BITBUCKET_BRANCH:-main}" | ||
| echo "Pushing HEAD -> github/$BRANCH (--force-with-lease) + tags" | ||
| git -c http.extraheader="$AUTH" push --force-with-lease github "HEAD:refs/heads/$BRANCH" | ||
| git -c http.extraheader="$AUTH" push github --tags |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the relevant section of the pipeline file
nl -ba bitbucket-pipelines.yml | sed -n '250,320p'
# Find the sync step and any branch/tag gating around it
rg -n -C 3 'sync-github|BITBUCKET_BRANCH|BITBUCKET_TAG|tags:|branches:' bitbucket-pipelines.ymlRepository: BotCoder254/limboo
Length of output: 196
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Read the relevant section with line numbers using awk
awk 'NR>=250 && NR<=320 { printf "%d:%s\n", NR, $0 }' bitbucket-pipelines.yml
# Search for the sync step and any branch/tag gating
rg -n -C 3 'sync-github|BITBUCKET_BRANCH|BITBUCKET_TAG|tags:|branches:' bitbucket-pipelines.ymlRepository: BotCoder254/limboo
Length of output: 5744
🌐 Web query:
Bitbucket Pipelines custom pipeline BITBUCKET_BRANCH BITBUCKET_TAG manual pipeline branch context documentation
💡 Result:
In Bitbucket Pipelines, the behavior of BITBUCKET_BRANCH and BITBUCKET_TAG environment variables in custom pipelines depends on how the pipeline is manually triggered [1]. When you run a custom pipeline from the Bitbucket Cloud interface, you typically select a branch or tag from which to trigger the build [2][1]. If you trigger the custom pipeline while viewing a specific branch, the BITBUCKET_BRANCH variable will be correctly populated with that branch name [1]. However, if you trigger a custom pipeline from a specific commit (e.g., via the Commits page) rather than from a branch or tag reference, the pipeline runs in a detached HEAD state [1][3]. In this context, both BITBUCKET_BRANCH and BITBUCKET_TAG will be null or empty, as the pipeline lacks an explicit association with a branch or tag ref [1][3]. Key points regarding manual/custom pipelines: - Definition: Custom pipelines are defined in the custom section of your bitbucket-pipelines.yml file and are designed to be triggered manually from the Bitbucket UI [2][4]. - Triggering: You can select the target branch or tag when initiating a manual run from the UI [1]. - Variables: If you require specific context, you can also define custom variables under your pipeline definition [2][5]. These allow you to supply single-use values at runtime, which are then available as environment variables within the pipeline steps [2][5][6]. - Limitations: Because they do not automatically run on every push, custom pipelines do not inherently match branch or tag definitions unless explicitly invoked for those references [2][4]. If you need to restrict a pipeline to only run on specific branches, it is often recommended to use standard branch-specific pipelines instead of or in addition to custom ones [4][7]. To handle cases where the context is missing (such as running from a commit), some users override these variables manually within the pipeline script by using commands like git branch to identify the current branch associated with the commit [3].
Citations:
- 1: https://community.atlassian.com/forums/Bitbucket-questions/BITBUCKET-BRANCH-Variable-in-Custom-Pipelines/qaq-p/2087590
- 2: https://support.atlassian.com/bitbucket-cloud/docs/pipeline-triggers/
- 3: https://support.atlassian.com/bitbucket-cloud/kb/bitbucket-cloud-default-environment-variable-bitbucket_branch-value-is-null-while-triggering-a-build-on-commits-view-page/
- 4: https://support.atlassian.com/bitbucket-cloud/docs/pipeline-start-conditions/
- 5: https://www.atlassian.com/blog/bitbucket/adding-human-interaction-back-into-automated-builds
- 6: https://community.atlassian.com/forums/Bitbucket-questions/Edit-env-vars-when-manually-triggering-pipelines/qaq-p/1812560
- 7: https://stackoverflow.com/questions/79043879/can-i-restrict-a-bitbucket-manual-custom-pipeline-to-a-specific-branch
Require an explicit branch context here. BITBUCKET_BRANCH can be empty in a manually triggered custom pipeline from a commit view, and the main fallback can push a detached HEAD to GitHub main. Fail fast unless a branch is present. bitbucket-pipelines.yml:285-287
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@bitbucket-pipelines.yml` around lines 285 - 288, The push step in the
Bitbucket pipeline currently falls back to main when BITBUCKET_BRANCH is unset,
which can send a detached HEAD to the GitHub main branch. Update the branch
resolution logic in the push block to require an explicit branch context and
fail fast with a clear error if BITBUCKET_BRANCH is empty, then use that
validated branch for the git push in the pipeline step that performs the github
remote push.
| three providers — GitLab CI, GitHub Actions, and Bitbucket Pipelines — so an | ||
| organization can adopt whichever CI it already runs without changing Limboo's | ||
| development workflow. All three execute the same stages in the same order and | ||
| produce the same artifacts, because the actual logic lives in provider-neutral | ||
| scripts under [`ci/scripts/`](../../ci/scripts) rather than in YAML. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Qualify the artifact-parity claim.
Bitbucket is documented elsewhere as Linux-only for release packaging, so saying all three providers “produce the same artifacts” is inaccurate. Limit this to shared validate/build/test logic, or note that Bitbucket’s release artifacts differ.
♻️ Suggested wording
- three providers — GitLab CI, GitHub Actions, and Bitbucket Pipelines — so an
- organization can adopt whichever CI it already runs without changing Limboo's
- development workflow. All three execute the same stages in the same order and
- produce the same artifacts, because the actual logic lives in provider-neutral
- scripts under [`ci/scripts/`](../../ci/scripts) rather than in YAML.
+ three providers — GitLab CI, GitHub Actions, and Bitbucket Pipelines — so an
+ organization can adopt whichever CI it already runs without changing Limboo's
+ development workflow. All three execute the same validate/build/test stages in
+ the same order via provider-neutral scripts under [`ci/scripts/`](../../ci/scripts).
+ Bitbucket's release path is Linux-only, so its release artifacts differ.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| three providers — GitLab CI, GitHub Actions, and Bitbucket Pipelines — so an | |
| organization can adopt whichever CI it already runs without changing Limboo's | |
| development workflow. All three execute the same stages in the same order and | |
| produce the same artifacts, because the actual logic lives in provider-neutral | |
| scripts under [`ci/scripts/`](../../ci/scripts) rather than in YAML. | |
| three providers — GitLab CI, GitHub Actions, and Bitbucket Pipelines — so an | |
| organization can adopt whichever CI it already runs without changing Limboo's | |
| development workflow. All three execute the same validate/build/test stages in | |
| the same order via provider-neutral scripts under [`ci/scripts/`](../../ci/scripts). | |
| Bitbucket's release path is Linux-only, so its release artifacts differ. |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/ci/README.md` around lines 5 - 9, The README wording in the CI overview
overstates artifact parity across GitLab CI, GitHub Actions, and Bitbucket
Pipelines; update the description in the CI intro to qualify that only the
shared validate/build/test logic is identical, or explicitly note that
Bitbucket’s release packaging artifacts differ. Use the existing CI overview
paragraph and the references to ci/scripts as the place to adjust the claim so
it stays accurate without implying all providers produce identical artifacts.
Summary
Adds Bitbucket Pipelines (
bitbucket-pipelines.yml) as the third implementation of the canonical pipeline (ci/pipeline.yml), a deep mirror of the primary GitLab pipeline running the same stages via the same provider-neutralci/scripts/*.mjs:validate(lint, compliance incl. tag-unique guard, non-blocking audit, gitleaks secret-scan) →build(renderer + forge package) →test(xvfb Electron smoke test, same GTK/ATK/CUPS/ALSA + t64 fallback set as GitLab).v*tags):package-linux(npm run dist, CycloneDX SBOM, verify-signing, stagedartifacts/linux/) →secure(SHA256SUMS) →release-notes→ GitHub Release co-publish (pinned gh CLI 2.95.0, idempotent create-or---clobber,--prereleaseon hyphen tags,latest*.yml+ blockmaps attached for electron-updater) → optional token-guarded Bitbucket Downloads upload.dry-run(package + secure, no publish) andsync-github(--force-with-leaseonly, per-invocationhttp.extraheader, token never written to.git/config).Supporting changes
apply-tag-version.mjs/check-tag-unique.mjs/check-manifest.mjsnow also resolve Bitbucket'sBITBUCKET_TAG/BITBUCKET_COMMITenv (additive; GitLab/GitHub detection unchanged) — versioning stays tag-driven.docs/ci/bitbucket-pipelines.md; linked fromdocs/ci/README.mdand link-checked bycheck-manifest.mjs.ci/pipeline.yml+CLAUDE.mdupdated to document the third provider.Invariants preserved
v*tag both release jobs are idempotent and GitLab's all-OS build normally finishes last and stays authoritative.GITHUB_TOKEN— already configured; optionalBITBUCKET_ACCESS_TOKEN), never in YAML;--force-with-leaseonly; no app/UI code touched.Verification
npm run lintclean;node ci/scripts/check-manifest.mjsgreen (incl. new docs link check);BITBUCKET_TAG=v9.9.9resolver dry-run stamps and restores cleanly; YAML parse-checked.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes