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
25 changes: 25 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ jobs:
NSHELL_TEST_PTY: "1"
run: nix develop -c sbcl --script run-tests.lisp

- name: Verify dependency suites and private history storage
env:
HOME: ${{ runner.temp }}/nshell-dependency-home
XDG_CACHE_HOME: ${{ runner.temp }}/nshell-dependency-cache
XDG_CONFIG_HOME: ${{ runner.temp }}/nshell-dependency-config
XDG_STATE_HOME: ${{ runner.temp }}/nshell-dependency-state
NSHELL_AI_COMMAND: /nonexistent
NSHELL_TEST_PTY: "1"
run: |
nix develop -c bash scripts/test-dependencies.sh
nix develop -c sbcl --script scripts/test-history-storage.lisp

coverage:
# Keep coverage separate from the integration gate: the report instrumented
# run is slower and writes generated files, while integration remains the
Expand Down Expand Up @@ -155,5 +167,18 @@ jobs:
- name: Build release bundle
run: nix build .#releaseBundle --print-build-logs

- name: Verify release PTY harness regressions
run: perl t/scripts/test-release-pty.pl

- name: Verify release bundle
run: perl scripts/verify-release-bundle.pl result

- name: Verify extracted release bundle with a real PTY
run: |
set -euo pipefail
archive="$RUNNER_TEMP/nshell-ci.tar.gz"
tar -czf "$archive" -C result .
extracted="$(mktemp -d "$RUNNER_TEMP/nshell-ci.XXXXXX")"
tar -xzf "$archive" -C "$extracted"
perl scripts/verify-release-bundle.pl "$extracted"
perl scripts/test-release-pty.pl "$extracted"
22 changes: 22 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,18 @@ jobs:
NSHELL_TEST_PTY: "1"
run: nix develop -c sbcl --script run-tests.lisp

- name: Verify dependency suites and private history storage
env:
HOME: ${{ runner.temp }}/nshell-dependency-home
XDG_CACHE_HOME: ${{ runner.temp }}/nshell-dependency-cache
XDG_CONFIG_HOME: ${{ runner.temp }}/nshell-dependency-config
XDG_STATE_HOME: ${{ runner.temp }}/nshell-dependency-state
NSHELL_AI_COMMAND: /nonexistent
NSHELL_TEST_PTY: "1"
run: |
nix develop -c bash scripts/test-dependencies.sh
nix develop -c sbcl --script scripts/test-history-storage.lisp

release:
name: build and publish x86_64-linux
needs: [verify, integration]
Expand Down Expand Up @@ -155,6 +167,16 @@ jobs:
rm "dist/${name}.repro.tar.gz"
( cd dist && shasum -a 256 "${name}.tar.gz" > "${name}.tar.gz.sha256" )

- name: Verify the packaged archive
run: |
set -euo pipefail
name="nshell-${RELEASE_REF}-x86_64-linux"
( cd dist && shasum -a 256 -c "${name}.tar.gz.sha256" )
extracted="$(mktemp -d "$RUNNER_TEMP/nshell-release.XXXXXX")"
tar -xzf "dist/${name}.tar.gz" -C "$extracted"
perl scripts/verify-release-bundle.pl "$extracted/$name"
perl scripts/test-release-pty.pl "$extracted/$name"

# Publish only after the maintainer supplies user-facing release notes.
- name: Create draft release
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
Expand Down
46 changes: 29 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ The release and Nix flake support `x86_64-linux` only. With
[Nix](https://nixos.org/download) and flakes enabled:

```sh
nix run github:nerima-lisp/nshell/v0.6.1
nix run github:nerima-lisp/nshell/v0.6.2
```

Then type as you would in any shell. Commands and paths colorize live, and a
At the prompt, enter `string upper hello`. Commands and paths colorize live, and a
dimmed completion of the most recent matching history entry trails the cursor;
press `→` or `Ctrl-F` to accept it:

Expand All @@ -43,20 +43,28 @@ Interactive history expansion supports `!!`, `!$`, `!-N`, `!?text?`, and
`!prefix`; exclamation marks inside single quotes or preceded by a backslash
remain literal. Press `Alt-E` to edit the current command in the editor named
by `NSHELL_EDITOR`, `VISUAL`, or `EDITOR` (falling back to `vi`), then return
the edited line to nshell.
the edited line to nshell. Save and quit the editor, then press Enter in nshell
to execute it. See [History expansion](docs/src/guide/concepts.md#history-expansion-is-explicit)
for the expansion forms.

History is stored in `~/.nshell_history` with owner-only permissions. Symlinks,
hard links, and files owned by another user are rejected. A malformed tail is
reported without discarding existing bytes; further appends are refused until
the file is moved aside. `--no-history` disables persistence.

## Install

```sh
nix profile install github:nerima-lisp/nshell/v0.6.1
nix profile install github:nerima-lisp/nshell/v0.6.2
```

Pin a release tag rather than following the default branch.

The `x86_64-linux` release bundle removes Nix store references, carries its
To install without Nix, use the `x86_64-linux` release bundle. It removes Nix store references, carries its
ELF runtime library closure, and is checked for required files and dependency
metadata. CI also runs `--help`, `--version`, and an `echo` smoke test on the
bundle. See [Getting
metadata. CI checks an extracted archive and exercises its executable with a
real PTY, including editing, signals, job control, history restart, and terminal
restoration. See [Getting
started](https://nerima-lisp.github.io/nshell/getting-started/) for the bundle
verification and installation procedure.

Expand All @@ -71,19 +79,27 @@ verification and installation procedure.

```sh
nix develop # SBCL with CL_SOURCE_REGISTRY already set (x86_64-linux)
perl -e '$SIG{ALRM}=sub { exit 124 }; alarm 300; exec @ARGV' nix build .#checks.$(nix eval --raw --impure --expr 'builtins.currentSystem').default --no-link # run the test suite
perl -e '$SIG{ALRM}=sub { exit 124 }; alarm 300; exec @ARGV' nix flake check # full hermetic gate on x86_64-linux CI
perl -e 'alarm 300; exec @ARGV' nix build .#checks.$(nix eval --raw --impure --expr 'builtins.currentSystem').default --no-link # run the test suite
perl -e 'alarm 300; exec @ARGV' nix flake check # time-limited local hermetic check
nix fmt # format Nix sources (treefmt)
nix build # produces ./result/bin/nshell
nix build .#releaseBundle
perl scripts/verify-release-bundle.pl result
perl scripts/test-release-pty.pl result
```

The Perl wrappers limit each local check to five minutes and return exit code
124 if that limit expires.
The Perl wrappers send `SIGALRM` to each local check after five minutes.
This is not the full CI gate's time limit; see
[Recipes](docs/src/guide/recipes.md#run-the-test-suite) for that command.
The bundle checks run on Linux and require Perl, Python 3, `readelf`, and
standard POSIX tools.

Run source-loaded integration, dependency, and history checks with the
[isolated HOME and XDG procedure](docs/src/project/public-readiness.md#verification-outside-ci)
to avoid reading or modifying personal history and configuration.

To measure executable-source coverage, keep the report outside the checkout
and run the same hermetic test loader used by CI:
and use the isolated HOME and XDG procedure above with this command:

```sh
NSHELL_COVERAGE_DIR="$(mktemp -d)" \
Expand All @@ -97,7 +113,7 @@ is 85% (`NSHELL_COVERAGE_MIN`); the target is 100%
(`NSHELL_COVERAGE_TARGET`).

Tests live in `t/` and run under
[cl-weave](https://github.com/nerima-lisp/cl-weave), the org's test framework.
[cl-weave](https://github.com/nerima-lisp/cl-weave).
Cases needing a real PTY, `stty`, or external binaries cannot run in the Nix
sandbox and are covered by CI's separate `integration` job; run them locally
with the command in
Expand All @@ -116,7 +132,3 @@ guide and the [package standard](https://github.com/nerima-lisp/.github/blob/mai
See [SUPPORT](https://github.com/nerima-lisp/.github/blob/main/SUPPORT.md).
Report vulnerabilities privately per this repository's
[security policy](SECURITY.md) rather than a public issue.

## License

MIT. See [LICENSE](LICENSE).
20 changes: 14 additions & 6 deletions docs/notes/nerima-lisp-package-audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,26 @@ nshell. Neither they nor `cl-log-kit` is a direct dependency in `nshell.asd`.
`nshell/test` uses `cl-weave`. `nshell/weave` additionally depends on
`cl-prolog-kit/weave` for completion-query tests. Loading a library or its test
helpers is not the same as running that library's own suite. The sibling
derivations do not enable `doCheck`, and the CI jobs run nshell's suites,
not the dependencies' own suites. In particular, `checks.weave` runs
`nshell/weave`, not `cl-weave/test`. Dependency suite results remain unverified.
derivations do not enable `doCheck`. In particular, `checks.weave` runs
`nshell/weave`, not `cl-weave/test`.

The current CI and release integration jobs additionally run
[`scripts/test-dependencies.sh`](../../scripts/test-dependencies.sh).
It starts a separate Lisp image for each pinned dependency suite. Its
[`runner`](../../scripts/test-dependencies.lisp) requires nonempty discovery,
matching discovered, selected, executed, and passed counts, and matching test
paths. Skipped, pending, focused, or failed tests do not clear that gate.
The jobs also run the private-history storage regressions. These gates do not
retroactively verify dependencies in the published v0.6.1 tree; their results
must be checked for the commit being released.

`cl-nix-forge` supplies the Nix build helpers. `paredit-cli` is a development
tool, not an executable runtime dependency. Release refs are declared in
`flake.nix`; resolved revisions and hashes are recorded in
[`flake.lock`](../../flake.lock). This audit makes no claim that those refs are
the newest upstream tags. An upgrade must update the declaration and lock file,
review the local [`cl-process-kit` patch](../../nix/patches/cl-process-kit-no-duplicate-monotonic-seconds.patch),
and rerun the release gates. The dependency's own suite also needs a separate
run.
review the local patches under [`nix/patches/`](../../nix/patches/), and rerun
the release gates, including the dependencies' own suites.

## Reproduce the source checks

Expand Down
90 changes: 47 additions & 43 deletions docs/src/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,49 +5,60 @@ outside the tested support boundary.

## Run without installing

With [Nix](https://nixos.org/download) (flakes enabled):
Install [Nix](https://nixos.org/download) and enable its `nix-command` and
`flakes` experimental features before running:

```sh
nix run github:nerima-lisp/nshell/v0.6.1
nix run github:nerima-lisp/nshell/v0.6.2
```

## Install

```sh
nix profile install github:nerima-lisp/nshell/v0.6.1
nshell
nix profile install github:nerima-lisp/nshell/v0.6.2
man nshell # the manual page is installed alongside the binary
nshell
```

Pin a release tag rather than following the default branch.
Pin a release tag rather than following the default branch. Type `exit` to
leave the interactive shell.

### Prebuilt Linux bundle

Without Nix, download both assets from the
[v0.6.1 release](https://github.com/nerima-lisp/nshell/releases/tag/v0.6.1),
[v0.6.2 release](https://github.com/nerima-lisp/nshell/releases/tag/v0.6.2),
verify the checksum, and extract the bundle. On `x86_64-linux`, with `curl`,
`sha256sum`, and `tar` available, run these commands in an empty directory:

```sh
curl --fail --location --remote-name https://github.com/nerima-lisp/nshell/releases/download/v0.6.1/nshell-v0.6.1-x86_64-linux.tar.gz
curl --fail --location --remote-name https://github.com/nerima-lisp/nshell/releases/download/v0.6.1/nshell-v0.6.1-x86_64-linux.tar.gz.sha256
sha256sum --check nshell-v0.6.1-x86_64-linux.tar.gz.sha256
curl --fail --location --remote-name https://github.com/nerima-lisp/nshell/releases/download/v0.6.2/nshell-v0.6.2-x86_64-linux.tar.gz
curl --fail --location --remote-name https://github.com/nerima-lisp/nshell/releases/download/v0.6.2/nshell-v0.6.2-x86_64-linux.tar.gz.sha256
sha256sum --check nshell-v0.6.2-x86_64-linux.tar.gz.sha256
```

Proceed only if the checksum command succeeds:
Proceed only if the checksum command exits successfully and prints
`nshell-v0.6.2-x86_64-linux.tar.gz: OK`:

```sh
tar -xzf nshell-v0.6.1-x86_64-linux.tar.gz
./nshell-v0.6.1-x86_64-linux/bin/nshell --version
./nshell-v0.6.1-x86_64-linux/bin/nshell
man ./nshell-v0.6.1-x86_64-linux/share/man/man1/nshell.1
tar -xzf nshell-v0.6.2-x86_64-linux.tar.gz
./nshell-v0.6.2-x86_64-linux/bin/nshell --version
man ./nshell-v0.6.2-x86_64-linux/share/man/man1/nshell.1
./nshell-v0.6.2-x86_64-linux/bin/nshell
```

Keep the extracted directory intact: the launcher resolves libraries and
helpers relative to itself. To invoke `nshell` by name, add its `bin`
directory to your existing shell's `PATH`.
helpers relative to itself. The version output must identify `v0.6.2`.
Type `exit` to return to your existing shell. To use `nshell` by name in
the examples below, add the extracted `bin` directory to that shell's
`PATH`. For Bash or Zsh, from the download directory:

```sh
export PATH="$PWD/nshell-v0.6.2-x86_64-linux/bin:$PATH"
```

This changes only the current terminal session. Alternatively, replace
`nshell` in the examples with the full path to the extracted launcher.

The release workflow publishes an `x86_64-linux` tarball and SHA-256 checksum.
The release bundle removes Nix store references, carries its ELF runtime
library closure, and is checked for required files and dependency metadata. CI
also runs `--help`, `--version`, and an `echo` smoke test on the bundle. The
Expand All @@ -56,21 +67,24 @@ attestation.

## First commands

Start nshell and type as you would in any shell. The prompt shows the
Start nshell with `nshell`. The prompt shows the
working directory, the git branch (with `*` when the tree is dirty), and a
`❯` that turns red after a failing command; the last exit code and any
command that took a second or more appear on the right. The distinguishing
`❯` that turns red after a failing command. The right prompt shows a failing
exit code, the duration of commands that took at least one second, and the
current time when the prompt is rendered. The distinguishing
behaviour shows up while typing: commands colorize live (an unknown command
turns red before you run it), existing paths are underlined, and a dimmed
completion of the most recent matching history entry trails the cursor. Press
`→` or `Ctrl-F` to accept it. A mistyped command gets a `did you mean`
suggestion, `FOO=bar cmd` exports `FOO` for that one command, and `theme list`
suggestion, `FOO=bar printenv FOO` prints `bar` without keeping `FOO` in the
shell environment, and `theme list`
shows the color presets. The prompt layout, the colors, and the key
bindings are all configurable; see [Customization](guide/customization.md).

Set `NSHELL_GREETING` to replace the startup banner with your own line, or to
the empty string to start silently. It is read after `~/.nshellrc` runs, so
`set -x NSHELL_GREETING ""` in that file works.
the empty string to start silently. If you want to make this persistent,
create the optional `~/.nshellrc` startup file and add
`set -x NSHELL_GREETING ""`.

### One-off command

Expand All @@ -81,13 +95,14 @@ nshell -c 'string upper hello'
### Run a script

```sh
nshell examples/greet.nsh World
curl --fail --location --output greet.nsh https://raw.githubusercontent.com/nerima-lisp/nshell/v0.6.2/examples/greet.nsh
nshell greet.nsh World
```

Script files support multiline blocks (functions, `if`/`for`/`while`/`switch`),
comments, and a `#!` shebang; arguments after the script name are available as
`$argv`. See
[`examples/`](https://github.com/nerima-lisp/nshell/tree/main/examples) for a
[`examples/`](https://github.com/nerima-lisp/nshell/tree/v0.6.2/examples) for a
runnable sample.

### Command line
Expand All @@ -112,26 +127,15 @@ Options:

## Build from source

nshell builds with [SBCL](http://www.sbcl.org/) and ASDF. The supported and
tested path is Nix:
The Nix build supplies [SBCL](http://www.sbcl.org/), ASDF, and the dependencies.
On `x86_64-linux`, with Git and flake-enabled Nix installed:

```sh
git clone https://github.com/nerima-lisp/nshell
git clone --branch v0.6.2 https://github.com/nerima-lisp/nshell
cd nshell
nix build # produces ./result/bin/nshell
nix flake check # full hermetic gate on x86_64-linux CI
nix develop # dev shell with SBCL + cl-weave
nix build
./result/bin/nshell
```

`flake.nix` declares `x86_64-linux` only. The full hermetic flake gate, the
release-binary gate, and the non-sandboxed integration suite run in CI on that
target. A remote `x86_64-linux` builder can build the artifacts from another
host, but running the dev shell or the non-sandboxed PTY suite requires an
`x86_64-linux` execution environment.

Inside `nix develop`, load the system into a REPL:

```lisp
(asdf:load-system "nshell")
(nshell:main)
```
For the development shell and test commands, see
[Recipes](guide/recipes.md#run-the-test-suite).
Loading
Loading