Skip to content
Open
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
11 changes: 11 additions & 0 deletions .cloud/docker/docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/sh
set -e

# Run command with nf if the first argument contains a "-" or is not a system command. The last
# part inside the "{}" is a workaround for the following bug in ash/dash:
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264
if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then
set -- nf "$@"
fi

exec "$@"
Comment on lines +1 to +11
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this useful ?

Copy link
Member Author

Choose a reason for hiding this comment

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

To override the node docker entrypoint

21 changes: 21 additions & 0 deletions .cloud/docker/nf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac

if [ -z "$NODE_PATH" ]; then
export NODE_PATH="/usr/nanoforge/node_modules"
else
export NODE_PATH="/usr/nanoforge/node_modules:$NODE_PATH"
fi
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/cli/dist/nf.js" "$@"
else
exec node "$basedir/cli/dist/nf.js" "$@"
fi
Comment on lines +1 to +21
Copy link
Contributor

Choose a reason for hiding this comment

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

cant we just use a release version of nanoforge instead of that ?

Copy link
Member Author

Choose a reason for hiding this comment

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

what do you mean by that ?

2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/01-command_bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ body:
description: List necessary versions here. This includes your package version, runtime version, operating system etc.
placeholder: |
- @nanoforge-dev/cli 1.0.0 (`npm ls @nanoforge-dev/cli`)
- Node.js 24.11.0 (`node --version`)
- Node.js 25.x.x (`node --version`)
- TypeScript 5.9.3 (`npm ls typescript` if you use it)
- macOS Ventura 13.3.1
validations:
Expand Down
31 changes: 31 additions & 0 deletions .github/actions/prepare/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: prepare
description: Prepare action
inputs:
node-install:
description: Install node
default: "true"
pnpm-install:
description: Install pnpm depedencies
default: "true"
build:
description: Build packages
default: "true"
runs:
using: composite
steps:
- if: inputs.node-install == 'true'
name: Install Node.js v25
uses: actions/setup-node@v6
with:
node-version: 25
package-manager-cache: false
registry-url: https://registry.npmjs.org

- if: inputs.pnpm-install == 'true'
name: Install dependencies
uses: ./.github/actions/pnpm-install

- if: inputs.build == 'true'
name: Build packages
shell: bash
run: pnpm run build
41 changes: 41 additions & 0 deletions .github/workflows/pre-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Pre-Release

on:
workflow_dispatch:
inputs:
version:
description: "New version of the package (leave empty for auto generated version)"
type: string
required: false
dry_run:
description: Perform a dry run?
type: boolean
default: false

permissions:
contents: write
pull-requests: write

jobs:
create-release-pr:
name: Create release pr
runs-on: ubuntu-latest
if: github.repository_owner == 'NanoForge-dev'
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true

- name: Prepare
uses: ./.github/actions/prepare

- name: Release packages
uses: ./node_modules/@nanoforge-dev/actions/dist/create-release-pr
with:
package: "@nanoforge-dev/cli"
version: ${{ inputs.version }}
dry: ${{ inputs.dry_run }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
105 changes: 105 additions & 0 deletions .github/workflows/release-docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
name: Release Docker

on:
release:
types:
- published

permissions:
contents: write

env:
IMAGE_NAME: nanoforge/cli

jobs:
build:
name: Build ${{ matrix.platform }}
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm
steps:
- name: Prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV

- name: Checkout repository
uses: actions/checkout@v6

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}

- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
platforms: ${{ matrix.platform }}
outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true

- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"

- name: Upload digest
uses: actions/upload-artifact@v5
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1

merge:
name: Create and push manifest list
runs-on: ubuntu-latest
needs: build
steps:
- name: Download digests
uses: actions/download-artifact@v6
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true

- name: Checkout repository
uses: actions/checkout@v6

- name: Version
id: version
run: |
VERSION=$(jq --raw-output '.version' package.json)
echo "version=$VERSION" >> $GITHUB_OUTPUT

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}

- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create -t ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }} \
$(printf '${{ env.IMAGE_NAME }}@sha256:%s ' *)

- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }}
31 changes: 31 additions & 0 deletions .github/workflows/release-tag.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Release Tag

on:
pull_request:
types:
- closed
branches:
- main

permissions:
contents: write

jobs:
create-release-tag:
name: Create release tag
runs-on: ubuntu-latest
if: github.repository_owner == 'NanoForge-dev' && github.event.pull_request.merged == true && startsWith(github.head_ref, 'releases/')
steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Prepare
uses: ./.github/actions/prepare

- name: Create release tag
uses: ./node_modules/@nanoforge-dev/actions/dist/create-release-tag
with:
commit: ${{ github.sha }}
branch: ${{ github.head_ref }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v6

- name: Install Node.js v24
- name: Install Node.js v25
uses: actions/setup-node@v6
with:
node-version: 24
node-version: 25
package-manager-cache: false
registry-url: https://registry.npmjs.org/

Expand Down
23 changes: 23 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Tests

on:
pull_request:
branches:
- main
push:
branches:
- main
workflow_dispatch:

jobs:
tests:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Prepare
uses: ./.github/actions/prepare

- name: Run linter
run: pnpm lint
1 change: 0 additions & 1 deletion .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
pnpm --no-install lint-staged
pnpm format
1 change: 1 addition & 0 deletions .husky/pre-push
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pnpm lint
pnpm build
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
24.11.1
25
42 changes: 42 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
FROM node:25-alpine AS base

ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
ENV CI=true

COPY . /usr/nanoforge
WORKDIR /usr/nanoforge

RUN npm --global install corepack@latest --force
RUN corepack enable

FROM base AS builder

RUN pnpm install --frozen-lockfile --ignore-scripts
RUN pnpm run build

FROM builder AS pruned

RUN pnpm --filter='@nanoforge-dev/cli' --prod deploy --legacy pruned

FROM node:25-alpine AS cli

WORKDIR /usr/nanoforge

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nanoforge
USER nanoforge

COPY --from=pruned /usr/nanoforge/pruned cli
COPY .cloud/docker/nf /usr/nanoforge

COPY .cloud/docker/docker-entrypoint.sh /usr/local/bin

ENV NANOFORGE_HOME="/usr/nanoforge"
ENV PATH="$NANOFORGE_HOME:$PATH"

ENTRYPOINT ["docker-entrypoint.sh"]

WORKDIR /app

CMD ["nf"]
38 changes: 2 additions & 36 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,3 @@
import pluginJs from "@eslint/js";
import eslintConfigPrettier from "eslint-config-prettier";
import globals from "globals";
import tseslint from "typescript-eslint";
import eslintConfig from "@nanoforge-dev/utils-eslint-config";

export default [
{ files: ["src/**/*.{ts}"] },
{ languageOptions: { globals: globals.node } },

pluginJs.configs.recommended,
...tseslint.configs.recommended,
...tseslint.configs.strict,
eslintConfigPrettier,
{ ignores: ["**/*.js", "**/*.d.ts", "dist/", ".cloud/", ".idea/"] },
{
rules: {
"@typescript-eslint/no-extraneous-class": "off",
"@typescript-eslint/no-empty-object-type": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/member-ordering": [
"error",
{
default: [
"static-field",
"field",
"public-static-method",
"constructor",
"method",
"protected-method",
"private-method",
],
},
],
},
},
];
export default eslintConfig;
Loading