diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
new file mode 100644
index 0000000..1fb811f
--- /dev/null
+++ b/.config/dotnet-tools.json
@@ -0,0 +1,13 @@
+{
+ "version": 1,
+ "isRoot": true,
+ "tools": {
+ "make": {
+ "version": "0.7.0",
+ "commands": [
+ "dotnet-make"
+ ],
+ "rollForward": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml
new file mode 100644
index 0000000..1f6a0df
--- /dev/null
+++ b/.github/workflows/pr.yaml
@@ -0,0 +1,38 @@
+# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
+name: Pull Request
+on: pull_request
+
+env:
+ DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
+ DOTNET_CLI_TELEMETRY_OPTOUT: true
+
+jobs:
+
+ ###################################################
+ # BUILD
+ ###################################################
+
+ build:
+ name: Build
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Setup .NET SDK
+ uses: actions/setup-dotnet@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: 22
+ cache: npm
+ cache-dependency-path: ./site/package-lock.json
+
+ - name: Build
+ shell: bash
+ run: |
+ dotnet tool restore
+ dotnet make ci --trace
\ No newline at end of file
diff --git a/.github/workflows/site.yaml b/.github/workflows/site.yaml
index d7f07da..d6ffa34 100644
--- a/.github/workflows/site.yaml
+++ b/.github/workflows/site.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
name: Deploy Site
on:
@@ -11,17 +12,26 @@ jobs:
name: Build Docusaurus
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - name: Checkout
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- - uses: actions/setup-node@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
with:
- node-version: 18
+ node-version: 22
cache: npm
cache-dependency-path: ./site/package-lock.json
- - name: Build website
- run: make ci
+ - name: Setup .NET SDK
+ uses: actions/setup-dotnet@v4
+
+ - name: Build
+ shell: bash
+ run: |
+ dotnet tool restore
+ dotnet make ci --trace
- name: Upload Build Artifact
uses: actions/upload-pages-artifact@v3
diff --git a/.gitignore b/.gitignore
index a64b1cf..8830bff 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,9 @@
# Artifacts
.artifacts
+# Build
+build/obj
+build/bin
+
# Other
.vscode
\ No newline at end of file
diff --git a/Makefile b/Makefile
deleted file mode 100644
index d85dd66..0000000
--- a/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-.PHONY: schema ci
-default: run
-
-help:
- @echo "Targets:"
- @echo "--------"
- @echo "schema Generates the JSON schema"
- @echo "run Runs the site"
- @echo "ci Builds the site (for CI)"
-
-init:
- @echo "Initializing..."
- @mkdir -p ./.artifacts
-
-schema: init
- @echo "Generating JSON schema..."
- @npm --prefix ./typespec install
- @tsp compile ./typespec --output-dir ./.artifacts
- @mv ./.artifacts/@typespec/json-schema/OpenCLI.json ./schema.json
-
-run: init
- @cd site && make run
-
-ci: init
- @cd site && make ci
\ No newline at end of file
diff --git a/README.md b/README.md
index e769c60..ed90a62 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,8 @@ language agnostic interface to CLI applications which allows both humans
and computers to understand how a CLI tool should be invoked without
access to source code or documentation.
+[https://opencli.org][opencli]
+
## Usage
* Create documentation for CLI tools
@@ -19,4 +21,28 @@ with the community to make sure that the first version can be as good as possibl
Head over to our [discussions][discussions] if you have feedback or ideas!
-[discussions]: https://github.com/spectreconsole/open-cli/discussions
\ No newline at end of file
+## Building
+
+We're using [Cake][cake]
+to build the OpenCLI JSON schema, and site.
+
+For this you will need to have the .NET 9.0 SDK installed
+which you can find over at [https://dotnet.microsoft.com/en-us/download][dotnet].
+
+After installing the .NET SDK, make sure that you've
+restored Cake by running the following in the repository root:
+
+```shell
+$ dotnet tool restore
+```
+
+After that, running the build is as easy as writing:
+
+```shell
+$ dotnet make
+```
+
+[opencli]: https://opencli.org
+[discussions]: https://github.com/spectreconsole/open-cli/discussions
+[cake]: https://github.com/cake-build/cake
+[dotnet]: https://dotnet.microsoft.com/en-us/download
\ No newline at end of file
diff --git a/build/Build.csproj b/build/Build.csproj
new file mode 100644
index 0000000..0e93f54
--- /dev/null
+++ b/build/Build.csproj
@@ -0,0 +1,10 @@
+
+
+ net9.0
+ $(MSBuildProjectDirectory)/..
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build/Build.slnx b/build/Build.slnx
new file mode 100644
index 0000000..af33527
--- /dev/null
+++ b/build/Build.slnx
@@ -0,0 +1,3 @@
+
+
+
diff --git a/build/build.cs b/build/build.cs
new file mode 100644
index 0000000..ea523da
--- /dev/null
+++ b/build/build.cs
@@ -0,0 +1,102 @@
+var target = Argument("target", defaultValue: "Default");
+if (target == "Default")
+{
+ AnsiConsole.Write(new FigletText("OpenCLI"));
+ AnsiConsole.Write(
+ new Table()
+ .AddColumns("Target", "")
+ .AddRow("[yellow]clean[/]", "Cleans up artifacts")
+ .AddRow("[yellow]build-schema[/]", "Builds the JSON schema")
+ .AddRow("[yellow]build-site[/]", "Builds the site")
+ .AddRow("[yellow]run-site[/]", "Runs the site locally")
+ .AddRow("[yellow]ci[/]", "Runs the CI build locally")
+ );
+
+ Environment.Exit(1);
+}
+
+//////////////////////////////////////////////////////////////////////
+// TARGETS
+//////////////////////////////////////////////////////////////////////
+
+Task("CI")
+ .IsDependentOn("Build-Schema")
+ .IsDependentOn("Build-Site");
+
+//////////////////////////////////////////////////////////////////////
+// TASKS
+//////////////////////////////////////////////////////////////////////
+
+// Clears all artifacts
+Task("Clean")
+ .Does(ctx =>
+{
+ ctx.CleanDirectory("./.artifacts");
+});
+
+// Updates the site contents
+Task("Update-Site-Contents")
+ .Does(ctx =>
+{
+ // Copy the draft.md content into the site
+ ctx
+ .TransformTextFile("./site/docs/spec.template", "<%", "%>")
+ .WithToken("SPEC", System.IO.File.ReadAllText("./draft.md"))
+ .Save("./site/docs/spec.md");
+
+ // Copy the schema
+ ctx.CopyFile("./schema.json", "./site/static/draft.json");
+});
+
+// Builds the JSON schema
+Task("Build-Schema")
+ .IsDependentOn("Clean")
+ .Does(ctx =>
+{
+ ctx.Npm(arguments: ["install"], workingDirectory: "./typespec");
+ ctx.Npm(arguments: ["run", "tsp-compile"], workingDirectory: "./typespec");
+
+ // TODO: No overload for overwriting?
+ if (ctx.FileExists("./schema.json"))
+ {
+ ctx.DeleteFile("./schema.json");
+ }
+
+ ctx.CopyFile("./.artifacts/@typespec/json-schema/OpenCLI.json", "./.artifacts/schema.json");
+ ctx.CopyFile("./.artifacts/@typespec/json-schema/OpenCLI.json", "./schema.json");
+});
+
+// Builds the site
+Task("Build-Site")
+ .IsDependentOn("Clean")
+ .IsDependentOn("Update-Site-Contents")
+ .Does(ctx =>
+{
+ ctx.Npm(
+ arguments: ["ci"],
+ workingDirectory: "./site");
+
+ ctx.Npm(
+ arguments: ["run build"],
+ workingDirectory: "./site");
+});
+
+// Runs the site locally
+Task("Run-Site")
+ .IsDependentOn("Update-Site-Contents")
+ .Does(ctx =>
+{
+ ctx.Npm(
+ arguments: ["install"],
+ workingDirectory: "./site");
+
+ ctx.Npx(
+ arguments: ["docusaurus", "start"],
+ workingDirectory: "./site");
+});
+
+//////////////////////////////////////////////////////////////////////
+// EXECUTION
+//////////////////////////////////////////////////////////////////////
+
+RunTarget(target);
diff --git a/build/utils.cs b/build/utils.cs
new file mode 100644
index 0000000..1aa5804
--- /dev/null
+++ b/build/utils.cs
@@ -0,0 +1,74 @@
+public static class Utilities
+{
+ public static void Npm(
+ this ICakeContext context,
+ string[] arguments,
+ DirectoryPath? workingDirectory = null)
+ {
+ var executable = GetNpmExecutable(context);
+ if (executable == null)
+ {
+ throw new InvalidOperationException("Could not locate 'npm'");
+ }
+
+ RunProcess(context, executable, arguments, workingDirectory);
+ }
+
+ public static void Npx(
+ this ICakeContext context,
+ string[] arguments,
+ DirectoryPath? workingDirectory = null)
+ {
+ var executable = GetNpxExecutable(context);
+ if (executable == null)
+ {
+ throw new InvalidOperationException("Could not locate 'npm'");
+ }
+
+ RunProcess(context, executable, arguments, workingDirectory);
+ }
+
+ public static void RunProcess(
+ this ICakeContext context,
+ string executable,
+ string[] arguments,
+ DirectoryPath? workingDirectory = null)
+ {
+ var args = ProcessArgumentBuilder.FromStrings(arguments);
+ var exitCode = StartProcess(executable, new ProcessSettings
+ {
+ Arguments = args,
+ WorkingDirectory = workingDirectory?.MakeAbsolute(context.Environment),
+ });
+
+ if (exitCode != 0)
+ {
+ throw new InvalidOperationException(
+ $"The tool '{executable}' returned a non-zero exit code");
+ }
+ }
+
+ private static string? GetNpmExecutable(ICakeContext context)
+ {
+ if (context.IsRunningOnWindows())
+ {
+ return context.Tools.Resolve("npm.cmd")?.FullPath;
+ }
+ else
+ {
+ return context.Tools.Resolve("npm")?.FullPath;
+ }
+ }
+
+ private static string? GetNpxExecutable(ICakeContext context)
+ {
+ if (context.IsRunningOnWindows())
+ {
+ return context.Tools.Resolve("npx.cmd")?.FullPath;
+ }
+ else
+ {
+ return context.Tools.Resolve("npx")?.FullPath;
+ }
+ }
+}
\ No newline at end of file
diff --git a/global.json b/global.json
new file mode 100644
index 0000000..a03a5e0
--- /dev/null
+++ b/global.json
@@ -0,0 +1,7 @@
+{
+ "$schema": "http://json.schemastore.org/global",
+ "sdk": {
+ "version": "9.0.100",
+ "rollForward": "latestFeature"
+ }
+}
\ No newline at end of file
diff --git a/site/Makefile b/site/Makefile
deleted file mode 100644
index ecbb5c5..0000000
--- a/site/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-.PHONY: build ci
-default: run
-
-help:
- @echo "Targets:"
- @echo "--------"
- @echo "update Syncs the OpenCLI spec with the site"
- @echo "run Runs the site"
- @echo "ci Builds the site (for CI)"
-
-update:
- @echo "Updating contents..."
- @./update.sh
-
-run: update
- @echo "Installing dependencies..."
- @npm install
- @echo "Running..."
- @npx docusaurus start
-
-ci: update
- @echo "Installing dependencies..."
- @npm ci
- @echo "Building..."
- @npm run build
\ No newline at end of file
diff --git a/site/docs/spec.template b/site/docs/spec.template
index 3dd655e..525021b 100644
--- a/site/docs/spec.template
+++ b/site/docs/spec.template
@@ -11,6 +11,4 @@ This specification is for now just a proposal.
Input and feedback is *VERY MUCH* welcome!
:::
-### BEGIN GENERATED CONTENT
-
-### END GENERATED CONTENT
\ No newline at end of file
+<%SPEC%>
\ No newline at end of file
diff --git a/site/sidebars.js b/site/sidebars.js
index d087e1b..33f2623 100644
--- a/site/sidebars.js
+++ b/site/sidebars.js
@@ -2,7 +2,7 @@
/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
const sidebars = {
- tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],
+ myAutogeneratedSidebar: [{type: 'autogenerated', dirName: '.'}],
};
module.exports = sidebars;
diff --git a/site/static/.gitignore b/site/static/.gitignore
new file mode 100644
index 0000000..4088224
--- /dev/null
+++ b/site/static/.gitignore
@@ -0,0 +1 @@
+draft.json
\ No newline at end of file
diff --git a/site/update.sh b/site/update.sh
deleted file mode 100755
index 81b1f4d..0000000
--- a/site/update.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-
-# Copy the draft into the spec template file and put the result
-# in the ./.artifacts directory
-BEGIN_GEN=$(cat docs/spec.template | grep -n '### BEGIN GENERATED CONTENT' | sed 's/\(.*\):.*/\1/g')
-END_GEN=$(cat docs/spec.template | grep -n '### END GENERATED CONTENT' | sed 's/\(.*\):.*/\1/g')
-cat <(head -n $(expr $BEGIN_GEN - 1) docs/spec.template) ../draft.md <(tail -n +$(expr $END_GEN + 1) docs/spec.template) > ../.artifacts/spec.md
-
-# Replace invalid markdown characters
-sed -i -e 's/\\/\\>/g' ../.artifacts/spec.md
-
-# Copy the artifact to the site
-mv ../.artifacts/spec.md docs/spec.md
\ No newline at end of file
diff --git a/typespec/package.json b/typespec/package.json
index 4dc1710..d18181e 100644
--- a/typespec/package.json
+++ b/typespec/package.json
@@ -3,6 +3,9 @@
"version": "0.1.0",
"type": "module",
"private": true,
+ "scripts": {
+ "tsp-compile": "tsp compile ./ --output-dir ../.artifacts"
+ },
"dependencies": {
"@typespec/compiler": "latest",
"@typespec/http": "latest",