Skip to content

Commit

Permalink
Merge 'atlassian' into wbinnssmith/merge-v2-2022-04-22
Browse files Browse the repository at this point in the history
* origin/atlassian:
  Add post-merge hook to update nightly versions
  Use temporally closest nightly version
  Extract run function
  Add script to update self-published versions
  • Loading branch information
lettertwo committed May 5, 2022
2 parents fa49329 + 2a92a66 commit e6b6f43
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 4 deletions.
15 changes: 15 additions & 0 deletions .husky/post-merge
@@ -0,0 +1,15 @@
#!/bin/sh
# Generated with husky-init and https://github.com/typicode/husky-4-to-6
. "$(dirname "$0")/_/husky.sh"

# ATLASSIAN: Update self-published (nightly) versions as part of a merge.
# Ideally, this would be done as part of a `pre-merge-commit` hook,
# but git does not support modifying the index during a merge commit.
# So, we hack it in this `post-merge` hook by immediately ammending the commit.
# Note that in cases where the merge commit did not automatically succeed,
# this hook will not be run. See comments in `pre-commit` hook for more.
yarn update-self-published -a
if [[ -f .git/MERGE_HEAD ]]; then
rm .git/MERGE_HEAD
fi
git log -n 1 --pretty=tformat:%s%n%n%b | git commit -F - --amend
11 changes: 11 additions & 0 deletions .husky/pre-commit
Expand Up @@ -3,3 +3,14 @@
. "$(dirname "$0")/_/husky.sh"

yarn lint-staged

# ATLASSIAN: Update self-published (nightly) versions as part of a merge.
# If a merge is committed automatically (e.g., no conflicts), this hook
# will not be run (see comments in `post-merge` for more). However,
# if a merge is not committed automatically (e.g., there are conflicts),
# the `post-merge` hook will not be run. Here we detect that a merge
# is being manually committed and replicate the work our `post-merge` hook
# would have done if the merge commit had proceeded automatically.
if git rev-parse -q --verify MERGE_HEAD >/dev/null 2>&1; then
yarn update-self-published -a
fi
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -29,6 +29,7 @@
"test:integration-ci": "yarn workspace @parcel/integration-tests test-ci",
"test": "yarn test:unit && yarn test:integration",
"update-readme-toc": "doctoc README.md",
"update-self-published": "node scripts/update-self-published.js",
"version:atlassian": "yarn lerna version patch --exact --force-publish=@atlassian/internal-parcel-utils,@atlassian/parcel-reporter-analytics",
"nightly:release": "lerna publish -y --canary --preid nightly --dist-tag=nightly --exact --force-publish=* --no-git-tag-version --no-push",
"tag:prerelease": "lerna version --exact --force-publish=* --no-git-tag-version --no-push && yarn adjust-versions --exact",
Expand Down
2 changes: 1 addition & 1 deletion packages/optimizers/image/package.json
Expand Up @@ -37,7 +37,7 @@
"@parcel/utils": "2.0.24",
"@parcel/workers": "2.0.24",
"detect-libc": "^1.0.3",
"self-published": "npm:@parcel/optimizer-image@2.5.1-nightly.2696"
"self-published": "npm:@parcel/optimizer-image@2.5.1-nightly.2700"
},
"devDependencies": {
"@napi-rs/cli": "^2.6.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/transformers/js/package.json
Expand Up @@ -40,7 +40,7 @@
"detect-libc": "^1.0.3",
"nullthrows": "^1.1.1",
"regenerator-runtime": "^0.13.7",
"self-published": "npm:@parcel/transformer-js@2.0.0-nightly.1073",
"self-published": "npm:@parcel/transformer-js@2.0.0-nightly.1077",
"semver": "^5.7.1"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/utils/fs-search/package.json
Expand Up @@ -29,7 +29,7 @@
},
"dependencies": {
"detect-libc": "^1.0.3",
"self-published": "npm:@parcel/fs-search@2.5.1-nightly.2696"
"self-published": "npm:@parcel/fs-search@2.5.1-nightly.2700"
},
"devDependencies": {
"@napi-rs/cli": "^2.6.2"
Expand Down
2 changes: 1 addition & 1 deletion packages/utils/hash/package.json
Expand Up @@ -33,7 +33,7 @@
},
"dependencies": {
"detect-libc": "^1.0.3",
"self-published": "npm:@parcel/hash@2.5.1-nightly.2696",
"self-published": "npm:@parcel/hash@2.5.1-nightly.2700",
"xxhash-wasm": "^0.4.2"
},
"devDependencies": {
Expand Down
112 changes: 112 additions & 0 deletions scripts/update-self-published.js
@@ -0,0 +1,112 @@
#!/usr/bin/env node

/* eslint-disable no-console */
const fs = require('fs');
const path = require('path');
const exec = require('child_process').execSync;

const UPSTREAM = /github.+parcel-bundler\/parcel/;
const NIGHTLY = /.*-nightly\..*/;

if (process.argv.includes('-h') || process.argv.includes('--help')) {
console.log(
[
` Usage: ${path.basename(process.argv[1])} [opts]`,
'',
' Options:',
' -h, --help Show help',
' -a Add updated files to git index',
' (handy in a precommit hook)',
'',
' Looks for self-published packages (e.g., @parcel/transformer-js),',
' and compares their nightly version numbers to the list',
' of published nightly versions (via `yarn info`).',
' If it finds a version that is newer, it updates the version',
' in the package.json.',
'',
' It will use the oldest nightly version that is newer than',
' the latest common commit between HEAD and the upstream default branch.',
].join('\n'),
);
process.exit();
}

const shouldStage = process.argv.includes('-a');

const fromVersionString = str => str.match(/npm:.+@(.+)$/)[1];
const toVersionString = (name, version) => `npm:${name}@${version}`;

function run(cmd) {
let result = exec(cmd, {stdio: [0, 'pipe', 2]});
try {
return JSON.parse(result);
} catch (e) {
if (e instanceof SyntaxError) {
return result.toString().trim();
} else {
throw e;
}
}
}

function getUpstreamRemoteName() {
for (let name of run(`git remote`).split(/\s+/)) {
if (UPSTREAM.test(run(`git remote get-url ${name}`))) {
return name;
}
}
throw new Error('Could not determine an upstream remote name!');
}

function getDefaultBranchName(remote) {
return run(`git rev-parse --abbrev-ref ${remote}`).split(`${remote}/`).pop();
}

/**
* Check nightly version timestamps for the given `pkgName`
* in reverse chronological order, returning the version
* with the timestamp closest to `time` without being younger.
*/
function getNearestNightlyVersion(pkgName, time) {
let candidate = null;
let info = run(`yarn info ${pkgName} --json`);
let versions = [...Object.entries(info.data.time)].reverse();
for (let [version, timestamp] of versions) {
if (NIGHTLY.test(version)) {
let versionTime = new Date(timestamp);
if (versionTime < time) break;
candidate = version;
}
}
return candidate;
}

console.log(`Updating self-published (nightly) versions...`);

let packages = run(
`${path.join(__dirname, '..', 'node_modules', '.bin', 'lerna')} ls --json`,
);

// Fetch the default upstream branch...
let upstream = getUpstreamRemoteName();
let branch = getDefaultBranchName(upstream);
run(`git fetch -q ${upstream} ${branch}`);
// ...so we can determine the latest common ancestor commit.
let baseRef = run(`git merge-base HEAD ${upstream}/${branch}`).split(/\s+/)[0];
// Get the commit time of the latest common ancestor between HEAD and upstream.
let baseRefTime = new Date(run(`git show -s --format=%cI ${baseRef}`));

for (let {location, name} of packages) {
let pkgPath = path.join(location, 'package.json');
let pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
if (pkg.dependencies && 'self-published' in pkg.dependencies) {
let current = fromVersionString(pkg.dependencies['self-published']);
let nightly = getNearestNightlyVersion(name, baseRefTime);
if (nightly && current !== nightly) {
console.log(`updating ${name} to nearest nightly ${nightly}`);
pkg.dependencies['self-published'] = toVersionString(name, nightly);
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
if (shouldStage) run(`git add -u ${pkgPath}`);
}
}
}

0 comments on commit e6b6f43

Please sign in to comment.