diff --git a/.github/workflows/pull-request-build-lint-api.yml b/.github/workflows/pull-request-build-lint-api.yml index 11612207b1..28a623f8e2 100644 --- a/.github/workflows/pull-request-build-lint-api.yml +++ b/.github/workflows/pull-request-build-lint-api.yml @@ -27,11 +27,13 @@ jobs: github.event.pull_request.draft == false && github.event.pull_request.requested_reviewers != null steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.12.x" + cache: 'pip' + cache-dependency-path: 'apps/api/requirements.txt' - name: Install Pylint run: python -m pip install ruff - name: Install API Dependencies diff --git a/.github/workflows/pull-request-build-lint-web-apps.yml b/.github/workflows/pull-request-build-lint-web-apps.yml index 7ddaceb796..2a463852c0 100644 --- a/.github/workflows/pull-request-build-lint-web-apps.yml +++ b/.github/workflows/pull-request-build-lint-web-apps.yml @@ -17,10 +17,11 @@ concurrency: cancel-in-progress: true jobs: - build-and-lint: - name: Build and lint web apps + # Format check has no build dependencies - run immediately in parallel + check-format: + name: check:format runs-on: ubuntu-latest - timeout-minutes: 25 + timeout-minutes: 10 if: | github.event.pull_request.draft == false && github.event.pull_request.requested_reviewers != null @@ -29,28 +30,140 @@ jobs: TURBO_SCM_HEAD: ${{ github.sha }} steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: fetch-depth: 50 filter: blob:none - name: Set up Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 - name: Enable Corepack and pnpm run: corepack enable pnpm + - name: Get pnpm store directory + shell: bash + run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + + - name: Cache pnpm store + uses: actions/cache@v4 + with: + path: ${{ env.STORE_PATH }} + key: pnpm-store-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + pnpm-store-${{ runner.os }}- + - name: Install dependencies run: pnpm install --frozen-lockfile - - name: Build Affected - run: pnpm turbo run build --affected - - - name: Lint Affected - run: pnpm turbo run check:lint --affected - - - name: Check Affected format + - name: Check formatting run: pnpm turbo run check:format --affected - - name: Check Affected types - run: pnpm turbo run check:types --affected + # Build packages - required for lint and type checks + build: + name: Build packages + runs-on: ubuntu-latest + timeout-minutes: 15 + if: | + github.event.pull_request.draft == false && + github.event.pull_request.requested_reviewers != null + env: + TURBO_SCM_BASE: ${{ github.event.pull_request.base.sha }} + TURBO_SCM_HEAD: ${{ github.sha }} + NODE_OPTIONS: "--max-old-space-size=4096" + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 50 + filter: blob:none + + - name: Set up Node.js + uses: actions/setup-node@v6 + + - name: Enable Corepack and pnpm + run: corepack enable pnpm + + - name: Get pnpm store directory + shell: bash + run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + + - name: Cache pnpm store + uses: actions/cache@v4 + with: + path: ${{ env.STORE_PATH }} + key: pnpm-store-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + pnpm-store-${{ runner.os }}- + + - name: Restore Turbo cache + uses: actions/cache/restore@v4 + with: + path: .turbo + key: turbo-${{ runner.os }}-${{ github.event.pull_request.base.sha }}-${{ github.sha }} + restore-keys: | + turbo-${{ runner.os }}-${{ github.event.pull_request.base.sha }}- + turbo-${{ runner.os }}- + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build packages + run: pnpm turbo run build --affected + + - name: Save Turbo cache + uses: actions/cache/save@v4 + with: + path: .turbo + key: turbo-${{ runner.os }}-${{ github.event.pull_request.base.sha }}-${{ github.sha }} + + # Lint and type checks depend on build artifacts + check: + name: ${{ matrix.task }} + runs-on: ubuntu-latest + needs: build + timeout-minutes: 15 + strategy: + fail-fast: false + matrix: + task: [check:lint, check:types] + env: + TURBO_SCM_BASE: ${{ github.event.pull_request.base.sha }} + TURBO_SCM_HEAD: ${{ github.sha }} + NODE_OPTIONS: "--max-old-space-size=4096" + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 50 + filter: blob:none + + - name: Set up Node.js + uses: actions/setup-node@v6 + + - name: Enable Corepack and pnpm + run: corepack enable pnpm + + - name: Get pnpm store directory + shell: bash + run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + + - name: Cache pnpm store + uses: actions/cache@v4 + with: + path: ${{ env.STORE_PATH }} + key: pnpm-store-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + pnpm-store-${{ runner.os }}- + + - name: Restore Turbo cache + uses: actions/cache/restore@v4 + with: + path: .turbo + key: turbo-${{ runner.os }}-${{ github.event.pull_request.base.sha }}-${{ github.sha }} + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run ${{ matrix.task }} + run: pnpm turbo run ${{ matrix.task }} --affected diff --git a/eslint.config.mjs b/eslint.config.mjs index 17d859f7ab..e45b2f0595 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -10,6 +10,7 @@ import promisePlugin from "eslint-plugin-promise"; import reactPlugin from "eslint-plugin-react"; import reactHooksPlugin from "eslint-plugin-react-hooks"; import reactRefreshPlugin from "eslint-plugin-react-refresh"; +import turboPlugin from "eslint-plugin-turbo"; import vitestPlugin from "@vitest/eslint-plugin"; // import storybookPlugin from "eslint-plugin-storybook"; @@ -42,6 +43,7 @@ export default defineConfig([ jsxA11yPlugin.flatConfigs.recommended, reactRefreshPlugin.configs.recommended, reactRefreshPlugin.configs.vite, + turboPlugin.configs["flat/recommended"], tseslint.configs.recommendedTypeChecked, vitestPlugin.configs.recommended, // TODO: enable storybook linting once issues are resolved diff --git a/package.json b/package.json index b73f0acc85..3a3edb4865 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "eslint-plugin-react-hooks": "7.0.1", "eslint-plugin-react-refresh": "0.4.24", "eslint-plugin-storybook": "10.1.4", + "eslint-plugin-turbo": "2.6.3", "globals": "16.5.0", "husky": "9.1.7", "lint-staged": "16.2.7", diff --git a/packages/shared-state/package.json b/packages/shared-state/package.json index b3f7c25060..6f93379881 100644 --- a/packages/shared-state/package.json +++ b/packages/shared-state/package.json @@ -4,9 +4,20 @@ "license": "AGPL-3.0", "description": "Shared state shared across multiple apps internally", "private": true, - "main": "./src/index.ts", - "types": "./src/index.ts", + "type": "module", + "main": "./dist/index.js", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + }, + "./package.json": "./package.json" + }, "scripts": { + "build": "tsdown", + "dev": "tsdown --watch", "check:lint": "eslint . --max-warnings=191", "check:types": "tsc --noEmit", "check:format": "prettier --check .", @@ -28,6 +39,7 @@ "@plane/typescript-config": "workspace:*", "@types/lodash-es": "catalog:", "@types/node": "catalog:", + "tsdown": "catalog:", "typescript": "catalog:" } } diff --git a/packages/shared-state/tsdown.config.ts b/packages/shared-state/tsdown.config.ts new file mode 100644 index 0000000000..78c3dcba86 --- /dev/null +++ b/packages/shared-state/tsdown.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "tsdown"; + +export default defineConfig({ + entry: ["src/index.ts"], + format: ["esm"], + dts: true, + platform: "neutral", +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ba3dd46113..9e1bfe96a0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -166,6 +166,9 @@ importers: eslint-plugin-storybook: specifier: 10.1.4 version: 10.1.4(eslint@9.39.1(jiti@2.6.1))(storybook@9.1.10(@testing-library/dom@10.4.0)(prettier@3.7.4)(vite@7.1.11(@types/node@22.12.0)(jiti@2.6.1)(terser@5.44.1)(yaml@2.8.2)))(typescript@5.8.3) + eslint-plugin-turbo: + specifier: 2.6.3 + version: 2.6.3(eslint@9.39.1(jiti@2.6.1))(turbo@2.6.3) globals: specifier: 16.5.0 version: 16.5.0 @@ -1231,6 +1234,9 @@ importers: '@types/node': specifier: 'catalog:' version: 22.12.0 + tsdown: + specifier: 'catalog:' + version: 0.16.0(typescript@5.8.3) typescript: specifier: 5.8.3 version: 5.8.3 @@ -4865,9 +4871,6 @@ packages: resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} engines: {node: '>=14.16'} - caniuse-lite@1.0.30001756: - resolution: {integrity: sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==} - caniuse-lite@1.0.30001759: resolution: {integrity: sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==} @@ -5431,6 +5434,10 @@ packages: dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + dotenv@16.0.3: + resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} + engines: {node: '>=12'} + dotenv@16.6.1: resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} engines: {node: '>=12'} @@ -5718,6 +5725,12 @@ packages: eslint: '>=8' storybook: ^10.1.4 + eslint-plugin-turbo@2.6.3: + resolution: {integrity: sha512-91WZ+suhT/pk+qNS0/rqT43xLUlUblsa3a8jKmAStGhkJCmR2uX0oWo/e0Edb+It8MdnteXuYpCkvsK4Vw8FtA==} + peerDependencies: + eslint: '>6.6.0' + turbo: '>2.0.0' + eslint-scope@5.1.1: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} @@ -13120,8 +13133,6 @@ snapshots: camelcase@7.0.1: {} - caniuse-lite@1.0.30001756: {} - caniuse-lite@1.0.30001759: {} capital-case@1.0.4: @@ -13659,6 +13670,8 @@ snapshots: no-case: 3.0.4 tslib: 2.8.1 + dotenv@16.0.3: {} + dotenv@16.6.1: {} dotenv@17.2.3: {} @@ -14059,6 +14072,12 @@ snapshots: - supports-color - typescript + eslint-plugin-turbo@2.6.3(eslint@9.39.1(jiti@2.6.1))(turbo@2.6.3): + dependencies: + dotenv: 16.0.3 + eslint: 9.39.1(jiti@2.6.1) + turbo: 2.6.3 + eslint-scope@5.1.1: dependencies: esrecurse: 4.3.0 @@ -15908,7 +15927,7 @@ snapshots: dependencies: '@next/env': 16.0.7 '@swc/helpers': 0.5.15 - caniuse-lite: 1.0.30001756 + caniuse-lite: 1.0.30001759 postcss: 8.4.31 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) diff --git a/turbo.json b/turbo.json index 9c96eae758..84b16c8483 100644 --- a/turbo.json +++ b/turbo.json @@ -1,85 +1,95 @@ { - "$schema": "https://turbo.build/schema.json", + "$schema": "https://turborepo.com/schema.json", + "globalDependencies": [".npmrc"], "globalEnv": [ + "APP_VERSION", + "DEV", + "LOG_LEVEL", "NODE_ENV", - "VITE_API_BASE_URL", - "VITE_ADMIN_BASE_URL", + "SENTRY_DSN", + "SENTRY_ENVIRONMENT", + "SENTRY_TRACES_SAMPLE_RATE", "VITE_ADMIN_BASE_PATH", - "VITE_SPACE_BASE_URL", - "VITE_SPACE_BASE_PATH", - "VITE_WEB_BASE_URL", - "VITE_LIVE_BASE_URL", - "VITE_LIVE_BASE_PATH", + "VITE_ADMIN_BASE_URL", + "VITE_API_BASE_PATH", + "VITE_API_BASE_URL", + "VITE_APP_VERSION", "VITE_ENABLE_SESSION_RECORDER", - "VITE_SESSION_RECORDER_KEY", - "VITE_POSTHOG_KEY", - "VITE_POSTHOG_HOST", + "VITE_LIVE_BASE_PATH", + "VITE_LIVE_BASE_URL", "VITE_POSTHOG_DEBUG", - "VITE_SUPPORT_EMAIL", - "ENABLE_EXPERIMENTAL_COREPACK", + "VITE_POSTHOG_HOST", + "VITE_POSTHOG_KEY", "VITE_SENTRY_DSN", "VITE_SENTRY_ENVIRONMENT", + "VITE_SENTRY_PROFILES_SAMPLE_RATE", + "VITE_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE", + "VITE_SENTRY_REPLAYS_SESSION_SAMPLE_RATE", "VITE_SENTRY_SEND_DEFAULT_PII", "VITE_SENTRY_TRACES_SAMPLE_RATE", - "VITE_SENTRY_PROFILES_SAMPLE_RATE", - "VITE_SENTRY_REPLAYS_SESSION_SAMPLE_RATE", - "VITE_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE", - "VITE_APP_VERSION" + "VITE_SESSION_RECORDER_KEY", + "VITE_SPACE_BASE_PATH", + "VITE_SPACE_BASE_URL", + "VITE_SUPPORT_EMAIL", + "VITE_WEB_BASE_PATH", + "VITE_WEB_BASE_URL", + "VITE_WEBSITE_URL" ], - "globalDependencies": ["pnpm-lock.yaml", "pnpm-workspace.yaml", ".npmrc"], + "remoteCache": { + "enabled": false + }, "tasks": { "build": { "dependsOn": ["^build"], - "outputs": ["dist/**", "build/**"] + "inputs": ["$TURBO_DEFAULT$", ".env*"], + "outputs": ["dist/**", "build/**", ".react-router/**"] }, "build-storybook": { "dependsOn": ["^build"], "outputs": ["storybook-static/**"] }, - "dev": { + "check": { + "dependsOn": ["check:format", "check:lint", "check:types"] + }, + "check:format": { + "inputs": ["$TURBO_DEFAULT$"], + "outputs": [] + }, + "check:lint": { "dependsOn": ["^build"], - "cache": false, - "persistent": true + "inputs": ["$TURBO_DEFAULT$", "!**/*.md"], + "outputs": [] }, "check:types": { "dependsOn": ["^build"], + "inputs": ["$TURBO_DEFAULT$", "!**/*.md"], + "outputs": [] + }, + "clean": { "cache": false }, - "lint": { + "dev": { "cache": false, - "inputs": ["**/*.{js,ts,tsx,mjs,jsx}", "!**/node_modules/**", "!**/build/**", "!**/dist/**"] + "dependsOn": ["^build"], + "persistent": true }, - "check:lint": { - "dependsOn": ["lint"], + "fix": { "cache": false, - "inputs": ["**/*.{js,ts,tsx,mjs,jsx}", "!**/build/**", "!**/dist/**"] + "dependsOn": ["fix:format", "fix:lint"] }, - "check:format": { - "cache": false - }, - "check": { - "dependsOn": ["check:format", "check:lint", "check:types"], + "fix:format": { "cache": false }, "fix:lint": { "cache": false }, - "fix:format": { - "cache": false - }, - "fix": { - "dependsOn": ["fix:format", "fix:lint"], - "cache": false + "start": { + "cache": false, + "persistent": true }, "test": { "dependsOn": ["^build"], "outputs": [] - }, - "start": { - "cache": false - }, - "clean": { - "cache": false } } }