Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "version" string and parsed "versionInfo" #1878

Merged
merged 1 commit into from May 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -33,7 +33,8 @@
"check": "flow check",
"check-cover": "flow batch-coverage --quiet --strip-root --show-all src/ && flow stop --quiet",
"build": "node resources/build.js",
"preversion": ". ./resources/checkgit.sh && npm test",
"preversion": ". ./resources/checkgit.sh",
"version": "node resources/gen-version.js && npm test",
"prepublishOnly": ". ./resources/prepublish.sh",
"gitpublish": ". ./resources/gitpublish.sh"
},
Expand Down
25 changes: 17 additions & 8 deletions resources/build.js
Expand Up @@ -18,6 +18,7 @@ const {
rmdirRecursive,
mkdirRecursive,
readdirRecursive,
parseSemver,
} = require('./utils');

if (require.main === module) {
Expand All @@ -26,14 +27,21 @@ if (require.main === module) {

copyFile('./LICENSE', './dist/LICENSE');
copyFile('./README.md', './dist/README.md');
writeFile('./dist/package.json', buildPackageJSON());

const srcFiles = readdirRecursive('./src', { ignoreDir: /^__.*__$/ });
for (const filepath of srcFiles) {
if (filepath.endsWith('.js')) {
buildJSFile(filepath);
}
}

const packageJSON = buildPackageJSON();
assert(
packageJSON.version === require('../dist/version').version,
'Version in package.json and version.js should match',
);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check guarantees that package.json and version.js are always in sync.


writeFile('./dist/package.json', packageJSON);
}

function buildJSFile(filepath) {
Expand All @@ -52,13 +60,14 @@ function buildPackageJSON() {
delete packageJSON.scripts;
delete packageJSON.devDependencies;

const { version } = packageJSON;
const match = /^[0-9]+\.[0-9]+\.[0-9]+-?([^.]*)/.exec(version);
assert(match, 'Version does not match semver spec.');
const tag = match[1];
assert(!tag || tag === 'rc', 'Only "rc" tag is supported.');
const { preReleaseTag } = parseSemver(packageJSON.version);
if (preReleaseTag != null) {
const [tag] = preReleaseTag.split('.');
assert(tag === 'rc', 'Only "rc" tag is supported.');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the code had this check before, but I'm just curious why only rc is supported?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@martijnwalraven Thanks for the review 👍
It was added to prevent issues similar to #1375
These scripts are run by Travis and package automatically published so I'm trying to use "fail fast" design for them. Especially since I don't have NPM keys to do a manual fix if something goes wrong.
If we decide to use other tags in future it will be a matter of just adding them here.


assert(!packageJSON.publishConfig, 'Can not override "publishConfig".');
packageJSON.publishConfig = { tag: tag || 'latest' };
}

assert(!packageJSON.publishConfig, 'Can not override "publishConfig".');
packageJSON.publishConfig = { tag: tag || 'latest' };
return JSON.stringify(packageJSON, null, 2);
}
48 changes: 48 additions & 0 deletions resources/gen-version.js
@@ -0,0 +1,48 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @noflow
*/

'use strict';

const { version } = require('../package.json');
const { writeFile, parseSemver } = require('./utils');

const versionInfo = parseSemver(version);
const body = `/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
*/

/**
* Note: This file is autogenerated using "resources/gen-version.js" script and
* automatically updated by "yarn version" command.
*/

/**
* A string containing the version of the GraphQL.js library
*/
export const version = '${version}';

/**
* An object containing the components of the GraphQL.js version string
*/
export const versionInfo = Object.freeze({
major: ${versionInfo.major},
minor: ${versionInfo.minor},
patch: ${versionInfo.patch},
preReleaseTag: ${JSON.stringify(versionInfo.preReleaseTag || null)},
});
`;

if (require.main === module) {
writeFile('./src/version.js', body);
}
11 changes: 11 additions & 0 deletions resources/utils.js
Expand Up @@ -61,10 +61,21 @@ function copyFile(srcPath, destPath) {
fs.copyFileSync(srcPath, destPath);
}

function parseSemver(version) {
const match = /^(\d+)\.(\d+)\.(\d+)-?(.*)?$/.exec(version);
if (!match) {
throw new Error('Version does not match semver spec: ' + version);
}

const [, major, minor, patch, preReleaseTag] = match;
return { major, minor, patch, preReleaseTag };
}

module.exports = {
copyFile,
writeFile,
rmdirRecursive,
mkdirRecursive,
readdirRecursive,
parseSemver,
};
43 changes: 43 additions & 0 deletions src/__tests__/version-test.js
@@ -0,0 +1,43 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
*/

import { expect } from 'chai';
import { describe, it } from 'mocha';
import { version, versionInfo } from '../version';

describe('Version', () => {
it('version', () => {
expect(version).to.be.a('string');
expect(version).to.match(/^\d+\.\d+\.\d(-rc.\d+)?$/);
});

it('versionInfo', () => {
expect(versionInfo).to.be.an('object');
expect(versionInfo).to.have.all.keys(
'major',
'minor',
'patch',
'preReleaseTag',
);

const { major, minor, patch, preReleaseTag } = versionInfo;

expect(major).to.be.a('number');
expect(minor).to.be.a('number');
expect(patch).to.be.a('number');
if (preReleaseTag !== null) {
expect(preReleaseTag).to.be.a('string');
}

expect(
`${major}.${minor}.${patch}` +
(preReleaseTag !== null ? '-' + preReleaseTag : ''),
).to.equal(version);
});
});
3 changes: 3 additions & 0 deletions src/index.js
Expand Up @@ -31,6 +31,9 @@
* import { parse } from 'graphql/language';
*/

// The GraphQL.js version info.
export { version, versionInfo } from './version';

// The primary entry point into fulfilling a GraphQL request.
export type { GraphQLArgs } from './graphql';
export { graphql, graphqlSync } from './graphql';
Expand Down
28 changes: 28 additions & 0 deletions src/version.js
@@ -0,0 +1,28 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
*/

/**
* Note: This file is autogenerated using "resources/gen-version.js" script and
* automatically updated by "yarn version" command.
*/

/**
* A string containing the version of the GraphQL.js library
*/
export const version = '14.3.0';

/**
* An object containing the components of the GraphQL.js version string
*/
export const versionInfo = Object.freeze({
major: 14,
minor: 3,
patch: 0,
preReleaseTag: null,
});