diff --git a/.github/workflows/adminBundleSize.yml b/.github/workflows/adminBundleSize.yml index ba41ca3b56..a3326e727f 100644 --- a/.github/workflows/adminBundleSize.yml +++ b/.github/workflows/adminBundleSize.yml @@ -37,8 +37,8 @@ jobs: with: build-script: 'build:size' pattern: '**/build/**/*.{js,css,html,svg}' - strip-hash: "\\.(?:(\\w{8})\\.chunk)|(?:\\.(\\w{8}))" - minimum-change-threshold: 10 + strip-hash: "-([-\\w]{8})(\\.\\w+)$" + minimum-change-threshold: '5%' # FIXME: exclude unnamed webpack chunks - remove once webpack # does not create them anymore diff --git a/.github/workflows/issues_handleLabel.yml b/.github/workflows/issues_handleLabel.yml index baabf10c5d..4a63199d36 100644 --- a/.github/workflows/issues_handleLabel.yml +++ b/.github/workflows/issues_handleLabel.yml @@ -70,6 +70,43 @@ jobs: issue-number: ${{ github.event.issue.number }} close-reason: 'not_planned' + # v4 Legacy Issues + - name: 'Comment: unsupported v4 issues' + if: "${{ github.event.label.name == 'flag: v4-unsupported' }}" + uses: actions-cool/issues-helper@v3 + with: + actions: 'create-comment' + token: ${{ secrets.GITHUB_TOKEN }} + issue-number: ${{ github.event.issue.number }} + body: | + > This is a templated message + + Hello @${{ github.event.issue.user.login }}, + + Thank you for reporting this potential bug report, please keep in mind that we are no longer accepting low/medium severity bug reports for Strapi v4. + We have confirmed that this issue is a low/medium severity bug and is not reproducable in Strapi 5. We advise upgrading to Strapi 5 to resolve this issue. + + The recommended action we suggest for v4 users is to utilize the various migration resources to upgrade from Strapi 4 to Strapi 5: + + - [Updating documentation](https://docs.strapi.io/dev-docs/migration/v4-to-v5/introduction-and-faq) + - [Step by Step Guide](https://docs.strapi.io/dev-docs/migration/v4-to-v5/step-by-step) + - [Upgrade Tool](https://docs.strapi.io/dev-docs/upgrade-tool) + - [Breaking Changes list](https://docs.strapi.io/dev-docs/migration/v4-to-v5/breaking-changes) + - [Specific Resources](https://docs.strapi.io/dev-docs/migration/v4-to-v5/additional-resources/introduction) + + Please see our [Security file](https://github.com/strapi/strapi/security) for more information about supported versions. + For now this issue is marked as closed. + + Thank You + - name: 'Close: unsupported v4 issues' + if: "${{ github.event.label.name == 'flag: v4-unsupported' }}" + uses: actions-cool/issues-helper@v3 + with: + actions: 'close-issue' + token: ${{ secrets.GITHUB_TOKEN }} + issue-number: ${{ github.event.issue.number }} + close-reason: 'not_planned' + # Feature request redirections - name: 'Comment: redirect feature request to canny' if: "${{ github.event.label.name == 'issue: feature request' }}" diff --git a/SECURITY.md b/SECURITY.md index 8753aaa67f..dc920c827a 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,18 +2,20 @@ ## Supported Versions -As of April 2024 (and until this document is updated), only the v4.x.x _GA_ or _STABLE_ releases of Strapi are supported for updates and bug fixes. Any previous versions are currently not supported and users are advised to use them "at their own risk". +As of September 2024 (and until this document is updated), only the v4.x.x and v5.x.x _GA_ or _STABLE_ releases of Strapi are supported for updates and bug fixes. Any previous versions are currently not supported and users are advised to use them "at their own risk". -| Version | Release Tag | Support Starts | Support Ends | Security Updates Until | Notes | -| ------- | ----------- | -------------- | -------------- | ---------------------- | -------------------- | -| 5.x.x | GA | October 2024 | Further Notice | Further Notice | LTS (Future) | -| 5.x.x | RC | N/A | October 2024 | N/A | Non-Production Usage | -| 5.x.x | Beta | N/A | N/A | N/A | Not Supported | -| 5.x.x | Alpha | N/A | N/A | N/A | Not Supported | -| 4.x.x | GA | November 2021 | October 2025 | April 2026 | LTS | -| 4.x.x | Beta | N/A | N/A | N/A | Not Supported | -| 4.x.x | Alpha | N/A | N/A | N/A | Not Supported | -| 3.x.x | N/A | N/A | N/A | N/A | End Of Life | +**Note**: The v4.x.x LTS version will only receive high/critical severity fixes until April 2026. Any Medium/Low severity issues will not be fixed unless specific exceptions are made. + +| Version | Release Tag | Support Starts | Support Ends | Security Updates Until | Notes | +| ------- | ----------- | -------------- | -------------- | ---------------------- | ------------------------------ | +| 5.x.x | GA / Stable | September 2024 | Further Notice | Further Notice | LTS | +| 5.x.x | RC | N/A | September 2024 | N/A | Not Supported | +| 5.x.x | Beta | N/A | N/A | N/A | Not Supported | +| 5.x.x | Alpha | N/A | N/A | N/A | Not Supported | +| 4.x.x | GA / Stable | November 2021 | October 2025 | April 2026 | LTS (High/Critical fixes only) | +| 4.x.x | Beta | N/A | N/A | N/A | Not Supported | +| 4.x.x | Alpha | N/A | N/A | N/A | Not Supported | +| 3.x.x | N/A | N/A | N/A | N/A | End Of Life | ## Reporting a Vulnerability diff --git a/examples/getstarted/config/features.js b/examples/getstarted/config/features.js index 222170aee6..817d6e26de 100644 --- a/examples/getstarted/config/features.js +++ b/examples/getstarted/config/features.js @@ -1,5 +1,5 @@ module.exports = ({ env }) => ({ future: { - contentReleasesScheduling: env.bool('STRAPI_FUTURE_CONTENT_RELEASES_SCHEDULING', false), + preview: env.bool('STRAPI_FUTURE_PREVIEW', false), }, }); diff --git a/package.json b/package.json index a4a444b207..a64df5f316 100644 --- a/package.json +++ b/package.json @@ -148,7 +148,7 @@ "stream-chain": "2.2.5", "stream-json": "1.8.0", "supertest": "6.3.3", - "tar": "6.1.13", + "tar": "6.2.1", "ts-jest": "29.1.0", "typescript": "5.3.2", "yalc": "1.0.0-pre.53", diff --git a/packages/cli/cloud/package.json b/packages/cli/cloud/package.json index bc0c066bb9..e5e54f1688 100644 --- a/packages/cli/cloud/package.json +++ b/packages/cli/cloud/package.json @@ -61,7 +61,7 @@ "open": "8.4.0", "ora": "5.4.1", "pkg-up": "3.1.0", - "tar": "6.1.13", + "tar": "6.2.1", "xdg-app-paths": "8.3.0", "yup": "0.32.9" }, diff --git a/packages/cli/create-strapi-app/src/create-strapi.ts b/packages/cli/create-strapi-app/src/create-strapi.ts index 94bd8e54b0..263a63a461 100644 --- a/packages/cli/create-strapi-app/src/create-strapi.ts +++ b/packages/cli/create-strapi-app/src/create-strapi.ts @@ -14,6 +14,7 @@ import { isStderrError } from './types'; import type { Scope } from './types'; import { logger } from './utils/logger'; import { gitIgnore } from './utils/gitignore'; +import { getInstallArgs } from './utils/get-package-manager-args'; async function createStrapi(scope: Scope) { const { rootPath } = scope; @@ -239,29 +240,27 @@ async function createApp(scope: Scope) { } } -const installArguments = ['install']; +async function runInstall({ rootPath, packageManager }: Scope) { + // include same cwd and env to ensure version check returns same version we use below + const { envArgs, cmdArgs } = await getInstallArgs(packageManager, { + cwd: rootPath, + env: { + ...process.env, + NODE_ENV: 'development', + }, + }); -const installArgumentsMap = { - npm: ['--legacy-peer-deps'], - yarn: ['--network-timeout 1000000'], - pnpm: [], -}; - -function runInstall({ rootPath, packageManager }: Scope) { const options: execa.Options = { cwd: rootPath, stdio: 'inherit', env: { ...process.env, + ...envArgs, NODE_ENV: 'development', }, }; - if (packageManager in installArgumentsMap) { - installArguments.push(...(installArgumentsMap[packageManager] ?? [])); - } - - const proc = execa(packageManager, installArguments, options); + const proc = execa(packageManager, cmdArgs, options); return proc; } diff --git a/packages/cli/create-strapi-app/src/utils/get-package-manager-args.ts b/packages/cli/create-strapi-app/src/utils/get-package-manager-args.ts new file mode 100644 index 0000000000..f1e21eef99 --- /dev/null +++ b/packages/cli/create-strapi-app/src/utils/get-package-manager-args.ts @@ -0,0 +1,144 @@ +import execa from 'execa'; +import semver from 'semver'; + +const installArguments = ['install']; + +type VersionedArgumentsMap = { + [key: string]: string[]; // Maps semver ranges to argument arrays +}; + +type VersionedEnvMap = { + [key: string]: Record; // Maps semver ranges to environment variables +}; + +// Set command line options for specific package managers, with full semver ranges +const installArgumentsMap: { + [key: string]: VersionedArgumentsMap; +} = { + npm: { + '*': ['--legacy-peer-deps'], + }, + yarn: { + '<4': ['--network-timeout', '1000000'], + '*': [], + }, + pnpm: { + '*': [], + }, +}; + +// Set environment variables for specific package managers, with full semver ranges +const installEnvMap: { + [key: string]: VersionedEnvMap; +} = { + yarn: { + '>=4': { YARN_HTTP_TIMEOUT: '1000000' }, + '*': {}, + }, + npm: { + '*': {}, + }, + pnpm: { + '*': {}, + }, +}; + +/** + * Retrieves the version of the specified package manager. + * + * Executes the package manager's `--version` command to determine its version. + * + * @param packageManager - The name of the package manager (e.g., 'npm', 'yarn', 'pnpm'). + * @param options - Optional execution options to pass to `execa`. + * @returns A promise that resolves to the trimmed version string of the package manager. + * + * @throws Will throw an error if the package manager's version cannot be determined. + */ +export const getPackageManagerVersion = async ( + packageManager: string, + options?: execa.Options +): Promise => { + try { + const { stdout } = await execa(packageManager, ['--version'], options); + return stdout.trim(); + } catch (err) { + throw new Error(`Error detecting ${packageManager} version: ${err}`); + } +}; + +/** + * Merges all matching semver ranges using a custom merge function. + * + * Iterates over the `versionMap`, checking if the provided `version` satisfies each semver range. + * If it does, the corresponding value is merged using the provided `mergeFn`. + * The merging starts with the value associated with the wildcard '*' key. + * + * @param version - The package manager version to check against the ranges. + * @param versionMap - A map of semver ranges to corresponding values (arguments or environment variables). + * @param mergeFn - A function that defines how to merge two values (accumulated and current). + * @returns The merged result of all matching ranges. + */ +function mergeMatchingVersionRanges( + version: string, + versionMap: { [key: string]: T }, + mergeFn: (acc: T, curr: T) => T +): T { + return Object.keys(versionMap).reduce((acc, range) => { + if (semver.satisfies(version, range) || range === '*') { + return mergeFn(acc, versionMap[range]); + } + return acc; + }, versionMap['*']); // Start with the wildcard entry +} + +function mergeArguments(acc: string[], curr: string[]): string[] { + return [...acc, ...curr]; +} + +function mergeEnvVars( + acc: Record, + curr: Record +): Record { + return { ...acc, ...curr }; +} + +/** + * Retrieves the install arguments and environment variables for a given package manager. + * + * This function determines the correct command line arguments and environment variables + * based on the package manager's version. It uses predefined semver ranges to match + * the package manager's version and merges all applicable settings. + * + * The arguments and environment variables are sourced from: + * - `installArgumentsMap` for command line arguments. + * - `installEnvMap` for environment variables. + * + * The function ensures that all matching semver ranges are considered and merged appropriately. + * It always includes the base `installArguments` (e.g., `['install']`) and applies any additional + * arguments or environment variables as defined by the matched version ranges. + * + * @param packageManager - The name of the package manager (e.g., 'npm', 'yarn', 'pnpm'). + * @param options - Optional execution options to pass to `execa`. + * @returns An object containing: + * - `cmdArgs`: The full array of install arguments for the given package manager and version. + * - `envArgs`: The merged environment variables applicable to the package manager and version. + * + * @throws Will throw an error if the package manager version cannot be determined. + */ +export const getInstallArgs = async (packageManager: string, options?: execa.Options) => { + const packageManagerVersion = await getPackageManagerVersion(packageManager, options); + + // Get environment variables + const envMap = installEnvMap[packageManager]; + const envArgs = packageManagerVersion + ? mergeMatchingVersionRanges(packageManagerVersion, envMap, mergeEnvVars) + : envMap['*']; + + // Get install arguments + const argsMap = installArgumentsMap[packageManager]; + const cmdArgs = packageManagerVersion + ? mergeMatchingVersionRanges(packageManagerVersion, argsMap, mergeArguments) + : argsMap['*']; + + return { envArgs, cmdArgs: [...installArguments, ...cmdArgs], version: packageManagerVersion }; +}; diff --git a/packages/core/admin/admin/src/pages/Settings/pages/Roles/CreatePage.tsx b/packages/core/admin/admin/src/pages/Settings/pages/Roles/CreatePage.tsx index b462951464..838561ed2f 100644 --- a/packages/core/admin/admin/src/pages/Settings/pages/Roles/CreatePage.tsx +++ b/packages/core/admin/admin/src/pages/Settings/pages/Roles/CreatePage.tsx @@ -11,6 +11,7 @@ import { TextInput, Typography, } from '@strapi/design-system'; +import { Check } from '@strapi/icons'; import { format } from 'date-fns'; import { Formik, Form, FormikHelpers } from 'formik'; import { useIntl } from 'react-intl'; @@ -197,14 +198,13 @@ const CreatePage = () => { handleReset(); permissionsRef.current?.resetForm(); }} - size="L" > {formatMessage({ id: 'app.components.Button.reset', defaultMessage: 'Reset', })} - diff --git a/packages/core/admin/admin/src/pages/Settings/pages/Webhooks/components/WebhookForm.tsx b/packages/core/admin/admin/src/pages/Settings/pages/Webhooks/components/WebhookForm.tsx index a117518ae8..3996ea7574 100644 --- a/packages/core/admin/admin/src/pages/Settings/pages/Webhooks/components/WebhookForm.tsx +++ b/packages/core/admin/admin/src/pages/Settings/pages/Webhooks/components/WebhookForm.tsx @@ -98,7 +98,6 @@ const WebhookForm = ({ variant="tertiary" startIcon={} disabled={isCreating || isTriggering} - size="L" > {formatMessage({ id: 'Settings.webhooks.trigger', @@ -108,7 +107,6 @@ const WebhookForm = ({