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
63 changes: 40 additions & 23 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
name: CI

on:
pull_request:
push:
branches:
- main

env:
NODE_VERSION: "22"
GO_VERSION: "1.24"
- "release/*"
pull_request:

jobs:
test:
Expand All @@ -17,28 +14,48 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
cache-dependency-path: web/package-lock.json
go-version-file: go.mod
cache: true

- name: Install frontend deps
run: npm ci
working-directory: web
- name: Go test
run: go test ./...

- name: Build frontend
run: npm run build
working-directory: web
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Go
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
go-version-file: go.mod
cache: true

- name: Go test
run: |
export GOMODCACHE="$GITHUB_WORKSPACE/.gocache"
export GOCACHE="$GITHUB_WORKSPACE/.gocache/go"
go test ./...
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v9
with:
version: latest
args: --config .golangci.yml
install-mode: goinstall

gosec:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true

- name: Install gosec
run: go install github.com/securego/gosec/v2/cmd/gosec@v2.22.1

- name: Run gosec
run: $(go env GOPATH)/bin/gosec -exclude-dir=internal/proto -exclude-dir=.gocache ./...
24 changes: 13 additions & 11 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
name: Build and Publish Docker Image

on:
push:
branches:
- main
tags:
- "v*"
workflow_dispatch:
workflow_call:
inputs:
tag:
required: true
type: string

env:
IMAGE_NAME: jesuspaz/clustercost-dashboard
Expand All @@ -30,6 +29,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ inputs.tag }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
Expand All @@ -46,8 +47,8 @@ jobs:
with:
images: ${{ env.IMAGE_NAME }}
tags: |
type=ref,event=tag
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value=${{ inputs.tag }}
type=raw,value=latest
type=sha
flavor: |
suffix=-${{ matrix.arch }}
Expand All @@ -71,6 +72,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ inputs.tag }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
Expand All @@ -87,9 +90,8 @@ jobs:
with:
images: ${{ env.IMAGE_NAME }}
tags: |
type=ref,event=tag
type=raw,value=latest,enable={{is_default_branch}}
type=sha
type=raw,value=${{ inputs.tag }}
type=raw,value=latest

- name: Create multi-arch manifests
run: |
Expand Down
93 changes: 93 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
name: Manual Release

on:
workflow_dispatch:
inputs:
bump:
description: "Version bump type"
required: true
type: choice
options:
- patch
- minor
- major
- custom
custom_version:
description: "Custom semver tag (e.g., v0.2.0). Required when bump=custom."
required: false

jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Compute release version
id: version
shell: bash
run: |
set -euo pipefail
bump="${{ inputs.bump }}"
custom="${{ inputs.custom_version }}"

if [[ "$bump" == "custom" ]]; then
if [[ -z "$custom" ]]; then
echo "custom_version is required when bump=custom" >&2
exit 1
fi
if [[ ! "$custom" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "custom_version must be semver like v0.2.0" >&2
exit 1
fi
version="$custom"
else
git fetch --tags --force
latest=$(git tag -l "v[0-9]*.[0-9]*.[0-9]*" | sort -V | tail -n 1)
if [[ -z "$latest" ]]; then
latest="v0.0.0"
fi
base="${latest#v}"
IFS='.' read -r major minor patch <<< "$base"
case "$bump" in
patch) patch=$((patch + 1)) ;;
minor) minor=$((minor + 1)); patch=0 ;;
major) major=$((major + 1)); minor=0; patch=0 ;;
esac
version="v${major}.${minor}.${patch}"
fi

echo "version=${version}" >> "$GITHUB_OUTPUT"

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true

- name: Run Go tests
env:
GOCACHE: ${{ github.workspace }}/.gocache
run: go test ./...

- name: Create GitHub release
uses: softprops/action-gh-release@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.version.outputs.version }}
name: ClusterCost Dashboard ${{ steps.version.outputs.version }}
generate_release_notes: true

docker:
needs: release
uses: ./.github/workflows/docker.yml
with:
tag: ${{ needs.release.outputs.version }}
secrets: inherit
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,8 @@ internal/static/dist/*
.DS_Store
.vscode/
.idea/

/dashboard
.env

data/clustercost.db
22 changes: 22 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: "2"
run:
tests: false
linters:
enable:
- misspell
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
issues:
max-issues-per-linter: 0
max-same-issues: 0
formatters:
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
5 changes: 4 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@ COPY web/tailwind.config.cjs web/postcss.config.cjs web/vite.config.ts web/tscon
COPY web/src ./web/src
COPY --from=frontend /app/web/dist ./web/dist
RUN mkdir -p internal/static && rm -rf internal/static/dist && cp -r web/dist internal/static/dist
COPY scripts ./scripts
# RUN go run scripts/generate_pricing.go
RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o /dashboard ./cmd/dashboard

FROM --platform=$TARGETPLATFORM gcr.io/distroless/base-debian12:nonroot
WORKDIR /app
COPY --from=backend /dashboard /app/dashboard
ENV LISTEN_ADDR=:9090
EXPOSE 9090
ENV GRPC_ADDR=:9091
EXPOSE 9090 9091
ENTRYPOINT ["/app/dashboard"]
22 changes: 21 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
.PHONY: backend frontend build docker test clean dev-backend dev-frontend dev-bundle
.PHONY: backend frontend build docker test lint sec clean dev-backend dev-frontend dev-bundle generate-pricing

generate-pricing:
go run scripts/generate_pricing.go

BACKEND_ENV ?= LISTEN_ADDR=:9010
AGENT_URLS ?=
BIN_DIR ?= $(PWD)/bin
BINARY ?= $(BIN_DIR)/clustercost

PROTOC ?= protoc

proto:
PATH="$(shell go env GOPATH)/bin:$$PATH" $(PROTOC) -I internal/proto \
--go_out=paths=source_relative:internal/proto \
--go-grpc_out=paths=source_relative:internal/proto \
internal/proto/agent/v1/agent.proto

dev-backend:
$(BACKEND_ENV) AGENT_URLS=$(AGENT_URLS) go run ./cmd/dashboard

Expand All @@ -29,7 +40,16 @@ docker:
test:
GOMODCACHE=$(PWD)/.gocache GOCACHE=$(PWD)/.gocache/go go test ./...

lint:
golangci-lint run

sec:
gosec -exclude-dir=internal/proto -exclude-dir=.gocache ./...

clean:
rm -rf .gocache web/node_modules web/dist $(BIN_DIR)
rm -rf internal/static/dist/*
touch internal/static/dist/.gitkeep

upload-latest:
docker buildx build --platform linux/amd64,linux/arm64 -t jesuspaz/clustercost-dashboard:latest --push --build-arg VERSION=$(VERSION) .
Loading