diff --git a/.github/ISSUE_TEMPLATE/1.bug_report.yml b/.github/ISSUE_TEMPLATE/1.bug_report.yml index 7e3c51a9ca0ce..e1ac19ead6b45 100644 --- a/.github/ISSUE_TEMPLATE/1.bug_report.yml +++ b/.github/ISSUE_TEMPLATE/1.bug_report.yml @@ -13,7 +13,7 @@ body: label: Verify canary release description: '`next@canary` is the canary version of Next.js that ships daily. It includes all features and fixes that have not been released to the stable version yet. Think of canary as a public beta. Some issues may already be fixed in the canary version, so please verify that your issue reproduces before opening a new issue.' options: - - label: I verified that the issue exists in Next.js canary release + - label: I verified that the issue exists in the latest Next.js canary release required: true - type: textarea attributes: @@ -44,13 +44,13 @@ body: - type: input attributes: label: Link to reproduction - description: A link to a https://stackblitz.com/ or git repo with a minimal reproduction. Minimal reproductions should be created from a create-next-app starter and include only relevant changes to cause the issue if possible. + description: A link to a GitHub repository, a [StackBlitz](https://stackblitz.com/fork/github/vercel/next.js/tree/canary/examples/reproduction-template), or a [CodeSandbox](https://codesandbox.io/s/github/vercel/next.js/tree/canary/examples/reproduction-template) minimal reproduction. Minimal reproductions should be created from our [bug report template with `npx create next-app -e reproduction-template`](https://github.com/vercel/next.js/tree/canary/examples/reproduction-template) and should include only changes that contribute to the issue. validations: required: true - type: textarea attributes: label: To Reproduce - description: Steps to reproduce the behavior, please provide a clear code snippets that always reproduces the issue or a GitHub repository. Screenshots can be provided in the issue body below. + description: Steps to reproduce the behavior, please provide a clear description of how to reproduce the issue, based on the linked minimal reproduction. Screenshots can be provided in the issue body below. If using code blocks, make sure that [syntax highlighting is correct](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#syntax-highlighting) and double check that the rendered preview is not broken. validations: required: true - type: markdown diff --git a/.github/ISSUE_TEMPLATE/2.example_bug_report.yml b/.github/ISSUE_TEMPLATE/2.example_bug_report.yml index 04483f5a4518c..88e5e74343a5f 100644 --- a/.github/ISSUE_TEMPLATE/2.example_bug_report.yml +++ b/.github/ISSUE_TEMPLATE/2.example_bug_report.yml @@ -13,7 +13,7 @@ body: label: Verify canary release description: '`next@canary` is the canary version of Next.js that ships daily. It includes all features and fixes that have not been released to the stable version yet. Think of canary as a public beta. Some issues may already be fixed in the canary version, so please verify that your issue reproduces before opening a new issue.' options: - - label: I verified that the issue exists in Next.js canary release + - label: I verified that the issue exists in the latest Next.js canary release required: true - type: textarea attributes: @@ -24,7 +24,7 @@ body: - type: input attributes: label: Which example does this report relate to? - description: "See a complete list in the [examples folder](https://github.com/vercel/next.js/tree/canary/examples). For example: with-styled-components. Note: Examples not in the examples folder might be maintained by the example's library author. Check out their projects before opening the issue on Next.js" + description: "See a complete list in the [examples folder](https://github.com/vercel/next.js/tree/canary/examples). For example: `with-styled-components`. Note: Examples not in the examples folder might be maintained by the example's library author. Check out their projects before opening the issue on Next.js" validations: required: true - type: input @@ -50,7 +50,7 @@ body: - type: textarea attributes: label: To Reproduce - description: Steps to reproduce the behavior, please provide a clear code snippets that always reproduces the issue or a GitHub repository. Screenshots can be provided in the issue body below. + description: Steps to reproduce the behavior, please provide a clear description of how to reproduce the issue, based on the relevant example. Screenshots can be provided in the issue body below. If using code blocks, make sure that [syntax highlighting is correct](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#syntax-highlighting) and double check that the rendered preview is not broken. validations: required: true - type: markdown diff --git a/.github/actions/issue-validator/index.js b/.github/actions/issue-validator/index.js new file mode 100644 index 0000000000000..8e8bc287525bf --- /dev/null +++ b/.github/actions/issue-validator/index.js @@ -0,0 +1,97 @@ +// @ts-check +import * as github from '@actions/github' +import * as core from '@actions/core' + +const verifyCanaryLabel = 'please verify canary' +const bugReportLabel = 'template: bug' +const addReproductionLabel = 'please add a complete reproduction' + +async function run() { + try { + const { + payload: { issue, pull_request }, + repo, + } = github.context + + if (pull_request || !issue?.body) return + + const { body, labels, number: issueNumber } = issue + + const isManuallyLabeled = labels.some( + (label) => label.name === verifyCanaryLabel + ) + + const isBugReport = labels.some((label) => label.name === bugReportLabel) + + if (!process.env.GITHUB_TOKEN) { + return core.setFailed('GITHUB_TOKEN is not set') + } + + // @ts-ignore + const client = github.getOctokit(process.env.GITHUB_TOKEN).rest + + /** + * @param {string} label + * @param {string} comment + */ + function notifyOnIssue(label, comment) { + const issueCommon = { ...repo, issue_number: issueNumber } + + return Promise.all([ + client.issues.addLabels({ ...issueCommon, labels: [label] }), + client.issues.createComment({ ...issueCommon, body: comment }), + ]) + } + + const isVerifyCanaryChecked = body.includes( + '- [X] I verified that the issue exists in Next.js canary release' + ) + + if ( + !isVerifyCanaryChecked || // This can happen if the issue was from a comment in another issue or discussion. + isManuallyLabeled + ) { + return await notifyOnIssue( + verifyCanaryLabel, + 'Please verify your issue reproduces with `next@canary`. The canary version of Next.js ships daily and includes all features and fixes that have not been released to the stable version yet. Think of canary as a public beta. Some issues may already be fixed in the canary version, so please verify that your issue reproduces by running `npm install next@canary`. If the issue does not reproduce with the canary version, then it has already been fixed and this issue can be closed.' + ) + } + + if (!isBugReport) return + + const reproductionUrl = body + .match(/### Link to reproduction\n\n(?.*)\n/) + ?.groups?.url.trim() + + if (!reproductionUrl || !(await (await fetch(reproductionUrl)).ok)) { + return await notifyOnIssue( + addReproductionLabel, + 'The link to the reproduction appears to be incorrect/unreachable. Please add a link to the reproduction of the issue. This is a required field.' + ) + } + + const reportedNextVersion = body.match( + /Relevant packages:\n next: (?\d+\.\d+\.\d+)/ + )?.groups?.version + + if (!reportedNextVersion) { + // REVIEW: Should we add a label here? + return + } + + const { tag_name: lastVersion } = await ( + await client.repos.listReleases(repo) + ).data[0] + + if (lastVersion.includes('canary') && reportedNextVersion !== lastVersion) { + return await notifyOnIssue( + verifyCanaryLabel, + `The reported Next.js version did not match the latest \`next@canary\` version (${lastVersion}). The canary version of Next.js ships daily and includes all features and fixes that have not been released to the stable version yet. Think of canary as a public beta. Some issues may already be fixed in the canary version, so please verify that your issue reproduces by running \`npm install next@canary\`. If the issue does not reproduce with the canary version, then it has already been fixed and this issue can be closed.` + ) + } + } catch (error) { + core.setFailed(error.message) + } +} + +run() diff --git a/.github/actions/issue-validator/package.json b/.github/actions/issue-validator/package.json new file mode 100644 index 0000000000000..b748827275b44 --- /dev/null +++ b/.github/actions/issue-validator/package.json @@ -0,0 +1,12 @@ +{ + "private": true, + "main": "index.js", + "type": "module", + "devDependencies": { + "typescript": "4.6.3" + }, + "dependencies": { + "@actions/core": "1.9.0", + "@actions/github": "5.0.3" + } +} diff --git a/.github/actions/next-stats-action/package.json b/.github/actions/next-stats-action/package.json index a9fb8c4e081e7..4d2e88dae3e3e 100644 --- a/.github/actions/next-stats-action/package.json +++ b/.github/actions/next-stats-action/package.json @@ -1,8 +1,6 @@ { - "name": "get-stats", - "version": "1.0.0", + "private": true, "main": "src/index.js", - "license": "MIT", "dependencies": { "async-sema": "^3.1.0", "fs-extra": "^8.1.0", diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index cb6abe0bc4885..b514ba2b7baec 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -11,12 +11,25 @@ jobs: if: github.repository_owner == 'vercel' steps: - uses: actions/stale@v4 - id: stale + id: stale-no-repro name: 'Close stale issues with no reproduction' with: repo-token: ${{ secrets.STALE_TOKEN }} only-labels: 'please add a complete reproduction' - close-issue-message: 'This issue has been automatically closed because it received no activity for a month and had no reproduction to investigate. If you think this was closed by accident, please leave a comment. If you are running into a similar issue, please open a new issue with a reproduction. Thank you.' + close-issue-message: 'This issue has been automatically closed because it received no activity for a month and had no reproduction to investigate. If you think it was closed by accident, please leave a comment. If you are running into a similar issue, please open a new issue with a reproduction. Thank you.' + days-before-issue-close: 1 + days-before-issue-stale: 30 + days-before-pr-close: -1 + days-before-pr-stale: -1 + exempt-issue-labels: 'blocked,must,should,keep' + operations-per-run: 300 # 1 operation per 100 issues, the rest is to label/comment/close + - uses: actions/stale@v4 + id: stale-no-canary + name: 'Close issues not verified on canary' + with: + repo-token: ${{ secrets.STALE_TOKEN }} + only-labels: 'please verify canary' + close-issue-message: "This issue has been automatically closed because it wasn't verified against next@canary. If you think it was closed by accident, please leave a comment. If you are running into a similar issue, please open a new issue with a reproduction. Thank you." days-before-issue-close: 1 days-before-issue-stale: 30 days-before-pr-close: -1 diff --git a/.github/workflows/validate_issue.yml b/.github/workflows/validate_issue.yml new file mode 100644 index 0000000000000..08c807d751aa9 --- /dev/null +++ b/.github/workflows/validate_issue.yml @@ -0,0 +1,12 @@ +name: Validate issue +on: + issues: + types: [opened, labeled] + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: ./.github/issue-validator + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/contributing.md b/contributing.md index 9256ab659f1e5..43a2fb269c0db 100644 --- a/contributing.md +++ b/contributing.md @@ -327,6 +327,8 @@ Issues are opened with one of these labels: In case of a bug report, a maintainer looks at the provided reproduction. If the reproduction is missing or insufficient, a `please add a complete reproduction` label is added. If a reproduction is not provided for more than 30 days, the issue becomes stale and will be automatically closed. If a reproduction is provided within 30 days, the `please add a complete reproduction` label is removed and the issue will not become stale anymore. +Bug reports must be verified against the `next@canary` release. The canary version of Next.js ships daily and includes all features and fixes that have not been released to the stable version yet. Think of canary as a public beta. Some issues may already be fixed in the canary version, so please verify that your issue reproduces before opening a new issue. Issues not verified against `next@canary` will be closed after 30 days. + If the issue is specific to the project and not to Next.js itself, it might be converted to a [🎓️ Help discussion](https://github.com/vercel/next.js/discussions/categories/help) If the bug is verified, it will receive the `kind: bug` label and will be tracked by the maintainers. An `area:` label can be added to indicate which part of Next.js is affected. diff --git a/examples/reproduction-template/.gitignore b/examples/reproduction-template/.gitignore new file mode 100644 index 0000000000000..55175ef867e0b --- /dev/null +++ b/examples/reproduction-template/.gitignore @@ -0,0 +1,32 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# local env files +.env*.local + +# vercel +.vercel diff --git a/examples/reproduction-template/README.md b/examples/reproduction-template/README.md new file mode 100644 index 0000000000000..8085f19c11818 --- /dev/null +++ b/examples/reproduction-template/README.md @@ -0,0 +1,29 @@ +This is a [Next.js](https://nextjs.org/) template to use when reporting a [bug in the Next.js repository](https://github.com/vercel/next.js/issues). + +## Getting Started + +These are the steps you should follow when creating a bug report: + +- Bug reports must be verified against the `next@canary` release. The canary version of Next.js ships daily and includes all features and fixes that have not been released to the stable version yet. Think of canary as a public beta. Some issues may already be fixed in the canary version, so please verify that your issue reproduces before opening a new issue. Issues not verified against `next@canary` will be closed after 30 days. +- Make sure your issue is not a duplicate. Use the [GitHub issue search](https://github.com/vercel/next.js/issues) to see if there is already an open issue that matches yours. If that is the case, upvoting the other issue's first comment is desireable as we often prioritize issues based on the number of votes they receive. Note: Adding a "+1" or "same issue" comment without adding more context about the issue should be avoided. If you only find closed related issues, you can link to them using the issue number and `#`, eg.: `I found this related issue: #3000`. +- If you think the issue is not in Next.js, the best place to ask for help is our [Discord community](https://nextjs.org/discord) or [GitHub discussions](https://github.com/vercel/next.js/discussions). Our community is welcoming and can often answer a project-related question faster than the Next.js core team. +- Make the reproduction as minimal as possible. Try to exclude any code that does not help reproducing the issue. E.g. if you experience problems with Routing, including ESLint configurations or API routes aren't necessary. The less lines of code is to read through, the easier it is for the Next.js team to investigate. It may also help catching bugs in your codebase before publishing an issue. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. +- [How to Contribute to Open Source (Next.js)](https://www.youtube.com/watch?v=cuoNzXFLitc) - a video tutorial by Lee Robinson +- [Triaging in the Next.js repository](https://github.com/vercel/next.js/blob/canary/contributing.md#triaging) - how we work on issues +- [StackBlitz](https://stackblitz.com/fork/github/vercel/next.js/tree/canary/examples/reproduction-template) - Edit this repository on StackBlitz +- [CodeSandbox](https://codesandbox.io/s/github/vercel/next.js/tree/canary/examples/reproduction-template) - Edit this repository on CodeSandbox + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deployment + +If your reproduction needs to be deployed, the easiest way is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/reproduction-template/next-env.d.ts b/examples/reproduction-template/next-env.d.ts new file mode 100644 index 0000000000000..4f11a03dc6cc3 --- /dev/null +++ b/examples/reproduction-template/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/examples/reproduction-template/next.config.js b/examples/reproduction-template/next.config.js new file mode 100644 index 0000000000000..b77e52627bdd2 --- /dev/null +++ b/examples/reproduction-template/next.config.js @@ -0,0 +1,6 @@ +/** @type {import("next").NextConfig} */ +const config = { + reactStrictMode: true, +} + +module.exports = config diff --git a/examples/reproduction-template/package.json b/examples/reproduction-template/package.json new file mode 100644 index 0000000000000..63e765c6ce94a --- /dev/null +++ b/examples/reproduction-template/package.json @@ -0,0 +1,18 @@ +{ + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start" + }, + "dependencies": { + "next": "canary", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/node": "^18.0.0", + "@types/react": "^18.0.14", + "typescript": "^4.7.4" + } +} diff --git a/examples/reproduction-template/pages/index.tsx b/examples/reproduction-template/pages/index.tsx new file mode 100644 index 0000000000000..b19de6e8aa816 --- /dev/null +++ b/examples/reproduction-template/pages/index.tsx @@ -0,0 +1,4 @@ +/** Add your relevant code here for the issue to reproduce */ +export default function Home() { + return null +} diff --git a/examples/reproduction-template/public/favicon.ico b/examples/reproduction-template/public/favicon.ico new file mode 100644 index 0000000000000..718d6fea4835e Binary files /dev/null and b/examples/reproduction-template/public/favicon.ico differ diff --git a/examples/reproduction-template/tsconfig.json b/examples/reproduction-template/tsconfig.json new file mode 100644 index 0000000000000..1563f3e878573 --- /dev/null +++ b/examples/reproduction-template/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": false, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "incremental": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve" + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +}