diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 04fcf19..d6336ba 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,12 +16,28 @@ jobs: - uses: actions/checkout@v6 with: persist-credentials: false + fetch-depth: 0 + - name: Relevant changes + id: changes + run: | + if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then + git fetch --no-tags origin "$GITHUB_BASE_REF" + base="origin/$GITHUB_BASE_REF" + else + base='${{ github.event.before }}' + fi + if git diff --quiet "$base"...HEAD -- '*.go' go.mod go.sum Dockerfile .dockerignore .github data README.md; then + echo "code=false" >> "$GITHUB_OUTPUT" + else + echo "code=true" >> "$GITHUB_OUTPUT" + fi # `docker build` streams the context to the daemon. A compose bind-mount of # `.` mounts an empty host dir instead, because the job is itself a container. - name: Latest supported Go + if: ${{ steps.changes.outputs.code == 'true' }} run: docker build . # Runs even when the step above failed, so a red build says whether the # failure is version-specific. - name: Lowest supported Go - if: ${{ !cancelled() }} + if: ${{ !cancelled() && steps.changes.outputs.code == 'true' }} run: docker build --build-arg GO_VERSION=1.22.12 . diff --git a/.gitignore b/.gitignore index 28f4f54..5995de4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ .claude *.out -__pycache__/ -todo.md \ No newline at end of file +__pycache__/ \ No newline at end of file diff --git a/README.md b/README.md index 95f444d..a96dd96 100644 --- a/README.md +++ b/README.md @@ -587,8 +587,10 @@ docker compose run --rm --user "$(id -u):$(id -g)" tidy # go mod tidy ``` Every pull request runs `docker build .` against both the latest and the lowest -supported Go, and must pass before it can be merged. That build is the whole -gate — vet, complexity, format check and tests — so run it locally before pushing: +supported Go, and must pass before it can be merged — unless it changes none of +the files the build and its tests read, nor the workflow itself, in which case +it's skipped (see [Decisions](#decisions)). That build is the whole gate — vet, +complexity, format check and tests — so run it locally before pushing: ```sh docker build . # latest diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..e38f182 --- /dev/null +++ b/todo.md @@ -0,0 +1,28 @@ +# Release checklist + +What to settle before the first tag, then the work that follows in a later, +data-heavy release. + +## Before the first release — settle the record flag and API contract + +- `--format` vocabulary — confirm `text`, `json`, `ndjson`, `csv`, `sql`; the + `json`-as-array vs `ndjson`-as-lines split; `--table` (the SQL INSERT target); + the `--separator` rejection on record formats; and the exit codes (misuse 2, + runtime 1). +- Library surface — confirm `Record`, `FakeRecord`, `NewRecordTemplate`, + `RecordTemplate`, `Column`/`Columns()`, and the `JSON()`, `CSVHeader()`, + `CSVLine()`, `SQLInsert()` serializers. +- Typed scalars — columns are strings today (`"42"`, quoted SQL). Confirm that + stays out of scope, or add a per-column `kind` before the tag. +- Struct-filling — `fake:"..."` tags (reflection over an arbitrary struct) stay + out of scope; `Columns()` hands the caller the values to map themselves. + Confirm. +- Independent reference draw — within one record every tailed reference to a + category is one draw, with no spelling for "these columns should disagree". + Confirm the per-record contract, or add the spelling. + +## Later, in a data-heavy release + +- Shipped-data de-duplication — `email.json`'s `local` is a drifted copy of + `username.json`; fold it in when the shipped set grows and we add lots more + data.