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
16 changes: 16 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,19 @@ jobs:
# so CI runs the VM suite only.
- name: Test
run: yarn mocha 'src/**/*.spec.ts' -r ts-node/register

# npm pack runs prepack, so this step needs the install above.
- name: Packaging
run: bash scripts/packaging.test.sh

release-notes:
runs-on: ubuntu-latest
name: release notes
steps:
- uses: actions/checkout@v4

# The script builds its own git repository under mktemp and sets the
# commit identity inside it, so the job needs no node setup and no git
# configuration of its own.
- name: Test
run: bash scripts/release-notes.test.sh
17 changes: 8 additions & 9 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Publish

# Tag-triggered publish to npm. A pushed v* tag starts the run, but the
# publish step is gated on maintainer sign-off through the npm-publish
# environment and authenticates with that environment's NPM_TOKEN secret.
# environment and authenticates through npm trusted publishing (OIDC).
on:
push:
tags: ['v*']
Expand All @@ -11,20 +11,21 @@ jobs:
publish:
runs-on: ubuntu-latest
# Required-reviewer environment: a pushed tag queues the publish until a
# maintainer approves the run, and the environment scopes the NPM_TOKEN
# secret so no other workflow can read it. id-token stays enabled for
# npm provenance attestation.
# maintainer approves the run. The job holds no npm credential, so it
# writes no .npmrc auth entry and npm exchanges the id-token below for a
# short-lived one; that same token signs the provenance attestation.
environment: npm-publish
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- uses: actions/setup-node@v4
# No registry-url: it writes an .npmrc _authToken line, and npm stops at
# that unresolvable credential instead of falling through to OIDC.
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
registry-url: https://registry.npmjs.org
cache: yarn

- name: Upgrade npm
Expand All @@ -51,5 +52,3 @@ jobs:

- name: Publish
run: npm publish --access public --provenance
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Changelog

## [2.2.0]

Renames the package to `@atomichub/vert` and gates chain-specific host functions to the emulated chain.

### Breaking changes

- The package is published as `@atomichub/vert`, not `@waxio/vert`. Change the install name and every import to the new name. `0bb4d95`

### Features

- Host functions are gated per emulated chain. `new Blockchain({ chain: 'wax' })` opts into the WAX set, which includes `verify_rsa_sha256_sig`, and the generic default withholds chain-specific functions. A contract that passes the harness therefore also passes `setcode` on chains that do not provide them. (#1)

### Other changes

- The npm publish is tag-triggered and gated on the `npm-publish` environment. `prepack` builds `dist`, so a publish always ships compiled output. (#2)
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# VeRT
# @atomichub/vert (VeRT)

[![npm version](https://img.shields.io/npm/v/%40atomichub%2Fvert)](https://www.npmjs.com/package/@atomichub/vert) [![CI](https://github.com/atomicassets/vert/actions/workflows/ci.yml/badge.svg)](https://github.com/atomicassets/vert/actions/workflows/ci.yml) [![License](https://img.shields.io/npm/l/%40atomichub%2Fvert)](LICENSE)

**VM emulation RunTime for WASM-based blockchain contracts**

Expand All @@ -13,6 +15,12 @@ The focus of VeRT is on the better compatibility than the performance, so it can
- Minimum dependencies (No native wrapper, docker or remote connection)
- Volatile key-value store with state rollback

## Installation

```shell
npm install @atomichub/vert
```

## Requirement

- WebAssembly binary with exported memory
Expand Down Expand Up @@ -40,12 +48,6 @@ instantiates under a `wax` blockchain and fails to instantiate under any other,
The chain-specific host functions are declared in `CHAIN_SPECIFIC_HOST_FUNCTIONS`; add an entry
there to model a new one.

## Installation

```shell
npm install @atomichub/vert
```

## Example usage

```typescript
Expand Down
198 changes: 198 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
# Releasing @atomichub/vert

How a version of this package reaches npm and GitHub. A release ends at a
rendered GitHub Release, not at the npm publish.

## Checklist

1. The feature PR carries the `CHANGELOG.md` entry for the version under
`## [X.Y.Z]`, written in the section shape below with H3 headings, and
lands on `main`. The entry is the editorial text of the Release, so it is
written once, in the PR that makes the change.

2. Land a `chore(release): X.Y.Z` commit on `main` that bumps the version in
`package.json` and touches nothing else. Read the `CHANGELOG.md` entry
against the template below now, because the next step publishes a tag.

3. Tag the release commit and push the tag:

```sh
git tag vX.Y.Z && git push origin vX.Y.Z
```

`.github/workflows/publish.yml` starts and waits on the `npm-publish`
environment. Push the tag before creating the Release, because
`gh release create` resolves the tag rather than creating it. The tag is
the release: consumers pin or float on it, so push it only once the entry
and the code behind it are ready.

4. Compose the body, read it, then create the Release:

```sh
scripts/release-notes.sh vX.Y.Z > notes.md
gh release create vX.Y.Z --verify-tag --title vX.Y.Z --notes-file notes.md
```

Add `--prerelease` for a candidate tag such as `vX.Y.Z-rc1`, so the
candidate does not take the latest marker. With more than one release in
flight, create them in ascending version order, so that marker stays
monotonic.

5. Approve the `npm-publish` environment for the tag. With more than one
release waiting, approve in ascending version order, so the npm `latest`
tag stays monotonic.

6. Verify the published version and the rendered Release:

```sh
npm view @atomichub/vert version
gh release view vX.Y.Z
```

## Publish auth

The publish job authenticates through npm trusted publishing (OIDC). It holds
no npm token and sets no registry URL on the setup step, so nothing writes an
`.npmrc` auth entry and npm 11.5.1 or later exchanges the job's OIDC identity
for a short-lived credential of its own. The `npm-publish` environment is the
gate on that identity: a pushed tag queues the run until a maintainer approves
it.

`publishConfig.provenance` in `package.json` makes a default local npm publish
fail, because no OIDC identity is available outside CI to satisfy it. It is
data inside the manifest being published, not an access control. The durable
control is the npm-side package setting that requires trusted publishing,
which is configured for `@atomichub/vert`.

## Body template

The Release title is the tag name verbatim. The body is an optional
one-sentence summary, then the sections that have items, then the commit list,
then the compare link as the last line. Nothing follows the link, and a
section with no items is left out.

```
<one-sentence summary, optional>

## Breaking changes

- <what changed, and what the reader does about it>. (#N)

## Upgrading

- <a renamed export, a configuration key to set, or a step to run>. (#N)

## Features

- <what is new>. (#N)

## Bug fixes

- <what was wrong and is not now>. (#N)

## Security

- <the advisory or the dependency lift, named>. (#N)

## Deprecations

- <what is deprecated and what replaces it>. (#N)

## Other changes

- <a change a consumer notices that fits no section above>. (#N)

## Commits

- <short sha> <subject>

Full changelog: https://github.com/atomicassets/vert/compare/<PREV>...<TAG>
```

The section order is breaking changes, upgrading, features, bug fixes,
security, deprecations, other changes. `## Security` carries advisories and
dependency lifts, each naming its GHSA or CVE identifier; a release with none
leaves the section out.

## Voice

- Neutral and factual, the register of the Node.js or esbuild release notes.
- Sectioned. The heading says what kind of change it is, so the item does not
repeat it.
- One to three plain sentences per item: what changed, and what the reader
does about it when action is needed. Code identifiers in backticks.
- Every item ends with its PR reference `(#N)`, or with its short sha in
backticks when the change had no PR.
- No preface, no motivation essay, no clause chain explaining how the author
got there. The why stays only where it changes what the reader does.
- Present tense for the new behavior, sentence-case headings, straight quotes,
and no em-dash.

## The CHANGELOG entry

`CHANGELOG.md` is where the editorial text is written, and the Release body is
that entry with its headings promoted one level. An entry heading is
`## [X.Y.Z]`. Under it comes an optional one-line summary, then the H3
sections in the order above. A candidate tag reads the entry for its base
version as it stands at that tag, so `vX.Y.Z-rc1` reads `## [X.Y.Z]`.

## Tag ranges and older releases

- `PREV` for a stable tag is the nearest earlier stable `v*` tag, so a stable
release lists every commit since the last stable release and skips the
prereleases between them. `PREV` for a prerelease tag is the nearest earlier
tag of any kind. A stable tag whose only earlier tags are prereleases takes
the nearest of them.
- `## Commits` lists the whole `PREV..TAG` range, oldest first, including the
release commit. Its line count equals `git rev-list --count PREV..TAG`.
- `v2.1.1` is the upstream-base tag. It marks the last commit taken from
upstream, where `package.json` still read `@waxio/vert`, and it carries no
Release by design. `v2.2.0` bounds its commit range on it. No tag earlier
than `v2.1.1` exists in this repository.
- A tag with no earlier tag has no `PREV`. Its body is the summary and the
sentence `Initial release.`, with no commit list and no compare link, and it
is written by hand.
- A Release created for a tag older than the current latest is created with
`--latest=false`, so the latest marker stays on the newest version.

`scripts/release-notes.sh` needs bash, git, awk and sed. It reads
`CHANGELOG.md` at the tag rather than from the working tree, so the body
describes what the tag ships. A second argument names a ref to read instead:
`scripts/release-notes.sh vX.Y.Z main` composes the same body from `main`
before the tag exists, prints the range it used on stderr, and refuses the
preview once that ref already carries the tag.

The script exits non-zero and names what is missing when no tag is given, when
the tag is neither v-prefixed nor bare semver, when the tag does not exist and
no ref was passed, when the CHANGELOG at that point carries no entry for the
version, and when no earlier tag in the namespace is reachable.
`scripts/release-notes.test.sh` is its paired check, and CI runs it on every
push and pull request.

## Published package metadata

A release publishes a package page as well as a Release, and the page reads
`package.json`. It carries `name` and `version`; `description` (one sentence
on what the package does and for whom); `license`, with the `LICENSE` file
shipped; `homepage`; `repository` (an object with `type: git` and the
`git+https` URL); `bugs` (an object with the issues URL); `author` (an object
with `name` and `url`); `keywords`; `engines`; `main`, `types` and the
`exports` map; `files` (the build output and the notices that must ship);
`sideEffects`; and `publishConfig` with `access: public` and
`provenance: true`. The package ships a CommonJS build only, so there is no
`module` field and the `exports` map declares the one entry and its type
declarations.

The README is the npm page: it opens with the package name, badges for the npm
version, CI and license, a short introduction, and an install line. Upstream
and lineage credit lives there too, in the opening paragraph, so no Release
body carries a credits section.

`npm pack --dry-run` lists what the tarball ships: `dist` with its type
declarations and source maps, `src` excluding its `tests` directories,
`README.md`, `LICENSE` and `package.json`. `src` ships so the source maps
resolve, but its test sources do not: `files` in `package.json` excludes
`src/**/tests`. A spec file anywhere in the list, compiled or source, means an
exclude stopped matching, and anything else unexpected is a `files` mistake.
`scripts/packaging.test.sh` runs that check in CI, on every Node version in
the matrix, so the tarball is proven before the tag.
28 changes: 26 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,31 @@
"version": "2.2.0",
"homepage": "https://github.com/atomicassets/vert",
"description": "Testing library for Antelope smart contracts, with per-chain host function parity",
"keywords": [
"antelope",
"eosio",
"wax",
"smart-contracts",
"testing",
"wasm"
],
"main": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"./package.json": "./package.json"
},
"sideEffects": false,
"engines": {
"node": ">=20"
},
"files": [
"dist",
"src"
"src",
"!src/**/tests"
],
"scripts": {
"build": "rm -rf dist && tsc",
Expand All @@ -20,8 +37,15 @@
"prepack": "npm run build",
"prepublishOnly": "npm run test"
},
"author": "Jeeyong Um <conr2d@gmail.com>",
"author": {
"name": "AtomicHub",
"url": "https://atomichub.io"
},
"license": "MIT",
"publishConfig": {
"access": "public",
"provenance": true
},
"devDependencies": {
"@types/chai": "^4.3.11",
"@types/elliptic": "^6.4.18",
Expand Down
Loading
Loading