Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support workspaces in destination #101

Merged
merged 36 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
987fe58
move destination discovery earlier into CLI and pass destination around
LekoArts Jul 4, 2024
488cae8
switch destPkg from Map to Set
LekoArts Jul 4, 2024
80a1ae7
improve error
LekoArts Jul 5, 2024
bc0da27
update tests
LekoArts Jul 5, 2024
5a0fc11
add last bit of workspaces functionality
LekoArts Jul 5, 2024
9130d7d
Merge branch 'main' into feat/workspaces
LekoArts Jul 5, 2024
e7874bd
add changeset
LekoArts Jul 5, 2024
f6773e7
update jsdoc
LekoArts Jul 5, 2024
c653222
update integration tests
LekoArts Jul 7, 2024
94c8845
add VERDACCIO_PORT env var
LekoArts Jul 8, 2024
826400f
update tests
LekoArts Jul 8, 2024
f7da2e5
update test
LekoArts Jul 8, 2024
626e79f
Modify test to speed up (revert me)
LekoArts Jul 9, 2024
3edb0f0
rename
LekoArts Jul 9, 2024
a9b1ba0
debug
LekoArts Jul 9, 2024
45118ef
update
LekoArts Jul 9, 2024
62ac342
test
LekoArts Jul 9, 2024
ad8ec9a
actual good fixes
LekoArts Jul 9, 2024
b2b0cff
Revert "Modify test to speed up (revert me)"
LekoArts Jul 9, 2024
1ae2891
Revert "debug"
LekoArts Jul 9, 2024
93d6e5c
revert more
LekoArts Jul 9, 2024
452ebf5
update
LekoArts Jul 9, 2024
efeb31f
put isolated dir into github_env
LekoArts Jul 9, 2024
27290c7
use glob
LekoArts Jul 9, 2024
f3a675a
revert me
LekoArts Jul 9, 2024
7340f51
update
LekoArts Jul 9, 2024
8cec610
update
LekoArts Jul 9, 2024
12fa378
update
LekoArts Jul 9, 2024
4b4e873
debug
LekoArts Jul 9, 2024
4ea8930
fix VERBOSE bug
LekoArts Jul 9, 2024
57a3eb9
try config option
LekoArts Jul 9, 2024
bdf592d
try config option
LekoArts Jul 9, 2024
1a57ceb
revert debug stuff
LekoArts Jul 9, 2024
db8af60
rename to SECCO_VERDACCIO_PORT
LekoArts Jul 9, 2024
a3efe2e
update docs
LekoArts Jul 9, 2024
2f170f4
update changesets
LekoArts Jul 9, 2024
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
5 changes: 5 additions & 0 deletions .changeset/beige-rings-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"secco": patch
---

Correctly display additional information e.g. during `npm install` when `VERBOSE` env var is set
2 changes: 1 addition & 1 deletion .changeset/cool-actors-visit.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
"secco": minor
---

Support Yarn Berry (currently v3 & v4) by modyfing the .yarnrc.yml file inside the destination before trying to install packages from the local Verdaccio registry
Support Yarn Berry (currently v3 & v4) by modyfing the `.yarnrc.yml` file inside the destination before trying to install packages from the local Verdaccio registry
5 changes: 5 additions & 0 deletions .changeset/fluffy-fans-explain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"secco": minor
---

Add `SECCO_VERDACCIO_PORT` environment variable. You can use this to change the default port (`4873`) when secco uses Verdaccio.
7 changes: 7 additions & 0 deletions .changeset/silver-oranges-wink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"secco": minor
---

You can now use secco inside destinations that are set up with [workspaces](https://docs.npmjs.com/cli/v10/using-npm/workspaces). It should work for all supported package managers (npm, yarn, pnpm, bun).

Please note: secco will automatically use the `--force-verdaccio` flag when inside a workspaces project.
7 changes: 7 additions & 0 deletions .github/workflows/integration-testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,10 @@ jobs:
env:
INTEGRATION_PM_NAME: ${{ matrix.pm.name }}
INTEGRATION_PM_VERSION: ${{ matrix.pm.version }}
- name: Upload temp dir (optional)
if: ${{ cancelled() || failure() }}
uses: actions/upload-artifact@v4
with:
name: temp-dir-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.pm.name }}
path: ${{ runner.temp }}/secco-**/**/*
retention-days: 1
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ secco solves these problems and streamlines the process of local package testing
- **Link Multiple Projects.** secco reads the `.seccorc` file to make the connection between destination and source. This allows you to use `secco` with as many source folders as you wish.
- **npm, yarn, pnpm, and bun support.** You can use any of these package managers in your source and destination projects.
- **Watch and CI mode.** By default, secco starts a watch task. But you can also only run it once, enabling CI End-To-End testing use cases.
- **Workspaces (in source).** Your source folder can be a monorepo using workspaces.
- **Workspaces.** Your source & destination folders can be a monorepo using workspaces.

<a href="https://www.lekoarts.de?utm_source=secco">
<img alt="lekoarts.de" src="https://img.shields.io/badge/-website-blue">
Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/guide/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ secco boasts a lot of features to enable you to test local changes more quickly.
- **Link Multiple Projects.** secco reads the `.seccorc` file to make the connection between destination and source. This allows you to use `secco` with as many source folders as you wish.
- **npm, yarn, pnpm, and bun support.** You can use any of these package managers in your source and destination projects.
- **Watch and CI mode.** By default, secco starts a watch task. But you can also only run it once, enabling CI End-To-End testing use cases.
- **Workspaces (in source).** Your source folder can be a monorepo using workspaces.
- **Workspaces.** Your source & destination folders can be a monorepo using workspaces.
7 changes: 7 additions & 0 deletions docs/src/content/docs/reference/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,10 @@ Equivalent to `source.path`.
- **Default:** `false`

Equivalent to the [`--verbose`](/reference/flags/#--verbose) flag.

### `SECCO_VERDACCIO_PORT`

- **Type:** `string`
- **Default:** `4873`

Configure the port that secco's internal Verdaccio instance uses.
1 change: 1 addition & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export default antfu(
},
],
'ts/array-type': ['error', { default: 'generic' }],
'node/prefer-global/process': 'off',
},
},
)
58 changes: 0 additions & 58 deletions integration/__tests__/kitchen-sink.ts

This file was deleted.

13 changes: 8 additions & 5 deletions integration/__tests__/missing-information.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,35 @@ import { SeccoCLI } from '../helpers/invoke-cli'

const missingSourcePackagesLocation = join(__dirname, '..', 'fixtures', 'missing-source-packages')

describe('missing .seccorc', () => {
describe('missing information', () => {
it('should display error when no .seccorc or env var is found', () => {
const [exitCode, logs] = SeccoCLI().setFixture('empty').invoke([''])

logs.should.contain('No `.seccorc` file found in')
logs.should.contain('Please run `secco init` to create a new `.seccorc` file.')
expect(exitCode).toBe(0)
})
})

describe('missing package.json', () => {
it('should display error when no package.json is found', () => {
const [exitCode, logs] = SeccoCLI().setFixture('existing-config-file').invoke([''])

logs.should.contain('No `package.json` found in')
logs.should.contain('Current directory must contain a `package.json` file.')
expect(exitCode).toBe(0)
})
})

describe('missing source packages', () => {
it('should display error when no source package is found in package.json', () => {
const [exitCode, logs] = SeccoCLI().setFixture('missing-source-packages').setEnv({ SECCO_SOURCE_PATH: missingSourcePackagesLocation }).invoke([''])

logs.should.contain(`You haven't got any source dependencies in your current \`package.json\`.`)
logs.should.contain(`If you only want to use \`secco\` you'll need to add the dependencies to your \`package.json\`.`)
expect(exitCode).toBe(0)
})

it('should display error when source.path is incorrect', () => {
const [exitCode, logs] = SeccoCLI().setFixture('missing-source-packages').setEnv({ SECCO_SOURCE_PATH: '/Users/secco' }).invoke([''])

logs.should.contain(`[fatal] Couldn't find package.json in /Users/secco`)
expect(exitCode).toBe(0)
})
})
87 changes: 87 additions & 0 deletions integration/__tests__/scan-once.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import fs from 'fs-extra'
import { join } from 'pathe'
import type { Application } from '../models/application'
import { presets } from '../presets'

async function renamePnpmWorkspaceFixture(app: Application) {
const fixture = join(app.dir, 'destination', 'fixture.pnpm-workspace.yaml')
const tmpWorkspaceYaml = join(app.dir, 'destination', 'pnpm-workspace.yaml')

await fs.rename(fixture, tmpWorkspaceYaml)
}

describe.sequential('scan-once', () => {
describe.sequential('single package', () => {
let app: Application

beforeAll(async () => {
app = await presets.kitchenSink.commit()

process.env.SECCO_VERDACCIO_PORT = '4873'
})

afterAll(async () => {
await app.cleanup()
})

it('should run Verdaccio with --force-verdaccio', () => {
const [exitCode, logs] = app.cli(['--scan-once', '--force-verdaccio', '--verbose'])

logs.should.contain('[log] [Verdaccio] Starting server...')
logs.should.contain('[log] [Verdaccio] Started successfully!')
logs.should.contain('[log] Publishing `say-hello-world@0.0.2-secco-')
logs.should.contain('[log] Published `say-hello-world@0.0.2-secco-')
logs.should.contain(`[debug] Detected package manager in destination: ${app.packageManager.split('@')[0]}`)
logs.should.contain('[log] Installing packages from local registry:')
logs.should.contain('[success] Installation finished successfully!')

expect(exitCode).toBe(0)
})

it('should copy files on consecutive runs', () => {
const [exitCode, logs] = app.cli(['--scan-once'], { verbose: true })

logs.should.not.contain('[log] [Verdaccio] Starting server...')
logs.should.not.contain('[success] Installation finished successfully!')
logs.should.contain('[log] Copied `index.mjs` to `node_modules/say-hello-world/index.mjs`')
logs.should.contain('[log] Copied `package.json` to `node_modules/say-hello-world/package.json`')
logs.should.contain('[info] Copied 2 files. Exiting...')

expect(exitCode).toBe(0)
})
})

describe.sequential('workspaces', () => {
let app: Application

beforeAll(async () => {
app = await presets.kitchenSinkWorkspaces.commit()

if (process.env.INTEGRATION_PM_NAME === 'pnpm') {
await renamePnpmWorkspaceFixture(app)
}

process.env.SECCO_VERDACCIO_PORT = '4874'
})

afterAll(async () => {
await app.cleanup()
})

it('should work (with Verdaccio by default)', () => {
const [exitCode, logs] = app.cli(['--scan-once'], { verbose: true })

logs.logOutput()

logs.should.contain('[log] [Verdaccio] Starting server...')
logs.should.contain('[log] [Verdaccio] Started successfully!')
logs.should.contain('[log] Publishing `say-hello-world-workspaces@1.0.0-secco-')
logs.should.contain('[log] Published `say-hello-world-workspaces@1.0.0-secco-')
logs.should.contain(`[debug] Detected package manager in destination: ${app.packageManager.split('@')[0]}`)
logs.should.contain('[log] Installing packages from local registry:')
logs.should.contain('[success] Installation finished successfully!')

expect(exitCode).toBe(0)
})
})
})
1 change: 1 addition & 0 deletions integration/fixtures/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { resolve } from 'pathe'
*/
export const fixtures = {
'kitchen-sink': resolve(__dirname, 'kitchen-sink'),
'kitchen-sink-workspaces': resolve(__dirname, 'kitchen-sink-workspaces'),
} as const

export type Fixture = keyof typeof fixtures
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
packages:
- 'packages/*'
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "kitchen-sink-workspaces-destination",
"private": true,
"workspaces": [
"packages/*"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { sayHelloWorld } from 'say-hello-world'

function run() {
sayHelloWorld()
}

run()
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "destination-workspaces",
"version": "1.0.0",
"private": true,
"main": "bin.mjs",
"scripts": {
"start": "node bin.mjs"
},
"dependencies": {
"say-hello-world-workspaces": "^1.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "kitchen-sink-workspaces-source",
"private": true,
"packageManager": "pnpm@9.4.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
function sayHelloWorld() {
// eslint-disable-next-line no-console
console.log('Hello World!')
}
export {
sayHelloWorld,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "say-hello-world-workspaces",
"version": "1.0.0",
"packageManager": "pnpm@9.4.0",
"main": "index.mjs"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
packages:
- 'packages/*'
3 changes: 2 additions & 1 deletion integration/models/application-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ export function applicationConfig() {
commit: async () => {
logger.log(`Creating application "${name}"`)

const isolatedDir = await mkdtemp(join(tmpdir(), `secco-${name}-`))
const tempDir = process.env.RUNNER_TEMP || tmpdir()
const isolatedDir = await mkdtemp(join(tempDir, `secco-${name}-`))

logger.log(`Copying template "${basename(template)}" to "${isolatedDir}"`)
await cp(template, isolatedDir, { recursive: true })
Expand Down
6 changes: 6 additions & 0 deletions integration/models/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { join } from 'pathe'
import type { InvokeResult } from '../helpers/invoke-cli'
import { SeccoCLI } from '../helpers/invoke-cli'
import { createLogger } from '../helpers/logger'
import { isTruthy } from '../../src/utils/is-truthy'
import type { ApplicationConfig } from './application-config'

export type Application = ReturnType<typeof application>
Expand All @@ -27,6 +28,11 @@ export function application(config: ApplicationConfig, isolatedDir: string) {
}).invoke(args)
},
cleanup: async () => {
if (isTruthy(process.env.CI)) {
logger.log(`Skipping cleanup in CI environment`)
return
}

logger.log(`Cleaning up...`)

await rm(isolatedDir, { recursive: true, force: true })
Expand Down
17 changes: 6 additions & 11 deletions integration/presets.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* eslint-disable ts/no-namespace */
/* eslint-disable node/prefer-global/process */
import { applicationConfig } from './models/application-config'
import { fixtures } from './fixtures'

Expand All @@ -8,20 +6,17 @@ const constants = {
INTEGRATION_PM_VERSION: process.env.INTEGRATION_PM_VERSION,
}

declare global {
namespace NodeJS {
interface ProcessEnv {
INTEGRATION_PM_NAME?: 'npm' | 'pnpm' | 'yarn' | 'bun'
INTEGRATION_PM_VERSION?: string
}
}
}

const kitchenSink = applicationConfig()
.setName('kitchen-sink')
.setTemplate(fixtures['kitchen-sink'])
.setPackageManager(constants.INTEGRATION_PM_NAME, constants.INTEGRATION_PM_VERSION)

const kitchenSinkWorkspaces = applicationConfig()
.setName('kitchen-sink-workspaces')
.setTemplate(fixtures['kitchen-sink-workspaces'])
.setPackageManager(constants.INTEGRATION_PM_NAME, constants.INTEGRATION_PM_VERSION)

export const presets = {
kitchenSink,
kitchenSinkWorkspaces,
} as const
Loading
Loading