Add new release line for testing

This commit is contained in:
Fedor Indutny 2024-11-20 19:14:21 -08:00 committed by GitHub
parent 70dd062753
commit 34cc87e8a8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 199 additions and 43 deletions

View file

@ -35,7 +35,9 @@
"clean-protobuf": "npm run clean-module-protobuf",
"prepare-beta-build": "node scripts/prepare_beta_build.js",
"prepare-alpha-build": "node scripts/prepare_alpha_build.js",
"prepare-alpha-version": "node scripts/prepare_alpha_version.js",
"prepare-alpha-version": "node scripts/prepare_tagged_version.js alpha",
"prepare-axolotl-build": "node scripts/prepare_axolotl_build.js",
"prepare-axolotl-version": "node scripts/prepare_tagged_version.js axolotl",
"prepare-staging-build": "node scripts/prepare_staging_build.js",
"prepare-windows-cert": "node scripts/prepare_windows_cert.js",
"test": "run-s test-node test-electron test-lint-intl test-eslint",

View file

@ -44,6 +44,9 @@ if [ "${BUILD_TYPE}" = "public" ]; then
elif [ "${BUILD_TYPE}" = "alpha" ]; then
npm run prepare-alpha-version
npm run prepare-alpha-build
elif [ "${BUILD_TYPE}" = "axolotl" ]; then
npm run prepare-axolotl-version
npm run prepare-axolotl-build
elif [ "${BUILD_TYPE}" = "staging" ]; then
npm run prepare-alpha-version
npm run prepare-staging-build

View file

@ -0,0 +1,77 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
const fs = require('fs');
const _ = require('lodash');
const packageJson = require('../package.json');
const { isAxolotl } = require('../ts/util/version');
const { version } = packageJson;
// You might be wondering why this file is necessary. It comes down to our desire to allow
// side-by-side installation of production and alpha builds. Electron-Builder uses
// top-level data from package.json for many things, like the executable name, the
// debian package name, the install directory under /opt on linux, etc. We tried
// adding the ${channel} macro to these values, but Electron-Builder didn't like that.
if (!isAxolotl(version)) {
console.error(`Version '${version}' is not an backup version!`);
process.exit(1);
}
console.log('prepare_backup_build: updating package.json');
// -------
const NAME_PATH = 'name';
const PRODUCTION_NAME = 'signal-desktop';
const AXOLOTL_NAME = 'signal-desktop-axolotl';
const PRODUCT_NAME_PATH = 'productName';
const PRODUCTION_PRODUCT_NAME = 'Signal';
const AXOLOTL_PRODUCT_NAME = 'Signal Axolotl';
const APP_ID_PATH = 'build.appId';
const PRODUCTION_APP_ID = 'org.whispersystems.signal-desktop';
const AXOLOTL_APP_ID = 'org.whispersystems.signal-desktop-axolotl';
const STARTUP_WM_CLASS_PATH = 'build.linux.desktop.StartupWMClass';
const PRODUCTION_STARTUP_WM_CLASS = 'Signal';
const AXOLOTL_STARTUP_WM_CLASS = 'Signal Axolotl';
const DESKTOP_NAME_PATH = 'desktopName';
// Note: we're avoiding dashes in our .desktop name due to xdg-settings behavior
// https://github.com/signalapp/Signal-Desktop/issues/3602
const PRODUCTION_DESKTOP_NAME = 'signal.desktop';
const AXOLOTL_DESKTOP_NAME = 'signalaxolotl.desktop';
// -------
function checkValue(object, objectPath, expected) {
const actual = _.get(object, objectPath);
if (actual !== expected) {
throw new Error(`${objectPath} was ${actual}; expected ${expected}`);
}
}
// ------
checkValue(packageJson, NAME_PATH, PRODUCTION_NAME);
checkValue(packageJson, PRODUCT_NAME_PATH, PRODUCTION_PRODUCT_NAME);
checkValue(packageJson, APP_ID_PATH, PRODUCTION_APP_ID);
checkValue(packageJson, STARTUP_WM_CLASS_PATH, PRODUCTION_STARTUP_WM_CLASS);
checkValue(packageJson, DESKTOP_NAME_PATH, PRODUCTION_DESKTOP_NAME);
// -------
_.set(packageJson, NAME_PATH, AXOLOTL_NAME);
_.set(packageJson, PRODUCT_NAME_PATH, AXOLOTL_PRODUCT_NAME);
_.set(packageJson, APP_ID_PATH, AXOLOTL_APP_ID);
_.set(packageJson, STARTUP_WM_CLASS_PATH, AXOLOTL_STARTUP_WM_CLASS);
_.set(packageJson, DESKTOP_NAME_PATH, AXOLOTL_DESKTOP_NAME);
// -------
fs.writeFileSync('./package.json', JSON.stringify(packageJson, null, ' '));

View file

@ -6,7 +6,13 @@ const { execSync } = require('child_process');
const _ = require('lodash');
const { generateAlphaVersion } = require('../ts/util/version');
const release = process.argv[2];
if (release !== 'alpha' && release !== 'axolotl') {
console.error(`Invalid release line: ${release}`);
process.exit(1);
}
const { generateTaggedVersion } = require('../ts/util/version');
const packageJson = require('../package.json');
@ -16,15 +22,15 @@ const shortSha = execSync('git rev-parse --short HEAD')
.toString('utf8')
.replace(/[\n\r]/g, '');
const alphaVersion = generateAlphaVersion({ currentVersion, shortSha });
const newVersion = generateTaggedVersion({ release, currentVersion, shortSha });
console.log(
`prepare_alpha_version: updating package.json.\n Previous: ${currentVersion}\n New: ${alphaVersion}`
`prepare_tagged_version: updating package.json.\n Previous: ${currentVersion}\n New: ${newVersion}`
);
// -------
_.set(packageJson, 'version', alphaVersion);
_.set(packageJson, 'version', newVersion);
// -------

View file

@ -19,12 +19,12 @@ export default {
args: {
i18n,
hasInitialLoadCompleted: false,
isAlpha: false,
isNightly: false,
isCustomizingPreferredReactions: false,
},
argTypes: {
daysAgo: { control: { type: 'number' } },
isAlpha: { control: { type: 'boolean' } },
isNightly: { control: { type: 'boolean' } },
},
} satisfies Meta<PropsType & { daysAgo?: number }>;

View file

@ -14,7 +14,7 @@ export type PropsType = {
envelopeTimestamp: number | undefined;
hasInitialLoadCompleted: boolean;
i18n: LocalizerType;
isAlpha: boolean;
isNightly: boolean;
isCustomizingPreferredReactions: boolean;
navTabsCollapsed: boolean;
onToggleNavTabsCollapse: (navTabsCollapsed: boolean) => unknown;
@ -32,7 +32,7 @@ export function Inbox({
envelopeTimestamp,
hasInitialLoadCompleted,
i18n,
isAlpha,
isNightly,
isCustomizingPreferredReactions,
navTabsCollapsed,
onToggleNavTabsCollapse,
@ -128,7 +128,7 @@ export function Inbox({
}
let logo: JSX.Element;
if (isAlpha) {
if (isNightly) {
const parts = new Array<JSX.Element>();
parts.push(
<i key="base" className="Inbox__logo__part Inbox__logo__part--base" />

View file

@ -116,7 +116,7 @@ import {
} from '../../util/backupMediaDownload';
import { getEnvironment, isTestEnvironment } from '../../environment';
import { hasAttachmentDownloads } from '../../util/hasAttachmentDownloads';
import { isAlpha } from '../../util/version';
import { isNightly } from '../../util/version';
import { ToastType } from '../../types/Toast';
const MAX_CONCURRENCY = 10;
@ -369,7 +369,7 @@ export class BackupImportStream extends Writable {
log.error(
`${this.logId}: errored while processing ${this.frameErrorCount} frames.`
);
if (isAlpha(window.getVersion())) {
if (isNightly(window.getVersion())) {
window.reduxActions.toast.showToast({
toastType: ToastType.FailedToImportBackup,
});

View file

@ -51,7 +51,7 @@ import { validateBackup } from './validator';
import { BackupType } from './types';
import { UnsupportedBackupVersion } from './errors';
import { ToastType } from '../../types/Toast';
import { isAlpha } from '../../util/version';
import { isNightly } from '../../util/version';
export { BackupType };
@ -388,7 +388,7 @@ export class BackupsService {
} catch (error) {
log.info(`importBackup: failed, error: ${Errors.toLogFormat(error)}`);
if (isAlpha(window.getVersion())) {
if (isNightly(window.getVersion())) {
window.reduxActions.toast.showToast({
toastType: ToastType.FailedToImportBackup,
});

View file

@ -12,7 +12,7 @@ import type { StateType } from '../reducer';
import type { CallingStateType } from '../ducks/calling';
import type { UserStateType } from '../ducks/user';
import { isAlpha, isBeta } from '../../util/version';
import { isNightly, isBeta } from '../../util/version';
export const getUser = (state: StateType): UserStateType => state.user;
@ -108,7 +108,7 @@ const getVersion = createSelector(
(state: UserStateType) => state.version
);
export const getIsAlpha = createSelector(getVersion, isAlpha);
export const getIsNightly = createSelector(getVersion, isNightly);
export const getIsBeta = createSelector(getVersion, isBeta);

View file

@ -4,7 +4,7 @@
import React, { memo } from 'react';
import { useSelector } from 'react-redux';
import { Inbox } from '../../components/Inbox';
import { isAlpha } from '../../util/version';
import { isNightly } from '../../util/version';
import { getIntl } from '../selectors/user';
import { SmartCustomizingPreferredReactionsModal } from './CustomizingPreferredReactionsModal';
import { getIsCustomizingPreferredReactions } from '../selectors/preferredReactions';
@ -59,7 +59,7 @@ export const SmartInbox = memo(function SmartInbox(): JSX.Element {
firstEnvelopeTimestamp={firstEnvelopeTimestamp}
hasInitialLoadCompleted={hasInitialLoadCompleted}
i18n={i18n}
isAlpha={isAlpha(window.getVersion())}
isNightly={isNightly(window.getVersion())}
isCustomizingPreferredReactions={isCustomizingPreferredReactions}
navTabsCollapsed={navTabsCollapsed}
onToggleNavTabsCollapse={toggleNavTabsCollapse}

View file

@ -7,7 +7,7 @@ import type { StateType } from '../../../state/reducer';
import type { UserStateType } from '../../../state/ducks/user';
import { getEmptyState } from '../../../state/ducks/user';
import { getIsAlpha, getIsBeta } from '../../../state/selectors/user';
import { getIsNightly, getIsBeta } from '../../../state/selectors/user';
describe('both/state/selectors/user', () => {
function getRootState(
@ -22,20 +22,20 @@ describe('both/state/selectors/user', () => {
} as any;
}
describe('#getIsAlpha', () => {
describe('#getIsNightly', () => {
it('returns false for beta', () => {
const state = getRootState({ version: '1.23.4-beta.5' });
assert.isFalse(getIsAlpha(state));
assert.isFalse(getIsNightly(state));
});
it('returns false for production', () => {
const state = getRootState({ version: '1.23.4' });
assert.isFalse(getIsAlpha(state));
assert.isFalse(getIsNightly(state));
});
it('returns true for alpha', () => {
const state = getRootState({ version: '1.23.4-alpha.987' });
assert.isTrue(getIsAlpha(state));
assert.isTrue(getIsNightly(state));
});
});

View file

@ -6,8 +6,10 @@ import { useFakeTimers } from 'sinon';
import * as semver from 'semver';
import {
generateAlphaVersion,
generateTaggedVersion,
isAlpha,
isAxolotl,
isNightly,
isBeta,
isProduction,
isStaging,
@ -57,6 +59,34 @@ describe('version utilities', () => {
});
});
describe('isAxolotl', () => {
it('returns false for non-axolotl version strings', () => {
assert.isFalse(isAxolotl('1.2.3'));
assert.isFalse(isAxolotl('1.2.3-staging.1'));
assert.isFalse(isAxolotl('1.2.3-beta'));
assert.isFalse(isAxolotl('1.2.3-beta.1'));
assert.isFalse(isAxolotl('1.2.3-rc.1'));
});
it('returns true for Axolotl version strings', () => {
assert.isTrue(isAxolotl('1.2.3-axolotl'));
assert.isTrue(isAxolotl('1.2.3-axolotl.1'));
});
});
describe('isNightly', () => {
it('returns false for non-nightly version strings', () => {
assert.isFalse(isNightly('1.2.3'));
assert.isFalse(isNightly('1.2.3-beta.1'));
assert.isFalse(isNightly('1.2.3-staging.1'));
});
it('returns true for nightly version strings', () => {
assert.isTrue(isNightly('1.2.3-alpha.1'));
assert.isTrue(isNightly('1.2.3-axolotl.1'));
});
});
describe('isStaging', () => {
it('returns false for non-staging version strings', () => {
assert.isFalse(isStaging('1.2.3'));
@ -73,7 +103,7 @@ describe('version utilities', () => {
});
});
describe('generateAlphaVersion', () => {
describe('generateTaggedVersion', () => {
beforeEach(function (this: Mocha.Context) {
// This isn't a hook.
this.clock = useFakeTimers();
@ -90,7 +120,11 @@ describe('version utilities', () => {
const shortSha = '07f0efc45';
const expected = '5.12.0-alpha.20210723.01-07f0efc45';
const actual = generateAlphaVersion({ currentVersion, shortSha });
const actual = generateTaggedVersion({
release: 'alpha',
currentVersion,
shortSha,
});
assert.strictEqual(expected, actual);
});
@ -100,7 +134,11 @@ describe('version utilities', () => {
const shortSha = '07f0efc45';
this.clock.setSystemTime(new Date('2021-07-23T01:22:55.692Z').getTime());
const actual = generateAlphaVersion({ currentVersion, shortSha });
const actual = generateTaggedVersion({
release: 'alpha',
currentVersion,
shortSha,
});
assert.isTrue(semver.gt('5.12.0', actual));
});
@ -110,7 +148,11 @@ describe('version utilities', () => {
const shortSha = '07f0efc45';
this.clock.setSystemTime(new Date('2021-07-23T01:22:55.692Z').getTime());
const actual = generateAlphaVersion({ currentVersion, shortSha });
const actual = generateTaggedVersion({
release: 'alpha',
currentVersion,
shortSha,
});
assert.isTrue(semver.gt(currentVersion, actual));
});
@ -120,10 +162,18 @@ describe('version utilities', () => {
const shortSha = '07f0efc45';
this.clock.setSystemTime(new Date('2021-07-23T00:22:55.692Z').getTime());
const actualEarlier = generateAlphaVersion({ currentVersion, shortSha });
const actualEarlier = generateTaggedVersion({
release: 'alpha',
currentVersion,
shortSha,
});
this.clock.setSystemTime(new Date('2021-07-23T01:22:55.692Z').getTime());
const actualLater = generateAlphaVersion({ currentVersion, shortSha });
const actualLater = generateTaggedVersion({
release: 'alpha',
currentVersion,
shortSha,
});
assert.isTrue(semver.lt(actualEarlier, actualLater));
});
@ -133,10 +183,18 @@ describe('version utilities', () => {
const shortSha = '07f0efc45';
this.clock.setSystemTime(new Date('2021-07-22T01:22:55.692Z').getTime());
const actualEarlier = generateAlphaVersion({ currentVersion, shortSha });
const actualEarlier = generateTaggedVersion({
release: 'alpha',
currentVersion,
shortSha,
});
this.clock.setSystemTime(new Date('2021-07-23T01:22:55.692Z').getTime());
const actualLater = generateAlphaVersion({ currentVersion, shortSha });
const actualLater = generateTaggedVersion({
release: 'alpha',
currentVersion,
shortSha,
});
assert.isTrue(semver.lt(actualEarlier, actualLater));
});

View file

@ -46,7 +46,7 @@ import WebSocketResource, {
import { ConnectTimeoutError, HTTPError } from './Errors';
import type { IRequestHandler, WebAPICredentials } from './Types.d';
import { connect as connectWebSocket } from './WebSocket';
import { isAlpha, isBeta, isStaging } from '../util/version';
import { isNightly, isBeta, isStaging } from '../util/version';
import { getBasicAuth } from '../util/getBasicAuth';
const FIVE_MINUTES = 5 * durations.MINUTE;
@ -601,7 +601,7 @@ export class SocketManager extends EventListener {
// in alpha, switch to using libsignal transport, unless user opts out,
// in which case switching to shadowing
if (isAlpha(this.options.version)) {
if (isNightly(this.options.version)) {
const configValue = window.Signal.RemoteConfig.isEnabled(
'desktop.experimentalTransportEnabled.alpha'
);

View file

@ -27,7 +27,7 @@ import * as Errors from '../types/errors';
import { strictAssert } from '../util/assert';
import { drop } from '../util/drop';
import * as durations from '../util/durations';
import { isAlpha, isBeta, isStaging } from '../util/version';
import { isAlpha, isAxolotl, isBeta, isStaging } from '../util/version';
import * as packageJson from '../../package.json';
import type { SettingsChannel } from '../main/settingsChannel';
@ -912,6 +912,9 @@ function getChannel(): string {
if (isAlpha(version)) {
return 'alpha';
}
if (isAxolotl(version)) {
return 'axolotl';
}
if (isBeta(version)) {
return 'beta';
}

View file

@ -27,7 +27,7 @@ import { DurationInSeconds, MINUTE } from './durations';
import { ToastType } from '../types/Toast';
import * as Errors from '../types/errors';
import { isTestOrMockEnvironment } from '../environment';
import { isAlpha } from './version';
import { isNightly } from './version';
import { parseStrict } from './schemas';
import { DataReader } from '../sql/Client';
import { maybeUpdateGroup } from '../groups';
@ -331,7 +331,7 @@ const showFailedToSendWithEndorsementsToast = throttle(
export function onFailedToSendWithEndorsements(error: Error): void {
log.error('onFailedToSendWithEndorsements', Errors.toLogFormat(error));
if (isTestOrMockEnvironment() || isAlpha(window.getVersion())) {
if (isTestOrMockEnvironment() || isNightly(window.getVersion())) {
showFailedToSendWithEndorsementsToast();
}
if (window.SignalCI) {

View file

@ -3,7 +3,7 @@
import { isTestOrMockEnvironment } from '../environment';
import { isStagingServer } from './isStagingServer';
import { isAlpha } from './version';
import { isNightly } from './version';
import { everDone as wasRegistrationEverDone } from './registration';
export function isLinkAndSyncEnabled(version: string): boolean {
@ -12,5 +12,5 @@ export function isLinkAndSyncEnabled(version: string): boolean {
return false;
}
return isStagingServer() || isTestOrMockEnvironment() || isAlpha(version);
return isStagingServer() || isTestOrMockEnvironment() || isNightly(version);
}

View file

@ -16,21 +16,28 @@ export const isProduction = (version: string): boolean => {
export const isBeta = (version: string): boolean =>
semver.parse(version)?.prerelease[0] === 'beta';
export const isNightly = (version: string): boolean =>
isAlpha(version) || isAxolotl(version);
export const isAlpha = (version: string): boolean =>
semver.parse(version)?.prerelease[0] === 'alpha';
export const isAxolotl = (version: string): boolean =>
semver.parse(version)?.prerelease[0] === 'axolotl';
export const isStaging = (version: string): boolean =>
semver.parse(version)?.prerelease[0] === 'staging';
export const generateAlphaVersion = (options: {
export const generateTaggedVersion = (options: {
release: string;
currentVersion: string;
shortSha: string;
}): string => {
const { currentVersion, shortSha } = options;
const { release, currentVersion, shortSha } = options;
const parsed = semver.parse(currentVersion);
if (!parsed) {
throw new Error(`generateAlphaVersion: Invalid version ${currentVersion}`);
throw new Error(`generateTaggedVersion: Invalid version ${currentVersion}`);
}
const dateTimeParts = new Intl.DateTimeFormat('en', {
@ -51,5 +58,5 @@ export const generateAlphaVersion = (options: {
const formattedVersion = `${parsed.major}.${parsed.minor}.${parsed.patch}`;
return `${formattedVersion}-alpha.${formattedDate}-${shortSha}`;
return `${formattedVersion}-${release}.${formattedDate}-${shortSha}`;
};