From 80030a31afb23b9be1a8adade350379b1e935df5 Mon Sep 17 00:00:00 2001 From: Sascha Depold Date: Sat, 22 Jan 2022 12:35:53 +0100 Subject: [PATCH] build: add v6 release script --- dev/release-v6.ts | 132 ++++++++++++++++++++++++++ package.json | 237 +++++++++++++++++++++++----------------------- yarn.lock | 2 +- 3 files changed, 249 insertions(+), 122 deletions(-) create mode 100755 dev/release-v6.ts diff --git a/dev/release-v6.ts b/dev/release-v6.ts new file mode 100755 index 000000000000..d8cfe4ca8d23 --- /dev/null +++ b/dev/release-v6.ts @@ -0,0 +1,132 @@ +/* eslint-disable camelcase */ +/** + * Merges all the to be released commits into the v6 branch and pushes it to the remote. + * The push will then trigger the release process via the GitHub Action workflow. + * + * Main branch must be up-to-date. To be executed on the target branch. + * + * Usage: + * DRY_RUN= GITHUB_TOKEN= node_modules/.bin/ts-node dev/release-v6.ts + */ + +import { Octokit } from '@octokit/rest'; +import { Endpoints } from '@octokit/types'; +import { execSync } from 'child_process'; + +type Card = + Endpoints['GET /projects/columns/cards/{card_id}']['response']['data']; +type PullRequest = + Endpoints['GET /repos/{owner}/{repo}/pulls/{pull_number}']['response']['data']; +type CardCommit = { + card: Card; + commit: PullRequest; +}; + +const OWNER = 'sequelize'; +const REPO = 'sequelize'; +const TO_BE_RELEASED_COLUMN_ID = 17352881; +const RELEASING_COLUMN_ID = 17444349; + +(async () => { + const token = process.env.GITHUB_TOKEN; + + if (!token) { + console.error('GITHUB_TOKEN variable is not set'); + process.exit(1); + } + + const github = new Octokit({ + auth: token + }); + const commits = await getCommitsFromProject(github); + + await Promise.all(commits.map(commit => mergeCommit(github, commit))); +})(); + +// Helpers + +async function getCommitsFromProject(github: Octokit): Promise { + const cards = await github.rest.projects.listCards({ + column_id: TO_BE_RELEASED_COLUMN_ID + }); + + const commits = await Promise.all( + cards.data.filter(isIssueCard).map(async (card: Card) => ({ + card, + commit: await cardToMergedCommit(github, card) + })) + ); + + const filtered = commits.filter(({ commit }) => + Boolean(commit) + ) as CardCommit[]; + + return filtered.sort(sortCommits); +} + +function isIssueCard(card: Card) { + return card.content_url?.includes('/issues/'); +} + +async function cardToMergedCommit( + github: Octokit, + card: Card +): Promise { + const issueNumber = card.content_url?.split('/').pop(); + const { data: pullRequest } = await github.pulls.get({ + owner: OWNER, + repo: REPO, + pull_number: Number(issueNumber) + }); + + if (!pullRequest?.merged) { + return; + } + + return pullRequest; +} + +function sortCommits(a: CardCommit, b: CardCommit) { + const aDate = new Date(a.commit.merged_at || ''); + const bDate = new Date(b.commit.merged_at || ''); + + return aDate.getTime() - bDate.getTime(); +} + +async function mergeCommit(github: Octokit, { card, commit }: CardCommit) { + mergeCommitTeaser(commit); + + if (commit.merge_commit_sha) { + await gitMerge(commit.merge_commit_sha); + await moveCard(github, card, RELEASING_COLUMN_ID); + } +} + +function mergeCommitTeaser(commit: PullRequest) { + console.info(); + console.info('Merging commit:', commit.title); + console.info('- Commit SHA:', commit.merge_commit_sha); + console.info('- Commit URL:', commit.html_url); +} + +async function moveCard(github: Octokit, card: Card, to: number) { + if (process.env.DRY_RUN === 'false') { + const a = await github.rest.projects.moveCard({ + card_id: card.id, + position: 'bottom', + column_id: to + }); + + console.log(a); + } +} + +async function gitMerge(sha: string) { + const gitCommand = `git cherry-pick ${sha}`; + + console.info('- Git command:', gitCommand); + + if (process.env.DRY_RUN === 'false') { + execSync(gitCommand, { stdio: 'inherit' }); + } +} diff --git a/package.json b/package.json index 01145854bac9..cf7dee1efffe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "@sequelize/core", - "description": "Sequelize is a promise-based Node.js ORM tool for Postgres, MySQL, MariaDB, SQLite, Microsoft SQL Server, Amazon Redshift, Snowflake’s Data Cloud, Db2, and IBM i. It features solid transaction support, relations, eager and lazy loading, read replication and more.", + "name": "sequelize", + "description": "Sequelize is a promise-based Node.js ORM tool for Postgres, MySQL, MariaDB, SQLite, Microsoft SQL Server, Amazon Redshift and Snowflake’s Data Cloud. It features solid transaction support, relations, eager and lazy loading, read replication and more.", "version": "0.0.0-development", "funding": [ { @@ -16,33 +16,35 @@ "url": "https://github.com/sequelize/sequelize/issues" }, "homepage": "https://sequelize.org/", - "main": "./lib/index.js", - "types": "./types", + "main": "./dist/index.js", + "types": "./dist", "type": "commonjs", "exports": { ".": { - "import": "./lib/index.mjs", - "require": "./lib/index.js" + "import": "./dist/index.mjs", + "require": "./dist/index.js" }, - "./_non-semver-use-at-your-own-risk_/*": "./lib/*", - "./package.json": "./package.json" + "./lib/*": "./dist/lib/*.js", + "./lib/errors": "./dist/lib/errors/index.js", + "./*": "./*" }, "engines": { - "node": "^14.17.0 || >=16.0.0" + "node": ">=10.0.0" }, "files": [ + "dist", "lib", - "types", - "index.js" + "index.js", + "types/index.d.ts", + "types/lib", + "types/type-helpers" ], "license": "MIT", "dependencies": { "@types/debug": "^4.1.7", - "@types/inflection": "^1.13.0", - "@types/validator": "^13.7.1", "debug": "^4.3.3", "dottie": "^2.0.2", - "inflection": "^1.13.2", + "inflection": "^1.13.1", "lodash": "^4.17.21", "moment": "^2.29.1", "moment-timezone": "^0.5.34", @@ -56,63 +58,65 @@ "wkx": "^0.5.0" }, "devDependencies": { - "@commitlint/cli": "16.2.4", - "@commitlint/config-angular": "16.2.4", - "@ephys/eslint-config-typescript": "17.0.0", - "@rushstack/eslint-patch": "1.1.3", - "@types/chai": "4.3.1", - "@types/chai-as-promised": "7.1.5", - "@types/chai-datetime": "0.0.37", - "@types/lodash": "4.14.182", - "@types/mocha": "9.1.1", - "@types/node": "16.11.34", - "@types/sinon": "10.0.11", - "@types/sinon-chai": "3.2.8", - "@types/uuid": "8.3.4", - "chai": "4.3.6", - "chai-as-promised": "7.1.1", - "chai-datetime": "1.8.0", - "cheerio": "1.0.0-rc.10", - "cls-hooked": "4.2.2", - "copyfiles": "2.4.1", - "cross-env": "7.0.3", - "delay": "5.0.0", - "esbuild": "0.14.39", - "eslint": "8.15.0", - "eslint-plugin-jsdoc": "39.2.9", - "eslint-plugin-mocha": "10.0.4", - "expect-type": "0.13.0", - "fast-glob": "3.2.11", - "fs-jetpack": "4.3.1", - "husky": "8.0.1", - "ibm_db": "2.8.1", - "lcov-result-merger": "3.1.0", - "lint-staged": "12.4.1", - "mariadb": "2.5.6", - "markdownlint-cli": "0.31.1", - "mocha": "10.0.0", - "module-alias": "2.2.2", - "mysql2": "2.3.3", - "node-hook": "1.0.0", - "nyc": "15.1.0", - "odbc": "2.4.4", - "p-map": "4.0.0", - "p-props": "4.0.0", - "p-settle": "4.1.1", - "p-timeout": "4.1.0", - "pg": "8.7.3", - "pg-hstore": "2.3.4", - "rimraf": "3.0.2", - "semantic-release": "19.0.2", - "semantic-release-fail-on-major-bump": "1.0.0", - "sinon": "14.0.0", - "sinon-chai": "3.7.0", - "snowflake-sdk": "1.6.9", - "source-map-support": "0.5.21", - "sqlite3": "5.0.8", - "tedious": "14.4.0", - "typedoc": "0.22.15", - "typescript": "4.6.4" + "@commitlint/cli": "^15.0.0", + "@commitlint/config-angular": "^15.0.0", + "@octokit/rest": "^18.12.0", + "@octokit/types": "^6.34.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.0.0", + "@types/node": "^16.11.17", + "@types/sinon": "^10.0.6", + "@types/validator": "^13.7.1", + "@typescript-eslint/eslint-plugin": "^5.8.1", + "@typescript-eslint/parser": "^5.8.1", + "acorn": "^8.7.0", + "chai": "^4.3.4", + "chai-as-promised": "^7.1.1", + "chai-datetime": "^1.8.0", + "cheerio": "^1.0.0-rc.10", + "cls-hooked": "^4.2.2", + "copyfiles": "^2.4.1", + "cross-env": "^7.0.3", + "delay": "^5.0.0", + "esbuild": "0.14.3", + "esdoc": "^1.1.0", + "esdoc-ecmascript-proposal-plugin": "^1.0.0", + "esdoc-inject-style-plugin": "^1.0.0", + "esdoc-standard-plugin": "^1.0.0", + "eslint": "^8.5.0", + "eslint-plugin-jsdoc": "^37.4.0", + "eslint-plugin-mocha": "^9.0.0", + "expect-type": "^0.12.0", + "fast-glob": "^3.2.7", + "fs-jetpack": "^4.3.0", + "husky": "^7.0.4", + "ibm_db": "^2.8.1", + "js-combinatorics": "^0.6.1", + "lcov-result-merger": "^3.1.0", + "lint-staged": "^12.1.4", + "mariadb": "^2.5.5", + "markdownlint-cli": "^0.30.0", + "mocha": "^7.2.0", + "module-alias": "^2.2.2", + "mysql2": "^2.3.3", + "node-hook": "^1.0.0", + "nyc": "^15.1.0", + "p-map": "^4.0.0", + "p-props": "^4.0.0", + "p-settle": "^4.1.1", + "p-timeout": "^4.0.0", + "pg": "^8.7.1", + "pg-hstore": "^2.3.4", + "rimraf": "^3.0.2", + "semantic-release": "^18.0.1", + "semantic-release-fail-on-major-bump": "^1.0.0", + "sinon": "^12.0.1", + "sinon-chai": "^3.7.0", + "snowflake-sdk": "^1.6.6", + "source-map-support": "^0.5.21", + "sqlite3": "npm:@vscode/sqlite3@^5.0.7", + "tedious": "8.3.0", + "typescript": "^4.5.4" }, "peerDependenciesMeta": { "pg": { @@ -127,9 +131,6 @@ "ibm_db": { "optional": true }, - "odbc": { - "optional": true - }, "snowflake-sdk": { "optional": true }, @@ -187,11 +188,12 @@ } }, "lint-staged": { - "*.{js,mjs,cjs,ts,mts,cts}": "eslint --fix --report-unused-disable-directives" + "*!(d).[tj]s": "eslint" }, "release": { "plugins": [ "@semantic-release/commit-analyzer", + "semantic-release-fail-on-major-bump", "@semantic-release/release-notes-generator", "@semantic-release/npm", "@semantic-release/github" @@ -199,31 +201,29 @@ "branches": [ "v6", { - "name": "v7", - "prerelease": "alpha" + "name": "v6-beta", + "prerelease": "beta" } ] }, "publishConfig": { - "access": "public", - "tag": "alpha" + "tag": "latest" }, "scripts": { "----------------------------------------- static analysis -----------------------------------------": "", - "lint": "eslint . --fix --report-unused-disable-directives", - "lint-no-fix": "eslint . --quiet --report-unused-disable-directives", - "test-typings": "tsc --noEmit --emitDeclarationOnly false && tsc -b test/tsconfig.json", + "lint": "eslint lib test --quiet --fix", + "lint-docs": "markdownlint docs", + "test-typings": "tsc -b types/tsconfig.json && tsc -b types/test/tsconfig.json && tsc --noEmit --emitDeclarationOnly false && tsc -b test/tsconfig.json", "----------------------------------------- documentation -------------------------------------------": "", - "docs": "typedoc", + "docs": "rimraf esdoc && esdoc -c docs/esdoc-config.js && cp docs/favicon.ico esdoc/favicon.ico && cp docs/ROUTER.txt esdoc/ROUTER && node docs/run-docs-transforms.js && node docs/redirects/create-redirects.js && rimraf esdoc/file esdoc/source.html", "----------------------------------------- tests ---------------------------------------------------": "", "mocha": "mocha -r ./test/registerEsbuild", "test-unit": "yarn mocha \"test/unit/**/*.test.[tj]s\"", "test-integration": "yarn mocha \"test/integration/**/*.test.[tj]s\"", - "test-smoke": "yarn mocha \"test/smoke/**/*.test.[tj]s\" --timeout 600000", "teaser": "node test/teaser.js", - "test": "yarn prepare && yarn test-typings && yarn teaser && yarn test-unit && yarn test-integration", + "test": "npm run prepare && npm run test-typings && npm run teaser && npm run test-unit && npm run test-integration", "----------------------------------------- coverage ------------------------------------------------": "", - "cover": "rimraf coverage && yarn teaser && yarn cover-integration && yarn cover-unit && yarn merge-coverage", + "cover": "rimraf coverage && npm run teaser && npm run cover-integration && npm run cover-unit && npm run merge-coverage", "cover-integration": "cross-env COVERAGE=true nyc --reporter=lcovonly yarn mocha \"test/integration/**/*.test.[tj]s\" && node -e \"require('fs').renameSync('coverage/lcov.info', 'coverage/integration.info')\"", "cover-unit": "cross-env COVERAGE=true nyc --reporter=lcovonly yarn mocha \"test/unit/**/*.test.[tj]s\" && node -e \"require('fs').renameSync('coverage/lcov.info', 'coverage/unit.info')\"", "merge-coverage": "lcov-result-merger \"coverage/*.info\" \"coverage/lcov.info\"", @@ -236,45 +236,40 @@ "start-db2": "bash dev/db2/11.5/start.sh", "stop-mariadb": "bash dev/mariadb/10.3/stop.sh", "stop-mysql": "bash dev/mysql/5.7/stop.sh", - "stop-mysql-8": "bash dev/mysql/8.0/stop.sh", "stop-postgres": "bash dev/postgres/10/stop.sh", "stop-mssql": "bash dev/mssql/2019/stop.sh", "stop-db2": "bash dev/db2/11.5/stop.sh", - "restart-mariadb": "yarn start-mariadb", - "restart-mysql": "yarn start-mysql", - "restart-postgres": "yarn start-postgres", - "restart-mssql": "yarn start-mssql", - "restart-db2": "yarn start-db2", + "restart-mariadb": "npm run start-mariadb", + "restart-mysql": "npm run start-mysql", + "restart-postgres": "npm run start-postgres", + "restart-mssql": "npm run start-mssql", + "restart-db2": "npm run start-db2", "----------------------------------------- local tests ---------------------------------------------": "", - "test-unit-mariadb": "cross-env DIALECT=mariadb yarn test-unit", - "test-unit-mysql": "cross-env DIALECT=mysql yarn test-unit", - "test-unit-postgres": "cross-env DIALECT=postgres yarn test-unit", - "test-unit-postgres-native": "cross-env DIALECT=postgres-native yarn test-unit", - "test-unit-sqlite": "cross-env DIALECT=sqlite yarn test-unit", - "test-unit-mssql": "cross-env DIALECT=mssql yarn test-unit", - "test-unit-db2": "cross-env DIALECT=db2 yarn test-unit", - "test-unit-ibmi": "cross-env DIALECT=ibmi yarn test-unit", - "test-unit-snowflake": "cross-env DIALECT=snowflake yarn test-unit", - "test-unit-all": "yarn test-unit-mariadb && yarn test-unit-mysql && yarn test-unit-postgres && yarn test-unit-postgres-native && yarn test-unit-mssql && yarn test-unit-sqlite && yarn test-unit-snowflake && yarn test-unit-db2 && yarn test-unit-ibmi", - "test-integration-mariadb": "cross-env DIALECT=mariadb yarn test-integration", - "test-integration-mysql": "cross-env DIALECT=mysql yarn test-integration", - "test-integration-postgres": "cross-env DIALECT=postgres yarn test-integration", - "test-integration-postgres-native": "cross-env DIALECT=postgres-native yarn test-integration", - "test-integration-sqlite": "cross-env DIALECT=sqlite yarn test-integration", - "test-integration-mssql": "cross-env DIALECT=mssql yarn test-integration", - "test-integration-db2": "cross-env DIALECT=db2 yarn test-integration", - "test-integration-ibmi": "cross-env DIALECT=ibmi yarn test-integration", - "test-integration-snowflake": "cross-env DIALECT=snowflake yarn test-integration", - "test-mariadb": "cross-env DIALECT=mariadb yarn test", - "test-mysql": "cross-env DIALECT=mysql yarn test", - "test-sqlite": "cross-env DIALECT=sqlite yarn test", - "test-postgres": "cross-env DIALECT=postgres yarn test", - "test-postgres-native": "cross-env DIALECT=postgres-native yarn test", - "test-mssql": "cross-env DIALECT=mssql yarn test", - "test-db2": "cross-env DIALECT=db2 yarn test", - "test-ibmi": "cross-env DIALECT=ibmi yarn test", + "test-unit-mariadb": "cross-env DIALECT=mariadb npm run test-unit", + "test-unit-mysql": "cross-env DIALECT=mysql npm run test-unit", + "test-unit-postgres": "cross-env DIALECT=postgres npm run test-unit", + "test-unit-postgres-native": "cross-env DIALECT=postgres-native npm run test-unit", + "test-unit-sqlite": "cross-env DIALECT=sqlite npm run test-unit", + "test-unit-mssql": "cross-env DIALECT=mssql npm run test-unit", + "test-unit-db2": "cross-env DIALECT=db2 npm run test-unit", + "test-unit-snowflake": "cross-env DIALECT=snowflake npm run test-unit", + "test-unit-all": "npm run test-unit-mariadb && npm run test-unit-mysql && npm run test-unit-postgres && npm run test-unit-postgres-native && npm run test-unit-mssql && npm run test-unit-sqlite && npm run test-unit-snowflake && npm run test-unit-db2", + "test-integration-mariadb": "cross-env DIALECT=mariadb npm run test-integration", + "test-integration-mysql": "cross-env DIALECT=mysql npm run test-integration", + "test-integration-postgres": "cross-env DIALECT=postgres npm run test-integration", + "test-integration-postgres-native": "cross-env DIALECT=postgres-native npm run test-integration", + "test-integration-sqlite": "cross-env DIALECT=sqlite npm run test-integration", + "test-integration-mssql": "cross-env DIALECT=mssql npm run test-integration", + "test-integration-db2": "cross-env DIALECT=db2 npm run test-integration", + "test-integration-snowflake": "cross-env DIALECT=snowflake npm run test-integration", + "test-mariadb": "cross-env DIALECT=mariadb npm test", + "test-mysql": "cross-env DIALECT=mysql npm test", + "test-sqlite": "cross-env DIALECT=sqlite npm test", + "test-postgres": "cross-env DIALECT=postgres npm test", + "test-postgres-native": "cross-env DIALECT=postgres-native npm test", + "test-mssql": "cross-env DIALECT=mssql npm test", + "test-db2": "cross-env DIALECT=db2 npm test", "----------------------------------------- development ---------------------------------------------": "", - "fix-commit": "export TMPFILE=$(mktemp) && grep -v '^#' $(git rev-parse --git-dir)/COMMIT_EDITMSG > $TMPFILE && git commit -e -F $TMPFILE", "sscce": "node sscce.js", "sscce-mariadb": "cross-env DIALECT=mariadb node sscce.js", "sscce-mysql": "cross-env DIALECT=mysql node sscce.js", @@ -283,7 +278,7 @@ "sscce-sqlite": "cross-env DIALECT=sqlite node sscce.js", "sscce-mssql": "cross-env DIALECT=mssql node sscce.js", "sscce-db2": "cross-env DIALECT=db2 node sscce.js", - "prepare": "yarn build && husky install", + "prepare": "npm run build && husky install", "build": "node ./build.js", "---------------------------------------------------------------------------------------------------": "" }, diff --git a/yarn.lock b/yarn.lock index 5a9e352c053c..45e0d5c100a2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1012,7 +1012,7 @@ node-fetch "^2.6.7" universal-user-agent "^6.0.0" -"@octokit/rest@^18.0.0": +"@octokit/rest@^18.0.0", "@octokit/rest@^18.12.0": version "18.12.0" resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.12.0.tgz#f06bc4952fc87130308d810ca9d00e79f6988881" integrity sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==