1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-12-24 16:49:26 +01:00

[PM-12989] Create process for qa to build client with particular sdk version (#11601)

* feat: update sdk service abstraction with documentation and new `userClient$` function

* feat: add uninitialized user client with cache

* feat: initialize user crypto

* feat: initialize org keys

* fix: org crypto not initializing properly

* feat: avoid creating clients unnecessarily

* chore: remove dev print/subscription

* fix: clean up cache

* chore: update sdk version

* feat: implement clean-up logic (#11504)

* chore: bump sdk version to fix build issues

* chore: bump sdk version to fix build issues

* fix: missing constructor parameters

* refactor: simplify free() and delete() calls

* refactor: use a named function for client creation

* fix: client never freeing after refactor

* fix: broken impl and race condition in tests

* feat: add sdk override to desktop build

* feat: add SDK version to browser about dialog

* feat: add sdk override to browser build

* fix: `npm ci` overriding the override

* fix: artifacts not properly downloaded

* fix: switch to new repository

* feat: add debug version function to web

* feat: add sdk-version to CLI

* feat: add version to desktop

* feat: add override to cli

* feat: add override to web

* fix: cli version acting as default command

* fix: consistent workflow input name

* feat: add error handling

* feat: upgrade sdk-internal

* fix: forgot to update package lock

* fix: broken CI build

move sdk version to a regular command

* chore: revert version changes

* refactor: move error handling code

* chore: bump SDK to 0.2.0.main-1

* fix: clean up references to inputs.sdk_commit

* refactor: rename `init` to `applyVersionToWindow`
This commit is contained in:
Andreas Coroiu 2024-11-19 13:59:59 +01:00 committed by GitHub
parent a07b072196
commit 33f7643e15
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 365 additions and 4 deletions

View File

@ -27,7 +27,11 @@ on:
workflow_call:
inputs: {}
workflow_dispatch:
inputs: {}
inputs:
sdk_branch:
description: "Custom SDK branch"
required: false
type: string
defaults:
run:
@ -168,6 +172,25 @@ jobs:
run: npm ci
working-directory: browser-source/
- name: Download SDK Artifacts
if: ${{ inputs.sdk_branch != '' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
artifacts: sdk-internal
repo: bitwarden/sdk-internal
path: sdk-internal
if_no_artifact_found: fail
- name: Override SDK
if: ${{ inputs.sdk_branch != '' }}
working-directory: browser-source/
run: |
npm link ../sdk-internal
- name: Build
run: npm run dist
working-directory: browser-source/apps/browser
@ -331,6 +354,25 @@ jobs:
run: npm ci
working-directory: ./
- name: Download SDK Artifacts
if: ${{ inputs.sdk_branch != '' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
artifacts: sdk-internal
repo: bitwarden/sdk-internal
path: ../sdk-internal
if_no_artifact_found: fail
- name: Override SDK
if: ${{ inputs.sdk_branch != '' }}
working-directory: ./
run: |
npm link ../sdk-internal
- name: Build Safari extension
run: npm run dist:safari
working-directory: apps/browser

View File

@ -28,7 +28,11 @@ on:
- '.github/workflows/build-cli.yml'
- 'bitwarden_license/bit-cli/**'
workflow_dispatch:
inputs: {}
inputs:
sdk_branch:
description: "Custom SDK branch"
required: false
type: string
defaults:
run:
@ -112,6 +116,26 @@ jobs:
run: npm ci
working-directory: ./
- name: Download SDK Artifacts
if: ${{ inputs.sdk_branch != '' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
artifacts: sdk-internal
repo: bitwarden/sdk-internal
path: ../sdk-internal
if_no_artifact_found: fail
- name: Override SDK
if: ${{ inputs.sdk_branch != '' }}
working-directory: ./
run: |
ls -l ../
npm link ../sdk-internal
- name: Build & Package Unix
run: npm run dist:${{ matrix.license_type.build_prefix }}:${{ env.SHORT_RUNNER_OS }} --quiet
@ -247,6 +271,26 @@ jobs:
run: npm ci
working-directory: ./
- name: Download SDK Artifacts
if: ${{ inputs.sdk_branch != '' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
artifacts: sdk-internal
repo: bitwarden/sdk-internal
path: ../sdk-internal
if_no_artifact_found: fail
- name: Override SDK
if: ${{ inputs.sdk_branch != '' }}
working-directory: ./
run: |
ls -l ../
npm link ../sdk-internal
- name: Build & Package Windows
run: npm run dist:${{ matrix.license_type.build_prefix }}:win --quiet

View File

@ -26,7 +26,11 @@ on:
- '!*.txt'
- '.github/workflows/build-desktop.yml'
workflow_dispatch:
inputs: {}
inputs:
sdk_branch:
description: "Custom SDK branch"
required: false
type: string
defaults:
run:
@ -182,6 +186,26 @@ jobs:
run: npm ci
working-directory: ./
- name: Download SDK Artifacts
if: ${{ inputs.sdk_branch != '' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
artifacts: sdk-internal
repo: bitwarden/sdk-internal
path: ../sdk-internal
if_no_artifact_found: fail
- name: Override SDK
if: ${{ inputs.sdk_branch != '' }}
working-directory: ./
run: |
ls -l ../
npm link ../sdk-internal
- name: Cache Native Module
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
id: cache
@ -328,6 +352,26 @@ jobs:
run: npm ci
working-directory: ./
- name: Download SDK Artifacts
if: ${{ inputs.sdk_branch != '' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
artifacts: sdk-internal
repo: bitwarden/sdk-internal
path: ../sdk-internal
if_no_artifact_found: fail
- name: Override SDK
if: ${{ inputs.sdk_branch != '' }}
working-directory: ./
run: |
ls -l ../
npm link ../sdk-internal
- name: Cache Native Module
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
id: cache
@ -616,6 +660,26 @@ jobs:
run: npm ci
working-directory: ./
- name: Download SDK Artifacts
if: ${{ inputs.sdk_branch != '' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
artifacts: sdk-internal
repo: bitwarden/sdk-internal
path: ../sdk-internal
if_no_artifact_found: fail
- name: Override SDK
if: ${{ inputs.sdk_branch != '' }}
working-directory: ./
run: |
ls -l ../
npm link ../sdk-internal
- name: Cache Native Module
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
id: cache
@ -784,6 +848,26 @@ jobs:
run: npm ci
working-directory: ./
- name: Download SDK Artifacts
if: ${{ inputs.sdk_branch != '' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
artifacts: sdk-internal
repo: bitwarden/sdk-internal
path: ../sdk-internal
if_no_artifact_found: fail
- name: Override SDK
if: ${{ inputs.sdk_branch != '' }}
working-directory: ./
run: |
ls -l ../
npm link ../sdk-internal
- name: Cache Native Module
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
id: cache
@ -1012,6 +1096,26 @@ jobs:
run: npm ci
working-directory: ./
- name: Download SDK Artifacts
if: ${{ inputs.sdk_branch != '' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
artifacts: sdk-internal
repo: bitwarden/sdk-internal
path: ../sdk-internal
if_no_artifact_found: fail
- name: Override SDK
if: ${{ inputs.sdk_branch != '' }}
working-directory: ./
run: |
ls -l ../
npm link ../sdk-internal
- name: Cache Native Module
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
id: cache
@ -1247,6 +1351,26 @@ jobs:
run: npm ci
working-directory: ./
- name: Download SDK Artifacts
if: ${{ inputs.sdk_branch != '' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
artifacts: sdk-internal
repo: bitwarden/sdk-internal
path: ../sdk-internal
if_no_artifact_found: fail
- name: Override SDK
if: ${{ inputs.sdk_branch != '' }}
working-directory: ./
run: |
ls -l ../
npm link ../sdk-internal
- name: Cache Native Module
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
id: cache

View File

@ -32,6 +32,10 @@ on:
custom_tag_extension:
description: "Custom image tag extension"
required: false
sdk_branch:
description: "Custom SDK branch"
required: false
type: string
env:
_AZ_REGISTRY: bitwardenprod.azurecr.io
@ -124,6 +128,26 @@ jobs:
- name: Install dependencies
run: npm ci
- name: Download SDK Artifacts
if: ${{ inputs.sdk_branch != '' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
artifacts: sdk-internal
repo: bitwarden/sdk-internal
path: ../sdk-internal
if_no_artifact_found: fail
- name: Override SDK
if: ${{ inputs.sdk_branch != '' }}
working-directory: ./
run: |
ls -l ../
npm link ../sdk-internal
- name: Add Git metadata to build version
working-directory: apps/web
if: matrix.git_metadata

View File

@ -6,6 +6,7 @@
<div bitDialogContent>
<p>&copy; Bitwarden Inc. 2015-{{ year }}</p>
<p class="user-select">{{ "version" | i18n }}: {{ version$ | async }}</p>
<p class="user-select">SDK: {{ sdkVersion$ | async }}</p>
<ng-container *ngIf="data$ | async as data">
<p *ngIf="data.isCloud">
{{ "serverVersion" | i18n }}: {{ data.serverConfig?.version }}

View File

@ -6,6 +6,7 @@ import { JslibModule } from "@bitwarden/angular/jslib.module";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service";
import { ButtonModule, DialogModule } from "@bitwarden/components";
@Component({
@ -22,10 +23,13 @@ export class AboutDialogComponent {
this.environmentService.environment$.pipe(map((env) => env.isCloud())),
]).pipe(map(([serverConfig, isCloud]) => ({ serverConfig, isCloud })));
protected sdkVersion$ = this.sdkService.version$;
constructor(
private configService: ConfigService,
private environmentService: EnvironmentService,
private platformUtilsService: PlatformUtilsService,
private sdkService: SdkService,
) {
this.version$ = defer(() => this.platformUtilsService.getApplicationVersion());
}

View File

@ -1,5 +1,6 @@
import * as chalk from "chalk";
import { program, Command, OptionValues } from "commander";
import { firstValueFrom } from "rxjs";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
@ -102,6 +103,14 @@ export class Program extends BaseProgram {
writeLn("", true);
});
program
.command("sdk-version")
.description("Print the SDK version.")
.action(async () => {
const sdkVersion = await firstValueFrom(this.serviceContainer.sdkService.version$);
writeLn(sdkVersion, true);
});
program
.command("login [email] [password]")
.description("Log into a user account.")

View File

@ -22,6 +22,7 @@ import { KeyService as KeyServiceAbstraction } from "@bitwarden/key-management";
import { I18nRendererService } from "../../platform/services/i18n.renderer.service";
import { SshAgentService } from "../../platform/services/ssh-agent.service";
import { VersionService } from "../../platform/services/version.service";
import { NativeMessagingService } from "../../services/native-messaging.service";
@Injectable()
@ -42,6 +43,7 @@ export class InitService {
private encryptService: EncryptService,
private userAutoUnlockKeyService: UserAutoUnlockKeyService,
private accountService: AccountService,
private versionService: VersionService,
private sshAgentService: SshAgentService,
@Inject(DOCUMENT) private document: Document,
) {}
@ -76,6 +78,8 @@ export class InitService {
htmlEl.classList.add("os_" + this.platformUtilsService.getDeviceString());
this.themingService.applyThemeChangesTo(this.document);
this.versionService.init();
const containerService = new ContainerService(this.keyService, this.encryptService);
containerService.attachToGlobal(this.win);
};

View File

@ -39,6 +39,7 @@ import { ClipboardMain } from "./platform/main/clipboard.main";
import { DesktopCredentialStorageListener } from "./platform/main/desktop-credential-storage-listener";
import { MainCryptoFunctionService } from "./platform/main/main-crypto-function.service";
import { MainSshAgentService } from "./platform/main/main-ssh-agent.service";
import { VersionMain } from "./platform/main/version.main";
import { DesktopSettingsService } from "./platform/services/desktop-settings.service";
import { ElectronLogMainService } from "./platform/services/electron-log.main.service";
import { ElectronStorageService } from "./platform/services/electron-storage.service";
@ -72,6 +73,7 @@ export class Main {
nativeMessagingMain: NativeMessagingMain;
clipboardMain: ClipboardMain;
desktopAutofillSettingsService: DesktopAutofillSettingsService;
versionMain: VersionMain;
sshAgentService: MainSshAgentService;
constructor() {
@ -199,6 +201,8 @@ export class Main {
});
});
this.versionMain = new VersionMain(this.windowMain);
this.powerMonitorMain = new PowerMonitorMain(this.messagingService, this.logService);
this.menuMain = new MenuMain(
this.i18nService,
@ -207,6 +211,7 @@ export class Main {
this.windowMain,
this.updaterMain,
this.desktopSettingsService,
this.versionMain,
);
this.biometricsService = new BiometricsService(

View File

@ -2,6 +2,7 @@ import { BrowserWindow, clipboard, dialog, MenuItemConstructorOptions } from "el
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { VersionMain } from "../../platform/main/version.main";
import { isMacAppStore, isSnapStore, isWindowsStore } from "../../utils";
import { UpdaterMain } from "../updater.main";
@ -22,17 +23,20 @@ export class AboutMenu implements IMenubarMenu {
private readonly _updater: UpdaterMain;
private readonly _window: BrowserWindow;
private readonly _version: string;
private readonly _versionMain: VersionMain;
constructor(
i18nService: I18nService,
version: string,
window: BrowserWindow,
updater: UpdaterMain,
versionMain: VersionMain,
) {
this._i18nService = i18nService;
this._updater = updater;
this._version = version;
this._window = window;
this._versionMain = versionMain;
}
private get separator(): MenuItemConstructorOptions {
@ -53,8 +57,11 @@ export class AboutMenu implements IMenubarMenu {
id: "aboutBitwarden",
label: this.localize("aboutBitwarden"),
click: async () => {
const sdkVersion = await this._versionMain.sdkVersion();
const aboutInformation =
this.localize("version", this._version) +
"\nSDK " +
sdkVersion +
"\nShell " +
process.versions.electron +
"\nRenderer " +

View File

@ -5,6 +5,7 @@ import { EnvironmentService } from "@bitwarden/common/platform/abstractions/envi
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { VersionMain } from "../../platform/main/version.main";
import { DesktopSettingsService } from "../../platform/services/desktop-settings.service";
import { UpdaterMain } from "../updater.main";
import { WindowMain } from "../window.main";
@ -22,6 +23,7 @@ export class MenuMain {
private windowMain: WindowMain,
private updaterMain: UpdaterMain,
private desktopSettingsService: DesktopSettingsService,
private versionMain: VersionMain,
) {}
async init() {
@ -44,6 +46,7 @@ export class MenuMain {
await this.getWebVaultUrl(),
app.getVersion(),
await firstValueFrom(this.desktopSettingsService.hardwareAcceleration$),
this.versionMain,
updateRequest,
).menu,
);

View File

@ -3,6 +3,7 @@ import { Menu, MenuItemConstructorOptions } from "electron";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { VersionMain } from "../../platform/main/version.main";
import { DesktopSettingsService } from "../../platform/services/desktop-settings.service";
import { isMac } from "../../utils";
import { UpdaterMain } from "../updater.main";
@ -54,6 +55,7 @@ export class Menubar {
webVaultUrl: string,
appVersion: string,
hardwareAccelerationEnabled: boolean,
versionMain: VersionMain,
updateRequest?: MenuUpdateRequest,
) {
let isLocked = true;
@ -96,7 +98,7 @@ export class Menubar {
desktopSettingsService,
webVaultUrl,
hardwareAccelerationEnabled,
new AboutMenu(i18nService, appVersion, windowMain.win, updaterMain),
new AboutMenu(i18nService, appVersion, windowMain.win, updaterMain, versionMain),
),
];

View File

@ -0,0 +1,17 @@
import { ipcMain } from "electron";
import { WindowMain } from "../../main/window.main";
export class VersionMain {
constructor(private windowMain: WindowMain) {}
sdkVersion() {
const timeout = new Promise((resolve) => setTimeout(() => resolve("Timeout error"), 1000));
const version = new Promise((resolve) => {
ipcMain.once("sdkVersion", (_, version) => resolve(version));
this.windowMain.win.webContents.send("sdkVersion");
});
return Promise.race([timeout, version]);
}
}

View File

@ -122,6 +122,13 @@ const localhostCallbackService = {
export default {
versions: {
app: (): Promise<string> => ipcRenderer.invoke("appVersion"),
registerSdkVersionProvider: (provide: (resolve: (version: string) => void) => void) => {
const resolve = (version: string) => ipcRenderer.send("sdkVersion", version);
ipcRenderer.on("sdkVersion", () => {
provide(resolve);
});
},
},
deviceType: deviceType(),
isDev: isDev(),

View File

@ -0,0 +1,18 @@
import { Injectable } from "@angular/core";
import { firstValueFrom } from "rxjs";
import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service";
@Injectable({
providedIn: "root",
})
export class VersionService {
constructor(private sdkService: SdkService) {}
init() {
ipc.platform.versions.registerSdkVersionProvider(async (resolve) => {
const version = await firstValueFrom(this.sdkService.version$);
resolve(version);
});
}
}

View File

@ -17,6 +17,8 @@ import { EventUploadService } from "@bitwarden/common/services/event/event-uploa
import { VaultTimeoutService } from "@bitwarden/common/services/vault-timeout/vault-timeout.service";
import { KeyService as KeyServiceAbstraction } from "@bitwarden/key-management";
import { VersionService } from "../platform/version.service";
@Injectable()
export class InitService {
constructor(
@ -32,6 +34,7 @@ export class InitService {
private encryptService: EncryptService,
private userAutoUnlockKeyService: UserAutoUnlockKeyService,
private accountService: AccountService,
private versionService: VersionService,
@Inject(DOCUMENT) private document: Document,
) {}
@ -54,6 +57,8 @@ export class InitService {
const htmlEl = this.win.document.documentElement;
htmlEl.classList.add("locale_" + this.i18nService.translationLocale);
this.themingService.applyThemeChangesTo(this.document);
this.versionService.applyVersionToWindow();
const containerService = new ContainerService(this.keyService, this.encryptService);
containerService.attachToGlobal(this.win);
};

View File

@ -0,0 +1,34 @@
import { Injectable } from "@angular/core";
import { catchError, firstValueFrom, map } from "rxjs";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service";
type Version = {
client: string;
sdk: string;
};
@Injectable({
providedIn: "root",
})
export class VersionService {
constructor(
private platformUtilsService: PlatformUtilsService,
private sdkService: SdkService,
) {}
applyVersionToWindow() {
(window as any).__version = async (): Promise<Version> => {
return {
client: await this.platformUtilsService.getApplicationVersion(),
sdk: await firstValueFrom(
this.sdkService.client$.pipe(
map((client) => client.version()),
catchError(() => "Unsupported"),
),
),
};
};
}
}

View File

@ -10,6 +10,11 @@ export abstract class SdkService {
*/
supported$: Observable<boolean>;
/**
* Retrieve the version of the SDK.
*/
version$: Observable<string>;
/**
* Retrieve a client initialized without a user.
* This client can only be used for operations that don't require a user context.

View File

@ -8,6 +8,7 @@ import {
distinctUntilChanged,
tap,
switchMap,
catchError,
} from "rxjs";
import { KeyService } from "@bitwarden/key-management";
@ -51,6 +52,11 @@ export class DefaultSdkService implements SdkService {
}),
);
version$ = this.client$.pipe(
map((client) => client.version()),
catchError(() => "Unsupported"),
);
constructor(
private sdkClientFactory: SdkClientFactory,
private environmentService: EnvironmentService,