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

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

permissions:
contents: read

env:
GOFLAGS: -buildvcs=false
GOWORK: "off"
GOPROXY: "direct"
GOSUMDB: "off"
Comment on lines +15 to +16

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In Go modules, what are the security implications of setting GOSUMDB=off in CI, and what are the recommended GOPROXY/GOSUMDB settings for public dependencies?

💡 Result:

Setting GOSUMDB=off in CI disables the Go checksum database (sum.golang.org by default), which verifies that downloaded public modules match expected cryptographic hashes recorded in a transparent log. This check occurs when adding new entries to go.sum. Without it, the go command accepts any unrecognized public modules without verifying against the database, giving up the security guarantee of verified repeatable downloads and protection against tampered or malicious modules not yet in go.sum. This exposes CI builds to supply chain attacks where an attacker could serve malicious content for public dependencies, especially if go.sum is incomplete or new versions are fetched. Even with go.sum present, it only checks local cache matches; GOSUMDB provides an external trust anchor for public modules. For public dependencies, use the default settings: GOPROXY=https://proxy.golang.org,direct and GOSUMDB=sum.golang.org. These ensure modules are fetched reliably from the official proxy (with direct fallback) and verified against the checksum database. In CI, commit complete go.mod and go.sum files, use go build -mod=readonly to prevent modifications, and avoid disabling GOSUMDB. If using private modules, set GOPRIVATE and GONOSUMDB for those paths only, keeping public ones verified.

Citations:


🏁 Script executed:

# Check if the workflow file exists
git ls-files '.github/workflows/ci.yml'

Repository: dAppCore/go-git

Length of output: 84


🏁 Script executed:

# Read the CI workflow file to verify lines 15-16
cat -n .github/workflows/ci.yml | head -30

Repository: dAppCore/go-git

Length of output: 768


🏁 Script executed:

# Check if there are any explanatory comments or documentation about these settings
grep -r "GOSUMDB\|GOPROXY" .github/ --include="*.yml" --include="*.yaml" -B 2 -A 2 || echo "No matches found"

Repository: dAppCore/go-git

Length of output: 296


🏁 Script executed:

# Check if there's any go.sum or go.mod in the repository to understand the module setup
find . -name "go.sum" -o -name "go.mod" -type f | head -20

Repository: dAppCore/go-git

Length of output: 83


🏁 Script executed:

# Check for any documentation or comments explaining the GOSUMDB/GOPROXY settings
find . -type f \( -name "README*" -o -name "*.md" \) -exec grep -l "GOSUMDB\|GOPROXY" {} \; 2>/dev/null | head -10

Repository: dAppCore/go-git

Length of output: 41


🏁 Script executed:

# Check the go.mod file to understand the module configuration
cat -n ./go/go.mod | head -40

Repository: dAppCore/go-git

Length of output: 158


🏁 Script executed:

# Search for any comments or issues related to these settings in the repository
git log --oneline --all --grep="GOSUMDB\|GOPROXY" 2>/dev/null | head -10 || echo "No git history found"

Repository: dAppCore/go-git

Length of output: 128


🏁 Script executed:

# Check if there are any other workflows or setup steps that might affect module verification
git ls-files '.github/workflows/*.yml' '.github/workflows/*.yaml' 2>/dev/null | while read f; do echo "=== $f ==="; cat "$f" | grep -A 5 -B 5 "go.*download\|go.*mod\|GOSUMDB\|GOPROXY" || echo "No matches"; done

Repository: dAppCore/go-git

Length of output: 1048


Go module integrity checks are disabled in CI

Lines 15–16 disable both module proxy verification (GOPROXY: "direct") and checksum database verification (GOSUMDB: "off"). This removes protection against tampered or malicious module downloads and exposes the build to supply-chain attacks. Given the public dependency on dappco.re/go v0.9.0, checksum verification is essential.

Replace with standard Go security settings:

Suggested hardening
 env:
   GOFLAGS: -buildvcs=false
   GOWORK: "off"
-  GOPROXY: "direct"
-  GOSUMDB: "off"
+  GOPROXY: "https://proxy.golang.org,direct"
+  GOSUMDB: "sum.golang.org"
📝 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.

Suggested change
GOPROXY: "direct"
GOSUMDB: "off"
env:
GOFLAGS: -buildvcs=false
GOWORK: "off"
GOPROXY: "https://proxy.golang.org,direct"
GOSUMDB: "sum.golang.org"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci.yml around lines 15 - 16, The CI currently disables Go
module integrity by setting GOPROXY to "direct" and GOSUMDB to "off"; change
these to enforce standard Go security: restore GOPROXY to use the Go proxy
(e.g., include "https://proxy.golang.org" before "direct") and set GOSUMDB to
the Go checksum database (e.g., "sum.golang.org") so module downloads and
checksums are verified; update the workflow keys GOPROXY and GOSUMDB
accordingly.


jobs:
test:
name: Test + Coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- uses: actions/setup-go@v6
with:
go-version: '1.26'
- name: Test with coverage
working-directory: go
run: go test -race -coverprofile=coverage.out -covermode=atomic -count=1 ./...
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: go/coverage.out
flags: unittests
fail_ci_if_error: false

lint:
name: golangci-lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
with:
go-version: '1.26'
- uses: golangci/golangci-lint-action@v9
with:
version: latest
working-directory: go
args: --timeout=5m --tests=false

sonarcloud:
name: SonarCloud
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- uses: actions/setup-go@v6
with:
go-version: '1.26'
- name: Test for coverage
working-directory: go
run: go test -coverprofile=coverage.out -covermode=atomic -count=1 ./...
- name: SonarCloud Scan
uses: SonarSource/sonarqube-scan-action@v6
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:
args: >
-Dsonar.organization=dappcore
-Dsonar.projectKey=dappcore_go-git
-Dsonar.sources=go
-Dsonar.exclusions=**/vendor/**,**/third_party/**,**/.tmp/**,**/*_test.go
-Dsonar.tests=go
-Dsonar.test.inclusions=**/*_test.go
-Dsonar.go.coverage.reportPaths=go/coverage.out
Comment on lines +73 to +80

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "sonar\\.projectKey|sonar\\.sources|sonar\\.tests|sonar\\.go\\.coverage\\.reportPaths" sonar-project.properties .github/workflows/ci.yml

Repository: dAppCore/go-git

Length of output: 551


🏁 Script executed:

cat -n sonar-project.properties

Repository: dAppCore/go-git

Length of output: 643


🌐 Web query:

SonarQube command-line properties override sonar-project.properties precedence

💡 Result:

Yes, SonarQube command-line properties override those in sonar-project.properties. The official documentation states the settings hierarchy in order of precedence: 1. Global properties (UI), 2. Project properties (UI), 3. Scanner configuration files (like sonar-project.properties), 4. Scanner arguments (command-line -D parameters). Command-line arguments explicitly override scanner configuration files. This applies to the SonarScanner CLI (sonar-scanner command). Example: sonar-scanner -Dsonar.projectKey=myproject -Dsonar.sources=src1 will override values from sonar-project.properties.

Citations:


Conflicting SonarCloud configuration between workflow and sonar-project.properties

Workflow arguments set sonar.projectKey=dappcore_go-git, sonar.sources=go, and sonar.tests=go, while sonar-project.properties defines different values (core_go-git, .). These will produce different analysis scopes, with the workflow arguments taking precedence. Consolidate to a single source of truth by either removing the conflicting workflow arguments and relying on the properties file, or updating the properties file to match the workflow configuration.

Suggested simplification (remove conflicting workflow args)
       - name: SonarCloud Scan
         uses: SonarSource/sonarqube-scan-action@v6
         env:
           SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
         with:
           args: >
             -Dsonar.organization=dappcore
-            -Dsonar.projectKey=dappcore_go-git
-            -Dsonar.sources=go
-            -Dsonar.exclusions=**/vendor/**,**/third_party/**,**/.tmp/**,**/*_test.go
-            -Dsonar.tests=go
-            -Dsonar.test.inclusions=**/*_test.go
             -Dsonar.go.coverage.reportPaths=go/coverage.out
📝 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.

Suggested change
args: >
-Dsonar.organization=dappcore
-Dsonar.projectKey=dappcore_go-git
-Dsonar.sources=go
-Dsonar.exclusions=**/vendor/**,**/third_party/**,**/.tmp/**,**/*_test.go
-Dsonar.tests=go
-Dsonar.test.inclusions=**/*_test.go
-Dsonar.go.coverage.reportPaths=go/coverage.out
args: >
-Dsonar.organization=dappcore
-Dsonar.go.coverage.reportPaths=go/coverage.out
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci.yml around lines 73 - 80, The CI workflow is overriding
sonar settings in sonar-project.properties causing conflicting analysis scopes;
either remove the Sonar CLI args from the workflow (the -Dsonar.projectKey,
-Dsonar.sources, -Dsonar.tests, -Dsonar.test.inclusions,
-Dsonar.go.coverage.reportPaths entries) so the properties file becomes the
single source of truth, or update the properties file to match the values used
in the workflow (e.g., set sonar.projectKey to dappcore_go-git, sonar.sources to
go, sonar.tests to go, test inclusions and coverage path accordingly) so both
places are consistent.

22 changes: 22 additions & 0 deletions .golangci.bck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
run:
timeout: 5m
go: "1.26"

linters:
enable:
- govet
- errcheck
- staticcheck
- unused
- gosimple
- ineffassign
- typecheck
- gocritic
- gofmt
disable:
- exhaustive
- wrapcheck

issues:
exclude-use-default: false
max-same-issues: 0
28 changes: 16 additions & 12 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
version: "2"
run:
timeout: 5m
go: "1.26"

linters:
enable:
- govet
- errcheck
- staticcheck
- unused
- gosimple
- ineffassign
- typecheck
- gocritic
- gofmt
disable:
- exhaustive
- wrapcheck

exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
issues:
exclude-use-default: false
max-same-issues: 0
formatters:
enable:
- gofmt
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
37 changes: 37 additions & 0 deletions .woodpecker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Woodpecker CI pipeline.
# Server: ci.lthn.sh. Lint + sonar in parallel, both depend only on clone.
# sonar_token is admin-scoped on the Woodpecker server.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reduce Sonar token privilege scope.

The comment confirms an admin-scoped token is used for CI scanning. That is broader than required and increases blast radius if CI secrets are exposed. Use a project-scoped token with analysis-only permissions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.woodpecker.yml at line 3, The CI config is referencing an admin-scoped
Sonar token (sonar_token) which is overly privileged; replace it with a
project-scoped Sonar token that has analysis-only permissions, update the
Woodpecker secret named sonar_token on the server to the new project-scoped
token, and ensure the pipeline continues using the same secret name so no other
pipeline changes are needed; also rotate/revoke the old admin-scoped token to
remove excess privilege.


when:
- event: push
branch: [dev, main]

steps:
- name: golangci-lint
image: golangci/golangci-lint:latest-alpine
depends_on: []
environment:
GOFLAGS: -buildvcs=false
GOWORK: "off"
commands:
- cd go && golangci-lint run --timeout=5m ./...

- name: go-test
image: golang:1.26-alpine
depends_on: []
environment:
GOFLAGS: -buildvcs=false
GOWORK: "off"
CGO_ENABLED: "1"
commands:
- apk add --no-cache git build-base
- cd go && go test -race -coverprofile=coverage.out -covermode=atomic -count=1 ./...
- name: sonar
image: sonarsource/sonar-scanner-cli:latest
depends_on: [go-test]
environment:
SONAR_HOST_URL: https://sonar.lthn.sh
SONAR_TOKEN:
from_secret: sonar_token
commands:
- sonar-scanner
28 changes: 28 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# go-git Agent Notes

This repository provides `dappco.re/go/git`, a Core-compatible git service and
helper package. It wraps status, push, pull, and multi-repository operations in
the `dappco.re/go` `Result` shape so callers can branch on `r.OK` and inspect
per-repository errors without importing standard-library compatibility shims.

Keep production code on the Core wrapper surface. Use `core.Context`,
`core.Result`, `core.Path*`, `core.WriteFile`, `core.NewBuffer`,
`core.Sprintf`, `core.NewError`, and the Core assertion helpers instead of
direct imports of formatting, filesystem, process, string, or error packages.
The package still exposes iterator-based APIs for streaming repository results;
tests should collect those iterators directly in the sibling test file for the
source that defines the symbol.

Public symbol coverage follows the repository's AX-7 convention. Every public
function or method in `git.go` is tested in `git_test.go` with
`TestGit_<Symbol>_{Good,Bad,Ugly}`, and every public service method in
`service.go` is tested in `service_test.go` with the matching
`TestService_<Symbol>_{Good,Bad,Ugly}` name. Examples live in
`git_example_test.go` and `service_example_test.go`, use `Println` from
`dappco.re/go`, and keep their output deterministic.

The tests create local temporary git repositories and bare remotes. They do not
contact network remotes, and they configure a local test author before making
commits. When changing push or pull behavior, keep the fixtures local and make
failure cases explicit through relative paths or repositories with no matching
remote state.
35 changes: 31 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,35 @@ Multi-repository git operations library. Parallel status checks, sequential push
**Module:** `dappco.re/go/git`
**Go:** 1.26+

The Go module has been moved under `go/` and the repo root now hosts cross-language/ancillary artefacts.

## Repo Layout

```text
core/go-git/
├── go/ ← Go module root (dappco.re/go/git)
├── tests/ ← non-Go-mixed helper fixtures (keep at root)
├── docs/ ← shared docs (symlinked from go/docs)
├── .woodpecker.yml
├── sonar-project.properties
├── README.md
├── CLAUDE.md
└── AGENTS.md
```

## Go Resolution Modes

Two practical ways this module is consumed:

| Mode | When | What runs |
|------|------|-----------|
| **Module mode (default)** | Local development and CI jobs run from `go/` | `go test`, `go vet`, `go mod tidy`, etc. use `go/go.mod` directly. |
| **`GOWORK=off` explicit** | Reproducibility checks | Forces pure `go.mod` resolution and bypasses any outer workspace fallback. This mode is used by the requested verification commands and local parity checks. |

## Build & Test

```bash
cd go
go test ./... -v # Run all tests
go test -run TestName # Run single test
golangci-lint run ./... # Lint (see .golangci.yml for enabled linters)
Expand All @@ -20,8 +46,8 @@ golangci-lint run ./... # Lint (see .golangci.yml for enabled linters)
## Architecture

Two files:
- `git.go` — Core operations: Status, Push, Pull, PushMultiple. Stdlib only, no framework dependency.
- `service.go` — Core framework integration via `dappco.re/go/core`. Exposes query types (QueryStatus, QueryDirtyRepos, QueryAheadRepos, QueryBehindRepos) and task types (TaskPush, TaskPull, TaskPushMultiple, TaskPullMultiple). Service uses `core.ServiceRuntime` with query and action handler registration in `OnStartup`. Also provides iterator methods (All, Dirty, Ahead, Behind) using `iter.Seq`.
- `go/git.go` — Core operations: Status, Push, Pull, PushMultiple. Stdlib only, no framework dependency.
- `go/service.go` — Core framework integration via `dappco.re/go/core`. Exposes query types (QueryStatus, QueryDirtyRepos, QueryAheadRepos, QueryBehindRepos) and task types (TaskPush, TaskPull, TaskPushMultiple, TaskPullMultiple). Service uses `core.ServiceRuntime` with query and action handler registration in `OnStartup`. Also provides iterator methods (All, Dirty, Ahead, Behind) using `iter.Seq`.

## Key Design Decisions

Expand All @@ -34,8 +60,9 @@ Two files:

- `_Good` / `_Bad` suffix pattern for success / failure cases.
- Tests use real git repos created by `initTestRepo()` in temp directories.
- Service helper tests (in `service_test.go`) construct `Service` structs directly without the framework.
- Framework integration tests (in `service_extra_test.go`) use `core.New()` and test handler dispatch.
- Service helper tests (in `go/service_test.go`) construct `Service` structs directly without the framework.
- Service tests in `go/service_test.go` can construct `Service` structs directly or via `core.New()` to exercise handler dispatch in the relevant scenarios.
- Module tests and CLI fixtures in `tests/` remain at repo root because `tests/` is mixed-language.

## Coding Standards

Expand Down
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
[![Go Reference](https://pkg.go.dev/badge/dappco.re/go/git.svg)](https://pkg.go.dev/dappco.re/go/git)
[![License: EUPL-1.2](https://img.shields.io/badge/License-EUPL--1.2-blue.svg)](LICENSE.md)
[![Go Version](https://img.shields.io/badge/Go-1.26-00ADD8?style=flat&logo=go)](go.mod)
<!-- SPDX-License-Identifier: EUPL-1.2 -->



> Git primitives — minimal in-house wrapper used by core tooling

[![CI](https://github.com/dappcore/go-git/actions/workflows/ci.yml/badge.svg?branch=dev)](https://github.com/dappcore/go-git/actions/workflows/ci.yml)
[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=dappcore_go-git&metric=alert_status)](https://sonarcloud.io/dashboard?id=dappcore_go-git)
[![Coverage](https://codecov.io/gh/dappcore/go-git/branch/dev/graph/badge.svg)](https://codecov.io/gh/dappcore/go-git)
[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=dappcore_go-git&metric=security_rating)](https://sonarcloud.io/dashboard?id=dappcore_go-git)
[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=dappcore_go-git&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=dappcore_go-git)
[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=dappcore_go-git&metric=reliability_rating)](https://sonarcloud.io/dashboard?id=dappcore_go-git)
[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=dappcore_go-git&metric=code_smells)](https://sonarcloud.io/dashboard?id=dappcore_go-git)
[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=dappcore_go-git&metric=ncloc)](https://sonarcloud.io/dashboard?id=dappcore_go-git)
[![Go Reference](https://pkg.go.dev/badge/dappco.re/go/go-git.svg)](https://pkg.go.dev/dappco.re/go/go-git)
[![License: EUPL-1.2](https://img.shields.io/badge/License-EUPL--1.2-blue.svg)](https://eupl.eu/1.2/en/)

# go-git

Go module: `dappco.re/go/git`
Comment on lines +15 to 19

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Go Reference badge target does not match the declared module path

Line 15 points to dappco.re/go/go-git, but Line 19 declares dappco.re/go/git. This likely leaves the badge pointing at the wrong package page.

Suggested fix
-[![Go Reference](https://pkg.go.dev/badge/dappco.re/go/go-git.svg)](https://pkg.go.dev/dappco.re/go/go-git)
+[![Go Reference](https://pkg.go.dev/badge/dappco.re/go/git.svg)](https://pkg.go.dev/dappco.re/go/git)
📝 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.

Suggested change
[![Go Reference](https://pkg.go.dev/badge/dappco.re/go/go-git.svg)](https://pkg.go.dev/dappco.re/go/go-git)
[![License: EUPL-1.2](https://img.shields.io/badge/License-EUPL--1.2-blue.svg)](https://eupl.eu/1.2/en/)
# go-git
Go module: `dappco.re/go/git`
[![Go Reference](https://pkg.go.dev/badge/dappco.re/go/git.svg)](https://pkg.go.dev/dappco.re/go/git)
[![License: EUPL-1.2](https://img.shields.io/badge/License-EUPL--1.2-blue.svg)](https://eupl.eu/1.2/en/)
Go module: `dappco.re/go/git`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 15 - 19, The README's Go Reference badge target
(currently pointing to dappco.re/go/go-git) does not match the declared module
path `dappco.re/go/git`; update the badge link and image target to use the
correct module path `dappco.re/go/git` so the pkg.go.dev badge points to the
actual package page (replace occurrences of `dappco.re/go/go-git` with
`dappco.re/go/git` in the badge markdown).


Expand Down
Loading
Loading