Skip to content

Commit

Permalink
Merge pull request #29 from BusyCityGuy/fix/wally-package-structure
Browse files Browse the repository at this point in the history
Fix/wally package structure
  • Loading branch information
BusyCityGuy authored Sep 27, 2024
2 parents 0938a09 + 9277438 commit 0e87abc
Show file tree
Hide file tree
Showing 12 changed files with 123 additions and 83 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ jobs:

- name: Analyze StateQ with luau-lsp
run: |
./scripts/sourcemap.sh default.project.json stateQSourcemap.json
./scripts/sourcemap.sh rbxm.project.json stateQSourcemap.json
./scripts/analyze.sh stateQSourcemap.json src/StateQ
- name: Analyze tests with luau-lsp
Expand Down
18 changes: 7 additions & 11 deletions .vscode/settings.json.example
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
{
"luau-lsp.require.mode": "relativeToFile",
"luau-lsp.require.directoryAliases": {
"@lune/": "~/.lune/.typedefs/0.8.8/"
},
"luau-lsp.sourcemap.rojoProjectFile": "test.project.json",
"luau-lsp.ignoreGlobs": [
"**/_Index/**",
"**/*.d.luau",
"*Packages/**"
],
"cSpell.words": ["rokit", "rbxl", "rojo"]
"luau-lsp.require.mode": "relativeToFile",
"luau-lsp.require.directoryAliases": {
"@lune/": "~/.lune/.typedefs/0.8.8/"
},
"luau-lsp.sourcemap.rojoProjectFile": "test.project.json",
"luau-lsp.ignoreGlobs": ["**/*.d.luau", "*Packages/**"],
"cSpell.words": ["rokit", "rbxl", "rojo"]
}
56 changes: 40 additions & 16 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Various tools used by the project are installed with [Rokit](https://github.com/
1. Run the following command in the repository directory:

```bash
rokit install
> rokit install
```

This installs tools from `rokit.toml` and adds them to your system environment path variable so you can use the tools in the command line.
Expand All @@ -34,6 +34,7 @@ Additionally, if you're using VS Code it's recommended to install the following
- [johnnymorganz.stylua](https://marketplace.visualstudio.com/items?itemName=JohnnyMorganz.stylua)
- [kampfkarren.selene-vscode](https://marketplace.visualstudio.com/items?itemName=Kampfkarren.selene-vscode)
- [streetsidesoftware.code-spell-checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker)

> [!TIP]
> You should be automatically prompted to install these plugins when opening the project in VS Code because they're listed in [extensions.json](.vscode/extensions.json)
Expand All @@ -58,7 +59,7 @@ The following tools are installed by Rokit:
This project depends on packages to run and for testing. These packages are installed by Wally by running the following command:

```bash
wally install
> wally install
```

This will create `Packages` and `DevPackages` folders in the top level of the directory that are referenced by the `*.project.json` files.
Expand All @@ -83,8 +84,9 @@ The following packages are installed as dev dependencies:
Lune provides type definitions and documentation, but has to be configured for your editor. To do so, do the following steps (source: [Lune Editor Setup](https://lune-org.github.io/docs/getting-started/4-editor-setup))

Run the command:

```bash
lune setup
> lune setup
```

Then, modify your editor settings. For VS Code, open [`settings.json`](./.vscode/settings.json) and verify it contains the following:
Expand All @@ -102,13 +104,22 @@ An example [`settings.json`](./.vscode/settings.json) file is provided (see [`se

Rojo builds from json files that map files on your file system to locations in the roblox data model. This project includes two project.json files:

| File | Purpose |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`default.project.json`](./default.project.json) | The distributable consumer build in the form of a single ModuleScript and its children. This defines the structure when a consumer links this project into their `project.json` file. |
| [`test.project.json`](./test.project.json) | Useful for developing this project, because it defines an entire place file that can be opened and synced rather than just the ModuleScript. This is the one you should build and serve with Rojo during development of this project. |
| File | Purpose |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`test.project.json`](./test.project.json) | Useful for developing this project, because it defines an entire place file that can be opened, synced, and tested. This is the one you should build and serve with Rojo during development of this project. |
| [`rbxm.project.json`](./rbxm.project.json) | The distributable rbxm build in the form of a ModuleScript and its children inside a Packages folder containing dependencies. This is built and made available on each Release as a downloadable artifact. |
| [`default.project.json`](./default.project.json) | The standalone module without dependencies included. This defines the structure when a consumer links this project into their `project.json` file as a submodule, requiring the consumer to install dependencies and place this into the Packages folder. |

If you plan to [run tests](#run-tests) from CLI (recommended), the test runner script automatically builds before running tests. You don't need to build it yourself.

There's also an available Lune command to build artifacts for each build target, like the CD script does.

```bash
> lune run build
```

This creates a `build` folder containing a subfolder for each build target (rbxm, zip, wally tar), which contains the artifact for that build target.

<details>
<summary>
If you're running tests in studio yourself (not recommended) instead of using the CLI, you can do an initial project build by expanding this section and doing either of the following:
Expand All @@ -118,6 +129,7 @@ If you're running tests in studio yourself (not recommended) instead of using th
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| CLI | `rojo build test.project.json -o StateQ-Test.rbxl` |
| VSC Extension | Click Rojo on the status bar at the bottom, mouse over `test.project.json` in the pop-up menu, and click the Build icon on the right of the list item. |

</details>

## Sync file changes to studio
Expand Down Expand Up @@ -166,8 +178,8 @@ However, running tests in Roblox Studio requires flipping the `FFlagEnableLoadMo

This instructions to flip this flag differ on Mac vs Windows.

* **For Mac users:** see [this issue](https://github.com/jsdotlua/jest-lua/issues/6).
* **For Windows users:** see [this devforum post](https://devforum.roblox.com/t/how-to-return-altenter-to-its-prior-functionality/997206)
- **For Mac users:** see [this issue](https://github.com/jsdotlua/jest-lua/issues/6).
- **For Windows users:** see [this devforum post](https://devforum.roblox.com/t/how-to-return-altenter-to-its-prior-functionality/997206)

You need to set the `FFlagEnableLoadModule` value to `true`. Be sure to restart Roblox Studio after flipping the flag.
</details>
Expand All @@ -179,7 +191,7 @@ You need to set the `FFlagEnableLoadModule` value to `true`. Be sure to restart
| CLI (recommended) | `lune run test` |
| Roblox Studio | Open the test place file `StateQ-Test.rbxl` [built in the above step](#build-the-project) in Roblox Studio and run the place (server only). The output widget will show the test results. |

### Continuous Integration (CI)
## Continuous integration (CI)

CI checks are set up to run on pull requests. These checks must pass before merging, including:

Expand All @@ -188,35 +200,47 @@ CI checks are set up to run on pull requests. These checks must pass before merg
1. `analyze` with luau-lsp
1. `test` with jest running in Lune

#### Running CI Locally
### Running CI locally

To run the same CI checks locally that would run on GitHub, a number of Lune scripts are provided.

From the project directory, you can run the following:

```bash
> lune run ci
```

This will run all the same checks that would run on GitHub.

Alternatively, you can run individual steps yourself:

```bash
> lune run lint
> lune run formatCheck
> lune run analyze
> lune run test
```

There is an additional script available to fix formatting with StyLua, that does not run on GitHub:

```bash
> lune run formatFix
```

## Releasing
## Creating a release

1. To make a release, use the GitHub web interface to [create a new release](https://github.com/BusyCityGuy/finite-state-machine-luau/releases/new).
1. Choose a tag with a version number like `v0.0.0`, beginning with `v` and using semantic versioning. No suffix like `-pre` is supported, only numbers as shown.
1. Create a release title, preferably something like "Version 0.0.0" to be consistent with the tag.
1. Describe the changes in the release
1. Publish release
1. A GitHub Actions workflow will automatically run and upload .zip and .rbxm artifacts to the release. It will also automatically publish the release to Wally, and update hardcoded numbers throughout the codebase like versions and copyright years.

## Continuous deployment (CD)

When a release is created, a GitHub Actions workflow automatically runs that does the following steps:

1. Performs preprocessing to update hardcoded numbers in the codebase, like versions and copyright years
1. Commits these preprocessing changes to the main branch
1. Builds artifacts for each build target
1. Uploads the `.zip` and `.rbxm` artifacts to the release on GitHub
1. Publishes the `.tar` package to Wally
27 changes: 18 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,20 @@ These signals, transition callbacks, and state changes are processed in the foll
![SequenceDiagram](https://github.com/BusyCityGuy/finite-state-machine-luau/assets/55513323/9ace09e3-a16e-474b-83ca-aac91cd69492)

1. Fire `beforeEvent` signal
- with arguments `eventName`, `beforeState`
- with arguments `eventName`, `beforeState`
1. Call `transition.beforeAsync()` (required, returns next state)
- with the VarArgs from `:handle(eventName, transitionArgs...)`
- with the VarArgs from `:handle(eventName, transitionArgs...)`
1. Fire `leavingState` signal
- with arguments `beforeState, afterState`
- with arguments `beforeState, afterState`
1. Update `_currentState` to next state
1. Fire `stateEntered` signal
- with arguments `afterState, beforeState`
- with arguments `afterState, beforeState`
1. Call `transition.afterAsync()` (if specified)
- with the VarArgs from `:handle(eventName, transitionArgs...)`
- with the VarArgs from `:handle(eventName, transitionArgs...)`
1. Fire `afterEvent` signal
- with arguments `eventName, afterState, beforeState`
- with arguments `eventName, afterState, beforeState`
1. Fire `finished` signal if next state from `beforeAsync()` was `nil`
- with argument `beforeState`
- with argument `beforeState`

Transitions can be asynchronous, which is supported by queuing each Event submitted via :handle() and processing them in First-In-First-Out (FIFO) order. The next Event starts processing immediately after the previous Event's handler fires `afterEvent`.

Expand All @@ -54,6 +54,10 @@ A simple state machine diagram for a light switch may look like this, where
![ExampleUsage](https://github.com/BusyCityGuy/finite-state-machine-luau/assets/55513323/3d5b2118-91ea-4427-ac2d-688fb0094d1f)

```luau
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local StateQ = require(ReplicatedStorage.Packages.StateQ)
local LightState = {
On = "On",
Off = "Off",
Expand Down Expand Up @@ -110,17 +114,22 @@ light:handle(Event.SwitchOn) -- warns "Illegal event `SwitchOn` called during st
## Rojo users

If your project is set up to build with Rojo, the preferred installation method is using [Wally](https://wally.run/). Add this to your `wally.toml` file:

```bash
> StateQ = "busycityguy/[email protected]"
```

If you're not using Wally, you can add this repository as a submodule of your project by running the following command:

> git submodule add https://github.com/BusyCityGuy/finite-state-machine-luau path/to/your/dependencies
```bash
> git submodule add <https://github.com/BusyCityGuy/finite-state-machine-luau> path/to/your/dependencies
```

If you want to avoid submodules too, you can download the `.zip` file from the [latest release](https://github.com/BusyCityGuy/finite-state-machine-luau/releases/latest) page.

## Non-Rojo users

If you aren't using Rojo, you can download the `.rbxm` file from the [latest release](https://github.com/BusyCityGuy/finite-state-machine-luau/releases/latest) page and drag it into Roblox Studio.
If you aren't using Rojo, you can download the `.rbxm` file from the [latest release](https://github.com/BusyCityGuy/finite-state-machine-luau/releases/latest) page and drag it into Roblox Studio, placing the `Packages` folder in `ReplicatedStorage`.

# Feedback

Expand Down
9 changes: 3 additions & 6 deletions default.project.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
{
"name": "StateQ",
"tree": {
"$path": "src/StateQ",
"Dependencies": {
"$path": "Packages"
"name": "StateQ",
"tree": {
"$path": "src/StateQ"
}
}
}
2 changes: 1 addition & 1 deletion lune/analyze.luau
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ local task = require("@lune/task")
local ANALYZE_PATHS: { { path: string, project: string?, sourceMap: string? } } = {
{
path = Path.join("src", "StateQ"),
project = "default.project.json",
project = "rbxm.project.json",
sourceMap = "stateQSourcemap.json",
},
{
Expand Down
8 changes: 4 additions & 4 deletions lune/build.luau
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ local build_targets = {
command = "rojo",
args = {
"build",
"default.project.json",
"rbxm.project.json",
"--output",
`{Path.join(ensurePath(buildFolder, "rbxm"), `{fileName}.rbxm`)}`,
Path.join(ensurePath(buildFolder, "rbxm"), `{fileName}.rbxm`),
},
},
{
Expand All @@ -66,15 +66,15 @@ local build_targets = {
args = {
"package",
"--output",
`{Path.join(ensurePath(buildFolder, "wally"), fileName:lower())}`,
Path.join(ensurePath(buildFolder, "wally"), `{fileName:lower()}.tar`),
},
},
{
description = "zip",
command = "zip",
args = {
"-r",
`{Path.join(ensurePath(buildFolder, "zip"), fileName)}.zip`,
Path.join(ensurePath(buildFolder, "zip"), `{fileName}.zip`),
"src/StateQ",
"default.project.json",
"Packages",
Expand Down
9 changes: 9 additions & 0 deletions rbxm.project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "Packages",
"tree": {
"$path": "Packages",
"StateQ": {
"$path": "src/StateQ"
}
}
}
8 changes: 7 additions & 1 deletion src/StateQ/init.luau
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,16 @@
light:handle(Event.SwitchOn) -- errors "Illegal event `SwitchOn` called during state `On`" with a stack trace
--]]

-- This module should be in a folder called Packages that contains other module dependencies.
-- If installed as an rbxm, the Packages folder should be included as the parent of this module already.
-- If installed with Wally, this should already be automatically set up as a descendant of the Packages folder with references to dependencies created.
-- If installed as a submodule, you'll need to edit your project.json file to set the path for this module inside of a Packages folder, and install dependencies there.
local Packages = script.Parent

local Logger = require(script.Modules.Logger)
local Signal = require(script.Modules.Signal)
local ThreadQueue = require(script.Modules.ThreadQueue)
local t = require(script.Dependencies.t)
local t = require(Packages.t)

-- These types are added for readability to disambiguate what the string is meant to represent in types
type State = string
Expand Down
8 changes: 4 additions & 4 deletions src/TestService/Source/Tests/StateQ.spec.luau
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
-- local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TestService = game:GetService("TestService")

local JestGlobals = require(TestService.Dependencies.JestGlobals)
-- local Freeze = require(TestService.Dependencies.Freeze)
-- local Logger = require(ReplicatedStorage.Source.StateQ.Modules.Logger)
-- local StateQ = require(ReplicatedStorage.Source.StateQ)
local JestGlobals = require(TestService.Source.DevPackages.JestGlobals)
-- local Freeze = require(DevPackages.Freeze)
-- local Logger = require(ReplicatedStorage.Source.Packages.StateQ.Modules.Logger)
-- local StateQ = require(ReplicatedStorage.Source.Packages.StateQ)

-- Shortening things is generally bad practice, but this greatly improves readability of tests
-- local Dict = Freeze.Dictionary
Expand Down
2 changes: 1 addition & 1 deletion src/TestService/Source/run.server.luau
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
local TestService = game:GetService("TestService")

local Jest = require(TestService.Dependencies.Jest)
local Jest = require(TestService.Source.DevPackages.Jest)
local runCLI = Jest.runCLI

-- Jest.TestBootstrap:run({ TestService.Source.Tests })
Expand Down
Loading

0 comments on commit 0e87abc

Please sign in to comment.