Skip to content

Commit

Permalink
chore(release): update build id, version generation (#4098)
Browse files Browse the repository at this point in the history
this commit changes the method used by the release scripts to generate
the build id and version number for "development builds", where a
"development build" is considered a build of stencil performed outside
using the `npm run release.*` scripts. this includes running `npm run
build` locally and in ci.

build id generation has changed from a date format 'yyyyMMddHHmmss', to
be epoch time in seconds. this allows us to easily convert the build
time to a human readable time if needed, with the added benefits of
easier de/serialization and a more compact representation. there exists
no place in the stencil codebase where this value is compared today, and
given this change only applies to dev builds, we can safely make this
change without breaking stencil or downstream consmers.

version generation has changed from '0.0.0-dev.BUILD_ID` to use the
current version stored in stencil's `package.json` as a base (so that it
is easily identifiable the stable version of stencil a build derives
from, the new build id, and a seven character sha to pinpoint the base
commit of the development build.

this commit is motivated by an effort to get development builds working
in a github actions ci environment. we wish to have this information
generated by stencil, rather than the ci process, such that commands
like `npx stencil info` returns the same version info as what's
published to the npm registry
  • Loading branch information
rwaskiewicz committed Mar 10, 2023
1 parent d715165 commit 30cb603
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 19 deletions.
70 changes: 55 additions & 15 deletions scripts/utils/options.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { execSync } from 'child_process';
import { readFileSync } from 'fs-extra';
import { join } from 'path';

Expand Down Expand Up @@ -71,7 +72,7 @@ export function getOptions(rootDir: string, inputOpts: BuildOptions = {}): Build
}

if (!opts.version) {
opts.version = '0.0.0-dev.' + opts.buildId;
opts.version = getDevVersionId({ buildId: opts.buildId, semverVersion: opts.packageJson?.version });
}

if (opts.isPublishRelease) {
Expand Down Expand Up @@ -195,20 +196,59 @@ export interface BuildOptions {
otp?: '';
}

export interface CmdLineArgs {
'config-version'?: string;
'config-build-id'?: string;
'config-prod'?: string;
/**
* Generate a build identifier, which is the Epoch Time in seconds
* @returns the generated build ID
*/
function getBuildId(): string {
return Date.now().toString(10).slice(0, -3);
}

/**
* Describes the contents of a version string for Stencil used in 'non-production' builds (e.g. a one-off dev build)
*/
interface DevVersionContents {
/**
* The build identifier string, used to uniquely identify when the build was generated
*/
buildId: string;
/**
* A semver-compliant string to add to the one-off build version sting, used to identify a base version of Stencil
* that was used in the build.
*/
semverVersion: string | undefined;
}

function getBuildId() {
const d = new Date();
return [
d.getUTCFullYear() + '',
('0' + (d.getUTCMonth() + 1)).slice(-2),
('0' + d.getUTCDate()).slice(-2),
('0' + d.getUTCHours()).slice(-2),
('0' + d.getUTCMinutes()).slice(-2),
('0' + d.getUTCSeconds()).slice(-2),
].join('');
/**
* Helper function to return the first seven characters of a git SHA
*
* We use the first seven characters for two reasons:
* 1. Seven characters _should_ be enough to uniquely ID a commit in Stencil
* 2. It matches the number of characters used in our CHANGELOG.md
*
* @returns the seven character SHA
*/
function getSevenCharGitSha(): string {
return execSync('git rev-parse HEAD').toString().trim().slice(0, 7);
}

/**
* Helper function to generate a dev build version string of the format:
*
* [BASE_VERSION]-dev.[BUILD_IDENTIFIER].[GIT_SHA]
*
* where:
* - BASE_VERSION is the version of Stencil currently assigned in `package.json`
* - BUILD_IDENTIFIER is a unique identifier for this particular build
* - GIT_SHA is the SHA of the HEAD of the branch this build was created from
*
* @param devVersionContents an object containing the necessary arguments to build a dev-version identifier
* @returns the generated version string
*/
function getDevVersionId(devVersionContents: DevVersionContents): string {
const { buildId, semverVersion } = devVersionContents;
// if `package.json#package` is empty, default to a value that doesn't imply any particular version of Stencil
const version = semverVersion ?? '0.0.0';
// '-' and '-dev.' are a magic substrings that may get checked on startup of a Stencil process.
return version + '-dev.' + buildId + '.' + getSevenCharGitSha();
}
19 changes: 15 additions & 4 deletions scripts/utils/test/options.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ import * as Vermoji from '../vermoji';
describe('release options', () => {
describe('getOptions', () => {
const ROOT_DIR = './';
// Friday, February 24, 2023 2:42:09.123 PM, GMT
const FAKE_SYSTEM_TIME_MS = 1677249729123;
const FAKE_SYSTEM_TIME_S = FAKE_SYSTEM_TIME_MS.toString(10).slice(0, -3);

beforeEach(() => {
jest.useFakeTimers();
jest.setSystemTime(FAKE_SYSTEM_TIME_MS);
});

afterEach(() => {
jest.useRealTimers();
});

it('returns the correct default value', () => {
const buildOpts = getOptions(ROOT_DIR);
Expand Down Expand Up @@ -58,8 +70,7 @@ describe('release options', () => {
const { buildId } = getOptions(ROOT_DIR);

expect(buildId).toBeDefined();
// Expect a Date of the format yyyyMMddHHmmss
expect(buildId).toMatch(/\d{14}/);
expect(buildId).toBe(FAKE_SYSTEM_TIME_S);
});

it('uses the provided the buildId', () => {
Expand All @@ -76,8 +87,8 @@ describe('release options', () => {
const { version } = getOptions(ROOT_DIR);

expect(version).toBeDefined();
// Expect a version string with the format 0.0.0-dev-yyyyMMddHHmmss
expect(version).toMatch(/0\.0\.0-dev\.\d{14}/);
// Expect a version string with the format 0.0.0-dev-[EPOCH_TIME]-[GIT_SHA_7_CHARS]
expect(version).toMatch(new RegExp(`\\d+\\.\\d+\\.\\d+-dev.${FAKE_SYSTEM_TIME_S}.\\w{7}`));
});

it('uses the provided the version', () => {
Expand Down

0 comments on commit 30cb603

Please sign in to comment.