From 3a33728438b7f8cabca6ee74c2cded18f6077517 Mon Sep 17 00:00:00 2001 From: Pete Stenger Date: Sat, 27 Jun 2026 14:11:00 -0700 Subject: [PATCH 1/4] various improvements --- .github/workflows/release-js.yaml | 42 ++++++++++++++++--- .github/workflows/release.yaml | 26 ++++++++++++ js/README.md | 29 +++++++++++++ js/launcher.ts | 41 +++++++++++++++++++ js/npm/darwin-arm64/bin/.gitignore | 2 + js/npm/darwin-arm64/package.json | 14 +++++++ js/npm/darwin-x64/bin/.gitignore | 2 + js/npm/darwin-x64/package.json | 14 +++++++ js/npm/linux-arm64/bin/.gitignore | 2 + js/npm/linux-arm64/package.json | 14 +++++++ js/npm/linux-x64/bin/.gitignore | 2 + js/npm/linux-x64/package.json | 14 +++++++ js/npm/win32-x64/bin/.gitignore | 2 + js/npm/win32-x64/package.json | 14 +++++++ js/package.json | 10 +++++ js/scripts/set-version.mjs | 42 +++++++++++++++++++ lib/format.go | 65 +++++++++++++++++++++++------- tests/in/copy.dockerfile | 9 +++++ tests/in/expose.dockerfile | 5 +++ tests/out/copy.dockerfile | 9 +++++ tests/out/expose.dockerfile | 5 +++ 21 files changed, 343 insertions(+), 20 deletions(-) create mode 100644 js/launcher.ts create mode 100644 js/npm/darwin-arm64/bin/.gitignore create mode 100644 js/npm/darwin-arm64/package.json create mode 100644 js/npm/darwin-x64/bin/.gitignore create mode 100644 js/npm/darwin-x64/package.json create mode 100644 js/npm/linux-arm64/bin/.gitignore create mode 100644 js/npm/linux-arm64/package.json create mode 100644 js/npm/linux-x64/bin/.gitignore create mode 100644 js/npm/linux-x64/package.json create mode 100644 js/npm/win32-x64/bin/.gitignore create mode 100644 js/npm/win32-x64/package.json create mode 100644 js/scripts/set-version.mjs create mode 100644 tests/in/copy.dockerfile create mode 100644 tests/in/expose.dockerfile create mode 100644 tests/out/copy.dockerfile create mode 100644 tests/out/expose.dockerfile diff --git a/.github/workflows/release-js.yaml b/.github/workflows/release-js.yaml index 83d3a1a..cc0a0a1 100644 --- a/.github/workflows/release-js.yaml +++ b/.github/workflows/release-js.yaml @@ -13,11 +13,41 @@ jobs: - uses: actions/setup-node@v4 with: node-version: '24.x' - - name: Set version from tag and publish + - uses: actions/setup-go@v5 + with: + go-version: '1.24.x' + # Compile the real dockerfmt binary for each published platform straight + # from cmd/root.go. The npm CLI is just a launcher around these binaries, + # so the CLI behaviour can never drift from the standalone Go tool. + - name: Build platform binaries + run: | + LDFLAGS="-s -w -X github.com/reteps/dockerfmt/cmd.Version=${GITHUB_REF_NAME}" + build() { + pkg=$1; goos=$2; goarch=$3; ext=$4 + echo "building $pkg ($goos/$goarch)" + GOOS=$goos GOARCH=$goarch CGO_ENABLED=0 \ + go build -ldflags "$LDFLAGS" -o "js/npm/${pkg}/bin/dockerfmt${ext}" . + } + build linux-x64 linux amd64 "" + build linux-arm64 linux arm64 "" + build darwin-x64 darwin amd64 "" + build darwin-arm64 darwin arm64 "" + build win32-x64 windows amd64 ".exe" + # Pin the main package, every sub-package, and the optionalDependencies to + # the release version so they publish in lockstep. + - name: Pin versions + run: node js/scripts/set-version.mjs "${GITHUB_REF_NAME#v}" + - name: Build JS library bindings + working-directory: js run: | - cd js - VERSION=${GITHUB_REF_NAME#v} - npm --no-git-tag-version version "${VERSION}" - npm ci + npm install --no-package-lock --omit=optional npm run build-js - npm publish --provenance --access public + # Publish the platform packages first so the main package's + # optionalDependencies resolve immediately on install. + - name: Publish platform packages + run: | + for dir in js/npm/*/; do + npm publish --provenance --access public "$dir" + done + - name: Publish main package + run: npm publish --provenance --access public ./js diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 795ace6..fa09cef 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -48,4 +48,30 @@ jobs: github_token: ${{ secrets.GITHUB_TOKEN }} goos: ${{ matrix.goos }} goarch: ${{ matrix.goarch }} + ldflags: -X github.com/reteps/dockerfmt/cmd.Version=${{ github.ref_name }} + # dockerfmt is pure Go (no cgo), so a CGO_ENABLED=0 build is fully static and + # already runs on musl-based systems like Alpine. This job re-publishes the + # static linux binaries under a clearly "musl"-labeled asset name so musl + # users have an obvious download. The default (glibc-labeled) artifacts above + # are left untouched. + releases-musl-matrix: + name: Release Go Binary (musl) + runs-on: ubuntu-latest + strategy: + matrix: + goos: [linux] + goarch: [amd64, arm64] + steps: + - uses: actions/checkout@v4 + - uses: wangyoucao577/go-release-action@v1 + env: + # Guarantee a statically linked binary with no libc dependency. + CGO_ENABLED: 0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + goos: ${{ matrix.goos }} + goarch: ${{ matrix.goarch }} + # Append a "musl" suffix to the default asset name so the static, + # Alpine-compatible build is easy to identify. + asset_name: dockerfmt-${{ github.ref_name }}-${{ matrix.goos }}-${{ matrix.goarch }}-musl ldflags: -X github.com/reteps/dockerfmt/cmd.Version=${{ github.ref_name }} \ No newline at end of file diff --git a/js/README.md b/js/README.md index 32b69bb..b884d72 100644 --- a/js/README.md +++ b/js/README.md @@ -11,3 +11,32 @@ const result = await formatDockerfile('../tests/comment.dockerfile', { indent: 4 console.log(result) ``` + +## CLI + +The package also ships the `dockerfmt` CLI, so you can use it via `npx` or as a +dev dependency in JS/CI workflows without separately installing the Go binary: + +```sh +# Format a Dockerfile and print to stdout +npx dockerfmt Dockerfile + +# Read from stdin +echo 'from alpine' | npx dockerfmt + +# Format in place +npx dockerfmt -w Dockerfile + +# Check mode (exits non-zero if any file is not formatted) +npx dockerfmt -c Dockerfile +``` + +This is **the same binary** as the standalone Go tool — npm just ships the +prebuilt binary for your platform (as an optional dependency) and a small +launcher that execs it. Flags, defaults, EditorConfig support and exit codes are +therefore identical to the Go CLI; see the [main README](../README.md) for the +full reference. + +Prebuilt binaries are published for `linux-x64`, `linux-arm64`, `darwin-x64`, +`darwin-arm64`, and `win32-x64`. On other platforms, install the Go binary from +the [releases page](https://github.com/reteps/dockerfmt/releases) instead. diff --git a/js/launcher.ts b/js/launcher.ts new file mode 100644 index 0000000..cff1e11 --- /dev/null +++ b/js/launcher.ts @@ -0,0 +1,41 @@ +#!/usr/bin/env node +// Thin launcher that execs the real `dockerfmt` Go binary. There is no JS +// reimplementation of the CLI: the binary is built from cmd/root.go, so flags, +// defaults, EditorConfig handling and exit codes are guaranteed to match the +// standalone Go tool exactly. Each platform's binary ships in its own optional +// dependency (see optionalDependencies in package.json); npm installs only the +// one matching the host's os/cpu. +import { execFileSync } from 'node:child_process' +import { createRequire } from 'node:module' + +const require = createRequire(import.meta.url) + +const platform = process.platform +const arch = process.arch + +// Keep this list in sync with optionalDependencies in package.json, the +// directories under js/npm/, and the build matrix in release-js.yaml. +const pkg = `@reteps/dockerfmt-${platform}-${arch}` +const binName = platform === 'win32' ? 'dockerfmt.exe' : 'dockerfmt' + +let binPath: string +try { + binPath = require.resolve(`${pkg}/bin/${binName}`) +} catch { + throw new Error( + `dockerfmt does not ship a prebuilt binary for ${platform}-${arch} ` + + `(expected optional dependency "${pkg}"). Supported platforms: ` + + `linux-x64, linux-arm64, darwin-x64, darwin-arm64, win32-x64. ` + + `Download the Go binary from ` + + `https://github.com/reteps/dockerfmt/releases instead.`, + ) +} + +try { + execFileSync(binPath, process.argv.slice(2), { stdio: 'inherit' }) +} catch (err: unknown) { + const status = (err as { status?: number; signal?: string })?.status + // Propagate the binary's own exit code (e.g. 1 from --check) so the launcher + // is behaviourally transparent. + process.exit(typeof status === 'number' ? status : 1) +} diff --git a/js/npm/darwin-arm64/bin/.gitignore b/js/npm/darwin-arm64/bin/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/js/npm/darwin-arm64/bin/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/js/npm/darwin-arm64/package.json b/js/npm/darwin-arm64/package.json new file mode 100644 index 0000000..9aa5080 --- /dev/null +++ b/js/npm/darwin-arm64/package.json @@ -0,0 +1,14 @@ +{ + "name": "@reteps/dockerfmt-darwin-arm64", + "version": "0.0.0-dev", + "description": "The macOS arm64 binary for dockerfmt.", + "repository": { + "type": "git", + "url": "https://github.com/reteps/dockerfmt.git", + "directory": "js" + }, + "license": "MIT", + "os": ["darwin"], + "cpu": ["arm64"], + "files": ["bin"] +} diff --git a/js/npm/darwin-x64/bin/.gitignore b/js/npm/darwin-x64/bin/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/js/npm/darwin-x64/bin/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/js/npm/darwin-x64/package.json b/js/npm/darwin-x64/package.json new file mode 100644 index 0000000..b8b650d --- /dev/null +++ b/js/npm/darwin-x64/package.json @@ -0,0 +1,14 @@ +{ + "name": "@reteps/dockerfmt-darwin-x64", + "version": "0.0.0-dev", + "description": "The macOS x64 binary for dockerfmt.", + "repository": { + "type": "git", + "url": "https://github.com/reteps/dockerfmt.git", + "directory": "js" + }, + "license": "MIT", + "os": ["darwin"], + "cpu": ["x64"], + "files": ["bin"] +} diff --git a/js/npm/linux-arm64/bin/.gitignore b/js/npm/linux-arm64/bin/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/js/npm/linux-arm64/bin/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/js/npm/linux-arm64/package.json b/js/npm/linux-arm64/package.json new file mode 100644 index 0000000..0b70a9c --- /dev/null +++ b/js/npm/linux-arm64/package.json @@ -0,0 +1,14 @@ +{ + "name": "@reteps/dockerfmt-linux-arm64", + "version": "0.0.0-dev", + "description": "The Linux arm64 binary for dockerfmt.", + "repository": { + "type": "git", + "url": "https://github.com/reteps/dockerfmt.git", + "directory": "js" + }, + "license": "MIT", + "os": ["linux"], + "cpu": ["arm64"], + "files": ["bin"] +} diff --git a/js/npm/linux-x64/bin/.gitignore b/js/npm/linux-x64/bin/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/js/npm/linux-x64/bin/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/js/npm/linux-x64/package.json b/js/npm/linux-x64/package.json new file mode 100644 index 0000000..757ed21 --- /dev/null +++ b/js/npm/linux-x64/package.json @@ -0,0 +1,14 @@ +{ + "name": "@reteps/dockerfmt-linux-x64", + "version": "0.0.0-dev", + "description": "The Linux x64 binary for dockerfmt.", + "repository": { + "type": "git", + "url": "https://github.com/reteps/dockerfmt.git", + "directory": "js" + }, + "license": "MIT", + "os": ["linux"], + "cpu": ["x64"], + "files": ["bin"] +} diff --git a/js/npm/win32-x64/bin/.gitignore b/js/npm/win32-x64/bin/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/js/npm/win32-x64/bin/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/js/npm/win32-x64/package.json b/js/npm/win32-x64/package.json new file mode 100644 index 0000000..de3e107 --- /dev/null +++ b/js/npm/win32-x64/package.json @@ -0,0 +1,14 @@ +{ + "name": "@reteps/dockerfmt-win32-x64", + "version": "0.0.0-dev", + "description": "The Windows x64 binary for dockerfmt.", + "repository": { + "type": "git", + "url": "https://github.com/reteps/dockerfmt.git", + "directory": "js" + }, + "license": "MIT", + "os": ["win32"], + "cpu": ["x64"], + "files": ["bin"] +} diff --git a/js/package.json b/js/package.json index 67f0f88..819069c 100644 --- a/js/package.json +++ b/js/package.json @@ -29,6 +29,16 @@ "./wasm_exec": "./dist/wasm_exec.js", "./wasm_exec.js": "./dist/wasm_exec.js" }, + "bin": { + "dockerfmt": "./dist/launcher.js" + }, + "optionalDependencies": { + "@reteps/dockerfmt-darwin-arm64": "0.0.0-dev", + "@reteps/dockerfmt-darwin-x64": "0.0.0-dev", + "@reteps/dockerfmt-linux-arm64": "0.0.0-dev", + "@reteps/dockerfmt-linux-x64": "0.0.0-dev", + "@reteps/dockerfmt-win32-x64": "0.0.0-dev" + }, "files": [ "dist" ], diff --git a/js/scripts/set-version.mjs b/js/scripts/set-version.mjs new file mode 100644 index 0000000..5a24dc2 --- /dev/null +++ b/js/scripts/set-version.mjs @@ -0,0 +1,42 @@ +// Pins the main package, every platform sub-package, and the main package's +// optionalDependencies to a single version. Run at publish time so the launcher +// always pulls in the exact-matching platform binary and the published versions +// can never drift apart. +// +// node scripts/set-version.mjs +import { readFileSync, writeFileSync, readdirSync } from 'node:fs' +import { dirname, join } from 'node:path' +import { fileURLToPath } from 'node:url' + +const version = process.argv[2] +if (!version) { + console.error('usage: node scripts/set-version.mjs ') + process.exit(1) +} + +const jsDir = dirname(dirname(fileURLToPath(import.meta.url))) +const npmDir = join(jsDir, 'npm') + +const writeJson = (path, obj) => + writeFileSync(path, JSON.stringify(obj, null, 2) + '\n') + +// Platform sub-packages. +const optionalDependencies = {} +for (const name of readdirSync(npmDir).sort()) { + const pkgPath = join(npmDir, name, 'package.json') + const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) + pkg.version = version + writeJson(pkgPath, pkg) + optionalDependencies[pkg.name] = version +} + +// Main package: bump version and pin every optional dependency exactly. +const mainPath = join(jsDir, 'package.json') +const main = JSON.parse(readFileSync(mainPath, 'utf8')) +main.version = version +main.optionalDependencies = optionalDependencies +writeJson(mainPath, main) + +console.log( + `Pinned ${version} on main + ${Object.keys(optionalDependencies).length} platform packages`, +) diff --git a/lib/format.go b/lib/format.go index d3722f3..bf13c80 100644 --- a/lib/format.go +++ b/lib/format.go @@ -63,10 +63,16 @@ func (n *ExtendedNode) directive() string { // prependFlags prepends flags (e.g. "--network=host") to content if any exist. // When any flag starts with "--mount", each flag is placed on its own continuation line. func prependFlags(flags []string, content string, c *Config) string { + return prependFlagsImpl(flags, content, c, hasMountFlag(flags)) +} + +// prependFlagsImpl prepends flags to content. When multiline is true, each flag +// is placed on its own continuation line. +func prependFlagsImpl(flags []string, content string, c *Config, multiline bool) string { if len(flags) == 0 { return content } - if hasMountFlag(flags) { + if multiline { indent := strings.Repeat(" ", int(c.IndentSize)) var b strings.Builder for _, flag := range flags { @@ -80,6 +86,12 @@ func prependFlags(flags []string, content string, c *Config) string { return strings.Join(flags, " ") + " " + content } +// hasLineContinuation reports whether the node's original source spanned multiple +// lines via "\" continuations. +func hasLineContinuation(n *ExtendedNode) bool { + return strings.Contains(n.OriginalMultiline, "\\\n") +} + func hasMountFlag(flags []string) bool { for _, f := range flags { if strings.HasPrefix(f, "--mount") { @@ -130,19 +142,18 @@ func extractDirectiveContent(n *ExtendedNode, flagCount int) (string, bool) { return parts[1], true } - var nodeFormatters map[string]func(*ExtendedNode, *Config) string func init() { nodeFormatters = map[string]func(*ExtendedNode, *Config) string{ - command.Add: formatSpaceSeparated, + command.Add: spaceSeparated(flagsOnOwnLines), command.Arg: formatBasic, command.Cmd: formatCmd, - command.Copy: formatSpaceSeparated, + command.Copy: spaceSeparated(flagsOnOwnLines), command.Entrypoint: formatCmd, command.Env: formatEnv, - command.Expose: formatSpaceSeparated, - command.From: formatSpaceSeparated, + command.Expose: spaceSeparated(argsOnOwnLines), + command.From: spaceSeparated(collapseLines), command.Healthcheck: formatBasic, command.Label: formatBasic, command.Maintainer: formatMaintainer, @@ -152,7 +163,7 @@ func init() { command.StopSignal: formatBasic, command.User: formatBasic, command.Volume: formatBasic, - command.Workdir: formatSpaceSeparated, + command.Workdir: spaceSeparated(collapseLines), } } @@ -528,14 +539,40 @@ func formatCmd(n *ExtendedNode, c *Config) string { return n.directive() + " " + prependFlags(flags, shell, c) } -func formatSpaceSeparated(n *ExtendedNode, c *Config) string { - isJSON := n.Attributes["json"] - cmd, success := GetHeredoc(n) - if !success { - cmd = prependFlags(n.Flags, strings.Join(getCmd(n.Next, isJSON), " "), c) + "\n" - } +// multilineMode controls how a space-separated directive that the author wrote +// across multiple "\" continuation lines is re-emitted. The modes differ because +// the natural break point differs per directive: COPY/ADD break before each flag +// but keep " " together, while EXPOSE breaks before each port. +type multilineMode int + +const ( + // collapseLines always joins everything onto a single line (FROM, WORKDIR). + collapseLines multilineMode = iota + // flagsOnOwnLines keeps each flag on its own continuation line (COPY, ADD). + flagsOnOwnLines + // argsOnOwnLines keeps each argument on its own continuation line (EXPOSE). + argsOnOwnLines +) + +// spaceSeparated returns a formatter for directives whose payload is a list of +// flags and space-separated arguments (COPY, ADD, EXPOSE, FROM, WORKDIR). The +// mode selects how multiline source is preserved; see multilineMode. +func spaceSeparated(mode multilineMode) func(*ExtendedNode, *Config) string { + return func(n *ExtendedNode, c *Config) string { + isJSON := n.Attributes["json"] + cmd, success := GetHeredoc(n) + if !success { + argSep := " " + if mode == argsOnOwnLines && hasLineContinuation(n) { + argSep = " \\\n" + strings.Repeat(" ", int(c.IndentSize)) + } + content := strings.Join(getCmd(n.Next, isJSON), argSep) + flagsMultiline := mode == flagsOnOwnLines && (hasLineContinuation(n) || hasMountFlag(n.Flags)) + cmd = prependFlagsImpl(n.Flags, content, c, flagsMultiline) + "\n" + } - return n.directive() + " " + cmd + return n.directive() + " " + cmd + } } func formatMaintainer(n *ExtendedNode, c *Config) string { diff --git a/tests/in/copy.dockerfile b/tests/in/copy.dockerfile new file mode 100644 index 0000000..fb4318e --- /dev/null +++ b/tests/in/copy.dockerfile @@ -0,0 +1,9 @@ +FROM scratch +COPY --exclude=nginx-default.conf \ + --exclude=zap-scan-automation-framework.yml \ + --exclude=renovate.json5 \ + --exclude=compose.yml \ + . . +COPY --chown=user:group ./single-line /dest +ADD --keep-git-dir \ + ./ /data/src diff --git a/tests/in/expose.dockerfile b/tests/in/expose.dockerfile new file mode 100644 index 0000000..24350b2 --- /dev/null +++ b/tests/in/expose.dockerfile @@ -0,0 +1,5 @@ +FROM scratch +EXPOSE 80 \ + 443 \ + 8080 +EXPOSE 9000 diff --git a/tests/out/copy.dockerfile b/tests/out/copy.dockerfile new file mode 100644 index 0000000..a5f3296 --- /dev/null +++ b/tests/out/copy.dockerfile @@ -0,0 +1,9 @@ +FROM scratch +COPY --exclude=nginx-default.conf \ + --exclude=zap-scan-automation-framework.yml \ + --exclude=renovate.json5 \ + --exclude=compose.yml \ + . . +COPY --chown=user:group ./single-line /dest +ADD --keep-git-dir \ + ./ /data/src diff --git a/tests/out/expose.dockerfile b/tests/out/expose.dockerfile new file mode 100644 index 0000000..dc32a3e --- /dev/null +++ b/tests/out/expose.dockerfile @@ -0,0 +1,5 @@ +FROM scratch +EXPOSE 80 \ + 443 \ + 8080 +EXPOSE 9000 From b656eb2b6b027e4cecb34a3425ff38604cd2181d Mon Sep 17 00:00:00 2001 From: Pete Stenger Date: Sat, 27 Jun 2026 14:13:36 -0700 Subject: [PATCH 2/4] windows --- .github/workflows/release-js.yaml | 13 ++++++------- .github/workflows/release.yaml | 2 +- js/README.md | 2 +- js/launcher.ts | 5 ++--- js/npm/win32-x64/bin/.gitignore | 2 -- js/npm/win32-x64/package.json | 14 -------------- js/package.json | 3 +-- 7 files changed, 11 insertions(+), 30 deletions(-) delete mode 100644 js/npm/win32-x64/bin/.gitignore delete mode 100644 js/npm/win32-x64/package.json diff --git a/.github/workflows/release-js.yaml b/.github/workflows/release-js.yaml index cc0a0a1..3db1e62 100644 --- a/.github/workflows/release-js.yaml +++ b/.github/workflows/release-js.yaml @@ -23,16 +23,15 @@ jobs: run: | LDFLAGS="-s -w -X github.com/reteps/dockerfmt/cmd.Version=${GITHUB_REF_NAME}" build() { - pkg=$1; goos=$2; goarch=$3; ext=$4 + pkg=$1; goos=$2; goarch=$3 echo "building $pkg ($goos/$goarch)" GOOS=$goos GOARCH=$goarch CGO_ENABLED=0 \ - go build -ldflags "$LDFLAGS" -o "js/npm/${pkg}/bin/dockerfmt${ext}" . + go build -ldflags "$LDFLAGS" -o "js/npm/${pkg}/bin/dockerfmt" . } - build linux-x64 linux amd64 "" - build linux-arm64 linux arm64 "" - build darwin-x64 darwin amd64 "" - build darwin-arm64 darwin arm64 "" - build win32-x64 windows amd64 ".exe" + build linux-x64 linux amd64 + build linux-arm64 linux arm64 + build darwin-x64 darwin amd64 + build darwin-arm64 darwin arm64 # Pin the main package, every sub-package, and the optionalDependencies to # the release version so they publish in lockstep. - name: Pin versions diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index fa09cef..efd0f08 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - # build and publish in parallel: linux/386, linux/amd64, linux/arm64, windows/386, windows/amd64, darwin/amd64, darwin/arm64 + # build and publish in parallel: linux/amd64, linux/arm64, darwin/arm64 goos: [linux, darwin] goarch: [amd64, arm64] exclude: diff --git a/js/README.md b/js/README.md index b884d72..7d30d01 100644 --- a/js/README.md +++ b/js/README.md @@ -38,5 +38,5 @@ therefore identical to the Go CLI; see the [main README](../README.md) for the full reference. Prebuilt binaries are published for `linux-x64`, `linux-arm64`, `darwin-x64`, -`darwin-arm64`, and `win32-x64`. On other platforms, install the Go binary from +and `darwin-arm64`. On other platforms, install the Go binary from the [releases page](https://github.com/reteps/dockerfmt/releases) instead. diff --git a/js/launcher.ts b/js/launcher.ts index cff1e11..5ee0e82 100644 --- a/js/launcher.ts +++ b/js/launcher.ts @@ -16,16 +16,15 @@ const arch = process.arch // Keep this list in sync with optionalDependencies in package.json, the // directories under js/npm/, and the build matrix in release-js.yaml. const pkg = `@reteps/dockerfmt-${platform}-${arch}` -const binName = platform === 'win32' ? 'dockerfmt.exe' : 'dockerfmt' let binPath: string try { - binPath = require.resolve(`${pkg}/bin/${binName}`) + binPath = require.resolve(`${pkg}/bin/dockerfmt`) } catch { throw new Error( `dockerfmt does not ship a prebuilt binary for ${platform}-${arch} ` + `(expected optional dependency "${pkg}"). Supported platforms: ` + - `linux-x64, linux-arm64, darwin-x64, darwin-arm64, win32-x64. ` + + `linux-x64, linux-arm64, darwin-x64, darwin-arm64. ` + `Download the Go binary from ` + `https://github.com/reteps/dockerfmt/releases instead.`, ) diff --git a/js/npm/win32-x64/bin/.gitignore b/js/npm/win32-x64/bin/.gitignore deleted file mode 100644 index d6b7ef3..0000000 --- a/js/npm/win32-x64/bin/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/js/npm/win32-x64/package.json b/js/npm/win32-x64/package.json deleted file mode 100644 index de3e107..0000000 --- a/js/npm/win32-x64/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "@reteps/dockerfmt-win32-x64", - "version": "0.0.0-dev", - "description": "The Windows x64 binary for dockerfmt.", - "repository": { - "type": "git", - "url": "https://github.com/reteps/dockerfmt.git", - "directory": "js" - }, - "license": "MIT", - "os": ["win32"], - "cpu": ["x64"], - "files": ["bin"] -} diff --git a/js/package.json b/js/package.json index 819069c..d1dbcb8 100644 --- a/js/package.json +++ b/js/package.json @@ -36,8 +36,7 @@ "@reteps/dockerfmt-darwin-arm64": "0.0.0-dev", "@reteps/dockerfmt-darwin-x64": "0.0.0-dev", "@reteps/dockerfmt-linux-arm64": "0.0.0-dev", - "@reteps/dockerfmt-linux-x64": "0.0.0-dev", - "@reteps/dockerfmt-win32-x64": "0.0.0-dev" + "@reteps/dockerfmt-linux-x64": "0.0.0-dev" }, "files": [ "dist" From e7aac6f17bab9dc8f7171a9b1ef8ba20e542d463 Mon Sep 17 00:00:00 2001 From: Pete Stenger Date: Sat, 27 Jun 2026 14:16:12 -0700 Subject: [PATCH 3/4] update readme --- js/README.md | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/js/README.md b/js/README.md index 7d30d01..26399d5 100644 --- a/js/README.md +++ b/js/README.md @@ -2,7 +2,6 @@ Bindings around the Golang `dockerfmt` tooling. It compiles the Go code to WebAssembly (using standard Go's `GOOS=js GOARCH=wasm` target), which is then used in the JS bindings. - ```js import { formatDockerfile } from '@reteps/dockerfmt' // Alternatively, you can use `formatDockerfileContents` to format a string instead of a file. @@ -14,29 +13,9 @@ console.log(result) ## CLI -The package also ships the `dockerfmt` CLI, so you can use it via `npx` or as a -dev dependency in JS/CI workflows without separately installing the Go binary: +The package also ships the `dockerfmt` CLI. ```sh # Format a Dockerfile and print to stdout npx dockerfmt Dockerfile - -# Read from stdin -echo 'from alpine' | npx dockerfmt - -# Format in place -npx dockerfmt -w Dockerfile - -# Check mode (exits non-zero if any file is not formatted) -npx dockerfmt -c Dockerfile ``` - -This is **the same binary** as the standalone Go tool — npm just ships the -prebuilt binary for your platform (as an optional dependency) and a small -launcher that execs it. Flags, defaults, EditorConfig support and exit codes are -therefore identical to the Go CLI; see the [main README](../README.md) for the -full reference. - -Prebuilt binaries are published for `linux-x64`, `linux-arm64`, `darwin-x64`, -and `darwin-arm64`. On other platforms, install the Go binary from -the [releases page](https://github.com/reteps/dockerfmt/releases) instead. From 81940365c83a4bb9972df68a25e6fe3732bc0781 Mon Sep 17 00:00:00 2001 From: Pete Stenger Date: Sat, 27 Jun 2026 14:17:07 -0700 Subject: [PATCH 4/4] bad comment --- .github/workflows/release-js.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/release-js.yaml b/.github/workflows/release-js.yaml index 3db1e62..ecadea7 100644 --- a/.github/workflows/release-js.yaml +++ b/.github/workflows/release-js.yaml @@ -16,9 +16,6 @@ jobs: - uses: actions/setup-go@v5 with: go-version: '1.24.x' - # Compile the real dockerfmt binary for each published platform straight - # from cmd/root.go. The npm CLI is just a launcher around these binaries, - # so the CLI behaviour can never drift from the standalone Go tool. - name: Build platform binaries run: | LDFLAGS="-s -w -X github.com/reteps/dockerfmt/cmd.Version=${GITHUB_REF_NAME}"