diff --git a/.eslintrc.json b/.eslintrc.json index e4c3c97e8..b2b2fd596 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -99,6 +99,12 @@ } ] } + }, + { + "files": ["**/ci/*.js"], + "rules": { + "no-undef": "off" + } } ] } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f57da9be1..46988480c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -96,6 +96,29 @@ jobs: test_type: nwaku-master debug: waku* + pre-release: + name: pre-release + runs-on: ubuntu-latest + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + needs: [check, proto, browser, node] + steps: + - uses: actions/checkout@v3 + with: + repository: waku-org/js-waku + + - uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_JS }} + registry-url: "https://registry.npmjs.org" + + - run: npm install + + - run: npm run build + + - run: npm run publish -- --tag next + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_JS_WAKU_PUBLISH }} + maybe-release: name: release runs-on: ubuntu-latest diff --git a/ci/publish.js b/ci/publish.js index 179558059..9fc5f288b 100644 --- a/ci/publish.js +++ b/ci/publish.js @@ -8,8 +8,13 @@ const PACKAGE_JSON = "package.json"; // hack to get __dirname const DIR = path.dirname(fileURLToPath(import.meta.url)); +const NEXT_TAG = "next"; +const LATEST_TAG = "latest"; +const CURRENT_TAG = readPublishTag(); + const exec = promisify(cp.exec); const readFile = promisify(fs.readFile); +const writeFile = promisify(fs.writeFile); run() .then(() => { @@ -23,26 +28,31 @@ async function run() { const rootPackage = await readJSON(path.resolve(DIR, "../", PACKAGE_JSON)); const workspacePaths = rootPackage.workspaces; - const workspaces = await Promise.all( - workspacePaths.map(async (workspacePath) => { - const workspaceInfo = await readWorkspace(workspacePath); - const allowPublishing = await shouldBePublished(workspaceInfo); + if (CURRENT_TAG === NEXT_TAG) { + await makeReleaseCandidate(); + } - if (allowPublishing) { - return workspaceInfo; - } + const workspaces = await Promise.all(workspacePaths.map(readWorkspace)); - return; - }) - ); + if (CURRENT_TAG === NEXT_TAG) { + await upgradeWakuDependencies(workspaces); + } await Promise.all( workspaces - .filter((v) => !!v) + .filter(async (info) => { + const allowPublishing = await shouldBePublished(info); + + if (allowPublishing) { + return true; + } + + return false; + }) .map(async (info) => { try { await exec( - `npm publish --workspace ${info.workspace} --tag latest --access public` + `npm publish --workspace ${info.workspace} --tag ${CURRENT_TAG} --access public` ); console.info( `Successfully published ${info.workspace} with version ${info.version}.` @@ -61,6 +71,11 @@ async function readJSON(path) { return JSON.parse(rawJSON); } +async function writeWorkspace(packagePath, text) { + const resolvedPath = path.resolve(DIR, "../", packagePath, PACKAGE_JSON); + await writeFile(resolvedPath, text); +} + async function readWorkspace(packagePath) { const json = await readJSON( path.resolve(DIR, "../", packagePath, PACKAGE_JSON) @@ -70,13 +85,14 @@ async function readWorkspace(packagePath) { name: json.name, private: !!json.private, version: json.version, - workspace: packagePath + workspace: packagePath, + rawPackageJson: json }; } async function shouldBePublished(info) { if (info.private) { - console.info(`Skipping ${info.path} because it is private.`); + console.info(`Skipping ${info.name} because it is private.`); return false; } @@ -99,3 +115,60 @@ async function shouldBePublished(info) { ); } } + +async function makeReleaseCandidate() { + try { + console.info("Marking workspace versions as release candidates."); + await exec( + `npm version prerelease --preid $(git rev-parse --short HEAD) --workspaces true` + ); + } catch (e) { + console.error("Failed to mark release candidate versions.", e); + } +} + +function readPublishTag() { + const args = process.argv.slice(2); + const tagIndex = args.indexOf("--tag"); + + if (tagIndex !== -1 && args[tagIndex + 1]) { + return args[tagIndex + 1]; + } + + return LATEST_TAG; +} + +async function upgradeWakuDependencies(workspaces) { + console.log("Upgrading Waku dependencies in workspaces."); + const map = workspaces.reduce((acc, item) => { + if (!item.private) { + acc[item.name] = item; + } + return acc; + }, {}); + const packageNames = Object.keys(map); + workspaces.forEach(async (info) => { + if (info.private) { + return; + } + ["dependencies", "devDependencies", "peerDependencies"].forEach((type) => { + const deps = info.rawPackageJson[type]; + if (!deps) { + return; + } + packageNames.forEach((name) => { + if (deps[name]) { + deps[name] = map[name].version; + } + }); + }); + try { + await writeWorkspace(info.workspace, JSON.stringify(info.rawPackageJson)); + } catch (error) { + console.error( + `Failed to update package.json for ${info.name} with: `, + error + ); + } + }); +}