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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@

`@nanoforge-dev/actions` is library that contains all utils for nanoforge actions.

Most of the sources of this package come from [discord.js][discordjs-source]. Spetial thanks to them !
Most of the sources of this package come from [discord.js][discordjs-source]. Special thanks to them!

## Installation

**Node.js 24.11.0 or newer is required.**
**Node.js 25 or newer is required.**

```sh
npm install --save-dev @nanoforge-dev/actions
Expand Down
117 changes: 115 additions & 2 deletions docs/docs/actions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,21 @@ Inputs
- No
- ``false``
- Publish development versions with commit hash suffix
* - ``npm``
- boolean
- No
- ``true``
- Publish to the npm registry
* - ``tag``
- string
- No
- ``"dev"``
- npm dist-tag for dev releases (only valid with ``dev: true``)
* - ``format``
- string
- No
- ``{org}/{package}@{version}``
- Tag format string (placeholders: ``{org}``, ``{package}``, ``{version}``)

Environment Variables
^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -227,6 +237,11 @@ Inputs
- Yes
- --
- Head branch of the merged PR (e.g., ``releases/actions@1.1.0``)
* - ``format``
- string
- No
- ``{org}/{package}@{version}``
- Tag format string (placeholders: ``{org}``, ``{package}``, ``{version}``)

Environment Variables
^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -251,9 +266,13 @@ Behavior
Tag Format
^^^^^^^^^^

Tags follow the npm package identifier format::
Tags are produced by substituting placeholders in the ``format`` input::

{org}/{package}@{version}

@nanoforge-dev/<package>@<version>
For example, with the default format and branch ``releases/actions@1.1.0``::

@nanoforge-dev/actions@1.1.0

Example Usage
^^^^^^^^^^^^^
Expand All @@ -270,6 +289,100 @@ Example Usage

----

.. _action-release-nanoforge-packages:

release-nanoforge-packages
--------------------------

Releases NanoForge components and systems to the NanoForge private registry
(``api.nanoforge.eu``). Discovers packages via ``nanoforge.manifest.json``
files and resolves publish order from their declared dependencies.

**Entry Point**: ``src/release-nanoforge-packages/index.ts``

Inputs
^^^^^^

.. list-table::
:header-rows: 1
:widths: 18 10 10 15 47

* - Input
- Type
- Required
- Default
- Description
* - ``path``
- string
- No
- ``packages``
- Path to the packages directory
* - ``package``
- string
- No
- ``"all"``
- Specific package to release (with dependencies), or ``"all"``
* - ``exclude``
- string
- No
- ``""``
- Comma-separated list of packages to skip (unless required by another package)
* - ``dry``
- boolean
- No
- ``false``
- Perform a dry run without actual publishing

Environment Variables
^^^^^^^^^^^^^^^^^^^^^

.. list-table::
:header-rows: 1
:widths: 30 70

* - Variable
- Description
* - ``GITHUB_TOKEN``
- GitHub token (required for job summary writing)

Behavior
^^^^^^^^

1. Recursively scans the ``path`` directory for ``nanoforge.manifest.json`` files
2. Builds a dependency tree from ``dependencies`` fields in each manifest
3. Releases packages in topological order; independent packages are released
in parallel within each level
4. After each publish, polls ``api.nanoforge.eu/registry/<name>`` every 15 s
(up to 5 min) to confirm the package is available before proceeding
5. Generates a job summary listing released and skipped packages

Manifest Format
^^^^^^^^^^^^^^^

Each package must have a ``nanoforge.manifest.json`` at its root:

.. code-block:: json

{
"name": "@nanoforge-dev/my-package",
"dependencies": ["@nanoforge-dev/other-package"]
}

Example Usage
^^^^^^^^^^^^^

.. code-block:: yaml

- name: Release NanoForge packages
uses: ./dist/release-nanoforge-packages
with:
path: packages
dry: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

----

Workflow Integration
--------------------

Expand Down
66 changes: 66 additions & 0 deletions docs/docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,72 @@ Functions
:param release: Release entry with changelog
:param dry: If true, logs instead of creating release

release-nanoforge-packages: generate-release-tree
-------------------------------------------------

**Module**: ``src/release-nanoforge-packages/generate-release-tree.ts``

Builds a dependency-ordered release tree for NanoForge packages discovered
via ``nanoforge.manifest.json`` manifests.

Types
^^^^^

.. code-block:: typescript

interface ReleaseEntry {
name: string; // Package name from manifest
path: string; // Absolute path to the package directory
dependsOn?: string[]; // Names of packages that must be released first
}

Functions
^^^^^^^^^

.. function:: generateReleaseTree(path: string, packageName?: string, exclude?: string[]): Promise<ReleaseEntry[][]>

Generates a two-dimensional array of release entries ordered by dependency
level. Each inner array can be released in parallel.

:param path: Root directory to scan for ``nanoforge.manifest.json`` files
:param packageName: Target a specific package (with its deps) or ``"all"``
:param exclude: Package names to skip (unless required by another package)
:returns: Promise resolving to ordered release tree
:raises Error: If a named package is not found, or a dependency cycle exists

**Algorithm**:

1. Recursively scans ``path`` for ``nanoforge.manifest.json`` files
2. Builds dependency graph from manifest ``dependencies`` fields
3. Topologically sorts into release levels (BFS)
4. Prunes tree based on ``packageName`` or ``exclude`` options

release-nanoforge-packages: release-package
--------------------------------------------

**Module**: ``src/release-nanoforge-packages/release-package.ts``

Handles publishing individual NanoForge packages via the ``nf publish`` CLI.

Functions
^^^^^^^^^

.. function:: releasePackage(release: ReleaseEntry, dry: boolean): Promise<boolean>

Publishes a single NanoForge package.

:param release: Release entry with name and path
:param dry: If true, logs instead of publishing
:returns: Promise resolving to ``true`` when done

**Behavior**:

1. In dry mode: logs the action and returns immediately
2. Runs ``bun exec "nf publish -d <path>"``
3. Polls ``api.nanoforge.eu/registry/<name>`` every 15 s (up to 5 min) to
confirm the package is available on the registry before returning
:raises Error: If the registry does not confirm the package within 5 minutes

create-release-pr Functions
---------------------------

Expand Down
11 changes: 9 additions & 2 deletions docs/docs/architecture.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ Overview
--------

NanoForge Actions is a collection of GitHub Actions designed to automate the
release workflow for NanoForge monorepo packages. It provides three main actions
release workflow for NanoForge monorepo packages. It provides four main actions
that handle different stages of the release process:

1. **create-release-pr** -- Creates a release pull request with version bumps
and changelog generation
2. **release-packages** -- Publishes packages to npm with proper dependency
sequencing
3. **create-release-tag** -- Creates git tags after a release PR is merged
4. **release-nanoforge-packages** -- Publishes NanoForge components and systems
to the private NanoForge registry

The package is published to npm as ``@nanoforge-dev/actions`` and is built
using tsup with ESM output.
Expand Down Expand Up @@ -59,12 +61,17 @@ Project Structure
| +-- index.ts # Entry point
| +-- functions.ts # Core functions
| +-- types.ts # Type definitions
+-- release-packages/ # Package publishing action
+-- release-packages/ # npm package publishing action
| +-- index.ts # Entry point
| +-- generate-release-tree.ts # Dependency tree generation
| +-- release-package.ts # Individual package release
+-- create-release-tag/ # Tag creation action
| +-- index.ts # Entry point
+-- release-nanoforge-packages/ # NanoForge registry publishing action
+-- index.ts # Entry point
+-- generate-release-tree.ts # Manifest-based dependency tree
+-- release-package.ts # Individual NanoForge package release
+-- action.yml # Action definition

Action Pattern
--------------
Expand Down
24 changes: 24 additions & 0 deletions src/release-nanoforge-packages/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: "Release Nanoforge Packages"
description: "Releases any nanoforge component or system"
inputs:
dry:
description: "Perform a dry run that skips publishing and outputs logs indicating what would have happened"
default: "false"
path:
description: "Path to the packages directory"
default: "packages"
package:
description: "The published name of a single package to release"
exclude:
description: "Comma separated list of packages to exclude from release (if not depended upon)"
runs:
using: composite
steps:
- uses: oven-sh/setup-bun@v2
- run: bun $GITHUB_ACTION_PATH/index.js
shell: bash
env:
INPUT_DRY: ${{ inputs.dry }}
INPUT_PATH: ${{ inputs.path }}
INPUT_PACKAGE: ${{ inputs.package }}
INPUT_EXCLUDE: ${{ inputs.exclude }}
Loading
Loading