Skip to content

feat: release Shipcheck v0.1.0#1

Merged
kodlbegiko merged 12 commits into
mainfrom
feat/shipcheck-v0.1.0
Jul 22, 2026
Merged

feat: release Shipcheck v0.1.0#1
kodlbegiko merged 12 commits into
mainfrom
feat/shipcheck-v0.1.0

Conversation

@kodlbegiko

@kodlbegiko kodlbegiko commented Jul 22, 2026

Copy link
Copy Markdown
Owner

Problem and product position

Release metadata can drift across package manifests, Chrome Extension manifests, README instructions, CHANGELOG headings, artifact filenames, and ZIP-internal manifests. Shipcheck is a local-first, deterministic, CI-friendly pre-release consistency checker.

Implemented

  • Strict JSON configuration and generated JSON Schema
  • Version sources from package.json, manifest.json, and arbitrary JSON paths
  • Contextual README version drift detection with line numbers
  • CHANGELOG current-version, duplicate, parsing, and ordering checks
  • Artifact filename and stale-sibling checks
  • ZIP central-directory inspection without extraction, including one wrapper directory
  • ZIP path traversal, symlink, encryption, entry-count, central-directory, entry-size, CRC, and compression-method safeguards
  • Required and forbidden repository/ZIP file checks
  • Terminal, JSON, and Markdown reporters using one result model
  • Exit codes 0/1/2, warning escalation, and safe shipcheck init
  • Node package and Chrome Extension examples
  • Cross-platform CI on Ubuntu, Windows, and macOS with Node 20 and 24
  • CodeQL workflow and npm audit

Explicitly not included

  • npm publication
  • GitHub Release automation inside Shipcheck
  • JavaScript configuration files
  • ZIP64 or encrypted archive support
  • General glob language
  • AI, telemetry, login, remote database, or cloud service

Validation

Local validation completed:

  • npm ci: pass, 0 vulnerabilities
  • npm run lint: pass
  • npm run typecheck: pass
  • npm test: 88/88 pass
  • npm run test:coverage: lines 94.91%, branches 84.36%, functions 97.99%
  • npm run build: pass
  • npm pack: pass; 65 files, 27.5 kB tarball
  • tarball installation smoke test: pass
  • node dist/cli.js . --ci: pass, 0 errors/warnings/info
  • new-user flow: init → detect stale README → fix → pass

Cross-platform validation

The final PR CI matrix passed on Ubuntu, Windows, and macOS with Node.js 20 and 24. Earlier runs exposed shell glob incompatibility and Windows command-shim behavior; both were fixed without skipping tests. The dedicated package job also passed coverage, npm pack, tarball installation, self-check, and npm audit.

Security considerations

Shipcheck never executes scanned repository code or JavaScript configuration, never extracts ZIP files, and performs no network requests or telemetry. Paths must remain inside the selected root. ZIP inspection is bounded and rejects unsafe or unsupported structures. Runtime code intentionally has no third-party dependencies.

GitHub Dependency Review was attempted on the first PR run but the action failed because the new repository's dependency-review platform capability was unavailable. The workflow was removed rather than marked continue-on-error; CodeQL and npm audit remain enforced and both passed.

Known limitations

  • Strict three-component semantic versions only; Chrome four-component versions are not supported in v0.1.0.
  • README detection is contextual and may flag intentional historical release prose.
  • CHANGELOG parsing supports common Markdown headings, not arbitrary formats.
  • ZIP64, multi-disk, encrypted, and non-stored/non-DEFLATE entries are unsupported.
  • npm package is packed and installation-tested locally but not published.

Acceptance checklist

  • Core version/document/artifact checks implemented
  • At least 40 meaningful tests (88 implemented)
  • Local lint/typecheck/tests/build/coverage/package/audit pass
  • Tarball installation smoke test passes
  • Shipcheck dogfoods its own repository
  • Ubuntu CI passes
  • Windows CI passes
  • macOS CI passes
  • CodeQL passes
  • Squash merged to main (a14330cb101645f60f3aa10ca0df4a1a60bc0dac)
  • Post-merge main push-run status could not be queried by the connected GitHub tool; its workflow-run endpoint exposes pull-request runs only

External release-tool limitation

The connected GitHub tool does not expose tag or GitHub Release creation endpoints. No branch was created as a fake substitute for tag v0.1.0, and npm publication is not claimed.

@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ce1fb9ab83

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/checks/artifact.ts
function forbiddenMatch(entry: string, forbidden: string): boolean {
const normalized = entry.replaceAll("\\", "/");
const rule = forbidden.replaceAll("\\", "/");
if (rule.endsWith("/")) return normalized === rule.slice(0, -1) || normalized.startsWith(rule);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Match forbidden directories below wrapper roots

When the forbidden rule ends in /, this branch only matches entries at the archive root (node_modules/... or .git/...). ZIPs with a single wrapper directory are explicitly supported elsewhere, so extension/node_modules/pkg/index.js or extension/.git/config will not produce ZIP_FORBIDDEN_ENTRY despite the default forbidden entries. Also check for nested /${rule} directory segments.

Useful? React with 👍 / 👎.

Comment thread src/zip.ts
const nameLength = u16(view, 26);
const extraLength = u16(view, 28);
const dataOffset = entry.localHeaderOffset + 30 + nameLength + extraLength;
const compressed = await readExactly(handle, dataOffset, entry.compressedSize);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Bound compressed ZIP reads before allocation

When an untrusted ZIP has a central-directory entry whose uncompressedSize is under maxEntryBytes but whose compressedSize is very large, this line allocates that advertised compressed length inside readExactly before any compressed-size or file-range bound. A malicious artifact selected by internalVersionSources can therefore force very large memory use instead of being rejected as invalid/unreadable. Bound compressedSize and dataOffset + compressedSize before reading.

Useful? React with 👍 / 👎.

Comment thread src/utils.ts
return current;
}

const SEMVER_RE = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Make accepted SemVer forms consistent across checks

With a primary version like 1.2.3+build.7, this accepts the version source, but the README, CHANGELOG, and artifact filename matchers only capture through 1.2.3/prerelease. Matching docs or artifacts then report drift or a missing current version even though they contain the same SemVer. Either reject build metadata here or make every downstream matcher capture the optional +... portion.

Useful? React with 👍 / 👎.

@kodlbegiko
kodlbegiko merged commit a14330c into main Jul 22, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants