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
37 changes: 34 additions & 3 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This directory contains all GitHub Actions workflows for the starter-gradle proj
| **CI/CD** | `pull-request-check-build-logic.yml` | Checks for build-logic changes | Changes to `gradle/build-logic/**` |
| **CI/CD** | `deploy-docs.yml` | Deploy documentation to GitHub Pages | Push docs to `main`, Release published |
| **Security** | `codeql-analysis.yml` | Security scanning with CodeQL | Push to main/minor, daily schedule |
| **Security** | `snyk-security.yml` | Snyk SAST/SCA/Container/IaC scans | Push/PR to main/minor, manual |
| **Publishing** | `publish-release.yml` | Publish release (Maven, Cargo, npm, Docker) | Tag push `v*.*.*` |
| **Publishing** | `publish-snapshot.yml` | Publish snapshot versions | Manual, daily schedule |
| **Publishing** | `_publish.yml` | Reusable publish workflow | Called by other workflows |
Expand Down Expand Up @@ -145,11 +146,40 @@ This directory contains all GitHub Actions workflows for the starter-gradle proj

---

### `snyk-security.yml` - Snyk Security Platform Scan

**Purpose**: Runs Snyk Code, Open Source, Container, and IaC scans and uploads SARIF to GitHub
Code Scanning.

**Triggers**:

- Push to `main` or `minor`
- Pull request to `main` or `minor`
- Manual trigger

**What it does**:

1. ✈ Checks out repository
2. 🔐 Installs Snyk CLI
3. 🔍 Runs `snyk code test` and uploads SARIF
4. 📚 Runs Open Source scan (`snyk test --all-projects`)
5. 🐳 Builds and scans runtime container image
6. 🧱 Runs IaC scan (`snyk iac test --report`)

**Key Points**:

- Requires `SNYK_TOKEN` secret
- `monitor` commands run only on non-PR events
- Findings are currently non-blocking (`continue-on-error: true`)

---

## 📦 Publishing Workflows

### `publish-release.yml` - Release Publishing

**Purpose**: Publishes release artifacts to Maven Central, crates.io, npm, Docker Hub, and GHCR, then creates a GitHub release.
**Purpose**: Publishes release artifacts to Maven Central, crates.io, npm, Docker Hub, GHCR, and
dashboard Docker images, then creates a GitHub release.

**Triggers**:

Expand Down Expand Up @@ -219,8 +249,9 @@ Calls the reusable `_publish.yml` workflow with:
3. 👻 Publishes to Maven Central using Gradle
4. 🦀 Publishes Rust crate to crates.io (release only)
5. 📦 Publishes npm package `@dallay/corvus` to npm (release only)
6. 🐳 Builds and publishes multi-arch Docker image to Docker Hub + GHCR (release only)
7. 🚀 Creates GitHub release (if enabled)
6. 🐳 Builds and publishes multi-arch runtime Docker image to Docker Hub + GHCR (release only)
7. 📊 Builds and publishes multi-arch dashboard Docker image to Docker Hub + GHCR (release only)
8. 🚀 Creates GitHub release (if enabled)

**Key Points**:

Expand Down
72 changes: 67 additions & 5 deletions .github/workflows/_publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -245,20 +245,20 @@ jobs:
chmod +x corvus-linux-x64 corvus-linux-arm64

- name: 🐳 Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3

- name: 🐳 Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3

- name: 🔐 Login to Docker Hub
continue-on-error: true
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: 🔐 Login to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand All @@ -278,7 +278,6 @@ jobs:
type=raw,value=latest

- name: 🐳 Build and push Docker image (prebuilt binaries)
continue-on-error: true
uses: docker/build-push-action@v6
with:
context: .
Expand All @@ -289,6 +288,69 @@ jobs:
tags: ${{ steps.docker-meta.outputs.tags }}
labels: ${{ steps.docker-meta.outputs.labels }}

docker-dashboard-image:
if: ${{ inputs.release }}
needs: publish
runs-on: ubuntu-latest
steps:
- name: ✈ Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: 🐳 Set up QEMU
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3

- name: 🐳 Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3

- name: 🔐 Login to Docker Hub
if: ${{ secrets.DOCKERHUB_USERNAME != '' && secrets.DOCKERHUB_TOKEN != '' }}
continue-on-error: true
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: 🔐 Login to GitHub Container Registry
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

- name: 🧮 Compute dashboard image targets
id: dashboard-targets
shell: bash
run: |
{
echo 'images<<EOF'
if [[ -n "${{ secrets.DOCKERHUB_USERNAME }}" && -n "${{ secrets.DOCKERHUB_TOKEN }}" ]]; then
echo "docker.io/${{ secrets.DOCKERHUB_USERNAME }}/corvus-dashboard"
fi
echo "ghcr.io/${{ github.repository_owner }}/corvus-dashboard"
echo 'EOF'
} >> "$GITHUB_OUTPUT"

- name: 🏷️ Generate dashboard Docker tags and labels
id: dashboard-docker-meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5
with:
images: ${{ steps.dashboard-targets.outputs.images }}
tags: |
type=semver,pattern={{version}},value=${{ github.ref_name }}
type=semver,pattern={{major}}.{{minor}},value=${{ github.ref_name }}
type=semver,pattern={{major}},value=${{ github.ref_name }}
type=raw,value=latest

- name: 🐳 Build and push dashboard Docker image
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
with:
context: clients/web
file: clients/web/apps/dashboard/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.dashboard-docker-meta.outputs.tags }}
labels: ${{ steps.dashboard-docker-meta.outputs.labels }}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

publish-npm-platforms:
if: ${{ inputs.release }}
needs: build-native-binaries
Expand Down
32 changes: 30 additions & 2 deletions .github/workflows/fix-renovate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,37 @@ jobs:
- name: 🔒 Write global locks
run: ./gradlew writeLocks --no-parallel --no-configuration-cache

- name: 🔐 Re-validate PR head SHA before write actions
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
EXPECTED_SHA: ${{ steps.get-pr-data.outputs.head_sha }}
EXPECTED_REPO: ${{ steps.get-pr-data.outputs.head_repo }}
with:
# language=javascript
script: |
const expectedSha = process.env.EXPECTED_SHA
const expectedRepo = process.env.EXPECTED_REPO
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
})

const currentRepo = pr.head.repo.full_name
const currentSha = pr.head.sha

core.info(`Expected repo/SHA: ${expectedRepo} @ ${expectedSha}`)
core.info(`Current repo/SHA: ${currentRepo} @ ${currentSha}`)

if (currentRepo !== expectedRepo || currentSha !== expectedSha) {
core.setFailed(
`PR head changed after approval/check (expected ${expectedRepo}@${expectedSha}, got ${currentRepo}@${currentSha}). Re-run /fix-lock.`
)
}

- name: 📝 Get Commit Message
run: |
COMMIT_MSG=$(git log --format=%s -n 1)
COMMIT_MSG=$(git log --format=%s -n 1 "${{ steps.get-pr-data.outputs.head_sha }}")
echo "COMMIT_MSG=${COMMIT_MSG}" >> $GITHUB_ENV

- name: 💾 Commit file changes (only for bots)
Expand All @@ -132,7 +160,7 @@ jobs:
git add -A

git diff --cached --quiet || git commit -m "${COMMIT_MSG}"
git push origin ${{ steps.get-pr-data.outputs.head_branch }}
git push origin HEAD:${{ steps.get-pr-data.outputs.head_branch }}

- name: 💬 Add reaction to trigger comment
uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
Expand Down
24 changes: 12 additions & 12 deletions .github/workflows/shell/check-commit-msg.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,26 @@ COMMIT_MSG_PATTERN='^(revert: )?(build|chore|ci|deps|docs|feat|fix|infra|perf|re
# ------------------------------
# Skip merge or initial commit
# ------------------------------
if echo "$COMMIT_MSG" | grep -Eq '^Merge'; then
if grep -Eq '^Merge' <<< "$COMMIT_MSG"; then
echo "⏭ Skipping merge commit."
exit 0
fi

if echo "$COMMIT_MSG" | grep -Eq '^Initial commit'; then
if grep -Eq '^Initial commit' <<< "$COMMIT_MSG"; then
echo "⏭ Skipping initial commit."
exit 0
fi

if ! echo "$COMMIT_MSG" | grep -Eq "$COMMIT_MSG_PATTERN"; then
echo -e "${BG_RED}ERROR${RESET} ${RED}invalid commit message format.${RESET}\n"
echo -e "${RED}Proper commit message format is required for automated changelog generation. Examples:${RESET}\n"
echo -e " ${GREEN}feat(parser): add support for empty tuples${RESET}"
echo -e " ${GREEN}fix(runtime): handle reconnect race condition${RESET}"
echo -e " ${GREEN}refactor(core)!: remove legacy provider fallback${RESET}\n"
echo -e "${RED}Commit message header: <type>(<scope>): <subject>${RESET}"
echo -e "${RED}Commit message header pattern: ${COMMIT_MSG_PATTERN}${RESET}"
echo -e "${RED}See${RESET} ${BLUE}https://www.conventionalcommits.org/en/v1.0.0/${RESET} ${RED}for more details.${RESET}\n"
echo -e "${RED}❌ Invalid commit message:${RESET} '${COMMIT_MSG}'"
if ! grep -Eq "$COMMIT_MSG_PATTERN" <<< "$COMMIT_MSG"; then
echo -e "${BG_RED}ERROR${RESET} ${RED}invalid commit message format.${RESET}\n" >&2
echo -e "${RED}Proper commit message format is required for automated changelog generation. Examples:${RESET}\n" >&2
echo -e " ${GREEN}feat(parser): add support for empty tuples${RESET}" >&2
echo -e " ${GREEN}fix(runtime): handle reconnect race condition${RESET}" >&2
echo -e " ${GREEN}refactor(core)!: remove legacy provider fallback${RESET}\n" >&2
echo -e "${RED}Commit message header: <type>(<scope>): <subject>${RESET}" >&2
echo -e "${RED}Commit message header pattern: ${COMMIT_MSG_PATTERN}${RESET}" >&2
echo -e "${RED}See${RESET} ${BLUE}https://www.conventionalcommits.org/en/v1.0.0/${RESET} ${RED}for more details.${RESET}\n" >&2
echo -e "${RED}❌ Invalid commit message:${RESET} '${COMMIT_MSG}'" >&2
exit 1
fi

Expand Down
74 changes: 74 additions & 0 deletions .github/workflows/snyk-security.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
# This workflow uses third-party actions that are governed by their own terms.
name: Snyk Security

on:
push:
branches:
- main
- minor
pull_request:
branches:
- main
- minor
workflow_dispatch:

permissions:
contents: read

jobs:
snyk:
if: ${{ secrets.SNYK_TOKEN != '' }}
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

steps:
- name: ✈ Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: 📦 Setup Node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: "24"

- name: 🔐 Setup Snyk CLI
uses: snyk/actions/setup@806182742461562b67788a64410098c9d9b96adb

- name: 🔍 Snyk Code test (SARIF)
continue-on-error: true
run: snyk code test --sarif > snyk-code.sarif

- name: 📤 Upload Snyk Code SARIF to GitHub
uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
with:
sarif_file: snyk-code.sarif

- name: 📚 Snyk Open Source test
continue-on-error: true
run: snyk test --all-projects

- name: 📡 Snyk Open Source monitor
if: github.event_name != 'pull_request'
continue-on-error: true
run: snyk monitor --all-projects

- name: 🏗️ Build runtime Docker image for scan
run: docker build -t corvus-runtime-snyk:scan -f clients/agent-runtime/Dockerfile .

- name: 🐳 Snyk Container test
continue-on-error: true
run: snyk container test corvus-runtime-snyk:scan --file=clients/agent-runtime/Dockerfile

- name: 🐳 Snyk Container monitor
if: github.event_name != 'pull_request'
continue-on-error: true
run: snyk container monitor corvus-runtime-snyk:scan --file=clients/agent-runtime/Dockerfile

- name: 🧱 Snyk IaC test
continue-on-error: true
run: snyk iac test --report
3 changes: 3 additions & 0 deletions .github/workflows/sonarqube-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ jobs:
-Dsonar.projectKey=${{ steps.sonar_meta.outputs.key }}
-Dsonar.projectName=${{ github.event.repository.name }}
-Dsonar.sources=.
-Dsonar.tests=.
-Dsonar.test.inclusions=**/*.spec.ts,**/*.test.ts,**/*.test.tsx,**/*_test.rs,**/tests/**
-Dsonar.exclusions=**/.git/**,**/.gradle/**,**/build/**,**/dist/**,**/coverage/**,**/node_modules/**,**/.next/**,**/.turbo/**,**/target/**,**/vendor/**,**/generated/**,**/clients/agent-runtime/target/**
-Dsonar.coverage.exclusions=**/*.spec.ts,**/*.test.ts,**/*.test.tsx,clients/web/apps/dashboard/src/App.vue,clients/web/packages/shared/index.ts,clients/agent-runtime/npm/corvus-cli/scripts/postinstall.js
-Dsonar.coverage.jacoco.xmlReportPaths=${{ github.workspace }}/modules/agent-core-kmp/build/reports/kover/report.xml,${{ github.workspace }}/clients/composeApp/build/reports/kover/report.xml
-Dsonar.rust.lcov.reportPaths=${{ github.workspace }}/coverage/agent-runtime-coverage.lcov

Expand Down
18 changes: 16 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,19 @@ dev-build: ## Rebuild dev images
dev-clean: ## Stop and wipe dev environment
@./dev/cli.sh clean

# --- LOCAL RUNTIME (Docker Compose) ---

runtime-up: ## Start local gateway runtime (clients/agent-runtime)
@docker compose -f clients/agent-runtime/docker-compose.yml up -d
runtime-up-dashboard: ## Start local gateway + dashboard runtime
@docker compose -f clients/agent-runtime/docker-compose.yml --profile dashboard up -d
runtime-down: ## Stop local gateway/dashboard runtime
@docker compose -f clients/agent-runtime/docker-compose.yml down
runtime-logs: ## Follow local gateway/dashboard logs
@docker compose -f clients/agent-runtime/docker-compose.yml logs -f
runtime-status: ## Show local gateway/dashboard status
@docker compose -f clients/agent-runtime/docker-compose.yml ps

# --- CONTINUOUS INTEGRATION ---

ci-build: ## CI: Build without daemon
Expand Down Expand Up @@ -365,5 +378,6 @@ sync-version: ## Sync VERSION with git tag
format check-format check lint-kotlin lint-rust lint-android lint-all \
test test-app test-core test-verbose test-coverage docs-code \
deps deps-app deps-analysis deps-update \
dev-up dev-down dev-shell dev-agent dev-logs dev-status dev-build dev-clean \
ci-build ci-test ci-check all quick tasks info version sync-version
dev-up dev-down dev-shell dev-agent dev-logs dev-status dev-build dev-clean \
runtime-up runtime-up-dashboard runtime-down runtime-logs runtime-status \
ci-build ci-test ci-check all quick tasks info version sync-version
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
[![Build Status](https://github.com/dallay/corvus/actions/workflows/pull-request-check.yml/badge.svg)](https://github.com/dallay/corvus/actions/workflows/pull-request-check.yml)
[![codecov](https://codecov.io/gh/dallay/corvus/graph/badge.svg?token=N4THEP2OF1)](https://codecov.io/gh/dallay/corvus)
[![License](https://img.shields.io/github/license/dallay/corvus?color=blue)](LICENSE)
[![Version](https://img.shields.io/badge/version-0.1.14-blue.svg)](gradle.properties)
[![Version](https://img.shields.io/github/v/tag/dallay/corvus?sort=semver&label=version)](https://github.com/dallay/corvus/tags)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://github.com/dallay/corvus/compare)

## 🛡️ Code Quality (SonarCloud)
Expand Down
Loading
Loading