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
70 changes: 70 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Copilot Instructions for csvdata

## Project Purpose

- `csvdata` provides a small, composable interface to read tabular data as CSV-like rows.
- The package supports plain CSV and adapters for spreadsheet formats:
- `exceldata` for `.xlsx`
- `calcdata` for `.ods`

## Design Principles

- Keep the public API small and predictable.
- Keep adapters thin: format-specific logic stays in adapter packages.
- Favor explicit error returns over hidden fallback behavior.
- Preserve backward compatibility unless a breaking change is explicitly planned.

## Error Handling Policy

- Return wrapped errors so callers can still use `errors.Is` and `errors.As`.
- Keep sentinel errors stable when exposed from public API.
- Handle nil-sensitive paths defensively (`io.Reader`, closer, and adapter resources).
- Do not panic for normal runtime failures; return errors with context.

## Testing and Validation

- Primary local check:

```text
task test
```

- Equivalent direct commands:

```text
go mod verify
go test -shuffle on ./...
golangci-lint-v2 run --enable gosec --timeout 3m0s ./...
```

- Prefer deterministic tests. Avoid external network dependencies.

## Lint and Security Notes

- In deferred cleanup, merge close errors with existing return errors using `errs.Join`.
- Example policy: `err = errs.Join(err, errs.Wrap(closeErr, errs.WithContext(...)))`
- For file path handling, prefer sanitizing with `filepath.Clean` before opening files.
- Avoid using `#nosec G304` as the first option when path normalization can mitigate the warning.
- For narrowing integer conversions (`G115`), prefer explicit range checks before conversion.
- If linter still reports a false positive after range checks, allow minimal `#nosec G115` with a reason comment.
- Prefer clear conversions over bit-mask tricks for readability.
- After range checks, use direct conversion (e.g. `byte(v)`), not masking (e.g. `byte(v & 0xff)`).

## Release Process

- Create releases from `main`.
- Use semantic version tags in `vMAJOR.MINOR.PATCH` format.
- Create annotated tag and push:

```text
git tag -a vX.Y.Z -m "Release vX.Y.Z"
git push origin vX.Y.Z
```

- Create GitHub release with generated notes:

```text
gh release create vX.Y.Z --generate-notes
```

- Verify module version and release assets after publishing.
44 changes: 44 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: CI

on:
push:
branches:
- main
pull_request:

permissions:
contents: read

jobs:
test-and-lint:
name: Test and Lint
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Verify modules
run: go mod verify
- name: Run tests
run: go test -shuffle on ./...
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v8
with:
version: latest
args: --enable gosec --timeout 3m0s ./...

vulncheck:
name: Vulnerability Check
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Run govulncheck
run: go run golang.org/x/vuln/cmd/govulncheck@latest ./...
58 changes: 0 additions & 58 deletions .github/workflows/codeql-analysis.yml

This file was deleted.

32 changes: 32 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: CodeQL

on:
push:
branches:
- main
pull_request:
branches:
- main
schedule:
- cron: '0 20 * * 0'

permissions:
actions: read
contents: read
security-events: write

jobs:
analyze:
name: Analyze (Go)
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: go
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL analysis
uses: github/codeql-action/analyze@v3
46 changes: 0 additions & 46 deletions .github/workflows/lint.yml

This file was deleted.

19 changes: 0 additions & 19 deletions .github/workflows/vulns.yml

This file was deleted.

49 changes: 44 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,54 @@
# [csvdata] -- Reading CSV Data

[![check vulns](https://github.com/goark/csvdata/workflows/vulns/badge.svg)](https://github.com/goark/csvdata/actions)
[![lint status](https://github.com/goark/csvdata/workflows/lint/badge.svg)](https://github.com/goark/csvdata/actions)
[![Go Reference](https://pkg.go.dev/badge/github.com/goark/csvdata.svg)](https://pkg.go.dev/github.com/goark/csvdata)
[![CI](https://github.com/goark/csvdata/actions/workflows/ci.yml/badge.svg)](https://github.com/goark/csvdata/actions/workflows/ci.yml)
[![CodeQL](https://github.com/goark/csvdata/actions/workflows/codeql.yml/badge.svg)](https://github.com/goark/csvdata/actions/workflows/codeql.yml)
[![GitHub license](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://raw.githubusercontent.com/goark/csvdata/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/goark/csvdata.svg)](https://github.com/goark/csvdata/releases/latest)

This package is required Go 1.16 or later.
This package is required Go 1.25 or later.

**Migrated repository to [github.com/goark/csvdata][csvdata]**
## Design Goals

## Import
- Provide a simple and stable interface for reading CSV-like rows.
- Keep parsing concerns separated by format adapters (`exceldata`, `calcdata`).
- Return explicit errors with context, and avoid hidden side effects.

## Development

### Local Validation

Primary command:

```text
task test
```

Equivalent direct commands:

```text
go mod verify
go test -shuffle on ./...
golangci-lint-v2 run --enable gosec --timeout 3m0s ./...
```

### Optional Checks

```text
task govulncheck
task graph
```

## CI Workflows

- `CI`: lint, tests, and vulnerability checks.
- `CodeQL`: security analysis.

All workflows are available in GitHub Actions for this repository.

## Usage

### Import

```go
import "github.com/goark/csvdata"
Expand Down
16 changes: 9 additions & 7 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,38 @@ version: '3'
tasks:
default:
cmds:
- task: clean
- task: prepare
- task: test
- task: nancy
- task: govulncheck
- task: graph

test:
desc: Test and lint.
cmds:
- go mod verify
- go test -shuffle on ./...
- docker run --rm -v $(pwd):/app -w /app golangci/golangci-lint:v1.51.1 golangci-lint run --enable gosec --timeout 3m0s ./...
- golangci-lint-v2 run --enable gosec --timeout 3m0s ./...
sources:
- ./go.mod
- '**/*.go'

nancy:
desc: Check vulnerability of external packages with Nancy.
govulncheck:
desc: Check reachable vulnerabilities with latest govulncheck.
cmds:
- depm list -j | nancy sleuth -n
- go run golang.org/x/vuln/cmd/govulncheck@latest ./...
sources:
- ./go.mod
- '**/*.go'

prepare:
- go mod tidy -v -go=1.25.10

clean:
desc: Initialize module and build cache, and remake go.sum file.
cmds:
- rm -f ./go.sum
- go clean -cache
- go clean -modcache
- go mod tidy -v -go=1.20

graph:
desc: Make grapth of dependency modules.
Expand Down
6 changes: 4 additions & 2 deletions calcdata/calcdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,14 @@ func (r *Reader) Read() ([]string, error) {
return cols, nil
}

func openFile(path string) (*ods.Doc, error) {
func openFile(path string) (_ *ods.Doc, err error) {
f, err := ods.Open(path)
if err != nil {
return nil, errs.Wrap(err, errs.WithContext("path", path))
}
defer f.Close()
defer func() {
err = errs.Join(err, errs.Wrap(f.Close(), errs.WithContext("path", path)))
}()
var doc ods.Doc
if err := f.ParseContent(&doc); err != nil {
return nil, errs.Wrap(err, errs.WithContext("path", path))
Expand Down
Loading
Loading