Skip to content

Commit

Permalink
ci: update CI/CD workflow, Node.js version, and registry settings
Browse files Browse the repository at this point in the history
Updated the Continuous Integration (CI) and Continuous Deployment (CD) workflows to utilize the latest versions of actions and Node.js. Adjusted the `.npmrc` and `package.json` to target a private registry and refined scripts to improve the CI process. Additionally, modified the `buildIndexes.ts` script to sort imports in a standard manner, avoiding linting issues post-build related to import ordering. This comprehensive update aims to streamline development operations and enforce consistency across CI/CD practices.
  • Loading branch information
shorwood committed Apr 25, 2024
1 parent 32c3073 commit 9f3f1f9
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 56 deletions.
55 changes: 20 additions & 35 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
name: Continuous Integration

name: CI
permissions:
id-token: write
contents: write
Expand All @@ -10,52 +9,38 @@ on:
- v*
branches:
- main
- next
pull_request:
branches:
- main
- next
merge_group: {}

jobs:
ci:
name: Node.js ${{ matrix.node }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}

strategy:
fail-fast: true
matrix:
node: [18.x]
os: [ubuntu-latest]
# node: [18.x, 16.x, 14.x]
# os: [ubuntu-latest, windows-latest, macos-latest]

name: Continuous Integration & Deployment
runs-on: ubuntu-latest
steps:

# Set up Node.js and PNPM
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with:
fetch-depth: 0

- uses: pnpm/action-setup@v2
with:
version: 8
- uses: actions/setup-node@v2
version: 9.x
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
registry-url: https://registry.npmjs.org/
node-version: 20.x
cache: "pnpm"

# Run tests and lint
# --- Install, build, and test.
- run: pnpm install
# - run: pnpm lint # Disabled until linting issues are resolved
- run: pnpm build
- run: pnpm lint:ci
- run: pnpm test:ci

# Publish to NPM
- name: Publish development version to NPM
if: github.ref == 'refs/heads/main' && matrix.node == 18
run: pnpm publish:ci
# --- Publish to private registry on main branch.
- if: github.event_name == 'push'
run: pnpm publish:ci --registry https://npm.hsjm.dev
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN_PRIVATE}}

# --- Publish to NPM registry on main branch. (Only on tags)
- if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
run: pnpm publish:ci --registry https://registry.npmjs.org
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
NPM_CONFIG_PROVENANCE: true
NODE_OPTIONS: --max-old-space-size=6144
5 changes: 4 additions & 1 deletion .npmrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
recursive-install=true
save-exact=true
always-auth=true

# Hoist all eslint and vue dependencies to the root.
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*vue*
public-hoist-pattern[]=*vue*
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@
"dev": "tsx ./scripts/build.ts --watch true",
"build": "tsx ./scripts/build.ts",
"examples:nuxt": "pnpm -F @unshared/examples-nuxt dev",
"lint": "DEBUG=eslint:eslint eslint . --cache",
"lint:ci": "eslint . --cache",
"lint:fix": "DEBUG=eslint:eslint eslint . --fix --cache",
"lint": "DEBUG=eslint:eslint eslint --cache",
"lint:ci": "eslint --cache --ignore-pattern examples",
"lint:fix": "DEBUG=eslint:eslint eslint --fix --cache",
"test": "vitest --watch",
"test:ci": "vitest --run --typecheck --coverage",
"test:ci": "vitest --run --coverage",
"test:ui": "vitest --ui",
"test:types": "vitest --typecheck",
"test:coverage": "vitest --coverage",
Expand Down
2 changes: 1 addition & 1 deletion scripts/buildIndexes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ async function buildIndex(path: string): Promise<IndexFile> {

// ---Sort the imports alphabetically and generate the index file content.
const indexContent = [...new Set(imports)]
.sort((a, b) => a.localeCompare(b))
.sort()
.map(script => `export * from './${script}'`)
.join('\n')

Expand Down
41 changes: 26 additions & 15 deletions scripts/publish.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { argv } from 'node:process'
// eslint-disable-next-line n/no-unsupported-features/node-builtins
import { cp } from 'node:fs/promises'
import { mapValues } from '@unshared/collection'
import { getPackageMetadata } from './utils'
import { PACKAGES_NAMES } from './constants'
import { createSemver } from '../packages/string/createSemver'
Expand All @@ -13,12 +14,12 @@ import { execute as $ } from '../packages/process/execute'
* hash will be appended to the version.
*
* @param packageName The name of the package to set the version for.
* @param registry The registry to publish the package to.
* @returns A promise that resolves when the version is set.
*/
export async function publishPackage(packageName: string) {
export async function pnpmPublish(packageName: string, registry: string) {
const { packageJson, packageJsonFS, packagePath } = await getPackageMetadata(packageName)
const version = createSemver(packageJson.version)
const registry = ['--registry', 'https://npm.hsjm.dev/']

// --- If the current hash has a tag, get the tag.
const hash = await $('git', ['rev-parse', 'HEAD'], 'utf8')
Expand Down Expand Up @@ -47,7 +48,7 @@ export async function publishPackage(packageName: string) {

// --- Check if the current version is already released.
// --- Get the latest version from the registry.
const npmViewJSON = await $('pnpm', ['view', packageJson.name!, '--json', ...registry], 'utf8')
const npmViewJSON = await $('pnpm', ['view', packageJson.name!, '--json'], 'utf8')
.then((json: string) => JSON.parse(json) as { version: string })
.catch(() => ({})) as { 'dist-tags': Record<string, string> }

Expand All @@ -61,6 +62,9 @@ export async function publishPackage(packageName: string) {

// --- Set the version in the package.json file.
packageJson.version = versionPublished
packageJson.dependencies = mapValues(packageJson.dependencies ?? {}, version =>
(version.startsWith('workspace:') ? versionPublished : version))

await packageJsonFS.commit()
const isNext = version.prerelease !== undefined
await $('pnpm', [
Expand All @@ -69,34 +73,41 @@ export async function publishPackage(packageName: string) {
isNext ? 'restricted' : 'public',
'--tag',
isNext ? 'next' : 'latest',
...registry,

// '--dry-run',
'--registry',
registry,
'--no-git-checks',
], {
cwd: packagePath,
stdio: 'inherit',
}).catch(() => {})

// --- Reset the version in the package.json file.
version.prerelease = undefined
packageJson.version = version.toString()
await packageJsonFS.commit()
})
}

export async function publish() {
const { parameters } = parseCliArguments(argv)
const { options, parameters } = parseCliArguments<{ registry?: string }>(argv)
const { registry } = options

// --- If not in CI, abort the process.
if (!process.env.CI) {
console.log('This script is intended to be run in a CI environment.')
return
}

// --- Registry must be explicitly set to avoid accidental publishing.
const token = process.env.NODE_AUTH_TOKEN
if (!registry) throw new Error('The NPM_REGISTRY environment variable is not set.')
if (!token) throw new Error('The NODE_AUTH_TOKEN environment variable is not set.')
await $('pnpm', ['set', `//${registry.replace('https://', '')}/:_authToken=${token}`])

// --- If package name(s) are provided, only publish the specified packages.
const packageNames = parameters.length > 0
? PACKAGES_NAMES.filter(argument => parameters.includes(argument))
: PACKAGES_NAMES

// --- Prepare the package for publishing.
for (const packageName of packageNames) {
await cp('LICENSE.md', `packages/${packageName}/LICENSE.md`)
await publishPackage(packageName)
await pnpmPublish(packageName, registry)
}
}

// --- Run the build script.
await publish()

0 comments on commit 9f3f1f9

Please sign in to comment.