Skip to content

Commit f550e66

Browse files
Add support for publishing to npm from GitHub (#26)
1 parent 0c227ae commit f550e66

File tree

10 files changed

+144
-27
lines changed

10 files changed

+144
-27
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@ name: CI
33
on:
44
push:
55
branches:
6-
- main
6+
- '**'
77
pull_request:
88
branches:
9-
- main
9+
- '**'
1010

1111
jobs:
1212
ci:
13-
if: github.repository == 'skirtles-code/create-vue-lib'
1413
runs-on: ubuntu-latest
1514
steps:
1615
- name: Checkout
@@ -31,4 +30,5 @@ jobs:
3130
- name: Build
3231
run: pnpm run build
3332
- name: Release
33+
if: github.repository == 'skirtles-code/create-vue-lib'
3434
run: pnpx pkg-pr-new publish --bin --commentWithSha --pnpm --packageManager=pnpm './packages/create-vue-lib'

.github/workflows/pages.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ concurrency:
2222
jobs:
2323
# Single deploy job since we're just deploying
2424
deploy:
25+
if: github.repository == 'skirtles-code/create-vue-lib'
2526
environment:
2627
name: github-pages
2728
url: ${{ steps.deployment.outputs.page_url }}

.github/workflows/publish.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ permissions:
1717

1818
jobs:
1919
publish:
20+
if: github.repository == 'skirtles-code/create-vue-lib'
2021
runs-on: ubuntu-latest
2122
steps:
2223
- name: Checkout

packages/create-vue-lib/src/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ type Config = {
8686
includeVitest: boolean
8787
includeGithubCi: boolean
8888
includePkgPrNew: boolean
89+
includeNpmPublish: boolean
8990
includeAtAliases: boolean
9091
includeTestVariable: boolean
9192
includeTailwind: boolean
@@ -277,6 +278,7 @@ async function init() {
277278
const includePlayground = await togglePrompt('Include playground application for development?', true)
278279
const includeGithubCi = await togglePrompt('Include GitHub CI configuration?', !!githubPath)
279280
const includePkgPrNew = includeGithubCi && await togglePrompt('Include pkg.pr.new in CI configuration?', false)
281+
const includeNpmPublish = await togglePrompt('Include GitHub configuration for publishing to npm?', !!githubPath)
280282
const includeExamples = await togglePromptIf(extended, 'Include example code?', true, 'Yes', 'No, just configs')
281283
const includeAtAliases = await togglePromptIf(extended, 'Configure @ as an alias for src?')
282284
const includeTestVariable = await togglePromptIf(extended, 'Configure global __TEST__ variable?')
@@ -345,6 +347,7 @@ async function init() {
345347
includeVitest,
346348
includeGithubCi,
347349
includePkgPrNew,
350+
includeNpmPublish,
348351
includeAtAliases,
349352
includeTestVariable,
350353
includeTailwind,
@@ -377,6 +380,10 @@ async function init() {
377380
copyTemplate('ci', config)
378381
}
379382

383+
if (config.includeNpmPublish) {
384+
copyTemplate('npm-publish', config)
385+
}
386+
380387
if (config.includeTailwind) {
381388
copyTemplate('tailwind', config)
382389
}

packages/create-vue-lib/src/template/ci/config/.github/workflows/ci.yml.ejs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,13 @@ name: CI
33
on:
44
push:
55
branches:
6-
- main
6+
- '**'
77
pull_request:
88
branches:
9-
- main
9+
- '**'
1010

1111
jobs:
1212
ci:
13-
<%_ if (config.githubPath) { _%>
14-
if: github.repository == '<%- config.githubPath %>'
15-
<%_ } _%>
1613
runs-on: ubuntu-latest
1714
steps:
1815
- name: Checkout
@@ -40,5 +37,6 @@ jobs:
4037
<%_ } _%>
4138
<%_ if (config.includePkgPrNew) { _%>
4239
- name: Release
40+
if: github.repository == '<%- config.githubPath %>'
4341
run: pnpx pkg-pr-new publish --commentWithSha --pnpm --packageManager=pnpm,npm,yarn './<%- config.packagesDir %><%- config.mainPackageDirName %>'
4442
<%_ } _%>

packages/create-vue-lib/src/template/gh-pages/config/.github/workflows/pages.yml.ejs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@
22
name: Deploy to GitHub Pages
33

44
on:
5-
# Runs on pushes targeting the default branch
6-
push:
7-
branches:
8-
- main
5+
<%_ if (config.includeNpmPublish) { _%>
6+
# Allows the workflow to be triggered from other workflows
7+
workflow_call:
8+
9+
<%_ } _%>
10+
# Run on pushes targeting the `main` branch
11+
# push:
12+
# branches:
13+
# - main
914
<%_ if (config.includePlayground) { _%>
10-
paths-ignore:
11-
- '<%- config.packagesDir %>playground/**'
15+
# paths-ignore:
16+
# - '<%- config.packagesDir %>playground/**'
1217
<%_ } _%>
1318

1419
# Allows you to run this workflow manually from the Actions tab
@@ -28,6 +33,9 @@ concurrency:
2833
jobs:
2934
# Single deploy job since we're just deploying
3035
deploy:
36+
<%_ if (config.githubPath) { _%>
37+
if: github.repository == '<%- config.githubPath %>'
38+
<%_ } _%>
3139
environment:
3240
name: github-pages
3341
url: ${{ steps.deployment.outputs.page_url }}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Publish package to the npm registry
2+
name: Publish package to npm
3+
4+
on:
5+
# Run the workflow when a new tag is pushed starting with `v`
6+
# push:
7+
# tags:
8+
# - 'v*'
9+
10+
# Allows you to run this workflow manually from the Actions tab
11+
workflow_dispatch:
12+
13+
permissions:
14+
contents: read
15+
<%_ if (config.includeGithubPages) { _%>
16+
pages: write
17+
<%_ } _%>
18+
id-token: write
19+
20+
jobs:
21+
publish:
22+
<%_ if (config.githubPath) { _%>
23+
if: github.repository == '<%- config.githubPath %>'
24+
<%_ } _%>
25+
runs-on: ubuntu-latest
26+
steps:
27+
- name: Checkout
28+
uses: actions/checkout@v6
29+
- name: Install pnpm
30+
uses: pnpm/action-setup@v5
31+
- name: Set up Node
32+
uses: actions/setup-node@v6
33+
with:
34+
node-version: 24
35+
cache: 'pnpm'
36+
registry-url: 'https://registry.npmjs.org'
37+
- name: Install dependencies
38+
run: pnpm install
39+
- name: Build
40+
run: pnpm --filter "<%- config.scopedPackageName %>" run build
41+
- name: Publish
42+
run: pnpm --filter "<%- config.scopedPackageName %>" publish
43+
<%_ if (config.includeGithubPages) { _%>
44+
docs:
45+
needs: publish
46+
uses: ./.github/workflows/pages.yml
47+
<%_ } _%>

packages/docs/src/publishing.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,14 @@ It's common to create a release on GitHub when publishing a package. This includ
102102

103103
## Automating the process
104104

105-
This scaffolding tool doesn't currently have any support for automating this process, but you can find various examples of automation scripts if you look through the GitHub repos for large projects.
105+
Several parts of the publishing process can be automated. You can find various examples of automation scripts if you look through the GitHub repos for large projects.
106+
107+
This scaffolding tool provides configuration for using *trusted publishing* via a GitHub Action. It will be included if you answered `Yes` to the question *[Include GitHub configuration for publishing to npm?](questions#include-npm-publish)*.
108+
109+
The workflow configuration is in `.github/workflows/publish.yml`. You'll also need to enable trusted publishing in the settings for your package on the npm registry:
110+
111+
- https://docs.npmjs.com/trusted-publishers
112+
113+
The first time you publish your package you'll need to do it manually, then you can enable trusted publishing for subsequent releases.
114+
115+
You should check the contents of `publish.yml` to ensure you understand what it's doing. It will build and publish the package, but it won't handle any other part of the release process. The other steps, such as updating the version number in `package.json`, are still down to you.

packages/docs/src/questions.md

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
<span class="check">✔</span> <a href="#include-playground">Include playground application for development? … No / Yes</a>
5555
<span class="check">✔</span> <a href="#include-github-ci">Include GitHub CI configuration? … No / Yes</a>
5656
<span class="check">✔</span> <a href="#include-pkg-pr-new">Include pkg.pr.new in CI configuration? … No / Yes</a>
57+
<span class="check">✔</span> <a href="#include-npm-publish">Include GitHub configuration for publishing to npm? … No / Yes</a>
5758
<span class="check">✔</span> <a href="#include-examples">Include example code? … No, just configs / Yes</a>
5859
<span class="check">✔</span> <a href="#configure-src-alias">Configure @ as an alias for src? … No / Yes</a>
5960
<span class="check">✔</span> <a href="#configure-test-variable">Configure global __TEST__ variable? … No / Yes</a></pre>
@@ -141,7 +142,7 @@ The GitHub path should be in the form `username/repo-name`.
141142

142143
For example, this project has its repository at `https://github.com/skirtles-code/create-vue-lib`, so the GitHub path is `skirtles-code/create-vue-lib`.
143144

144-
While answering this question is optional, it can be especially useful if you intend to use GitHub Pages to host your documentation, as the generated configuration files will be much closer to their final form.
145+
While answering this question is optional, it can be especially useful if you intend to use GitHub Pages to host your documentation, as the generated configuration files will be much closer to their final form. It is also used in some of the workflow configurations for GitHub Actions to help ensure they don't run on forks.
145146

146147
## Include Tailwind CSS?{#include-tailwind-css}
147148

@@ -221,22 +222,34 @@ The playground application will use your library direct from the source code, wi
221222

222223
## Include GitHub CI configuration?{#include-github-ci}
223224

224-
Continuous Integration (CI) is used to help catch problems as soon as they occur.
225+
*Continuous integration* (CI) is used to help catch problems as soon as they occur.
225226

226-
This option will include a GitHub Actions configuration for a CI workflow. It will run the `lint`, `type-check`, `build` and `test:unit` targets from the `scripts` section of the root `package.json`. The workflow is triggered by any PRs opened against the `main` branch, as well as when changes are pushed to `main`.
227-
228-
If a [GitHub path](#github-path) has been provided, the job will be configured so that it only runs for that specific fork.
227+
This option will include a GitHub Actions configuration for a CI workflow. It will run the `lint`, `type-check`, `build` and `test:unit` targets from the `scripts` section of the root `package.json`. The workflow is triggered when a PR is opened or when new commits are pushed to a branch.
229228

230229
## Include pkg.pr.new in CI configuration?{#include-pkg-pr-new}
231230

232231
:::info NOTE
233232
You'll only see this question if you chose to include GitHub CI configuration.
234233
:::
235234

236-
[pkg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new) allows for continuous releases. Every PR and every commit to `main` will be published as a package on pkg.pr.new, which is similar to the npm registry but with each 'release' tied to a specific commit rather than a version number. This allows changes to be installed and tested before they're merged or released to npm.
235+
[pkg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new) allows for *continuous releases*. Every PR and every commit to a branch will be published as a package on pkg.pr.new, which is similar to the npm registry but with each 'release' tied to a specific commit rather than a version number. This allows changes to be installed and tested before they're merged or released to npm.
237236

238237
You'll also need to install the [pkg.pr.new GitHub App](https://github.com/apps/pkg-pr-new) and enable it on your GitHub repository.
239238

239+
## Include GitHub configuration for publishing to npm?{#include-npm-publish}
240+
241+
The recommended way to publish a package to the npm registry is via *trusted publishing*:
242+
243+
- https://docs.npmjs.com/trusted-publishers
244+
245+
If you'd like to publish your package using a GitHub Action then select this option. It will include a suitable workflow in `.github/workflow/publish.yml` with trusted publishing enabled.
246+
247+
By default, this workflow will only run when it is triggered manually, via the **Actions** tab of your GitHub repository.
248+
249+
You will also need to configure trusted publishing for your package on the npm registry. This can only be done for packages that already exist, so the first release of your package won't be able to use the automated workflow.
250+
251+
- See also: [Publishing to npm](publishing)
252+
240253
## Include example code?{#include-examples}
241254

242255
:::info NOTE

packages/docs/src/why.md

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ The project's root `package.json` uses `preinstall` and `postinstall` hooks. It'
3232

3333
## TypeScript configuration
3434

35-
The TypeScript configuration is mostly done of a per-package basis. The configuration files are closely based on the files created by `create-vue`.
35+
The TypeScript configuration is mostly done on a per-package basis. The configuration files are closely based on the files created by `create-vue`.
3636

3737
A root-level `tsconfig.json` is only created if ESLint is included. That is just used to check `eslint.config.ts`, which is at the root of the project. There currently aren't any other TS files that live outside the sub-packages.
3838

@@ -112,9 +112,27 @@ For `__TEST__` we replace the value with a simple `true` or `false`, which can b
112112

113113
For `__DEV__` it's a little more complicated, because in some builds we replace it with `!(process.env.NODE_ENV === "production")`. This allows the downstream bundler to make the decision about what mode we're in. We can't use `define` for a complex value like this, so `@rollup/plugin-replace` is used instead.
114114

115-
## `pages.yml`
115+
## GitHub Action workflows
116116

117-
The file `.github/worksflows/pages.yml` configures the GitHub Pages workflow for the documentation. The exact name of the file is not important, GitHub will run all workflows configured in `.github/workflows`.
117+
The files in `.github/workflows` are workflow configurations for GitHub Actions. The exact names of these files aren't important, GitHub will load all workflows in that directory and run them as needed.
118+
119+
Different workflows need to run at different times. This is controlled via the `on` setting, which specifies exactly which events should trigger the workflow. Some events can also be filtered further to target specific branches, tags or file paths within the repo.
120+
121+
It's also necessary to consider how workflows should behave on forks. If other contributors fork your repo on GitHub then they'll also copy the workflow configurations. For a CI workflow, building and testing changes on the fork is probably what you'd want. But a workflow for deploying the documentation probably shouldn't be enabled on a fork.
122+
123+
Where relevant, the workflows will try to use an `if` check on `github.repository` to ensure that they only run on the original repo. This can only be configured correctly if you provided a [GitHub path](questions#github-path) when running the scaffolding tool.
124+
125+
### `ci.yml`
126+
127+
Depending on exactly which options you picked, the CI workflow will build the project (including the docs and playground), run the tests, linting and type checking. It's also responsible for [deploying to pkg.pr.new](questions#include-pkg-pr-new).
128+
129+
### `pages.yml`
130+
131+
:::info NOTE
132+
You'll also need to enable GitHub Pages in the settings for your repo.
133+
:::
134+
135+
The file `.github/worksflows/pages.yml` configures the GitHub Pages workflow for the documentation.
118136

119137
The configuration is similar to those found at:
120138

@@ -123,11 +141,25 @@ The configuration is similar to those found at:
123141

124142
pnpm is enabled in the configuration, but a specific version isn't specified as we're using the `packageManager` option in `package.json`.
125143

126-
The workflow is configured to run on the `main` branch. You'd typically want the documentation to reflect the latest release, so whether `main` is an appropriate choice will depend on your release process.
144+
The workflow can be run manually from the **Actions** tab in GitHub. If you opted to [include a workflow for npm publishing](questions#include-npm-publish) then that will also trigger deployment of the docs. This ensures the latest docs are deployed when a new release is published to the npm registry.
127145

128-
The [`paths-ignore`](https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#onpushpull_requestpull_request_targetpathspaths-ignore) setting can be used to avoid running GitHub Pages for changes that don't impact the documentation. The default configuration will only ignore the playground package. Trying to be really precise about what changes trigger the workflow is error-prone and the small gains usually aren't worth the extra effort.
146+
If you want to deploy the docs for all commits to `main` then you'll need to edit `pages.yml` to enable that. The relevant configuration is already included, it's just commented out. This can lead to the docs for new features being released before they're published to npm, so it should only be enabled if it makes sense for your branching strategy and release process.
129147

130-
You'll also need to enable GitHub Pages in the settings for your repo.
148+
### `publish.yml`
149+
150+
:::info NOTE
151+
You'll also need to enable *trusted publishing* in the settings for your package on the npm registry.
152+
:::
153+
154+
The file `.github/worksflows/publish.yml` configures a GitHub workflow to release your package to the npm registry.
155+
156+
By default, this workflow will not run automatically. It must be run manually from the **Actions** tab in your GitHub repository. This is intentionally cautious but can easily be changed. A common approach is to tag each release with a git tag and to trigger the workflow whenever a new tag is added to the repo. There's example configuration for that in `publish.yml`.
157+
158+
The workflow will build the package and publish it to the npm registry. It avoids building the other packages, such as the docs or playground, and won't run the tests or linting checks. Those checks are already performed by the CI workflow and aren't strictly required to make a release. It is left to your discretion to decide whether your codebase is ready for a release.
159+
160+
Running the workflow won't make any changes to the code, such as bumping the version number. You'll need to ensure the version is set correctly in the relevant `package.json` before running the workflow.
161+
162+
- See also: [Publishing to npm](publishing)
131163

132164
## `jiti`
133165

0 commit comments

Comments
 (0)