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
1 change: 1 addition & 0 deletions .github/actionlint.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
---
self-hosted-runner:
labels:
- windows-latest-arm64-s
16 changes: 8 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:

- uses: actions/setup-go@v6
with:
go-version: '1.26'
go-version: '1.26.4'

- name: Install system tools
run: |
Expand All @@ -38,7 +38,7 @@ jobs:
- name: Install goneat via sfetch (dogfooding)
run: |
./bin/sfetch --repo fulmenhq/goneat \
--tag v0.5.10 \
--tag v0.5.13 \
--dest-dir bin \
--require-minisign
./bin/goneat version
Expand Down Expand Up @@ -75,7 +75,7 @@ jobs:

- uses: actions/setup-go@v6
with:
go-version: '1.26'
go-version: '1.26.4'

- name: Build sfetch (from this commit)
shell: bash
Expand All @@ -94,7 +94,7 @@ jobs:
export PATH="$BIN_DIR:$PATH"

sfetch --repo fulmenhq/goneat \
--tag v0.5.10 \
--tag v0.5.13 \
--dest-dir "$BIN_DIR" \
--cache-dir "$CACHE_DIR" \
--require-minisign
Expand All @@ -109,7 +109,7 @@ jobs:

- uses: actions/setup-go@v6
with:
go-version: '1.26'
go-version: '1.26.4'

- name: Install minisign
shell: pwsh
Expand All @@ -127,7 +127,7 @@ jobs:
run: |
.\bin\sfetch.exe `
--repo fulmenhq/goneat `
--tag v0.5.10 `
--tag v0.5.13 `
--dest-dir bin `
--require-minisign
.\bin\goneat.exe version
Expand All @@ -140,7 +140,7 @@ jobs:

- uses: actions/setup-go@v6
with:
go-version: '1.26'
go-version: '1.26.4'

- name: Install minisign
shell: pwsh
Expand Down Expand Up @@ -174,7 +174,7 @@ jobs:
run: |
.\bin\sfetch.exe `
--repo fulmenhq/goneat `
--tag v0.5.10 `
--tag v0.5.13 `
--dest-dir bin `
--require-minisign
.\bin\goneat.exe version
46 changes: 17 additions & 29 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,25 @@ env:
jobs:
create_release:
runs-on: ubuntu-latest
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
steps:
- uses: actions/checkout@v5

- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# softprops/action-gh-release@v2 (Node 24) replaces the archived,
# Node12-era actions/create-release@v1 + actions/upload-release-asset@v1.
# It creates the release for the pushed tag (idempotent) and uploads the
# install script. The build matrix below appends per-platform archives to
# the same release. Maintainer signs + adds SHA256SUMS/notes afterward via
# scripts/ (see README "Manual signing workflow").
- name: Create release and upload install script
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref }}
release_name: sfetch ${{ github.ref }}
name: sfetch ${{ github.ref_name }}
body: |
## sfetch ${{ github.ref }}
## sfetch ${{ github.ref_name }}
Auto-generated release.
draft: false
prerelease: false

- name: Upload install script
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: scripts/install-sfetch.sh
asset_name: install-sfetch.sh
asset_content_type: text/x-shellscript
files: scripts/install-sfetch.sh

build:
needs: create_release
Expand Down Expand Up @@ -77,7 +68,7 @@ jobs:

- uses: actions/setup-go@v6
with:
go-version: '1.26'
go-version: '1.26.4'

- name: License check
# go-licenses v1.6.0 errors on stdlib packages ("Package fmt does not
Expand Down Expand Up @@ -128,19 +119,16 @@ jobs:
# Per-file .sha256 removed - signed SHA256SUMS is the authoritative source
# Maintainer generates SHA256SUMS locally and signs with minisign/pgp

# Appends this matrix entry's archive to the release created above.
# action-gh-release@v2 is idempotent on the tag; parallel matrix jobs each
# upload a distinctly-named asset, so no upload_url plumbing is needed.
- name: Upload Archive
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: softprops/action-gh-release@v2
with:
upload_url: ${{ needs.create_release.outputs.upload_url }}
asset_path: ${{ env.ASSET_FILE }}
asset_name: ${{ env.ASSET_FILE }}
asset_content_type: ${{ env.ASSET_CONTENT_TYPE }}
files: ${{ env.ASSET_FILE }}

- name: Signing handled manually
# NOTE: actionlint rejects constant expressions like `${{ false }}`.
# Keep this step effectively disabled while leaving a breadcrumb.
if: ${{ github.ref == 'refs/tags/__disabled__' }}
run: echo "Signing occurs via scripts/sign-release.sh after CI"
...
4 changes: 2 additions & 2 deletions .goneat/tools.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ tools:
- scoop
- winget
version_scheme: semver
minimum_version: 1.21.0
recommended_version: 1.22.0
minimum_version: 1.25.5
recommended_version: 1.26.4
golangci-lint:
name: golangci-lint
description: Fast linters runner for Go
Expand Down
26 changes: 26 additions & 0 deletions .yamlfmt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Pinned yamlfmt config — stops the YAML formatting tug-of-war.
#
# Without this file, goneat's bundled yamlfmt and a standalone `yamlfmt`
# disagree on inline-comment padding: goneat deliberately writes two spaces
# before `#` (the yamllint-compatible default), while standalone yamlfmt
# defaults to one. That mismatch caused unrelated files (.goneat/*.yaml,
# .github/workflows/*) to flip back and forth and fail `make precommit`.
#
# Pinning here makes every yamlfmt invocation — goneat's `assess --categories
# format` and any bare `yamlfmt` (which auto-loads .yamlfmt from the repo
# root) — agree on two spaces, which is also what yamllint's `comments` rule
# expects by default. See the goneat appnote `yaml-format-lint-alignment` and
# https://github.com/google/yamlfmt/blob/main/docs/config-file.md.

formatter:
type: basic
indent: 2
line_ending: lf
# Two spaces before "#" in inline comments — matches goneat's pinned default
# and yamllint convention. This is the setting that actually stops the churn.
pad_line_comments: 2
# sfetch house style differs from gonimbus: every YAML file opens with `---`
# and uses blank lines to separate top-level blocks. Preserve both so this
# config pins comment padding WITHOUT reformatting every workflow/config file.
include_document_start: true
retain_line_breaks: true
11 changes: 11 additions & 0 deletions .yamllint
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
extends: default

rules:
# sfetch YAML consistently opens with `---`, but goneat runs yamllint in
# strict mode (.goneat/assess.yaml), so a single stray file without it would
# fail an unrelated `make precommit`. Disable rather than churn every file.
document-start: disable
# Workflow `run:` blocks, URLs, and signing commands routinely exceed 80
# columns. Leaving line-length on forces cosmetic reflow churn on files that
# are otherwise fine; keep that out of mechanical config PRs.
line-length: disable
116 changes: 15 additions & 101 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.4.8] - 2026-06-22

### Changed
- **Go toolchain pinned to 1.26.4.** `go.mod` now declares `go 1.25.5` with `toolchain go1.26.4`, and CI/release `setup-go` pins `1.26.4` (was the floating `1.26`). Default builds (`GOTOOLCHAIN=auto`) transparently use the patched 1.26.4 standard library while the module still builds on Go 1.25.x, keeping us inside Go's supported-major window and clearing the stdlib advisories that source-based vulnerability scans were flagging.
- **Dependencies updated:** `golang.org/x/crypto` v0.47.0 → v0.53.0, `golang.org/x/text` v0.33.0 → v0.38.0, `golang.org/x/sys` v0.40.0 → v0.46.0, `github.com/dlclark/regexp2` v1.11.5 → v1.12.0, and `github.com/jedisct1/go-minisign` refreshed to its latest commit. `govulncheck ./...` reports no vulnerabilities.
- **goneat pinned to v0.5.13** (was v0.5.10) across the `Makefile` and the CI dogfood install steps.
- **Release workflow migrated off archived Node12 actions.** `actions/create-release@v1` and `actions/upload-release-asset@v1` (both archived, Node12-era) are replaced with `softprops/action-gh-release@v2` (Node 24), completing the Node 20 → 24 runner transition begun in v0.4.7 (which had already moved `checkout`/`setup-go`).

### Added
- **Pinned YAML formatting standard.** Added repo-root `.yamlfmt` and `.yamllint` so goneat's bundled yamlfmt and any standalone yamlfmt agree on inline-comment padding (two spaces) and document-start handling. Ends the intermittent `make precommit`/CI churn on workflow and config files. The config preserves sfetch's `---` + blank-line house style rather than collapsing it.

### Fixed
- Normalized `scripts/install-sfetch.sh` to 4-space indentation, matching the other `scripts/*.sh` and `.goneat/assess.yaml`'s shfmt `-i 4` setting. Whitespace-only; platform detection and argument handling verified unchanged.
- Re-applied go1.26 `gofmt` alignment to `internal/host/github/client.go`.

## [0.4.7] - 2026-04-20

### Removed
Expand Down Expand Up @@ -132,107 +147,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Documentation
- Documented proxy support in `README.md`.

## [0.3.3] - 2026-01-10

### Documentation
- Added a local agent role catalog and operating model guidance for supervised sessions.

## [0.3.2] - 2026-01-02

### Added
- **shellsentry integration:** Added shellsentry to `testdata/corpus.json` with minisign verification fixtures.
- **Test coverage improvements:** Comprehensive test suite expansion across 5 passes:
- Pass 1: Pure functions (inferBinaryName, archiveFormat, tokenCI, etc.)
- Pass 2: internal/verify edge cases (checksum detection, signature formats)
- Pass 3: CLI flag validation (mutual exclusivity, required flags, help/version)
- Pass 4: Asset selection logic (heuristics, match/regex, pattern rendering)
- Pass 5: Trust score calculation (algorithms, penalties, score capping)

### Changed
- **stdout/stderr convention:** All human-readable output now goes to stderr; stdout reserved for JSON only. Affected: `--version`, `--version-extended`, `--self-verify`, `--show-trust-anchors`, `--dry-run`, `--helpextended`, success messages. This enables clean piping of JSON output in CI/CD pipelines.

### Fixed
- **LICENSE:** Added project name notice and updated contact email.

## [0.3.1] - 2025-12-31

### Fixed
- **Raw scripts no longer misclassified as archives:** Fixed regression where raw scripts (e.g., `install-sfetch.sh`) were incorrectly treated as archives when the default config includes `archiveType: "tar.gz"`. The legacy `archiveType` field now only applies to assets that are actually archives or have unknown type.

### Documentation
- Added `make release-verify-checksums` step to `RELEASE_CHECKLIST.md`.

## [0.3.0] - 2025-12-29

### Added
- **Trust rating system (v0.3.0):** Numeric trust score (0–100) with transparent factor breakdown.
- **Policy gating:** New `--trust-minimum <0-100>` blocks downloads below the threshold.
- **Workflow `none`:** Explicitly represents sources that provide no verification artifacts (distinct from bypass via `--insecure`).
- **Dogfood corpus expansion:** Corpus continues to live in `testdata/corpus.json` and is runnable via `make corpus-dryrun`.

### Changed
- **Provenance schema:** Added `trust` object (`score`, `level`, `levelName`, `factors`) while retaining legacy `trustLevel` for one minor cycle.
- **CLI output:** Normal runs now print trust score; dry-run includes a verifiable/validated breakdown.

### Fixed
- Clarified dry-run messaging to avoid implying integrity when signature artifacts exist but no verification key is available.

## [0.2.9] - 2025-12-25

### Fixed
- **Asset selection now works for `minisign` and similar tool names:** Fixed false positive in supplemental file detection where tools containing "sig" in their name (like `minisign`, `cosign`, `design-tool`) were incorrectly excluded from asset selection. The fix removes the overly broad substring check and adds explicit `.minisig` suffix detection.

### Documentation
- Added "Install permissions" section to README documenting permission behavior for archives, raw scripts/binaries, and cross-device installs.

## [0.2.8] - 2025-12-14

### Added
- **Linux `noexec` detection (warn-only):** sfetch now warns when the install destination appears to be mounted with `noexec`.

### Changed
- **Release notes source is now versioned:** `make release-notes` now requires `docs/releases/$RELEASE_TAG.md` and fails if missing.
- **More deterministic install behavior tests:** install logic is factored into a helper to enable unit tests for rename vs EXDEV copy fallback.

### Security
- Expanded test coverage for ZIP extraction edge cases (zip slip, absolute paths, symlinks).

## [0.2.7] - 2025-12-14

### Changed
- **ZIP extraction is now pure-Go:** `.zip` assets are extracted via the Go standard library (`archive/zip`), removing the runtime dependency on `unzip`.

### Security
- **Hardened ZIP extraction:** ZIP slip/path traversal, absolute paths, and symlinks are rejected during extraction.

## [0.2.6] - 2025-12-14

### Fixed
- **Cross-device installs/caching (EXDEV):** When `--dest-dir` or `--cache-dir` is on a different filesystem than the temp directory (common in containerized CI), sfetch now falls back to copy when `rename(2)` fails with "invalid cross-device link".

### Changed
- Refactored internals to improve auditability and testability (moved logic into `internal/*` and introduced an injectable CLI entrypoint); CLI behavior is intended to be unchanged.

### Documentation
- Added CI/CD usage guide: `docs/cicd-usage-guide.md`.

## [0.2.5] - 2025-12-13

### Added
- **Self-update version check:** `--self-update` now skips reinstall when already at the target version; `--self-update-force` reinstalls; `--tag` allows explicit downgrades (major-version guard still applies).
- **Embedded self-update config:** Self-update uses an embedded, schema-backed update target config (`configs/update/sfetch.json`), with `--show-update-config` and `--validate-update-config`.
- **Update library (initial):** New `pkg/update` package exposes self-update decision logic for reuse.
- **Dry-run version info:** `--self-update --dry-run` now shows version comparison (current/target/status).

### Changed
- Build now targets the package (not `./main.go`) so multi-file `main` builds work (`Makefile` `MAIN ?= .`).
- **Signing env vars standardized:** All signing-related environment variables now use an `SFETCH_` prefix for CI/scripting consistency:
- `MINISIGN_KEY` → `SFETCH_MINISIGN_KEY`
- `PGP_KEY_ID` → `SFETCH_PGP_KEY_ID`
- `GPG_HOMEDIR` → `SFETCH_GPG_HOMEDIR`
- Added `SFETCH_MINISIGN_PUB` for explicit public key path.
- Dev builds no longer require `--self-update-force` to proceed (easier exit path for developers).

---

> **Maintenance note:** This file is pruned to the latest 10 releases. For older entries, see `docs/releases/`.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ BIN_DIR := $(CURDIR)/bin

# Pinned tool versions (minimums; existing installs are respected)
SFETCH_VERSION := v0.3.4
GONEAT_VERSION ?= v0.5.10
GONEAT_VERSION ?= v0.5.13

# Tool paths (sfetch bootstrap may land in bin/; goneat must be on PATH)
SFETCH = $(shell [ -x "$(BIN_DIR)/sfetch" ] && echo "$(BIN_DIR)/sfetch" || command -v sfetch 2>/dev/null)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# sfetch

[![Go 1.23+](https://img.shields.io/badge/Go-1.23+-00ADD8?logo=go&logoColor=white)](https://go.dev/)
[![Go 1.25+](https://img.shields.io/badge/Go-1.25+-00ADD8?logo=go&logoColor=white)](https://go.dev/)
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
[![Release](https://img.shields.io/github/v/release/3leaps/sfetch?include_prereleases)](https://github.com/3leaps/sfetch/releases)

Expand Down
Loading