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
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# discourse-skeleton-update
# @discourse/update-skeleton

Update a Discourse theme or plugin's scaffolding and install its dependencies.
Requires Node.js 22.13+, pnpm, Ruby, and Bundler.

Run from the theme or plugin root:

```sh
pnpx discourse-skeleton-update@latest
pnpx @discourse/update-skeleton@latest
```

Skeletons also provide `pnpm discourse-skeleton-update`, which runs that command
Skeletons also provide `pnpm update-skeleton`, which runs that command
without adding the updater as a dependency. For local development, run
`node /path/to/discourse-skeleton-update/bin/discourse-skeleton-update.js`.
`node /path/to/update-skeleton/bin/update-skeleton.js`.

## What it does

Expand Down Expand Up @@ -54,7 +54,7 @@ To release, bump `version` in `package.json` and merge to `main`.
Already published versions are skipped by `pnpm publish -r`.

Configure an [npm trusted publisher](https://docs.npmjs.com/trusted-publishers/)
for the package: organization `discourse`, repository `discourse-skeleton-update`,
for the package: organization `discourse`, repository `update-skeleton`,
workflow `ci.yml`, no environment, with direct publishing allowed. No npm token
secret is needed. If the package does not exist yet, publish its first version
manually before configuring the trusted publisher.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ try {
});
if (values.help) {
console.log(
"Run discourse-skeleton-update from a theme or plugin root to replace scaffolding and install dependencies."
"Run update-skeleton from a theme or plugin root to replace scaffolding and install dependencies."
);
} else {
await update();
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"name": "discourse-skeleton-update",
"name": "@discourse/update-skeleton",
"version": "0.1.0",
"description": "Update Discourse theme and plugin scaffolding and install its dependencies",
"type": "module",
"bin": {
"discourse-skeleton-update": "bin/discourse-skeleton-update.js"
"update-skeleton": "bin/update-skeleton.js"
},
"files": [
"bin/",
Expand All @@ -21,7 +21,7 @@
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/discourse/discourse-skeleton-update.git"
"url": "git+https://github.com/discourse/update-skeleton.git"
},
"publishConfig": {
"access": "public"
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"type": "plugin",
"repository": "discourse/discourse-plugin-skeleton",
"files": {
"package.json": "{\n \"private\": true,\n \"devDependencies\": {\n \"@discourse/lint-configs\": \"3.2.0\",\n \"@glint/ember-tsc\": \"1.8.11\",\n \"concurrently\": \"^9.2.3\",\n \"discourse\": \"npm:@discourse/types@2026.3.0-d02b2966\",\n \"eslint\": \"10.6.0\",\n \"lint-to-the-future\": \"^2.6.4\",\n \"lint-to-the-future-eslint\": \"^3.3.0\",\n \"prettier\": \"3.8.1\",\n \"stylelint\": \"17.5.0\"\n },\n \"scripts\": {\n \"lint\": \"concurrently \\\"pnpm:lint:*(!fix)\\\" --names \\\"lint:\\\"\",\n \"lint:fix\": \"concurrently \\\"pnpm:lint:*:fix\\\" --names \\\"fix:\\\"\",\n \"lint:css\": \"pnpm stylelint 'assets/stylesheets/**/*.scss' --allow-empty-input\",\n \"lint:css:fix\": \"pnpm stylelint 'assets/stylesheets/**/*.scss' --fix --allow-empty-input\",\n \"lint:js\": \"eslint {assets,admin/assets,test}/javascripts --cache --no-error-on-unmatched-pattern\",\n \"lint:js:fix\": \"eslint {assets,admin/assets,test}/javascripts --fix --no-error-on-unmatched-pattern\",\n \"lint:prettier\": \"pnpm prettier 'assets/stylesheets/**/*.scss' '{assets,admin/assets,test}/javascripts/**/*.{js,gjs,ts,gts,mts,cts}' --check --no-error-on-unmatched-pattern\",\n \"lint:prettier:fix\": \"pnpm prettier 'assets/stylesheets/**/*.scss' '{assets,admin/assets,test}/javascripts/**/*.{js,gjs,ts,gts,mts,cts}' -w --no-error-on-unmatched-pattern\",\n \"lint:types\": \"ember-tsc -b\",\n \"lttf:ignore\": \"lint-to-the-future ignore\",\n \"discourse-skeleton-update\": \"pnpx discourse-skeleton-update@latest\"\n },\n \"engines\": {\n \"node\": \">= 22\",\n \"npm\": \"please-use-pnpm\",\n \"yarn\": \"please-use-pnpm\",\n \"pnpm\": \"^10\"\n },\n \"packageManager\": \"pnpm@10.28.0\"\n}\n",
"package.json": "{\n \"private\": true,\n \"devDependencies\": {\n \"@discourse/lint-configs\": \"3.2.0\",\n \"@glint/ember-tsc\": \"1.8.11\",\n \"concurrently\": \"^9.2.3\",\n \"discourse\": \"npm:@discourse/types@2026.3.0-d02b2966\",\n \"eslint\": \"10.6.0\",\n \"lint-to-the-future\": \"^2.6.4\",\n \"lint-to-the-future-eslint\": \"^3.3.0\",\n \"prettier\": \"3.8.1\",\n \"stylelint\": \"17.5.0\"\n },\n \"scripts\": {\n \"lint\": \"concurrently \\\"pnpm:lint:*(!fix)\\\" --names \\\"lint:\\\"\",\n \"lint:fix\": \"concurrently \\\"pnpm:lint:*:fix\\\" --names \\\"fix:\\\"\",\n \"lint:css\": \"pnpm stylelint 'assets/stylesheets/**/*.scss' --allow-empty-input\",\n \"lint:css:fix\": \"pnpm stylelint 'assets/stylesheets/**/*.scss' --fix --allow-empty-input\",\n \"lint:js\": \"eslint {assets,admin/assets,test}/javascripts --cache --no-error-on-unmatched-pattern\",\n \"lint:js:fix\": \"eslint {assets,admin/assets,test}/javascripts --fix --no-error-on-unmatched-pattern\",\n \"lint:prettier\": \"pnpm prettier 'assets/stylesheets/**/*.scss' '{assets,admin/assets,test}/javascripts/**/*.{js,gjs,ts,gts,mts,cts}' --check --no-error-on-unmatched-pattern\",\n \"lint:prettier:fix\": \"pnpm prettier 'assets/stylesheets/**/*.scss' '{assets,admin/assets,test}/javascripts/**/*.{js,gjs,ts,gts,mts,cts}' -w --no-error-on-unmatched-pattern\",\n \"lint:types\": \"ember-tsc -b\",\n \"lttf:ignore\": \"lint-to-the-future ignore\",\n \"update-skeleton\": \"pnpx @discourse/update-skeleton@latest\"\n },\n \"engines\": {\n \"node\": \">= 22\",\n \"npm\": \"please-use-pnpm\",\n \"yarn\": \"please-use-pnpm\",\n \"pnpm\": \"^10\"\n },\n \"packageManager\": \"pnpm@10.28.0\"\n}\n",
".gitignore": "node_modules\n/gems\n/auto_generated\n.eslintcache\n",
"eslint.config.mjs": "import DiscourseRecommended from \"@discourse/lint-configs/eslint\";\n\nexport default [...DiscourseRecommended];\n",
".prettierrc.cjs": "module.exports = require(\"@discourse/lint-configs/prettier\");\n",
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"type": "theme",
"repository": "discourse/discourse-theme-skeleton",
"files": {
"package.json": "{\n \"private\": true,\n \"devDependencies\": {\n \"@discourse/lint-configs\": \"3.2.0\",\n \"@glint/ember-tsc\": \"1.8.11\",\n \"concurrently\": \"^9.2.3\",\n \"discourse\": \"npm:@discourse/types@2026.3.0-d02b2966\",\n \"eslint\": \"10.6.0\",\n \"lint-to-the-future\": \"^2.6.4\",\n \"lint-to-the-future-eslint\": \"^3.3.0\",\n \"prettier\": \"3.8.1\",\n \"stylelint\": \"17.5.0\"\n },\n \"scripts\": {\n \"lint\": \"concurrently \\\"pnpm:lint:*(!fix)\\\" --names \\\"lint:\\\"\",\n \"lint:fix\": \"concurrently \\\"pnpm:lint:*:fix\\\" --names \\\"fix:\\\"\",\n \"lint:css\": \"pnpm stylelint '{javascripts,desktop,mobile,common,scss,stylesheets}/**/*.scss' --allow-empty-input\",\n \"lint:css:fix\": \"pnpm stylelint '{javascripts,desktop,mobile,common,scss,stylesheets}/**/*.scss' --fix --allow-empty-input\",\n \"lint:js\": \"eslint {javascripts,test} --cache --no-error-on-unmatched-pattern\",\n \"lint:js:fix\": \"eslint {javascripts,test} --fix --no-error-on-unmatched-pattern\",\n \"lint:prettier\": \"pnpm prettier '{javascripts,desktop,mobile,common,scss,stylesheets}/**/*.scss' '{javascripts,test}/**/*.{js,gjs,ts,gts,mts,cts}' --check --no-error-on-unmatched-pattern\",\n \"lint:prettier:fix\": \"pnpm prettier '{javascripts,desktop,mobile,common,scss,stylesheets}/**/*.scss' '{javascripts,test}/**/*.{js,gjs,ts,gts,mts,cts}' -w --no-error-on-unmatched-pattern\",\n \"lint:types\": \"ember-tsc -b\",\n \"lttf:ignore\": \"lint-to-the-future ignore\",\n \"discourse-skeleton-update\": \"pnpx discourse-skeleton-update@latest\"\n },\n \"engines\": {\n \"node\": \">= 22\",\n \"npm\": \"please-use-pnpm\",\n \"yarn\": \"please-use-pnpm\",\n \"pnpm\": \"^10\"\n },\n \"packageManager\": \"pnpm@10.28.0\"\n}\n",
"package.json": "{\n \"private\": true,\n \"devDependencies\": {\n \"@discourse/lint-configs\": \"3.2.0\",\n \"@glint/ember-tsc\": \"1.8.11\",\n \"concurrently\": \"^9.2.3\",\n \"discourse\": \"npm:@discourse/types@2026.3.0-d02b2966\",\n \"eslint\": \"10.6.0\",\n \"lint-to-the-future\": \"^2.6.4\",\n \"lint-to-the-future-eslint\": \"^3.3.0\",\n \"prettier\": \"3.8.1\",\n \"stylelint\": \"17.5.0\"\n },\n \"scripts\": {\n \"lint\": \"concurrently \\\"pnpm:lint:*(!fix)\\\" --names \\\"lint:\\\"\",\n \"lint:fix\": \"concurrently \\\"pnpm:lint:*:fix\\\" --names \\\"fix:\\\"\",\n \"lint:css\": \"pnpm stylelint '{javascripts,desktop,mobile,common,scss,stylesheets}/**/*.scss' --allow-empty-input\",\n \"lint:css:fix\": \"pnpm stylelint '{javascripts,desktop,mobile,common,scss,stylesheets}/**/*.scss' --fix --allow-empty-input\",\n \"lint:js\": \"eslint {javascripts,test} --cache --no-error-on-unmatched-pattern\",\n \"lint:js:fix\": \"eslint {javascripts,test} --fix --no-error-on-unmatched-pattern\",\n \"lint:prettier\": \"pnpm prettier '{javascripts,desktop,mobile,common,scss,stylesheets}/**/*.scss' '{javascripts,test}/**/*.{js,gjs,ts,gts,mts,cts}' --check --no-error-on-unmatched-pattern\",\n \"lint:prettier:fix\": \"pnpm prettier '{javascripts,desktop,mobile,common,scss,stylesheets}/**/*.scss' '{javascripts,test}/**/*.{js,gjs,ts,gts,mts,cts}' -w --no-error-on-unmatched-pattern\",\n \"lint:types\": \"ember-tsc -b\",\n \"lttf:ignore\": \"lint-to-the-future ignore\",\n \"update-skeleton\": \"pnpx @discourse/update-skeleton@latest\"\n },\n \"engines\": {\n \"node\": \">= 22\",\n \"npm\": \"please-use-pnpm\",\n \"yarn\": \"please-use-pnpm\",\n \"pnpm\": \"^10\"\n },\n \"packageManager\": \"pnpm@10.28.0\"\n}\n",
".gitignore": "node_modules\n.discourse-site\n.eslintcache\n",
"eslint.config.mjs": "import DiscourseRecommendedTheme from \"@discourse/lint-configs/eslint-theme\";\n\nexport default [...DiscourseRecommendedTheme];\n",
".prettierrc.cjs": "module.exports = require(\"@discourse/lint-configs/prettier\");\n",
Expand Down
9 changes: 4 additions & 5 deletions test/update.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ for (const type of ["theme", "plugin"]) {
assert.equal(pkg.private, false);
assert.equal(pkg.scripts.build, "custom build");
assert.equal(
pkg.scripts["discourse-skeleton-update"],
"pnpx discourse-skeleton-update@latest"
pkg.scripts["update-skeleton"],
"pnpx @discourse/update-skeleton@latest"
);
assert.equal(pkg.optionalDependencies.eslint, "10.6.0");
assert.equal(pkg.devDependencies.eslint, undefined);
assert.equal(pkg.devDependencies["ember-template-lint"], undefined);
assert.equal(pkg.devDependencies["discourse-skeleton-update"], undefined);
assert.equal(pkg.devDependencies["@discourse/update-skeleton"], undefined);
assert.equal(
await fs.readFile(path.join(f.directory, "eslint.config.mjs"), "utf8"),
f.snapshot.files["eslint.config.mjs"]
Expand Down Expand Up @@ -158,8 +158,7 @@ test("a failed Bundler update stops subsequent commands and can be retried", asy
});

test("CLI help works without a project and unknown options fail", async () => {
const cli = new URL("../bin/discourse-skeleton-update.js", import.meta.url)
.pathname;
const cli = new URL("../bin/update-skeleton.js", import.meta.url).pathname;
const { stdout } = await execa(process.execPath, [cli, "--help"]);
assert.match(stdout, /theme or plugin root/);
await assert.rejects(
Expand Down