Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: CI

on:
push:
branches: [ main, dev ]
pull_request:
branches: [ main ]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.23.1'

- name: Cache Go modules
uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-

- name: Install dependencies
run: go mod download

- name: Run tests
run: go test -v ./...

- name: Run go vet
run: go vet ./...

- name: Run go fmt check
run: |
if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then
echo "Code is not formatted properly"
gofmt -s -l .
exit 1
fi
229 changes: 229 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
# .github/workflows/release.yml - 自动发布 (基于VERSION文件)
name: Auto Release

on:
push:
branches: [ main ] # 当PR合并到main时触发

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # 获取完整历史,用于生成changelog

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.23.1'

- name: Check VERSION file and determine release
id: version
run: |
# 检查VERSION文件是否存在
if [ ! -f "VERSION" ]; then
echo "❌ VERSION file not found!"
echo "Please create a VERSION file in the root directory with format: 1.0.0"
exit 1
fi

# 读取VERSION文件内容
CURRENT_VERSION=$(cat VERSION | tr -d '[:space:]')
echo "Version in file: $CURRENT_VERSION"

# 验证版本格式 (x.y.z)
if ! echo "$CURRENT_VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+
Copy link

Copilot AI May 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The grep pattern for version validation is incomplete and missing the closing delimiter; please complete the regular expression to properly match the x.y.z pattern.

Suggested change
if ! echo "$CURRENT_VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+
if ! echo "$CURRENT_VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then

Copilot uses AI. Check for mistakes.

- name: Build binaries
if: steps.version.outputs.skip_release != 'true'
run: |
VERSION=${{ steps.version.outputs.current_version }}
mkdir -p dist

# 构建不同平台的二进制文件
platforms=("linux/amd64" "linux/arm64" "windows/amd64" "darwin/amd64" "darwin/arm64")

for platform in "${platforms[@]}"; do
platform_split=(${platform//\// })
GOOS=${platform_split[0]}
GOARCH=${platform_split[1]}

output_name="bamboo-exporter-v${VERSION}-${GOOS}-${GOARCH}"
if [ $GOOS = "windows" ]; then
output_name+='.exe'
fi

echo "Building for $GOOS/$GOARCH..."
env CGO_ENABLED=0 GOOS=$GOOS GOARCH=$GOARCH go build \
-ldflags="-s -w -X main.version=v${VERSION}" \
-o dist/$output_name .

# 创建压缩包
cd dist
if [ $GOOS = "windows" ]; then
zip ${output_name%.exe}.zip $output_name
rm $output_name
else
tar -czf ${output_name}.tar.gz $output_name
rm $output_name
fi
cd ..
done

- name: Create Release
if: steps.version.outputs.skip_release != 'true'
uses: actions/create-release@v1
id: create_release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.version.outputs.new_version }}
release_name: Release ${{ steps.version.outputs.new_version }}
body: |
## 🚀 What's New

${{ steps.version.outputs.changelog }}

## 📦 Download

选择适合你平台的二进制文件下载:
- **Linux (x64)**: `bamboo-exporter-${{ steps.version.outputs.new_version }}-linux-amd64.tar.gz`
- **Linux (ARM64)**: `bamboo-exporter-${{ steps.version.outputs.new_version }}-linux-arm64.tar.gz`
- **Windows (x64)**: `bamboo-exporter-${{ steps.version.outputs.new_version }}-windows-amd64.zip`
- **macOS (Intel)**: `bamboo-exporter-${{ steps.version.outputs.new_version }}-darwin-amd64.tar.gz`
- **macOS (Apple Silicon)**: `bamboo-exporter-${{ steps.version.outputs.new_version }}-darwin-arm64.tar.gz`
draft: false
prerelease: false

- name: Upload Release Assets
if: steps.version.outputs.skip_release != 'true'
run: |
upload_url="${{ steps.create_release.outputs.upload_url }}"

for file in dist/*; do
filename=$(basename "$file")
echo "Uploading $filename..."
curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Content-Type: application/octet-stream" \
--data-binary @"$file" \
"${upload_url%{?name,label}*}?name=$filename"
done; then
echo "❌ Invalid version format in VERSION file: $CURRENT_VERSION"
echo "Expected format: x.y.z (e.g., 1.0.0)"
exit 1
Comment on lines +111 to +114
Copy link

Copilot AI May 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The syntax 'done; then' appears to be erroneous in the shell script; remove or adjust it so that the conditional structure is correctly formed.

Suggested change
done; then
echo "❌ Invalid version format in VERSION file: $CURRENT_VERSION"
echo "Expected format: x.y.z (e.g., 1.0.0)"
exit 1
done

Copilot uses AI. Check for mistakes.
fi

# 添加v前缀
NEW_VERSION="v${CURRENT_VERSION}"

# 获取最后一个tag
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
echo "Last release tag: $LAST_TAG"
echo "New version: $NEW_VERSION"

# 检查版本是否有变化
if [ "$NEW_VERSION" = "$LAST_TAG" ]; then
echo "✅ Version $NEW_VERSION already released, skipping..."
echo "skip_release=true" >> $GITHUB_OUTPUT
exit 0
fi

# 检查版本是否比上一个版本新
if [ "$LAST_TAG" != "v0.0.0" ]; then
LAST_VERSION=$(echo $LAST_TAG | sed 's/v//')
if ! printf '%s\n%s\n' "$LAST_VERSION" "$CURRENT_VERSION" | sort -V -C; then
echo "⚠️ Warning: New version $CURRENT_VERSION is not higher than last version $LAST_VERSION"
echo "This might indicate a version rollback or incorrect versioning"
fi
fi

echo "✅ Version changed from $LAST_TAG to $NEW_VERSION, creating release..."
echo "new_version=${NEW_VERSION}" >> $GITHUB_OUTPUT
echo "current_version=${CURRENT_VERSION}" >> $GITHUB_OUTPUT

# 生成changelog (从上个tag到现在的提交)
if [ "$LAST_TAG" = "v0.0.0" ]; then
CHANGELOG=$(git log --pretty=format:"- %s (%h)" --reverse HEAD)
else
CHANGELOG=$(git log ${LAST_TAG}..HEAD --pretty=format:"- %s (%h)" --reverse)
fi

echo "changelog<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGELOG" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

- name: Build binaries
if: steps.version.outputs.skip_release != 'true'
run: |
VERSION=${{ steps.version.outputs.new_version }}
mkdir -p dist

# 构建不同平台的二进制文件
platforms=("linux/amd64" "linux/arm64" "windows/amd64" "darwin/amd64" "darwin/arm64")

for platform in "${platforms[@]}"; do
platform_split=(${platform//\// })
GOOS=${platform_split[0]}
GOARCH=${platform_split[1]}

output_name="bamboo-exporter-${VERSION}-${GOOS}-${GOARCH}"
if [ $GOOS = "windows" ]; then
output_name+='.exe'
fi

echo "Building for $GOOS/$GOARCH..."
env CGO_ENABLED=0 GOOS=$GOOS GOARCH=$GOARCH go build \
-ldflags="-s -w -X main.version=${VERSION}" \
-o dist/$output_name .

# 创建压缩包
cd dist
if [ $GOOS = "windows" ]; then
zip ${output_name%.exe}.zip $output_name
rm $output_name
else
tar -czf ${output_name}.tar.gz $output_name
rm $output_name
fi
cd ..
done

- name: Create Release
if: steps.version.outputs.skip_release != 'true'
uses: actions/create-release@v1
id: create_release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.version.outputs.new_version }}
release_name: Release ${{ steps.version.outputs.new_version }}
body: |
## 🚀 What's New

${{ steps.version.outputs.changelog }}

## 📦 Download

选择适合你平台的二进制文件下载:
- **Linux (x64)**: `bamboo-exporter-${{ steps.version.outputs.new_version }}-linux-amd64.tar.gz`
- **Linux (ARM64)**: `bamboo-exporter-${{ steps.version.outputs.new_version }}-linux-arm64.tar.gz`
- **Windows (x64)**: `bamboo-exporter-${{ steps.version.outputs.new_version }}-windows-amd64.zip`
- **macOS (Intel)**: `bamboo-exporter-${{ steps.version.outputs.new_version }}-darwin-amd64.tar.gz`
- **macOS (Apple Silicon)**: `bamboo-exporter-${{ steps.version.outputs.new_version }}-darwin-arm64.tar.gz`
draft: false
prerelease: false

- name: Upload Release Assets
if: steps.version.outputs.skip_release != 'true'
run: |
upload_url="${{ steps.create_release.outputs.upload_url }}"

for file in dist/*; do
filename=$(basename "$file")
echo "Uploading $filename..."
curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Content-Type: application/octet-stream" \
--data-binary @"$file" \
"${upload_url%{?name,label}*}?name=$filename"
done
File renamed without changes.
76 changes: 76 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,78 @@
# bamboo-prometheus-exporter

Bamboo-prometheus-exporter is a tool that scrapes metrics from Atlassian Bamboo and exposes them for Prometheus monitoring, enabling detailed CI/CD pipeline observability.

## Features
- **Agent Monitoring**
Track agent status (enabled/active/busy) with labels including ID, name, and type
- **Build Queue Analytics**
Monitor queue size changes and agent utilization rates in real-time
- **Project Build Metrics**
Capture success/failure counts. Capture total builds per project-plan combination
- **Dynamic Labeling**
Auto-split plan.name into project and name labels (e.g., XXXX Releases - PB-XXXX-21.2 → project="XXXX Releases", name="PB-XXXX-21.2")

## Installation

### Binary
```bash
go install github.com/EIETS/bamboo_exporter@latest
./bamboo_exporter \
--bamboo.uri="http://bamboo.example.com" \
--web.listen-address=":9117"
```

### Docker
```bash
docker run -d -p 9117:9117 -v ./config.json:/app/config.json eitets/bamboo_exporter \
--bamboo.uri="https://bamboo.example.com" \
--insecure
```

## Configuration
### Flags
| Parameter | Default | Description |
|:-----------------------|:------------------------|:-------------------------|
| --telemetry.endpoint | /metrics | Metrics exposure path |
| --bamboo.uri | http://localhost:8085 | Bamboo server URL |
| --insecure | false | Disable SSL verification |
| --web.listen-address | :9117 | Exporter listening port |

### Authentication
Create config.json:
```json
{
"bamboo_username": "admin",
"bamboo_password": "secure_password"
}
```

### Exported Metrics
| Metric Name | Type | Labels | Description |
|:-----------------------------|:--------|:--------------------------------------|:--------------------------------------|
| bamboo_agents_status | Gauge | id, name, type, enabled, active, busy | Agent operational states |
| bamboo_queue_size | Gauge | - | Current build queue count |
| bamboo_queue_change | Gauge | - | Queue size delta since last scrape |
| bamboo_agent_utilization | Gauge | - | Busy/active agent ratio |
| bamboo_build_success_total | Counter | - | Total successful builds |
| bamboo_build_failure_total | Counter | - | Total failed builds |
| bamboo_build_total | Gauge | project, name | Latest build number per plan |

## FAQ
Q: Metrics not appearing?

A.Verify Bamboo API accessibility: curl -u user:pass http://bamboo-server/rest/api/latest/queue

Check label parsing rules in parseProjectAndName()

Q: Authentication failures?

A.Ensure config.json has 600 permissions

Confirm user has ​​View Configuration​​ permissions in Bamboo

Q: Handle large-scale deployments?

A.Deploy multiple exporters with Prometheus service discovery


1 change: 1 addition & 0 deletions bamboo_exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ func main() {
os.Exit(0)
}()

// expose metrics endpoint
http.Handle(*metricsEndpoint, promhttp.Handler())

// configure the landing page
Expand Down
Loading
Loading