Merge pull request #2 from DigitallyRefined/feature/unix-biometrics

Merge branch 'main' into feature/unix-biometrics
This commit is contained in:
Bernd Schoolmann 2024-04-26 00:44:43 +02:00 committed by GitHub
commit 74df3e5513
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3286 changed files with 310113 additions and 79173 deletions

12
.checkmarx/config.yml Normal file
View File

@ -0,0 +1,12 @@
version: 1
# Checkmarx configuration file
#
# https://checkmarx.com/resource/documents/en/34965-68549-configuring-projects-using-config-as-code-files.html
checkmarx:
scan:
configs:
sast:
presetName: "BW ASA Premium"
# Exclude spec files, and test specific files
filter: "!*.spec.ts,!**/spec/**,!apps/desktop/native-messaging-test-runner/**"

View File

@ -0,0 +1,14 @@
{
"usage": "Documentation: https://codescene.io/docs/guides/technical/code-health.html. Template: https://codescene.io/projects/26215/config/codehealth/export/code-health-rules.json",
"rule_sets": [
{
"matching_content_path": "**/*.spec.ts",
"rules": [
{
"name": "Code Duplication",
"weight": 0.0
}
]
}
]
}

View File

@ -12,14 +12,12 @@ storybook-static
apps/browser/config/config.js apps/browser/config/config.js
apps/browser/src/auth/scripts/duo.js apps/browser/src/auth/scripts/duo.js
apps/browser/src/autofill/content/autofill.js
apps/desktop/desktop_native apps/desktop/desktop_native
apps/desktop/src/auth/scripts/duo.js apps/desktop/src/auth/scripts/duo.js
apps/web/config.js apps/web/config.js
apps/web/scripts/*.js apps/web/scripts/*.js
apps/web/src/theme.js
apps/web/tailwind.config.js apps/web/tailwind.config.js
apps/cli/config/config.js apps/cli/config/config.js

View File

@ -20,7 +20,8 @@
"plugin:import/recommended", "plugin:import/recommended",
"plugin:import/typescript", "plugin:import/typescript",
"prettier", "prettier",
"plugin:rxjs/recommended" "plugin:rxjs/recommended",
"plugin:storybook/recommended"
], ],
"settings": { "settings": {
"import/parsers": { "import/parsers": {
@ -33,20 +34,15 @@
} }
}, },
"rules": { "rules": {
"@typescript-eslint/no-explicit-any": "off", // TODO: This should be re-enabled
"@typescript-eslint/no-unused-vars": ["error", { "args": "none" }],
"@typescript-eslint/explicit-member-accessibility": [ "@typescript-eslint/explicit-member-accessibility": [
"error", "error",
{ { "accessibility": "no-public" }
"accessibility": "no-public"
}
],
"@typescript-eslint/no-this-alias": [
"error",
{
"allowedNames": ["self"]
}
], ],
"@typescript-eslint/no-explicit-any": "off", // TODO: This should be re-enabled
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-misused-promises": ["error", { "checksVoidReturn": false }],
"@typescript-eslint/no-this-alias": ["error", { "allowedNames": ["self"] }],
"@typescript-eslint/no-unused-vars": ["error", { "args": "none" }],
"no-console": "error", "no-console": "error",
"import/no-unresolved": "off", // TODO: Look into turning off once each package is an actual package. "import/no-unresolved": "off", // TODO: Look into turning off once each package is an actual package.
"import/order": [ "import/order": [
@ -71,7 +67,7 @@
"pathGroupsExcludedImportTypes": ["builtin"] "pathGroupsExcludedImportTypes": ["builtin"]
} }
], ],
"rxjs-angular/prefer-takeuntil": "error", "rxjs-angular/prefer-takeuntil": ["error", { "alias": ["takeUntilDestroyed"] }],
"rxjs/no-exposed-subjects": ["error", { "allowProtected": true }], "rxjs/no-exposed-subjects": ["error", { "allowProtected": true }],
"no-restricted-syntax": [ "no-restricted-syntax": [
"error", "error",
@ -103,16 +99,26 @@
// Import/export // Import/export
"./libs/importer/**/*", "./libs/importer/**/*",
"./libs/exporter/**/*" "./libs/tools/export/vault-export/vault-export-core/**/*"
] ]
},
{
// avoid import of unexported state objects
"target": [
"!(libs)/**/*",
"libs/!(common)/**/*",
"libs/common/!(src)/**/*",
"libs/common/src/!(platform)/**/*",
"libs/common/src/platform/!(state)/**/*"
],
"from": ["./libs/common/src/platform/state/**/*"],
// allow module index import
"except": ["**/state/index.ts"]
} }
] ]
} }
], ],
"no-restricted-imports": [ "no-restricted-imports": ["error", { "patterns": ["src/**/*"] }]
"error",
{ "patterns": ["src/**/*"], "paths": ["@fluffy-spoon/substitute"] }
]
} }
}, },
{ {
@ -134,6 +140,15 @@
"tailwindcss/no-contradicting-classname": "error" "tailwindcss/no-contradicting-classname": "error"
} }
}, },
{
"files": ["libs/admin-console/src/**/*.ts"],
"rules": {
"no-restricted-imports": [
"error",
{ "patterns": ["@bitwarden/admin-console/*", "src/**/*"] }
]
}
},
{ {
"files": ["libs/angular/src/**/*.ts"], "files": ["libs/angular/src/**/*.ts"],
"rules": { "rules": {
@ -146,6 +161,12 @@
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/auth/*", "src/**/*"] }] "no-restricted-imports": ["error", { "patterns": ["@bitwarden/auth/*", "src/**/*"] }]
} }
}, },
{
"files": ["libs/billing/src/**/*.ts"],
"rules": {
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/billing/*", "src/**/*"] }]
}
},
{ {
"files": ["libs/common/src/**/*.ts"], "files": ["libs/common/src/**/*.ts"],
"rules": { "rules": {
@ -155,13 +176,28 @@
{ {
"files": ["libs/components/src/**/*.ts"], "files": ["libs/components/src/**/*.ts"],
"rules": { "rules": {
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/components/*", "src/**/*"] }] "no-restricted-imports": [
"error",
{ "patterns": ["@bitwarden/components/*", "src/**/*", "@bitwarden/angular/*"] }
]
} }
}, },
{ {
"files": ["libs/exporter/src/**/*.ts"], "files": ["libs/tools/export/vault-export/vault-export-core/src/**/*.ts"],
"rules": { "rules": {
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/exporter/*", "src/**/*"] }] "no-restricted-imports": [
"error",
{ "patterns": ["@bitwarden/vault-export-core/*", "src/**/*"] }
]
}
},
{
"files": ["libs/tools/export/vault-export/vault-export-ui/src/**/*.ts"],
"rules": {
"no-restricted-imports": [
"error",
{ "patterns": ["@bitwarden/vault-export-ui/*", "src/**/*"] }
]
} }
}, },
{ {
@ -175,6 +211,41 @@
"rules": { "rules": {
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/node/*", "src/**/*"] }] "no-restricted-imports": ["error", { "patterns": ["@bitwarden/node/*", "src/**/*"] }]
} }
},
{
"files": ["libs/platform/src/**/*.ts"],
"rules": {
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/platform/*", "src/**/*"] }]
}
},
{
"files": ["libs/vault/src/**/*.ts"],
"rules": {
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/vault/*", "src/**/*"] }]
}
},
{
"files": ["apps/browser/src/**/*.ts", "libs/**/*.ts"],
"excludedFiles": [
"apps/browser/src/autofill/{content,notification}/**/*.ts",
"apps/browser/src/**/background/**/*.ts", // It's okay to have long lived listeners in the background
"apps/browser/src/platform/background.ts"
],
"rules": {
"no-restricted-syntax": [
"error",
{
"message": "Using addListener in the browser popup produces a memory leak in Safari, use `BrowserApi.addListener` instead",
// This selector covers events like chrome.storage.onChange & chrome.runtime.onMessage
"selector": "CallExpression > [object.object.object.name='chrome'][property.name='addListener']"
},
{
"message": "Using addListener in the browser popup produces a memory leak in Safari, use `BrowserApi.addListener` instead",
// This selector covers events like chrome.storage.local.onChange
"selector": "CallExpression > [object.object.object.object.name='chrome'][property.name='addListener']"
}
]
}
} }
] ]
} }

View File

@ -22,3 +22,6 @@
193434461dbd9c48fe5dcbad95693470aec422ac 193434461dbd9c48fe5dcbad95693470aec422ac
# Jslib: Monorepository https://github.com/bitwarden/clients/pull/2824/commits/d7492e3cf320410e74ebd0e0675ab994e64bd01a # Jslib: Monorepository https://github.com/bitwarden/clients/pull/2824/commits/d7492e3cf320410e74ebd0e0675ab994e64bd01a
d7492e3cf320410e74ebd0e0675ab994e64bd01a d7492e3cf320410e74ebd0e0675ab994e64bd01a
# All Clients: Apply Prettier https://github.com/bitwarden/clients/pull/7014
28de9439beb87133c8683434df952a0c0be94100

57
.github/CODEOWNERS vendored
View File

@ -1,11 +1,9 @@
# Please sort lines alphabetically, this will ensure we don't accidentally add duplicates. # Please sort into logical groups with comment headers. Sort groups in order of specificity.
# For example, default owners should always be the first group.
# Sort lines alphabetically within these groups to avoid accidentally adding duplicates.
# #
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
# The following owners will be the default owners for everything in the repo.
# Unless a later match takes precedence
* @bitwarden/team-leads-eng
## Secrets Manager team files ## ## Secrets Manager team files ##
bitwarden_license/bit-web/src/app/secrets-manager @bitwarden/team-secrets-manager-dev bitwarden_license/bit-web/src/app/secrets-manager @bitwarden/team-secrets-manager-dev
@ -29,8 +27,15 @@ apps/web/src/app/tools @bitwarden/team-tools-dev
libs/angular/src/tools @bitwarden/team-tools-dev libs/angular/src/tools @bitwarden/team-tools-dev
libs/common/src/models/export @bitwarden/team-tools-dev libs/common/src/models/export @bitwarden/team-tools-dev
libs/common/src/tools @bitwarden/team-tools-dev libs/common/src/tools @bitwarden/team-tools-dev
libs/exporter @bitwarden/team-tools-dev
libs/importer @bitwarden/team-tools-dev libs/importer @bitwarden/team-tools-dev
libs/tools @bitwarden/team-tools-dev
## Localization/Crowdin (Tools team)
apps/browser/src/_locales @bitwarden/team-tools-dev
apps/browser/store/locales @bitwarden/team-tools-dev
apps/cli/src/locales @bitwarden/team-tools-dev
apps/desktop/src/locales @bitwarden/team-tools-dev
apps/web/src/locales @bitwarden/team-tools-dev
## Vault team files ## ## Vault team files ##
apps/browser/src/vault @bitwarden/team-vault-dev apps/browser/src/vault @bitwarden/team-vault-dev
@ -39,6 +44,7 @@ apps/desktop/src/vault @bitwarden/team-vault-dev
apps/web/src/app/vault @bitwarden/team-vault-dev apps/web/src/app/vault @bitwarden/team-vault-dev
libs/angular/src/vault @bitwarden/team-vault-dev libs/angular/src/vault @bitwarden/team-vault-dev
libs/common/src/vault @bitwarden/team-vault-dev libs/common/src/vault @bitwarden/team-vault-dev
libs/vault @bitwarden/team-vault-dev
## Admin Console team files ## ## Admin Console team files ##
apps/browser/src/admin-console @bitwarden/team-admin-console-dev apps/browser/src/admin-console @bitwarden/team-admin-console-dev
@ -48,11 +54,14 @@ apps/web/src/app/admin-console @bitwarden/team-admin-console-dev
bitwarden_license/bit-web/src/app/admin-console @bitwarden/team-admin-console-dev bitwarden_license/bit-web/src/app/admin-console @bitwarden/team-admin-console-dev
libs/angular/src/admin-console @bitwarden/team-admin-console-dev libs/angular/src/admin-console @bitwarden/team-admin-console-dev
libs/common/src/admin-console @bitwarden/team-admin-console-dev libs/common/src/admin-console @bitwarden/team-admin-console-dev
libs/admin-console @bitwarden/team-admin-console-dev
## Billing team files ## ## Billing team files ##
apps/web/src/app/billing @bitwarden/team-billing-dev apps/web/src/app/billing @bitwarden/team-billing-dev
libs/angular/src/billing @bitwarden/team-billing-dev libs/angular/src/billing @bitwarden/team-billing-dev
libs/common/src/billing @bitwarden/team-billing-dev libs/common/src/billing @bitwarden/team-billing-dev
libs/billing @bitwarden/team-billing-dev
bitwarden_license/bit-web/src/app/billing @bitwarden/team-billing-dev
## Platform team files ## ## Platform team files ##
apps/browser/src/platform @bitwarden/team-platform-dev apps/browser/src/platform @bitwarden/team-platform-dev
@ -61,6 +70,9 @@ apps/desktop/src/platform @bitwarden/team-platform-dev
apps/web/src/app/platform @bitwarden/team-platform-dev apps/web/src/app/platform @bitwarden/team-platform-dev
libs/angular/src/platform @bitwarden/team-platform-dev libs/angular/src/platform @bitwarden/team-platform-dev
libs/common/src/platform @bitwarden/team-platform-dev libs/common/src/platform @bitwarden/team-platform-dev
libs/common/spec @bitwarden/team-platform-dev
libs/common/src/state-migrations @bitwarden/team-platform-dev
libs/platform @bitwarden/team-platform-dev
# Node-specifc platform files # Node-specifc platform files
libs/node @bitwarden/team-platform-dev libs/node @bitwarden/team-platform-dev
# Web utils used across app and connectors # Web utils used across app and connectors
@ -72,34 +84,29 @@ apps/web/src/translation-constants.ts @bitwarden/team-platform-dev
## Autofill team files ## ## Autofill team files ##
apps/browser/src/autofill @bitwarden/team-autofill-dev apps/browser/src/autofill @bitwarden/team-autofill-dev
apps/desktop/src/autofill @bitwarden/team-autofill-dev
libs/common/src/autofill @bitwarden/team-autofill-dev
## Component Library ## ## Component Library ##
libs/components @bitwarden/team-platform-dev .storybook @bitwarden/team-component-library
libs/components @bitwarden/team-component-library
apps/web/src/app/layouts/header
## Desktop native module ## ## Desktop native module ##
apps/desktop/desktop_native @bitwarden/team-platform-dev apps/desktop/desktop_native @bitwarden/team-platform-dev
## Multiple file owners ## ## DevOps team files ##
apps/browser/package.json /.github/workflows @bitwarden/dept-devops
apps/browser/src/manifest.json
apps/browser/src/manifest.v3.json
apps/cli/package.json # DevOps for Docker changes.
**/Dockerfile @bitwarden/dept-devops
**/*.Dockerfile @bitwarden/dept-devops
**/.dockerignore @bitwarden/dept-devops
**/entrypoint.sh @bitwarden/dept-devops
apps/desktop/package.json ## Locales ##
apps/desktop/src/package-lock.json
apps/desktop/src/package.json
/apps/web/config
/apps/web/package.json
package-lock.json
## Locales ##
apps/browser/src/_locales/en/messages.json apps/browser/src/_locales/en/messages.json
apps/browser/store/locales/en
apps/cli/src/locales/en/messages.json apps/cli/src/locales/en/messages.json
apps/desktop/src/locales/en/messages.json apps/desktop/src/locales/en/messages.json
apps/web/src/locales/en/messages.json apps/web/src/locales/en/messages.json
## DevOps team files ##
/.github/workflows @bitwarden/dept-devops

View File

@ -90,4 +90,4 @@ body:
description: | description: |
Issue tracking information Issue tracking information
options: options:
- label: I understand that work is tracked outside of Github. A PR will be linked to this issue should one be opened to address it, but Bitwarden doesn't use fields like "assigned", "milestone", or "project" to track progress. - label: I understand that work is tracked outside of GitHub. A PR will be linked to this issue should one be opened to address it, but Bitwarden doesn't use fields like "assigned", "milestone", or "project" to track progress.

2
.github/codecov.yml vendored Normal file
View File

@ -0,0 +1,2 @@
ignore:
- "**/*.spec.ts" # Tests

271
.github/renovate.json vendored
View File

@ -1,55 +1,266 @@
{ {
"$schema": "https://docs.renovatebot.com/renovate-schema.json", "$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [ "extends": ["github>bitwarden/renovate-config"],
"config:base",
":combinePatchMinorReleases",
":dependencyDashboard",
":maintainLockFilesWeekly",
":pinAllExceptPeerDependencies",
":rebaseStalePrs",
"schedule:weekends",
":separateMajorReleases"
],
"prConcurrentLimit": 3,
"enabledManagers": ["cargo", "github-actions", "npm"], "enabledManagers": ["cargo", "github-actions", "npm"],
"packageRules": [ "packageRules": [
{
"groupName": "cargo minor",
"matchManagers": ["cargo"],
"matchUpdateTypes": ["minor", "patch"]
},
{ {
"groupName": "gh minor", "groupName": "gh minor",
"matchManagers": ["github-actions"], "matchManagers": ["github-actions"],
"matchUpdateTypes": ["minor", "patch"] "matchUpdateTypes": ["minor", "patch"]
}, },
{ {
"groupName": "npm minor", "matchManagers": ["github-actions"],
"matchManagers": ["npm"], "commitMessagePrefix": "[deps] DevOps:"
"matchUpdateTypes": ["minor", "patch"]
}, },
{ {
"matchPackageNames": ["typescript"], "matchManagers": ["cargo"],
"commitMessagePrefix": "[deps] Platform:"
},
{
"groupName": "napi",
"matchPackageNames": ["napi", "napi-build", "napi-derive"]
},
{
"matchPackageNames": ["typescript", "zone.js"],
"matchUpdateTypes": ["major", "minor"], "matchUpdateTypes": ["major", "minor"],
"description": "Determined by Angular",
"enabled": false "enabled": false
}, },
{ {
"matchPackageNames": ["typescript"], "matchPackageNames": ["typescript", "zone.js"],
"matchUpdateTypes": "patch" "matchUpdateTypes": "patch"
}, },
{ {
"groupName": "jest", "groupName": "jest",
"matchPackageNames": ["@types/jest", "jest", "ts-jest", "jest-preset-angular"], "matchPackageNames": ["@types/jest", "jest", "ts-jest", "jest-preset-angular"],
"matchUpdateTypes": "major" "matchUpdateTypes": "major"
},
{
"matchPackageNames": [
"@ngtools/webpack",
"base64-loader",
"buffer",
"bufferutil",
"copy-webpack-plugin",
"core-js",
"css-loader",
"html-loader",
"html-webpack-injector",
"html-webpack-plugin",
"mini-css-extract-plugin",
"ngx-infinite-scroll",
"postcss",
"postcss-loader",
"process",
"sass",
"sass-loader",
"style-loader",
"ts-loader",
"tsconfig-paths-webpack-plugin",
"url",
"util",
"webpack",
"webpack-cli",
"webpack-dev-server",
"webpack-node-externals"
],
"description": "Admin Console owned dependencies",
"commitMessagePrefix": "[deps] AC:",
"reviewers": ["team:team-admin-console-dev"]
},
{
"matchPackageNames": [
"@types/duo_web_sdk",
"@types/node-ipc",
"duo_web_sdk",
"node-ipc",
"qrious",
"regedit"
],
"description": "Auth owned dependencies",
"commitMessagePrefix": "[deps] Auth:",
"reviewers": ["team:team-auth-dev"]
},
{
"matchPackageNames": [
"@webcomponents/custom-elements",
"concurrently",
"cross-env",
"del",
"gulp",
"gulp-filter",
"gulp-if",
"gulp-json-editor",
"gulp-replace",
"gulp-zip",
"nord",
"patch-package",
"prettier",
"prettier-plugin-tailwindcss",
"rimraf",
"tabbable",
"tldts",
"wait-on"
],
"description": "Autofill owned dependencies",
"commitMessagePrefix": "[deps] Autofill:",
"reviewers": ["team:team-autofill-dev"]
},
{
"matchPackageNames": ["braintree-web-drop-in"],
"description": "Billing owned dependencies",
"commitMessagePrefix": "[deps] Billing:",
"reviewers": ["team:team-billing-dev"]
},
{
"matchPackageNames": [
"@angular-devkit/build-angular",
"@angular/animations",
"@angular/cdk",
"@angular/cli",
"@angular/common",
"@angular/compiler",
"@angular/compiler-cli",
"@angular/core",
"@angular/forms",
"@angular/platform",
"@angular/compiler",
"@angular/router",
"@types/argon2-browser",
"@types/chrome",
"@types/firefox-webext-browser",
"@types/jquery",
"@types/node",
"@types/node-forge",
"argon2",
"argon2-browser",
"big-integer",
"bootstrap",
"jquery",
"node-forge",
"popper.js",
"rxjs",
"type-fest",
"typescript",
"zone.js"
],
"description": "Platform owned dependencies",
"commitMessagePrefix": "[deps] Platform:",
"reviewers": ["team:team-platform-dev"]
},
{
"matchPackageNames": [
"@compodoc/compodoc",
"@ng-select/ng-select",
"@storybook/addon-a11y",
"@storybook/addon-actions",
"@storybook/addon-designs",
"@storybook/addon-essentials",
"@storybook/addon-links",
"@storybook/angular",
"@types/react",
"autoprefixer",
"chromatic",
"ngx-toastr",
"react",
"react-dom",
"remark-gfm",
"storybook",
"tailwindcss"
],
"description": "Component library owned dependencies",
"commitMessagePrefix": "[deps] Platform (CL):",
"reviewers": ["team:team-component-library"]
},
{
"matchPackageNames": [
"@angular-eslint/eslint-plugin",
"@angular-eslint/eslint-plugin-template",
"@angular-eslint/template-parser",
"@types/jest",
"@typescript-eslint/eslint-plugin",
"@typescript-eslint/parser",
"eslint",
"eslint-config-prettier",
"eslint-import-resolver-typescript",
"eslint-plugin-import",
"eslint-plugin-rxjs",
"eslint-plugin-rxjs-angular",
"eslint-plugin-storybook",
"eslint-plugin-tailwindcss",
"husky",
"jest-junit",
"jest-mock-extended",
"jest-preset-angular",
"lint-staged",
"ts-jest"
],
"description": "Secrets Manager owned dependencies",
"commitMessagePrefix": "[deps] SM:",
"reviewers": ["team:team-secrets-manager-dev"]
},
{
"matchPackageNames": [
"@electron/notarize",
"@electron/rebuild",
"@microsoft/signalr-protocol-msgpack",
"@microsoft/signalr",
"@types/jsdom",
"@types/papaparse",
"@types/zxcvbn",
"electron-builder",
"electron-log",
"electron-reload",
"electron-store",
"electron-updater",
"electron",
"jsdom",
"jszip",
"oidc-client-ts",
"papaparse",
"utf-8-validate",
"zxcvbn"
],
"description": "Tools owned dependencies",
"commitMessagePrefix": "[deps] Tools:",
"reviewers": ["team:team-tools-dev"]
},
{
"matchPackageNames": [
"@koa/multer",
"@koa/router",
"@types/inquirer",
"@types/koa",
"@types/koa__multer",
"@types/koa__router",
"@types/koa-bodyparser",
"@types/koa-json",
"@types/lowdb",
"@types/lunr",
"@types/node-fetch",
"@types/proper-lockfile",
"@types/retry",
"chalk",
"commander",
"form-data",
"https-proxy-agent",
"inquirer",
"koa",
"koa-bodyparser",
"koa-json",
"lowdb",
"lunr",
"multer",
"node-fetch",
"open",
"pkg",
"proper-lockfile",
"qrcode-parser"
],
"description": "Vault owned dependencies",
"commitMessagePrefix": "[deps] Vault:",
"reviewers": ["team:team-vault-dev"]
} }
], ],
"ignoreDeps": [ "ignoreDeps": ["@types/koa-bodyparser", "bootstrap", "node-ipc", "node", "npm", "regedit"]
"@types/koa-bodyparser",
"bootstrap",
"electron-builder",
"electron",
"node-ipc",
"regedit",
"zone.js"
]
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -2,10 +2,7 @@
./apps/browser/src/safari/desktop/Assets.xcassets/AccentColor.colorset ./apps/browser/src/safari/desktop/Assets.xcassets/AccentColor.colorset
./apps/browser/src/safari/desktop/Assets.xcassets/AppIcon.appiconset ./apps/browser/src/safari/desktop/Assets.xcassets/AppIcon.appiconset
./apps/browser/src/safari/desktop/Base.lproj ./apps/browser/src/safari/desktop/Base.lproj
./apps/browser/src/services/vaultTimeout
./apps/browser/store/windows/Assets ./apps/browser/store/windows/Assets
./libs/common/src/abstractions/vaultTimeout
./libs/common/src/services/vaultTimeout
./bitwarden_license/README.md ./bitwarden_license/README.md
./libs/angular/src/directives/cipherListVirtualScroll.directive.ts ./libs/angular/src/directives/cipherListVirtualScroll.directive.ts
./libs/angular/src/scss/webfonts/Open_Sans-italic-700.woff ./libs/angular/src/scss/webfonts/Open_Sans-italic-700.woff
@ -18,20 +15,13 @@
./libs/angular/src/scss/webfonts/Open_Sans-normal-600.woff ./libs/angular/src/scss/webfonts/Open_Sans-normal-600.woff
./libs/angular/src/scss/webfonts/Open_Sans-normal-800.woff ./libs/angular/src/scss/webfonts/Open_Sans-normal-800.woff
./libs/angular/src/scss/webfonts/Open_Sans-normal-400.woff ./libs/angular/src/scss/webfonts/Open_Sans-normal-400.woff
./libs/angular/src/validators/inputsFieldMatch.validator.ts ./libs/admin-console/README.md
./libs/angular/src/validators/notAllowedValueAsync.validator.ts
./libs/angular/src/services/theming/themeBuilder.ts
./libs/common/src/misc/nodeUtils.ts
./libs/common/src/misc/linkedFieldOption.decorator.ts
./libs/common/src/misc/serviceUtils.ts
./libs/common/src/misc/serviceUtils.spec.ts
./libs/common/src/abstractions/vaultTimeout/vaultTimeoutSettings.service.ts
./libs/common/src/abstractions/vaultTimeout/vaultTimeout.service.ts
./libs/common/src/abstractions/anonymousHub.service.ts
./libs/common/src/services/vaultTimeout/vaultTimeoutSettings.service.ts
./libs/common/src/services/vaultTimeout/vaultTimeout.service.ts
./libs/common/src/services/anonymousHub.service.ts
./libs/auth/README.md ./libs/auth/README.md
./libs/billing/README.md
./libs/platform/README.md
./libs/tools/README.md
./libs/tools/export/vault-export/README.md
./libs/vault/README.md
./README.md ./README.md
./LICENSE_BITWARDEN.txt ./LICENSE_BITWARDEN.txt
./CONTRIBUTING.md ./CONTRIBUTING.md
@ -54,15 +44,6 @@
./apps/browser/README.md ./apps/browser/README.md
./apps/browser/store/windows/AppxManifest.xml ./apps/browser/store/windows/AppxManifest.xml
./apps/browser/src/background/nativeMessaging.background.ts ./apps/browser/src/background/nativeMessaging.background.ts
./apps/browser/src/background/models/addLoginRuntimeMessage.ts
./apps/browser/src/background/models/addChangePasswordQueueMessage.ts
./apps/browser/src/background/models/addLoginQueueMessage.ts
./apps/browser/src/background/models/changePasswordRuntimeMessage.ts
./apps/browser/src/background/models/notificationQueueMessage.ts
./apps/browser/src/background/models/notificationQueueMessageType.ts
./apps/browser/src/background/models/lockedVaultPendingNotificationsItem.ts
./apps/browser/src/background/webRequest.background.ts
./apps/browser/src/popup/services/debounceNavigationService.ts
./apps/browser/src/models/browserComponentState.ts ./apps/browser/src/models/browserComponentState.ts
./apps/browser/src/models/browserSendComponentState.ts ./apps/browser/src/models/browserSendComponentState.ts
./apps/browser/src/models/browserGroupingsComponentState.ts ./apps/browser/src/models/browserGroupingsComponentState.ts
@ -78,5 +59,4 @@
./apps/browser/src/safari/safari/SafariWebExtensionHandler.swift ./apps/browser/src/safari/safari/SafariWebExtensionHandler.swift
./apps/browser/src/safari/safari/Info.plist ./apps/browser/src/safari/safari/Info.plist
./apps/browser/src/safari/desktop.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ./apps/browser/src/safari/desktop.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
./apps/browser/src/services/vaultTimeout/vaultTimeout.service.ts
./SECURITY.md ./SECURITY.md

View File

@ -4,7 +4,7 @@ name: Auto Update Branch
on: on:
push: push:
branches: branches:
- 'master' - 'main'
- 'rc' - 'rc'
paths: paths:
- 'apps/web/**' - 'apps/web/**'
@ -29,7 +29,7 @@ jobs:
run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with: with:
ref: 'eu-web-${{ steps.setup.outputs.branch }}' ref: 'eu-web-${{ steps.setup.outputs.branch }}'
fetch-depth: 0 fetch-depth: 0

View File

@ -7,7 +7,7 @@ on:
jobs: jobs:
close-issue: close-issue:
name: 'Close issue with automatic response' name: 'Close issue with automatic response'
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
permissions: permissions:
issues: write issues: write
steps: steps:

View File

@ -7,7 +7,7 @@ on:
jobs: jobs:
close-issue: close-issue:
name: 'Close pull request with automatic response' name: 'Close pull request with automatic response'
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
permissions: permissions:
pull-requests: write pull-requests: write
steps: steps:

View File

@ -14,22 +14,22 @@ defaults:
jobs: jobs:
update-desktop-cask: update-desktop-cask:
name: Update Bitwarden CLI Formula name: Update Bitwarden CLI Formula
runs-on: macos-11 runs-on: macos-13
steps: steps:
- name: Login to Azure - name: Login to Azure
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "brew-bump-workflow-pat" secrets: "brew-bump-workflow-pat"
- name: Update Homebrew formula - name: Update Homebrew formula
uses: dawidd6/action-homebrew-bump-formula@d3667e5ae14df19579e4414897498e3e88f2f458 # v3.10.0 uses: dawidd6/action-homebrew-bump-formula@baf2b60c51fc1f8453c884b0c61052668a71bd1d # v3.11.0
with: with:
# Required, custom GitHub access token with the 'public_repo' and 'workflow' scopes # Required, custom GitHub access token with the 'public_repo' and 'workflow' scopes
token: ${{ steps.retrieve-secrets.outputs.brew-bump-workflow-pat }} token: ${{ steps.retrieve-secrets.outputs.brew-bump-workflow-pat }}
@ -38,4 +38,4 @@ jobs:
formula: bitwarden-cli formula: bitwarden-cli
tag: ${{ github.ref }} tag: ${{ github.ref }}
revision: ${{ github.sha }} revision: ${{ github.sha }}
force: false force: true

View File

@ -14,16 +14,16 @@ defaults:
jobs: jobs:
update-desktop-cask: update-desktop-cask:
name: Update Bitwarden Desktop Cask name: Update Bitwarden Desktop Cask
runs-on: macos-11 runs-on: macos-13
steps: steps:
- name: Login to Azure - name: Login to Azure
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "brew-bump-workflow-pat" secrets: "brew-bump-workflow-pat"
@ -38,5 +38,5 @@ jobs:
cask: bitwarden cask: bitwarden
tag: ${{ github.ref }} tag: ${{ github.ref }}
revision: ${{ github.sha }} revision: ${{ github.sha }}
force: false force: true
dryrun: true dryrun: true

View File

@ -10,19 +10,17 @@ on:
- 'apps/browser/**' - 'apps/browser/**'
- 'libs/**' - 'libs/**'
- '*' - '*'
- '!libs/importer'
- '!*.md' - '!*.md'
- '!*.txt' - '!*.txt'
push: push:
branches: branches:
- 'master' - 'main'
- 'rc' - 'rc'
- 'hotfix-rc-browser' - 'hotfix-rc-browser'
paths: paths:
- 'apps/browser/**' - 'apps/browser/**'
- 'libs/**' - 'libs/**'
- '*' - '*'
- '!libs/importer'
- '!*.md' - '!*.md'
- '!*.txt' - '!*.txt'
- '.github/workflows/build-browser.yml' - '.github/workflows/build-browser.yml'
@ -36,29 +34,17 @@ defaults:
shell: bash shell: bash
jobs: jobs:
cloc:
name: CLOC
runs-on: ubuntu-20.04
steps:
- name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- name: Set up cloc
run: |
sudo apt update
sudo apt -y install cloc
- name: Print lines of code
run: cloc --include-lang TypeScript,JavaScript,HTML,Sass,CSS --vcs git
setup: setup:
name: Setup name: Setup
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
outputs: outputs:
repo_url: ${{ steps.gen_vars.outputs.repo_url }} repo_url: ${{ steps.gen_vars.outputs.repo_url }}
adj_build_number: ${{ steps.gen_vars.outputs.adj_build_number }} adj_build_number: ${{ steps.gen_vars.outputs.adj_build_number }}
node_version: ${{ steps.retrieve-node-version.outputs.node_version }}
steps: steps:
- name: Checkout repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Get Package Version - name: Get Package Version
id: gen_vars id: gen_vars
run: | run: |
@ -68,10 +54,18 @@ jobs:
echo "repo_url=$repo_url" >> $GITHUB_OUTPUT echo "repo_url=$repo_url" >> $GITHUB_OUTPUT
echo "adj_build_number=$adj_build_num" >> $GITHUB_OUTPUT echo "adj_build_number=$adj_build_num" >> $GITHUB_OUTPUT
- name: Get Node Version
id: retrieve-node-version
working-directory: ./
run: |
NODE_NVMRC=$(cat .nvmrc)
NODE_VERSION=${NODE_NVMRC/v/''}
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
locales-test: locales-test:
name: Locales Test name: Locales Test
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
needs: needs:
- setup - setup
defaults: defaults:
@ -79,7 +73,7 @@ jobs:
working-directory: apps/browser working-directory: apps/browser
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Testing locales - extName length - name: Testing locales - extName length
run: | run: |
@ -108,121 +102,123 @@ jobs:
build: build:
name: Build name: Build
runs-on: windows-2019 runs-on: ubuntu-22.04
needs: needs:
- setup - setup
- locales-test - locales-test
env: env:
_BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }} _BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }}
defaults: _NODE_VERSION: ${{ needs.setup.outputs.node_version }}
run:
working-directory: apps/browser
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up Node - name: Set up Node
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with: with:
cache: 'npm' cache: 'npm'
cache-dependency-path: '**/package-lock.json' cache-dependency-path: '**/package-lock.json'
node-version: '18' node-version: ${{ env._NODE_VERSION }}
- name: Install node-gyp
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Print environment - name: Print environment
run: | run: |
node --version node --version
npm --version npm --version
- name: Build sources for reviewers
run: |
# Include hidden files in glob copy
shopt -s dotglob
# Remove ".git" directory
rm -r .git
# Copy root level files to source directory
mkdir browser-source
FILES=$(find . -maxdepth 1 -type f)
for FILE in $FILES; do cp "$FILE" browser-source/; done
# Copy patches to the Browser source directory
mkdir -p browser-source/patches
cp -r patches/* browser-source/patches
# Copy apps/browser to the Browser source directory
mkdir -p browser-source/apps/browser
cp -r apps/browser/* browser-source/apps/browser
# Copy libs to Browser source directory
mkdir browser-source/libs
cp -r libs/* browser-source/libs
zip -r browser-source.zip browser-source
- name: NPM setup - name: NPM setup
run: npm ci run: npm ci
working-directory: ./ working-directory: browser-source/
- name: Build - name: Build
run: npm run dist run: npm run dist
working-directory: browser-source/apps/browser
# - name: Build Manifest v3 # - name: Build Manifest v3
# run: npm run dist:mv3 # run: npm run dist:mv3
# working-directory: browser-source/apps/browser
- name: Gulp - name: Gulp
run: gulp ci run: gulp ci
working-directory: browser-source/apps/browser
- name: Build sources for reviewers
shell: cmd
run: |
REM Remove ".git" directory
rmdir /S /Q ".git"
REM Copy root level files to source directory
mkdir browser-source
copy * browser-source
REM Copy apps\browser to Browser source directory
mkdir browser-source\apps\browser
xcopy apps\browser\* browser-source\apps\browser /E
REM Copy libs to Browser source directory
mkdir browser-source\libs
xcopy libs\* browser-source\libs /E
call 7z a browser-source.zip "browser-source\*"
working-directory: ./
- name: Upload Opera artifact - name: Upload Opera artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: dist-opera-${{ env._BUILD_NUMBER }}.zip name: dist-opera-${{ env._BUILD_NUMBER }}.zip
path: apps/browser/dist/dist-opera.zip path: browser-source/apps/browser/dist/dist-opera.zip
if-no-files-found: error if-no-files-found: error
# - name: Upload Opera MV3 artifact # - name: Upload Opera MV3 artifact
# uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 # uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
# with: # with:
# name: dist-opera-MV3-${{ env._BUILD_NUMBER }}.zip # name: dist-opera-MV3-${{ env._BUILD_NUMBER }}.zip
# path: apps/browser/dist/dist-opera-mv3.zip # path: browser-source/apps/browser/dist/dist-opera-mv3.zip
# if-no-files-found: error # if-no-files-found: error
- name: Upload Chrome artifact - name: Upload Chrome artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: dist-chrome-${{ env._BUILD_NUMBER }}.zip name: dist-chrome-${{ env._BUILD_NUMBER }}.zip
path: apps/browser/dist/dist-chrome.zip path: browser-source/apps/browser/dist/dist-chrome.zip
if-no-files-found: error if-no-files-found: error
# - name: Upload Chrome MV3 artifact # - name: Upload Chrome MV3 artifact
# uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 # uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
# with: # with:
# name: dist-chrome-MV3-${{ env._BUILD_NUMBER }}.zip # name: dist-chrome-MV3-${{ env._BUILD_NUMBER }}.zip
# path: apps/browser/dist/dist-chrome-mv3.zip # path: browser-source/apps/browser/dist/dist-chrome-mv3.zip
# if-no-files-found: error # if-no-files-found: error
- name: Upload Firefox artifact - name: Upload Firefox artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: dist-firefox-${{ env._BUILD_NUMBER }}.zip name: dist-firefox-${{ env._BUILD_NUMBER }}.zip
path: apps/browser/dist/dist-firefox.zip path: browser-source/apps/browser/dist/dist-firefox.zip
if-no-files-found: error if-no-files-found: error
- name: Upload Edge artifact - name: Upload Edge artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: dist-edge-${{ env._BUILD_NUMBER }}.zip name: dist-edge-${{ env._BUILD_NUMBER }}.zip
path: apps/browser/dist/dist-edge.zip path: browser-source/apps/browser/dist/dist-edge.zip
if-no-files-found: error if-no-files-found: error
# - name: Upload Edge MV3 artifact # - name: Upload Edge MV3 artifact
# uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 # uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
# with: # with:
# name: dist-edge-MV3-${{ env._BUILD_NUMBER }}.zip # name: dist-edge-MV3-${{ env._BUILD_NUMBER }}.zip
# path: apps/browser/dist/dist-edge-mv3.zip # path: browser-source/apps/browser/dist/dist-edge-mv3.zip
# if-no-files-found: error # if-no-files-found: error
- name: Upload browser source - name: Upload browser source
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: browser-source-${{ env._BUILD_NUMBER }}.zip name: browser-source-${{ env._BUILD_NUMBER }}.zip
path: browser-source.zip path: browser-source.zip
@ -230,88 +226,103 @@ jobs:
- name: Upload coverage artifact - name: Upload coverage artifact
if: false if: false
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: coverage-${{ env._BUILD_NUMBER }}.zip name: coverage-${{ env._BUILD_NUMBER }}.zip
path: apps/browser/coverage/coverage-${{ env._BUILD_NUMBER }}.zip path: browser-source/apps/browser/coverage/coverage-${{ env._BUILD_NUMBER }}.zip
if-no-files-found: error if-no-files-found: error
build-safari: build-safari:
name: Build Safari name: Build Safari
runs-on: macos-11 runs-on: macos-13
needs: needs:
- setup - setup
- locales-test - locales-test
env: env:
_BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }} _BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }}
_NODE_VERSION: ${{ needs.setup.outputs.node_version }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up Node - name: Set up Node
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with: with:
cache: 'npm' cache: 'npm'
cache-dependency-path: '**/package-lock.json' cache-dependency-path: '**/package-lock.json'
node-version: '18' node-version: ${{ env._NODE_VERSION }}
- name: Print environment - name: Print environment
run: | run: |
node --version node --version
npm --version npm --version
- name: Decrypt secrets - name: Login to Azure
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Download Provisioning Profiles secrets
env: env:
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} ACCOUNT_NAME: bitwardenci
CONTAINER_NAME: profiles
run: | run: |
mkdir -p $HOME/secrets mkdir -p $HOME/secrets
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/bitwarden-desktop-key.p12" \ az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
"$GITHUB_WORKSPACE/.github/secrets/bitwarden-desktop-key.p12.gpg" --name bitwarden_desktop_appstore.provisionprofile \
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ --file $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \
--output "$HOME/secrets/appstore-app-cert.p12" \ --output none
"$GITHUB_WORKSPACE/.github/secrets/appstore-app-cert.p12.gpg"
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - name: Get certificates
--output "$HOME/secrets/appstore-installer-cert.p12" \ run: |
"$GITHUB_WORKSPACE/.github/secrets/appstore-installer-cert.p12.gpg" mkdir -p $HOME/certificates
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/devid-app-cert.p12" \ az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/bitwarden-desktop-key |
"$GITHUB_WORKSPACE/.github/secrets/devid-app-cert.p12.gpg" jq -r .value | base64 -d > $HOME/certificates/bitwarden-desktop-key.p12
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/devid-installer-cert.p12" \ az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/appstore-app-cert |
"$GITHUB_WORKSPACE/.github/secrets/devid-installer-cert.p12.gpg" jq -r .value | base64 -d > $HOME/certificates/appstore-app-cert.p12
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/macdev-cert.p12" \ az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/appstore-installer-cert |
"$GITHUB_WORKSPACE/.github/secrets/macdev-cert.p12.gpg" jq -r .value | base64 -d > $HOME/certificates/appstore-installer-cert.p12
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/bitwarden_desktop_appstore.provisionprofile" \ az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-app-cert |
"$GITHUB_WORKSPACE/.github/secrets/bitwarden_desktop_appstore.provisionprofile.gpg" jq -r .value | base64 -d > $HOME/certificates/devid-app-cert.p12
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-installer-cert |
jq -r .value | base64 -d > $HOME/certificates/devid-installer-cert.p12
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/macdev-cert |
jq -r .value | base64 -d > $HOME/certificates/macdev-cert.p12
- name: Set up keychain - name: Set up keychain
env: env:
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
DESKTOP_KEY_PASSWORD: ${{ secrets.DESKTOP_KEY_PASSWORD }}
DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_PASSWORD }}
APPSTORE_CERT_PASSWORD: ${{ secrets.APPSTORE_CERT_PASSWORD }}
MACDEV_CERT_PASSWORD: ${{ secrets.MACDEV_CERT_PASSWORD }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
run: | run: |
security create-keychain -p $KEYCHAIN_PASSWORD build.keychain security create-keychain -p $KEYCHAIN_PASSWORD build.keychain
security default-keychain -s build.keychain security default-keychain -s build.keychain
security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain
security set-keychain-settings -lut 1200 build.keychain security set-keychain-settings -lut 1200 build.keychain
security import "$HOME/secrets/bitwarden-desktop-key.p12" -k build.keychain -P $DESKTOP_KEY_PASSWORD \
security import "$HOME/certificates/bitwarden-desktop-key.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/devid-app-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \
security import "$HOME/certificates/devid-app-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/devid-installer-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \
security import "$HOME/certificates/devid-installer-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/appstore-app-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \
security import "$HOME/certificates/appstore-app-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/appstore-installer-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \
security import "$HOME/certificates/appstore-installer-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/macdev-cert.p12" -k build.keychain -P $MACDEV_CERT_PASSWORD \
security import "$HOME/certificates/macdev-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain
- name: NPM setup - name: NPM setup
@ -330,7 +341,7 @@ jobs:
ls -la ls -la
- name: Upload Safari artifact - name: Upload Safari artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: dist-safari-${{ env._BUILD_NUMBER }}.zip name: dist-safari-${{ env._BUILD_NUMBER }}.zip
path: apps/browser/dist/dist-safari.zip path: apps/browser/dist/dist-safari.zip
@ -338,45 +349,44 @@ jobs:
crowdin-push: crowdin-push:
name: Crowdin Push name: Crowdin Push
if: github.ref == 'refs/heads/master' if: github.ref == 'refs/heads/main'
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
needs: needs:
- build - build
- build-safari - build-safari
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Login to Azure - name: Login to Azure
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "crowdin-api-token" secrets: "crowdin-api-token"
- name: Upload Sources - name: Upload Sources
uses: crowdin/github-action@ee4ab4ea2feadc0fdc3b200729c7b1c4cf4b38f3 # v1.11.0 uses: crowdin/github-action@c953b17499daa6be3e5afbf7a63616fb02d8b18d # v1.19.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
CROWDIN_PROJECT_ID: "268134" CROWDIN_PROJECT_ID: "268134"
with: with:
config: apps/browser/crowdin.yml config: apps/browser/crowdin.yml
crowdin_branch_name: master crowdin_branch_name: main
upload_sources: true upload_sources: true
upload_translations: false upload_translations: false
check-failures: check-failures:
name: Check for failures name: Check for failures
if: always() if: always()
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
needs: needs:
- cloc
- setup - setup
- locales-test - locales-test
- build - build
@ -384,31 +394,11 @@ jobs:
- crowdin-push - crowdin-push
steps: steps:
- name: Check if any job failed - name: Check if any job failed
if: ${{ (github.ref == 'refs/heads/master') || (github.ref == 'refs/heads/rc') }} if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') && contains(needs.*.result, 'failure')
env: run: exit 1
CLOC_STATUS: ${{ needs.cloc.result }}
SETUP_STATUS: ${{ needs.setup.result }}
LOCALES_TEST_STATUS: ${{ needs.locales-test.result }}
BUILD_STATUS: ${{ needs.build.result }}
SAFARI_BUILD_STATUS: ${{ needs.build-safari.result }}
CROWDIN_PUSH_STATUS: ${{ needs.crowdin-push.result }}
run: |
if [ "$CLOC_STATUS" = "failure" ]; then
exit 1
elif [ "$SETUP_STATUS" = "failure" ]; then
exit 1
elif [ "$LOCALES_TEST_STATUS" = "failure" ]; then
exit 1
elif [ "$BUILD_STATUS" = "failure" ]; then
exit 1
elif [ "$SAFARI_BUILD_STATUS" = "failure" ]; then
exit 1
elif [ "$CROWDIN_PUSH_STATUS" = "failure" ]; then
exit 1
fi
- name: Login to Azure - Prod Subscription - name: Login to Azure - Prod Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
if: failure() if: failure()
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
@ -416,7 +406,7 @@ jobs:
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
if: failure() if: failure()
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "devops-alerts-slack-webhook-url" secrets: "devops-alerts-slack-webhook-url"

View File

@ -15,7 +15,7 @@ on:
- '.github/workflows/build-cli.yml' - '.github/workflows/build-cli.yml'
push: push:
branches: branches:
- 'master' - 'main'
- 'rc' - 'rc'
- 'hotfix-rc-cli' - 'hotfix-rc-cli'
paths: paths:
@ -33,53 +33,47 @@ defaults:
working-directory: apps/cli working-directory: apps/cli
jobs: jobs:
cloc:
name: CLOC
runs-on: ubuntu-20.04
steps:
- name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- name: Set up cloc
run: |
sudo apt update
sudo apt -y install cloc
- name: Print lines of code
run: cloc --include-lang TypeScript,JavaScript --vcs git
setup: setup:
name: Setup name: Setup
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
outputs: outputs:
package_version: ${{ steps.retrieve-version.outputs.package_version }} package_version: ${{ steps.retrieve-package-version.outputs.package_version }}
node_version: ${{ steps.retrieve-node-version.outputs.node_version }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Get Package Version - name: Get Package Version
id: retrieve-version id: retrieve-package-version
run: | run: |
PKG_VERSION=$(jq -r .version package.json) PKG_VERSION=$(jq -r .version package.json)
echo "package_version=$PKG_VERSION" >> $GITHUB_OUTPUT echo "package_version=$PKG_VERSION" >> $GITHUB_OUTPUT
- name: Get Node Version
id: retrieve-node-version
working-directory: ./
run: |
NODE_NVMRC=$(cat .nvmrc)
NODE_VERSION=${NODE_NVMRC/v/''}
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
cli: cli:
name: Build CLI ${{ matrix.os }} name: Build CLI ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [ubuntu-20.04, macos-11] os: [ubuntu-22.04, macos-11]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
needs: needs:
- setup - setup
env: env:
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
_NODE_VERSION: ${{ needs.setup.outputs.node_version }}
_WIN_PKG_FETCH_VERSION: 18.5.0 _WIN_PKG_FETCH_VERSION: 18.5.0
_WIN_PKG_VERSION: 3.4 _WIN_PKG_VERSION: 3.4
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup Unix Vars - name: Setup Unix Vars
run: | run: |
@ -88,16 +82,11 @@ jobs:
awk '{print tolower($0)}')" >> $GITHUB_ENV awk '{print tolower($0)}')" >> $GITHUB_ENV
- name: Set up Node - name: Set up Node
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with: with:
cache: 'npm' cache: 'npm'
cache-dependency-path: '**/package-lock.json' cache-dependency-path: '**/package-lock.json'
node-version: '18' node-version: ${{ env._NODE_VERSION }}
- name: Install node-gyp
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Install - name: Install
run: npm ci run: npm ci
@ -129,14 +118,14 @@ jobs:
| awk '{split($0, a); print a[1]}' > bw-${{ env.LOWER_RUNNER_OS }}-sha256-${{ env._PACKAGE_VERSION }}.txt | awk '{split($0, a); print a[1]}' > bw-${{ env.LOWER_RUNNER_OS }}-sha256-${{ env._PACKAGE_VERSION }}.txt
- name: Upload unix zip asset - name: Upload unix zip asset
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bw-${{ env.LOWER_RUNNER_OS }}-${{ env._PACKAGE_VERSION }}.zip name: bw-${{ env.LOWER_RUNNER_OS }}-${{ env._PACKAGE_VERSION }}.zip
path: apps/cli/dist/bw-${{ env.LOWER_RUNNER_OS }}-${{ env._PACKAGE_VERSION }}.zip path: apps/cli/dist/bw-${{ env.LOWER_RUNNER_OS }}-${{ env._PACKAGE_VERSION }}.zip
if-no-files-found: error if-no-files-found: error
- name: Upload unix checksum asset - name: Upload unix checksum asset
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bw-${{ env.LOWER_RUNNER_OS }}-sha256-${{ env._PACKAGE_VERSION }}.txt name: bw-${{ env.LOWER_RUNNER_OS }}-sha256-${{ env._PACKAGE_VERSION }}.txt
path: apps/cli/dist/bw-${{ env.LOWER_RUNNER_OS }}-sha256-${{ env._PACKAGE_VERSION }}.txt path: apps/cli/dist/bw-${{ env.LOWER_RUNNER_OS }}-sha256-${{ env._PACKAGE_VERSION }}.txt
@ -144,16 +133,17 @@ jobs:
cli-windows: cli-windows:
name: Build CLI Windows name: Build CLI Windows
runs-on: windows-2019 runs-on: windows-2022
needs: needs:
- setup - setup
env: env:
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
_NODE_VERSION: ${{ needs.setup.outputs.node_version }}
_WIN_PKG_FETCH_VERSION: 18.5.0 _WIN_PKG_FETCH_VERSION: 18.5.0
_WIN_PKG_VERSION: 3.4 _WIN_PKG_VERSION: 3.4
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup Windows builder - name: Setup Windows builder
run: | run: |
@ -162,16 +152,11 @@ jobs:
choco install nasm --no-progress choco install nasm --no-progress
- name: Set up Node - name: Set up Node
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with: with:
cache: 'npm' cache: 'npm'
cache-dependency-path: '**/package-lock.json' cache-dependency-path: '**/package-lock.json'
node-version: '18' node-version: ${{ env._NODE_VERSION }}
- name: Install node-gyp
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Get pkg-fetch - name: Get pkg-fetch
shell: pwsh shell: pwsh
@ -264,28 +249,28 @@ jobs:
-t sha256 | Out-File -Encoding ASCII ./dist/bw-windows-sha256-${env:_PACKAGE_VERSION}.txt -t sha256 | Out-File -Encoding ASCII ./dist/bw-windows-sha256-${env:_PACKAGE_VERSION}.txt
- name: Upload windows zip asset - name: Upload windows zip asset
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bw-windows-${{ env._PACKAGE_VERSION }}.zip name: bw-windows-${{ env._PACKAGE_VERSION }}.zip
path: apps/cli/dist/bw-windows-${{ env._PACKAGE_VERSION }}.zip path: apps/cli/dist/bw-windows-${{ env._PACKAGE_VERSION }}.zip
if-no-files-found: error if-no-files-found: error
- name: Upload windows checksum asset - name: Upload windows checksum asset
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bw-windows-sha256-${{ env._PACKAGE_VERSION }}.txt name: bw-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
path: apps/cli/dist/bw-windows-sha256-${{ env._PACKAGE_VERSION }}.txt path: apps/cli/dist/bw-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
if-no-files-found: error if-no-files-found: error
- name: Upload Chocolatey asset - name: Upload Chocolatey asset
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bitwarden-cli.${{ env._PACKAGE_VERSION }}.nupkg name: bitwarden-cli.${{ env._PACKAGE_VERSION }}.nupkg
path: apps/cli/dist/chocolatey/bitwarden-cli.${{ env._PACKAGE_VERSION }}.nupkg path: apps/cli/dist/chocolatey/bitwarden-cli.${{ env._PACKAGE_VERSION }}.nupkg
if-no-files-found: error if-no-files-found: error
- name: Upload NPM Build Directory asset - name: Upload NPM Build Directory asset
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bitwarden-cli-${{ env._PACKAGE_VERSION }}-npm-build.zip name: bitwarden-cli-${{ env._PACKAGE_VERSION }}-npm-build.zip
path: apps/cli/build path: apps/cli/build
@ -293,13 +278,16 @@ jobs:
snap: snap:
name: Build Snap name: Build Snap
runs-on: ubuntu-20.04 # Note, before updating the ubuntu version of the workflow, ensure the snap base image
# is equal or greater than the new version. Otherwise there might be GLIBC version issues.
# The snap base for CLI is defined in `apps/cli/stores/snap/snapcraft.yaml`
runs-on: ubuntu-22.04
needs: [setup, cli] needs: [setup, cli]
env: env:
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Print environment - name: Print environment
run: | run: |
@ -309,7 +297,7 @@ jobs:
echo "BW Package Version: $_PACKAGE_VERSION" echo "BW Package Version: $_PACKAGE_VERSION"
- name: Get bw linux cli - name: Get bw linux cli
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4
with: with:
name: bw-linux-${{ env._PACKAGE_VERSION }}.zip name: bw-linux-${{ env._PACKAGE_VERSION }}.zip
path: apps/cli/dist/snap path: apps/cli/dist/snap
@ -322,7 +310,7 @@ jobs:
ls -alth ls -alth
- name: Build snap - name: Build snap
uses: snapcore/action-build@3457752ec9b1c79a8290b5167fce2d14df0997c1 # v1.1.2 uses: snapcore/action-build@2096990827aa966f773676c8a53793c723b6b40f # v1.2.0
with: with:
path: apps/cli/dist/snap path: apps/cli/dist/snap
@ -351,14 +339,14 @@ jobs:
run: sudo snap remove bw run: sudo snap remove bw
- name: Upload snap asset - name: Upload snap asset
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bw_${{ env._PACKAGE_VERSION }}_amd64.snap name: bw_${{ env._PACKAGE_VERSION }}_amd64.snap
path: apps/cli/dist/snap/bw_${{ env._PACKAGE_VERSION }}_amd64.snap path: apps/cli/dist/snap/bw_${{ env._PACKAGE_VERSION }}_amd64.snap
if-no-files-found: error if-no-files-found: error
- name: Upload snap checksum asset - name: Upload snap checksum asset
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bw-snap-sha256-${{ env._PACKAGE_VERSION }}.txt name: bw-snap-sha256-${{ env._PACKAGE_VERSION }}.txt
path: apps/cli/dist/snap/bw-snap-sha256-${{ env._PACKAGE_VERSION }}.txt path: apps/cli/dist/snap/bw-snap-sha256-${{ env._PACKAGE_VERSION }}.txt
@ -368,9 +356,8 @@ jobs:
check-failures: check-failures:
name: Check for failures name: Check for failures
if: always() if: always()
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
needs: needs:
- cloc
- setup - setup
- cli - cli
- cli-windows - cli-windows
@ -378,25 +365,11 @@ jobs:
steps: steps:
- name: Check if any job failed - name: Check if any job failed
working-directory: ${{ github.workspace }} working-directory: ${{ github.workspace }}
if: ${{ (github.ref == 'refs/heads/master') || (github.ref == 'refs/heads/rc') }} if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') && contains(needs.*.result, 'failure')
env: run: exit 1
CLOC_STATUS: ${{ needs.cloc.result }}
SETUP_STATUS: ${{ needs.setup.result }}
CLI_STATUS: ${{ needs.cli.result }}
SNAP_STATUS: ${{ needs.snap.result }}
run: |
if [ "$CLOC_STATUS" = "failure" ]; then
exit 1
elif [ "$SETUP_STATUS" = "failure" ]; then
exit 1
elif [ "$CLI_STATUS" = "failure" ]; then
exit 1
elif [ "$SNAP_STATUS" = "failure" ]; then
exit 1
fi
- name: Login to Azure - Prod Subscription - name: Login to Azure - Prod Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
if: failure() if: failure()
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
@ -404,7 +377,7 @@ jobs:
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
if: failure() if: failure()
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "devops-alerts-slack-webhook-url" secrets: "devops-alerts-slack-webhook-url"

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@ on:
- '.github/workflows/build-web.yml' - '.github/workflows/build-web.yml'
push: push:
branches: branches:
- 'master' - 'main'
- 'rc' - 'rc'
- 'hotfix-rc-web' - 'hotfix-rc-web'
paths: paths:
@ -25,50 +25,46 @@ on:
- '!*.md' - '!*.md'
- '!*.txt' - '!*.txt'
- '.github/workflows/build-web.yml' - '.github/workflows/build-web.yml'
release:
types: [published]
workflow_dispatch: workflow_dispatch:
inputs: inputs:
custom_tag_extension: custom_tag_extension:
description: "Custom image tag extension" description: "Custom image tag extension"
required: false required: false
env:
_AZ_REGISTRY: bitwardenprod.azurecr.io
jobs: jobs:
cloc:
name: CLOC
runs-on: ubuntu-22.04
steps:
- name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- name: Set up cloc
run: |
sudo apt update
sudo apt -y install cloc
- name: Print lines of code
working-directory: apps/web
run: cloc --include-lang TypeScript,JavaScript,HTML,Sass,CSS --vcs git
setup: setup:
name: Setup name: Setup
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
outputs: outputs:
version: ${{ steps.version.outputs.value }} version: ${{ steps.version.outputs.value }}
node_version: ${{ steps.retrieve-node-version.outputs.node_version }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Get GitHub sha as version - name: Get GitHub sha as version
id: version id: version
run: echo "value=${GITHUB_SHA:0:7}" >> $GITHUB_OUTPUT run: echo "value=${GITHUB_SHA:0:7}" >> $GITHUB_OUTPUT
- name: Get Node Version
id: retrieve-node-version
run: |
NODE_NVMRC=$(cat .nvmrc)
NODE_VERSION=${NODE_NVMRC/v/''}
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
build-artifacts: build-artifacts:
name: Build artifacts name: Build artifacts
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
needs: needs: setup
- setup
env: env:
_VERSION: ${{ needs.setup.outputs.version }} _VERSION: ${{ needs.setup.outputs.version }}
_NODE_VERSION: ${{ needs.setup.outputs.node_version }}
strategy: strategy:
matrix: matrix:
include: include:
@ -80,23 +76,29 @@ jobs:
npm_command: "dist:bit:selfhost" npm_command: "dist:bit:selfhost"
- name: "cloud-QA" - name: "cloud-QA"
npm_command: "build:bit:qa" npm_command: "build:bit:qa"
git_metadata: true
- name: "ee" - name: "ee"
npm_command: "build:bit:ee" npm_command: "build:bit:ee"
git_metadata: true
- name: "cloud-euprd" - name: "cloud-euprd"
npm_command: "build:bit:euprd" npm_command: "build:bit:euprd"
- name: "cloud-euqa" - name: "cloud-euqa"
npm_command: "build:bit:euqa" npm_command: "build:bit:euqa"
git_metadata: true
- name: "cloud-usdev"
npm_command: "build:bit:usdev"
git_metadata: true
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up Node - name: Set up Node
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with: with:
cache: 'npm' cache: 'npm'
cache-dependency-path: '**/package-lock.json' cache-dependency-path: '**/package-lock.json'
node-version: "16" node-version: ${{ env._NODE_VERSION }}
- name: Print environment - name: Print environment
run: | run: |
@ -111,9 +113,9 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: npm ci run: npm ci
- name: Setup QA metadata - name: Add Git metadata to build version
working-directory: apps/web working-directory: apps/web
if: matrix.name == 'cloud-QA' if: matrix.git_metadata
run: | run: |
VERSION=$( jq -r ".version" package.json) VERSION=$( jq -r ".version" package.json)
jq --arg version "$VERSION+${GITHUB_SHA:0:7}" '.version = $version' package.json > package.json.tmp jq --arg version "$VERSION+${GITHUB_SHA:0:7}" '.version = $version' package.json > package.json.tmp
@ -128,7 +130,7 @@ jobs:
run: zip -r web-${{ env._VERSION }}-${{ matrix.name }}.zip build run: zip -r web-${{ env._VERSION }}-${{ matrix.name }}.zip build
- name: Upload ${{ matrix.name }} artifact - name: Upload ${{ matrix.name }} artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: web-${{ env._VERSION }}-${{ matrix.name }}.zip name: web-${{ env._VERSION }}-${{ matrix.name }}.zip
path: apps/web/web-${{ env._VERSION }}-${{ matrix.name }}.zip path: apps/web/web-${{ env._VERSION }}-${{ matrix.name }}.zip
@ -146,23 +148,20 @@ jobs:
matrix: matrix:
include: include:
- artifact_name: cloud-QA - artifact_name: cloud-QA
registries: [bitwardenprod.azurecr.io, bitwardenqa.azurecr.io]
image_name: web-qa-cloud image_name: web-qa-cloud
- artifact_name: ee - artifact_name: ee
registries: [bitwardenprod.azurecr.io, bitwardenqa.azurecr.io]
image_name: web-ee image_name: web-ee
- artifact_name: selfhosted-COMMERCIAL - artifact_name: selfhosted-COMMERCIAL
registries: [bitwarden, bitwardenprod.azurecr.io, bitwardenqa.azurecr.io]
image_name: web image_name: web
env: env:
_VERSION: ${{ needs.setup.outputs.version }} _VERSION: ${{ needs.setup.outputs.version }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Check Branch to Publish - name: Check Branch to Publish
env: env:
PUBLISH_BRANCHES: "master,rc,hotfix-rc-web" PUBLISH_BRANCHES: "main,rc,hotfix-rc-web"
id: publish-branch-check id: publish-branch-check
run: | run: |
IFS="," read -a publish_branches <<< $PUBLISH_BRANCHES IFS="," read -a publish_branches <<< $PUBLISH_BRANCHES
@ -174,24 +173,28 @@ jobs:
fi fi
########## ACRs ########## ########## ACRs ##########
- name: Login to Azure - QA - name: Login to Prod Azure
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }}
- name: Log into QA container registry
run: az acr login -n bitwardenqa
- name: Login to Azure - Prod
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
with: with:
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
- name: Log into Prod container registry - name: Log into Prod container registry
run: az acr login -n bitwardenprod run: az acr login -n bitwardenprod
- name: Login to Azure - CI Subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve github PAT secrets
id: retrieve-secret-pat
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: "bitwarden-ci"
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
- name: Download ${{ matrix.artifact_name }} artifact - name: Download ${{ matrix.artifact_name }} artifact
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4
with: with:
name: web-${{ env._VERSION }}-${{ matrix.artifact_name }}.zip name: web-${{ env._VERSION }}-${{ matrix.artifact_name }}.zip
path: apps/web path: apps/web
@ -203,10 +206,10 @@ jobs:
if [[ $(grep "pull" <<< "${GITHUB_REF}") ]]; then if [[ $(grep "pull" <<< "${GITHUB_REF}") ]]; then
IMAGE_TAG=$(echo "${GITHUB_HEAD_REF}" | sed "s#/#-#g") IMAGE_TAG=$(echo "${GITHUB_HEAD_REF}" | sed "s#/#-#g")
else else
IMAGE_TAG=$(echo "${GITHUB_REF:11}" | sed "s#/#-#g") IMAGE_TAG=$(echo "${GITHUB_REF_NAME}" | sed "s#/#-#g")
fi fi
if [[ "$IMAGE_TAG" == "master" ]]; then if [[ "$IMAGE_TAG" == "main" ]]; then
IMAGE_TAG=dev IMAGE_TAG=dev
fi fi
@ -218,135 +221,117 @@ jobs:
echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT
- name: Generate tag list
id: tag-list
env:
IMAGE_TAG: ${{ steps.tag.outputs.image_tag }}
PROJECT_NAME: ${{ matrix.image_name }}
run: echo "tags=bitwardenqa.azurecr.io/${PROJECT_NAME}:${IMAGE_TAG},bitwardenprod.azurecr.io/${PROJECT_NAME}:${IMAGE_TAG}" >> $GITHUB_OUTPUT
########## Build Image ########## ########## Build Image ##########
- name: Extract artifact - name: Extract artifact
working-directory: apps/web working-directory: apps/web
run: unzip web-${{ env._VERSION }}-${{ matrix.artifact_name }}.zip run: unzip web-${{ env._VERSION }}-${{ matrix.artifact_name }}.zip
- name: Login to Azure - name: Generate image full name
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 id: image-name
with: env:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} IMAGE_TAG: ${{ steps.tag.outputs.image_tag }}
PROJECT_NAME: ${{ matrix.image_name }}
- name: Retrieve github PAT secrets run: echo "name=$_AZ_REGISTRY/${PROJECT_NAME}:${IMAGE_TAG}" >> $GITHUB_OUTPUT
id: retrieve-secret-pat
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c
with:
keyvault: "bitwarden-ci"
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
- name: Setup DCT
if: ${{ env.is_publish_branch == 'true' }}
id: setup-dct
uses: bitwarden/gh-actions/setup-docker-trust@a30e9c3d658dc97c4c2e61ec749fdab64b83386c
with:
azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
azure-keyvault-name: "bitwarden-ci"
- name: Build Docker image - name: Build Docker image
uses: docker/build-push-action@2eb1c1961a95fc15694676618e422e8ba1d63825 # v4.1.1 uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0
with: with:
context: apps/web context: apps/web
file: apps/web/Dockerfile file: apps/web/Dockerfile
platforms: linux/amd64 platforms: linux/amd64
push: true push: true
tags: ${{ steps.tag-list.outputs.tags }} tags: ${{ steps.image-name.outputs.name }}
secrets: | secrets: |
"GH_PAT=${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }}" "GH_PAT=${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }}"
- name: Push to DockerHub
if: contains(matrix.registries, 'bitwarden') && env.is_publish_branch == 'true'
env:
IMAGE_TAG: ${{ steps.tag.outputs.image_tag }}
PROJECT_NAME: ${{ matrix.image_name }}
DOCKER_CONTENT_TRUST: 1
DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ steps.setup-dct.outputs.dct-delegate-repo-passphrase }}
run: |
docker tag bitwardenprod.azurecr.io/$PROJECT_NAME:$IMAGE_TAG bitwarden/$PROJECT_NAME:$IMAGE_TAG
docker push bitwarden/$PROJECT_NAME:$IMAGE_TAG
- name: Log out of Docker - name: Log out of Docker
run: docker logout run: docker logout
crowdin-push: crowdin-push:
name: Crowdin Push name: Crowdin Push
if: github.ref == 'refs/heads/master' if: github.ref == 'refs/heads/main'
needs: needs: build-artifacts
- build-artifacts
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Login to Azure - name: Login to Azure
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "crowdin-api-token" secrets: "crowdin-api-token"
- name: Upload Sources - name: Upload Sources
uses: crowdin/github-action@ee4ab4ea2feadc0fdc3b200729c7b1c4cf4b38f3 # v1.11.0 uses: crowdin/github-action@c953b17499daa6be3e5afbf7a63616fb02d8b18d # v1.19.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
CROWDIN_PROJECT_ID: "308189" CROWDIN_PROJECT_ID: "308189"
with: with:
config: apps/web/crowdin.yml config: apps/web/crowdin.yml
crowdin_branch_name: master crowdin_branch_name: main
upload_sources: true upload_sources: true
upload_translations: false upload_translations: false
trigger-web-vault-deploy:
name: Trigger web vault deploy
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-22.04
needs: build-artifacts
steps:
- name: Login to Azure - CI Subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve github PAT secrets
id: retrieve-secret-pat
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: "bitwarden-ci"
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
- name: Trigger web vault deploy using GitHub Run ID
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
github-token: ${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
script: |
await github.rest.actions.createWorkflowDispatch({
owner: 'bitwarden',
repo: 'clients',
workflow_id: 'deploy-web.yml',
ref: 'main',
inputs: {
'environment': 'USDEV',
'build-web-run-id': '${{ github.run_id }}'
}
})
check-failures: check-failures:
name: Check for failures name: Check for failures
if: always() if: always()
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
needs: needs:
- cloc
- setup - setup
- build-artifacts - build-artifacts
- build-containers - build-containers
- crowdin-push - crowdin-push
- trigger-web-vault-deploy
steps: steps:
- name: Check if any job failed - name: Check if any job failed
if: ${{ (github.ref == 'refs/heads/master') || (github.ref == 'refs/heads/rc') }} if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc') && contains(needs.*.result, 'failure')
env: run: exit 1
CLOC_STATUS: ${{ needs.cloc.result }}
SETUP_STATUS: ${{ needs.setup.result }}
ARTIFACT_STATUS: ${{ needs.build-artifacts.result }}
BUILD_CONTAINERS_STATUS: ${{ needs.build-containers.result }}
CROWDIN_PUSH_STATUS: ${{ needs.crowdin-push.result }}
run: |
if [ "$CLOC_STATUS" = "failure" ]; then
exit 1
elif [ "$SETUP_STATUS" = "failure" ]; then
exit 1
elif [ "$ARTIFACT_STATUS" = "failure" ]; then
exit 1
elif [ "$BUILD_SELFHOST_STATUS" = "failure" ]; then
exit 1
elif [ "$BUILD_CONTAINERS_STATUS" = "failure" ]; then
exit 1
elif [ "$CROWDIN_PUSH_STATUS" = "failure" ]; then
exit 1
fi
- name: Login to Azure - Prod Subscription - name: Login to Azure - Prod Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
if: failure() if: failure()
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
@ -354,7 +339,7 @@ jobs:
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
if: failure() if: failure()
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "devops-alerts-slack-webhook-url" secrets: "devops-alerts-slack-webhook-url"

View File

@ -3,45 +3,54 @@ name: Chromatic
on: on:
push: push:
branches-ignore:
- 'renovate/**'
paths-ignore: paths-ignore:
- '.github/workflows/**' - '.github/workflows/**'
jobs: jobs:
chromatic: chromatic:
name: Chromatic name: Chromatic
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
steps: steps:
- name: Set up Node
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
with:
node-version: "16"
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Get Node Version
id: retrieve-node-version
run: |
NODE_NVMRC=$(cat .nvmrc)
NODE_VERSION=${NODE_NVMRC/v/''}
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
- name: Set up Node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: ${{ steps.retrieve-node-version.outputs.node_version }}
- name: Cache npm - name: Cache npm
id: npm-cache id: npm-cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4.0.1
with: with:
path: "~/.npm" path: "~/.npm"
key: ${{ runner.os }}-npm-chromatic-${{ hashFiles('**/package-lock.json') }} key: ${{ runner.os }}-npm-chromatic-${{ hashFiles('**/package-lock.json') }}
- name: Install Node dependencies - name: Install Node dependencies
run: npm ci run: npm ci
# Manual build the storybook to resolve a chromatic/storybook bug related to TurboSnap # Manual build the storybook to resolve a chromatic/storybook bug related to TurboSnap
- name: Build Storybook - name: Build Storybook
run: npm run build-storybook:ci run: npm run build-storybook:ci
- name: Publish to Chromatic - name: Publish to Chromatic
uses: chromaui/action@44caff7e88d584b04f79f04e31e819f9a95d4d8f uses: chromaui/action@c9067691aca4a28d6fbb40d9eea6e144369fbcae # v10.9.5
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
storybookBuildDir: ./storybook-static storybookBuildDir: ./storybook-static
exitOnceUploaded: true exitOnceUploaded: true
onlyChanged: true onlyChanged: true
externals: "[\"libs/components/**/*.scss\", \"libs/components/tailwind.config*.js\"]" externals: "[\"libs/components/**/*.scss\", \"libs/components/**/*.css\", \"libs/components/tailwind.config*.js\"]"

View File

@ -10,7 +10,7 @@ on:
jobs: jobs:
crowdin-sync: crowdin-sync:
name: Autosync name: Autosync
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -23,29 +23,29 @@ jobs:
crowdin_project_id: "308189" crowdin_project_id: "308189"
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Login to Azure - name: Login to Azure
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase" secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase"
- name: Download translations - name: Download translations
uses: bitwarden/gh-actions/crowdin@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/crowdin@main
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
CROWDIN_PROJECT_ID: ${{ matrix.crowdin_project_id }} CROWDIN_PROJECT_ID: ${{ matrix.crowdin_project_id }}
with: with:
config: crowdin.yml config: crowdin.yml
crowdin_branch_name: master crowdin_branch_name: main
upload_sources: false upload_sources: false
upload_translations: false upload_translations: false
download_translations: true download_translations: true

View File

@ -1,60 +0,0 @@
---
name: Deploy Web to EU-PRD Cloud
on:
workflow_dispatch:
inputs:
tag:
description: "Branch name to deploy (examples: 'master', 'feature/sm')"
required: true
type: string
default: master
jobs:
azure-deploy:
name: Deploy to Azure
runs-on: ubuntu-22.04
env:
_WEB_ARTIFACT: "web-*-cloud-euprd.zip"
steps:
- name: Login to Azure - EU Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
with:
creds: ${{ secrets.AZURE_KV_EU_PRD_SERVICE_PRINCIPAL }}
- name: Retrieve Storage Account connection string
id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c
with:
keyvault: webvault-westeurope-prod
secrets: "sa-bitwarden-web-vault-dev-key-temp"
- name: Download latest cloud asset
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c
with:
workflow: build-web.yml
path: apps/web
workflow_conclusion: success
branch: ${{ github.event.inputs.tag }}
artifacts: ${{ env._WEB_ARTIFACT }}
- name: Unzip build asset
working-directory: apps/web
run: unzip ${{ env._WEB_ARTIFACT }}
- name: Empty container in Storage Account
run: |
az storage blob delete-batch \
--source '$web' \
--pattern '*' \
--connection-string "${{ steps.retrieve-secrets.outputs.sa-bitwarden-web-vault-dev-key-temp }}"
- name: Deploy to Azure Storage Account
working-directory: apps/web
run: |
az storage blob upload-batch \
--source "./build" \
--destination '$web' \
--connection-string "${{ steps.retrieve-secrets.outputs.sa-bitwarden-web-vault-dev-key-temp }}" \
--overwrite \
--no-progress

View File

@ -1,60 +0,0 @@
---
name: Deploy Web to EU-QA Cloud
on:
workflow_dispatch:
inputs:
tag:
description: "Branch name to deploy (examples: 'master', 'feature/sm')"
required: true
type: string
default: master
jobs:
azure-deploy:
name: Deploy to Azure
runs-on: ubuntu-22.04
env:
_WEB_ARTIFACT: "web-*-cloud-euqa.zip"
steps:
- name: Login to Azure - EU Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
with:
creds: ${{ secrets.AZURE_KV_EU_QA_SERVICE_PRINCIPAL }}
- name: Retrieve Storage Account connection string
id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c
with:
keyvault: webvaulteu-westeurope-qa
secrets: "sa-bitwarden-web-vault-dev-key-temp"
- name: Download latest cloud asset
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c
with:
workflow: build-web.yml
path: apps/web
workflow_conclusion: success
branch: ${{ github.event.inputs.tag }}
artifacts: ${{ env._WEB_ARTIFACT }}
- name: Unzip build asset
working-directory: apps/web
run: unzip ${{ env._WEB_ARTIFACT }}
- name: Empty container in Storage Account
run: |
az storage blob delete-batch \
--source '$web' \
--pattern '*' \
--connection-string "${{ steps.retrieve-secrets.outputs.sa-bitwarden-web-vault-dev-key-temp }}"
- name: Deploy to Azure Storage Account
working-directory: apps/web
run: |
az storage blob upload-batch \
--source "./build" \
--destination '$web' \
--connection-string "${{ steps.retrieve-secrets.outputs.sa-bitwarden-web-vault-dev-key-temp }}" \
--overwrite \
--no-progress

View File

@ -1,128 +0,0 @@
---
name: Deploy Web - Non-Prod
run-name: Deploy Web ${{ inputs.environment }}
on:
workflow_dispatch:
inputs:
environment:
description: 'Environment'
default: 'QA'
type: choice
options:
- QA
workflow_call:
inputs:
environment:
description: 'Environment'
default: 'QA'
type: string
jobs:
setup:
name: Setup
runs-on: ubuntu-20.04
outputs:
environment: ${{ steps.config.outputs.environment }}
environment-url: ${{ steps.config.outputs.environment-url }}
environment-name: ${{ steps.config.outputs.environment-name }}
environment-branch: ${{ steps.config.outputs.environment-branch }}
environment-artifact: ${{ steps.config.outputs.environment-artifact }}
steps:
- name: Configure
id: config
run: |
ENV_NAME_LOWER=$(echo "${{ inputs.environment }}" | awk '{print tolower($0)}')
echo "configuring the Web deploy for ${{ inputs.environment }}"
echo "environment=${{ inputs.environment }}" >> $GITHUB_OUTPUT
echo "environment-url=http://vault.$ENV_NAME_LOWER.bitwarden.pw" >> $GITHUB_OUTPUT
echo "environment-name=Web Vault - ${{ inputs.environment }}" >> $GITHUB_OUTPUT
echo "environment-branch=cf-pages-$ENV_NAME_LOWER" >> $GITHUB_OUTPUT
echo "environment-artifact=web-*-cloud-${{ inputs.environment }}.zip" >> $GITHUB_OUTPUT
cfpages-deploy:
name: Deploy Web Vault to ${{ inputs.environment }} CloudFlare Pages branch
needs: setup
runs-on: ubuntu-20.04
env:
_ENVIRONMENT: ${{ needs.setup.outputs.environment }}
_ENVIRONMENT_URL: ${{ needs.setup.outputs.environment-url }}
_ENVIRONMENT_NAME: ${{ needs.setup.outputs.environment-name }}
_ENVIRONMENT_BRANCH: ${{ needs.setup.outputs.environment-branch }}
_ENVIRONMENT_ARTIFACT: ${{ needs.setup.outputs.environment-artifact }}
steps:
- name: Create GitHub deployment
uses: chrnorm/deployment-action@d42cde7132fcec920de534fffc3be83794335c00 # v2.0.5
id: deployment
with:
token: '${{ secrets.GITHUB_TOKEN }}'
initial-status: 'in_progress'
environment-url: ${{ env._ENVIRONMENT_URL }}
environment: ${{ env._ENVIRONMENT_NAME }}
description: 'Deployment from branch ${{ github.ref_name }}'
- name: Checkout Repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- name: Download latest cloud asset
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c
with:
workflow: build-web.yml
path: apps/web
workflow_conclusion: success
branch: ${{ github.ref_name }}
artifacts: ${{ env._ENVIRONMENT_ARTIFACT }}
- name: Unzip cloud asset
working-directory: apps/web
run: unzip ${{ env._ENVIRONMENT_ARTIFACT }}
- name: Checkout Repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
with:
ref: ${{ env._ENVIRONMENT_BRANCH }}
path: deployment
- name: Setup git config
run: |
git config --global user.name "GitHub Action Bot"
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --global url."https://github.com/".insteadOf ssh://git@github.com/
git config --global url."https://".insteadOf ssh://
- name: Deploy CloudFlare Pages
run: |
rm -rf ./*
cp -R ../apps/web/build/* .
working-directory: deployment
- name: Push new ver to ${{ env._ENVIRONMENT_BRANCH }}
run: |
if [ -n "$(git status --porcelain)" ]; then
git add .
git commit -m "Deploy ${{ github.ref_name }} to ${{ env._ENVIRONMENT }} Cloudflare pages"
git push -u origin ${{ env._ENVIRONMENT_BRANCH }}
else
echo "No changes to commit!";
fi
working-directory: deployment
- name: Update deployment status to Success
if: ${{ success() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1
with:
token: '${{ secrets.GITHUB_TOKEN }}'
environment-url: ${{ env._ENVIRONMENT_URL }}
state: 'success'
deployment-id: ${{ steps.deployment.outputs.deployment_id }}
- name: Update deployment status to Failure
if: ${{ failure() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1
with:
token: '${{ secrets.GITHUB_TOKEN }}'
environment-url: ${{ env._ENVIRONMENT_URL }}
state: 'failure'
deployment-id: ${{ steps.deployment.outputs.deployment_id }}

367
.github/workflows/deploy-web.yml vendored Normal file
View File

@ -0,0 +1,367 @@
---
name: Deploy Web Vault
run-name: Deploy Web Vault to ${{ inputs.environment }} from ${{ inputs.branch-or-tag }}
on:
workflow_dispatch:
inputs:
environment:
description: 'Environment'
default: 'QA'
type: choice
options:
- USQA
- EUQA
- USPROD
- EUPROD
- USDEV
branch-or-tag:
description: "Branch or Tag name to deploy (examples: 'main', 'feature/sm', 'web-v2023.12.0')"
type: string
default: main
force-delete-destination:
description: "Delete remote files that are not found locally"
type: boolean
default: false
debug:
description: "Debug mode"
type: boolean
default: true
build-web-run-id:
description: "Build-web workflow Run ID to use for artifact download"
type: string
required: false
workflow_call:
inputs:
environment:
description: 'Environment'
default: 'USQA'
type: string
branch-or-tag:
description: "Branch or Tag name to deploy (examples: 'main', 'feature/sm', 'web-v2023.12.0')"
type: string
default: main
force-delete-destination:
description: "Delete remote files that are not found locally"
type: boolean
default: false
debug:
description: "Debug mode"
type: boolean
default: true
build-web-run-id:
description: "Build-web workflow Run ID to use for artifact download"
type: string
required: false
permissions:
deployments: write
jobs:
setup:
name: Setup
runs-on: ubuntu-22.04
outputs:
environment: ${{ steps.config.outputs.environment }}
environment-url: ${{ steps.config.outputs.environment-url }}
environment-name: ${{ steps.config.outputs.environment-name }}
environment-artifact: ${{ steps.config.outputs.environment-artifact }}
azure-login-creds: ${{ steps.config.outputs.azure-login-creds }}
retrieve-secrets-keyvault: ${{ steps.config.outputs.retrieve-secrets-keyvault }}
sync-utility: ${{ steps.config.outputs.sync-utility }}
sync-delete-destination-files: ${{ steps.config.outputs.sync-delete-destination-files }}
steps:
- name: Configure
id: config
run: |
ENV_NAME_LOWER=$(echo "${{ inputs.environment }}" | awk '{print tolower($0)}')
echo "configuring the Web deploy for ${{ inputs.environment }}"
echo "environment=${{ inputs.environment }}" >> $GITHUB_OUTPUT
case ${{ inputs.environment }} in
"USQA")
echo "azure-login-creds=AZURE_KV_US_QA_SERVICE_PRINCIPAL" >> $GITHUB_OUTPUT
echo "retrieve-secrets-keyvault=bw-webvault-rlktusqa-kv" >> $GITHUB_OUTPUT
echo "environment-artifact=web-*-cloud-QA.zip" >> $GITHUB_OUTPUT
echo "environment-name=Web Vault - US QA Cloud" >> $GITHUB_OUTPUT
echo "environment-url=http://vault.$ENV_NAME_LOWER.bitwarden.pw" >> $GITHUB_OUTPUT
;;
"EUQA")
echo "azure-login-creds=AZURE_KV_EU_QA_SERVICE_PRINCIPAL" >> $GITHUB_OUTPUT
echo "retrieve-secrets-keyvault=webvaulteu-westeurope-qa" >> $GITHUB_OUTPUT
echo "environment-artifact=web-*-cloud-euqa.zip" >> $GITHUB_OUTPUT
echo "environment-name=Web Vault - EU QA Cloud" >> $GITHUB_OUTPUT
echo "environment-url=http://vault.$ENV_NAME_LOWER.bitwarden.pw" >> $GITHUB_OUTPUT
;;
"USPROD")
echo "azure-login-creds=AZURE_KV_US_PROD_SERVICE_PRINCIPAL" >> $GITHUB_OUTPUT
echo "retrieve-secrets-keyvault=bw-webvault-klrt-kv" >> $GITHUB_OUTPUT
echo "environment-artifact=web-*-cloud-COMMERCIAL.zip" >> $GITHUB_OUTPUT
echo "environment-name=Web Vault - US Production Cloud" >> $GITHUB_OUTPUT
echo "environment-url=http://vault.bitwarden.com" >> $GITHUB_OUTPUT
;;
"EUPROD")
echo "azure-login-creds=AZURE_KV_EU_PRD_SERVICE_PRINCIPAL" >> $GITHUB_OUTPUT
echo "retrieve-secrets-keyvault=webvault-westeurope-prod" >> $GITHUB_OUTPUT
echo "environment-artifact=web-*-cloud-euprd.zip" >> $GITHUB_OUTPUT
echo "environment-name=Web Vault - EU Production Cloud" >> $GITHUB_OUTPUT
echo "environment-url=http://vault.bitwarden.eu" >> $GITHUB_OUTPUT
;;
"USDEV")
echo "azure-login-creds=AZURE_KV_US_DEV_SERVICE_PRINCIPAL" >> $GITHUB_OUTPUT
echo "retrieve-secrets-keyvault=webvault-eastus-dev" >> $GITHUB_OUTPUT
echo "environment-artifact=web-*-cloud-usdev.zip" >> $GITHUB_OUTPUT
echo "environment-name=Web Vault - US Development Cloud" >> $GITHUB_OUTPUT
echo "environment-url=http://vault.$ENV_NAME_LOWER.bitwarden.pw" >> $GITHUB_OUTPUT
;;
esac
# Set the sync utility to use for deployment to the environment (az-sync or azcopy)
echo "sync-utility=azcopy" >> $GITHUB_OUTPUT
approval:
name: Approval for Deployment to ${{ needs.setup.outputs.environment-name }}
needs: setup
runs-on: ubuntu-22.04
environment: ${{ needs.setup.outputs.environment-name }}
steps:
- name: Success Code
run: exit 0
get-branch-or-tag-sha:
name: Get Branch or Tag SHA
runs-on: ubuntu-22.04
outputs:
branch-or-tag-sha: ${{ steps.get-branch-or-tag-sha.outputs.sha }}
steps:
- name: Checkout Branch
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ inputs.branch-or-tag }}
fetch-depth: 0
- name: Get Branch or Tag SHA
id: get-branch-or-tag-sha
run: |
echo "sha=$(git rev-parse origin/${{ inputs.branch-or-tag }})" >> $GITHUB_OUTPUT
notify-start:
name: Notify Slack with start message
needs:
- approval
- setup
- get-branch-or-tag-sha
runs-on: ubuntu-22.04
if: ${{ always() && contains( inputs.environment , 'QA' ) }}
outputs:
channel_id: ${{ steps.slack-message.outputs.channel_id }}
ts: ${{ steps.slack-message.outputs.ts }}
steps:
- uses: bitwarden/gh-actions/report-deployment-status-to-slack@main
id: slack-message
with:
project: Clients
environment: ${{ needs.setup.outputs.environment-name }}
tag: ${{ inputs.branch-or-tag }}
slack-channel: team-eng-qa-devops
event: 'start'
commit-sha: ${{ needs.get-branch-or-tag-sha.outputs.branch-or-tag-sha }}
url: https://github.com/bitwarden/clients/actions/runs/${{ github.run_id }}
AZURE_KV_CI_SERVICE_PRINCIPAL: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
artifact-check:
name: Check if Web artifact is present
runs-on: ubuntu-22.04
needs: setup
env:
_ENVIRONMENT_ARTIFACT: ${{ needs.setup.outputs.environment-artifact }}
steps:
- name: 'Download latest cloud asset using GitHub Run ID: ${{ inputs.build-web-run-id }}'
if: ${{ inputs.build-web-run-id }}
uses: bitwarden/gh-actions/download-artifacts@main
id: download-latest-artifacts
continue-on-error: true
with:
workflow: build-web.yml
path: apps/web
workflow_conclusion: success
run_id: ${{ inputs.build-web-run-id }}
artifacts: ${{ env._ENVIRONMENT_ARTIFACT }}
- name: 'Download latest cloud asset from branch/tag: ${{ inputs.branch-or-tag }}'
if: ${{ !inputs.build-web-run-id }}
uses: bitwarden/gh-actions/download-artifacts@main
id: download-artifacts
continue-on-error: true
with:
workflow: build-web.yml
path: apps/web
workflow_conclusion: success
branch: ${{ inputs.branch-or-tag }}
artifacts: ${{ env._ENVIRONMENT_ARTIFACT }}
- name: Login to Azure
if: ${{ steps.download-artifacts.outcome == 'failure' }}
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets for Build trigger
if: ${{ steps.download-artifacts.outcome == 'failure' }}
id: retrieve-secret
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: "bitwarden-ci"
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
- name: 'Trigger build web for missing branch/tag ${{ inputs.branch-or-tag }}'
if: ${{ steps.download-artifacts.outcome == 'failure' }}
uses: convictional/trigger-workflow-and-wait@f69fa9eedd3c62a599220f4d5745230e237904be # v1.6.5
with:
owner: bitwarden
repo: clients
github_token: ${{ steps.retrieve-secret.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
workflow_file_name: build-web.yml
ref: ${{ inputs.branch-or-tag }}
wait_interval: 100
azure-deploy:
name: Deploy Web Vault to ${{ inputs.environment }} Storage Account
needs:
- setup
- artifact-check
- approval
runs-on: ubuntu-22.04
env:
_ENVIRONMENT: ${{ needs.setup.outputs.environment }}
_ENVIRONMENT_URL: ${{ needs.setup.outputs.environment-url }}
_ENVIRONMENT_NAME: ${{ needs.setup.outputs.environment-name }}
_ENVIRONMENT_ARTIFACT: ${{ needs.setup.outputs.environment-artifact }}
steps:
- name: Create GitHub deployment
uses: chrnorm/deployment-action@55729fcebec3d284f60f5bcabbd8376437d696b1 # v2.0.7
id: deployment
with:
token: '${{ secrets.GITHUB_TOKEN }}'
initial-status: 'in_progress'
environment-url: ${{ env._ENVIRONMENT_URL }}
environment: ${{ env._ENVIRONMENT_NAME }}
task: 'deploy'
description: 'Deployment from branch/tag: ${{ inputs.branch-or-tag }}'
- name: Login to Azure
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets[needs.setup.outputs.azure-login-creds] }}
- name: Retrieve Storage Account connection string for az sync
if: ${{ needs.setup.outputs.sync-utility == 'az-sync' }}
id: retrieve-secrets-az-sync
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: ${{ needs.setup.outputs.retrieve-secrets-keyvault }}
secrets: "sa-bitwarden-web-vault-dev-key-temp"
- name: Retrieve Storage Account name and SPN credentials for azcopy
if: ${{ needs.setup.outputs.sync-utility == 'azcopy' }}
id: retrieve-secrets-azcopy
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: ${{ needs.setup.outputs.retrieve-secrets-keyvault }}
secrets: "sa-bitwarden-web-vault-name,sp-bitwarden-web-vault-password,sp-bitwarden-web-vault-appid,sp-bitwarden-web-vault-tenant"
- name: 'Download latest cloud asset using GitHub Run ID: ${{ inputs.build-web-run-id }}'
if: ${{ inputs.build-web-run-id }}
uses: bitwarden/gh-actions/download-artifacts@main
id: download-latest-artifacts
continue-on-error: true
with:
workflow: build-web.yml
path: apps/web
workflow_conclusion: success
run_id: ${{ inputs.build-web-run-id }}
artifacts: ${{ env._ENVIRONMENT_ARTIFACT }}
- name: 'Download cloud asset from branch/tag: ${{ inputs.branch-or-tag }}'
if: ${{ !inputs.build-web-run-id }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
workflow: build-web.yml
path: apps/web
workflow_conclusion: success
branch: ${{ inputs.branch-or-tag }}
artifacts: ${{ env._ENVIRONMENT_ARTIFACT }}
- name: Unzip build asset
working-directory: apps/web
run: unzip ${{ env._ENVIRONMENT_ARTIFACT }}
- name: Sync to Azure Storage Account using az storage blob sync
if: ${{ needs.setup.outputs.sync-utility == 'az-sync' }}
working-directory: apps/web
run: |
az storage blob sync \
--source "./build" \
--container '$web' \
--connection-string "${{ steps.retrieve-secrets-az-sync.outputs.sa-bitwarden-web-vault-dev-key-temp }}" \
--delete-destination=${{ inputs.force-delete-destination }}
- name: Sync to Azure Storage Account using azcopy
if: ${{ needs.setup.outputs.sync-utility == 'azcopy' }}
working-directory: apps/web
env:
AZCOPY_AUTO_LOGIN_TYPE: SPN
AZCOPY_SPA_APPLICATION_ID: ${{ steps.retrieve-secrets-azcopy.outputs.sp-bitwarden-web-vault-appid }}
AZCOPY_SPA_CLIENT_SECRET: ${{ steps.retrieve-secrets-azcopy.outputs.sp-bitwarden-web-vault-password }}
AZCOPY_TENANT_ID: ${{ steps.retrieve-secrets-azcopy.outputs.sp-bitwarden-web-vault-tenant }}
run: |
azcopy sync ./build 'https://${{ steps.retrieve-secrets-azcopy.outputs.sa-bitwarden-web-vault-name }}.blob.core.windows.net/$web/' \
--delete-destination=${{ inputs.force-delete-destination }} --compare-hash="MD5"
- name: Debug sync logs
if: ${{ inputs.debug }}
run: cat /home/runner/.azcopy/*.log
- name: Debug index.html
if: ${{ inputs.debug }}
run: cat apps/web/build/index.html
- name: Update deployment status to Success
if: success()
uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
with:
token: '${{ secrets.GITHUB_TOKEN }}'
environment-url: ${{ env._ENVIRONMENT_URL }}
state: 'success'
deployment-id: ${{ steps.deployment.outputs.deployment_id }}
- name: Update deployment status to Failure
if: failure()
uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
with:
token: '${{ secrets.GITHUB_TOKEN }}'
environment-url: ${{ env._ENVIRONMENT_URL }}
state: 'failure'
deployment-id: ${{ steps.deployment.outputs.deployment_id }}
notify:
name: Notify Slack with result
runs-on: ubuntu-22.04
if: ${{ always() && contains( inputs.environment , 'QA' ) }}
needs:
- notify-start
- azure-deploy
- setup
- get-branch-or-tag-sha
steps:
- uses: bitwarden/gh-actions/report-deployment-status-to-slack@main
with:
project: Clients
environment: ${{ needs.setup.outputs.environment-name }}
tag: ${{ inputs.branch-or-tag }}
slack-channel: ${{ needs.notify-start.outputs.channel_id }}
event: ${{ needs.azure-deploy.result }}
url: https://github.com/bitwarden/clients/actions/runs/${{ github.run_id }}
commit-sha: ${{ needs.get-branch-or-tag-sha.outputs.branch-or-tag-sha }}
update-ts: ${{ needs.notify-start.outputs.ts }}
AZURE_KV_CI_SERVICE_PRINCIPAL: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}

View File

@ -8,7 +8,7 @@ on:
jobs: jobs:
enforce-label: enforce-label:
name: EnforceLabel name: EnforceLabel
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
steps: steps:
- name: Enforce Label - name: Enforce Label
uses: yogevbd/enforce-label-action@a3c219da6b8fa73f6ba62b68ff09c469b3a1c024 # 2.2.2 uses: yogevbd/enforce-label-action@a3c219da6b8fa73f6ba62b68ff09c469b3a1c024 # 2.2.2

View File

@ -1,5 +1,5 @@
# Runs creation of Pull Requests # Runs creation of Pull Requests
# If the PR destination branch is master, add a needs-qa label # If the PR destination branch is main, add a needs-qa label unless created by renovate[bot]
--- ---
name: Label Issue Pull Request name: Label Issue Pull Request
@ -10,11 +10,12 @@ on:
paths-ignore: paths-ignore:
- .github/workflows/** # We don't need QA on workflow changes - .github/workflows/** # We don't need QA on workflow changes
branches: branches:
- 'master' # We only want to check when PRs target master - 'main' # We only want to check when PRs target main
jobs: jobs:
add-needs-qa-label: add-needs-qa-label:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ github.actor != 'renovate[bot]' }}
steps: steps:
- name: Add label to pull request - name: Add label to pull request
uses: andymckay/labeler@e6c4322d0397f3240f0e7e30a33b5c5df2d39e90 # 1.0.4 uses: andymckay/labeler@e6c4322d0397f3240f0e7e30a33b5c5df2d39e90 # 1.0.4

View File

@ -18,10 +18,10 @@ defaults:
jobs: jobs:
lint: lint:
name: Lint name: Lint
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Lint filenames (no capital characters) - name: Lint filenames (no capital characters)
run: | run: |
@ -38,12 +38,19 @@ jobs:
> tmp.txt > tmp.txt
diff <(sort .github/whitelist-capital-letters.txt) <(sort tmp.txt) diff <(sort .github/whitelist-capital-letters.txt) <(sort tmp.txt)
- name: Get Node Version
id: retrieve-node-version
run: |
NODE_NVMRC=$(cat .nvmrc)
NODE_VERSION=${NODE_NVMRC/v/''}
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
- name: Set up Node - name: Set up Node
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with: with:
cache: 'npm' cache: 'npm'
cache-dependency-path: '**/package-lock.json' cache-dependency-path: '**/package-lock.json'
node-version: '18' node-version: ${{ steps.retrieve-node-version.outputs.node_version }}
- name: Run linter - name: Run linter
run: | run: |

View File

@ -22,12 +22,12 @@ defaults:
jobs: jobs:
setup: setup:
name: Setup name: Setup
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
outputs: outputs:
release-version: ${{ steps.version.outputs.version }} release-version: ${{ steps.version.outputs.version }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Branch check - name: Branch check
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
@ -41,7 +41,7 @@ jobs:
- name: Check Release Version - name: Check Release Version
id: version id: version
uses: bitwarden/gh-actions/release-version-check@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/release-version-check@main
with: with:
release-type: ${{ github.event.inputs.release_type }} release-type: ${{ github.event.inputs.release_type }}
project-type: ts project-type: ts
@ -52,11 +52,11 @@ jobs:
locales-test: locales-test:
name: Locales Test name: Locales Test
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
needs: setup needs: setup
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Testing locales - extName length - name: Testing locales - extName length
run: | run: |
@ -86,13 +86,13 @@ jobs:
release: release:
name: Create GitHub Release name: Create GitHub Release
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
needs: needs:
- setup - setup
- locales-test - locales-test
steps: steps:
- name: Create GitHub deployment - name: Create GitHub deployment
uses: chrnorm/deployment-action@d42cde7132fcec920de534fffc3be83794335c00 # v2.0.5 uses: chrnorm/deployment-action@55729fcebec3d284f60f5bcabbd8376437d696b1 # v2.0.7
id: deployment id: deployment
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
@ -103,7 +103,7 @@ jobs:
- name: Download latest Release build artifacts - name: Download latest Release build artifacts
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-browser.yml workflow: build-browser.yml
workflow_conclusion: success workflow_conclusion: success
@ -114,13 +114,13 @@ jobs:
dist-firefox-*.zip, dist-firefox-*.zip,
dist-edge-*.zip' dist-edge-*.zip'
- name: Dry Run - Download latest master build artifacts - name: Dry Run - Download latest build artifacts
if: ${{ github.event.inputs.release_type == 'Dry Run' }} if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-browser.yml workflow: build-browser.yml
workflow_conclusion: success workflow_conclusion: success
branch: master branch: main
artifacts: 'browser-source-*.zip, artifacts: 'browser-source-*.zip,
dist-chrome-*.zip, dist-chrome-*.zip,
dist-opera-*.zip, dist-opera-*.zip,
@ -139,7 +139,7 @@ jobs:
- name: Create release - name: Create release
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: ncipollo/release-action@a2e71bdd4e7dab70ca26a852f29600c98b33153e # v1.12.0 uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0
with: with:
artifacts: 'browser-source-${{ needs.setup.outputs.release-version }}.zip, artifacts: 'browser-source-${{ needs.setup.outputs.release-version }}.zip,
dist-chrome-${{ needs.setup.outputs.release-version }}.zip, dist-chrome-${{ needs.setup.outputs.release-version }}.zip,
@ -155,7 +155,7 @@ jobs:
- name: Update deployment status to Success - name: Update deployment status to Success
if: ${{ success() }} if: ${{ success() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
state: 'success' state: 'success'
@ -163,7 +163,7 @@ jobs:
- name: Update deployment status to Failure - name: Update deployment status to Failure
if: ${{ failure() }} if: ${{ failure() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
state: 'failure' state: 'failure'

View File

@ -15,12 +15,12 @@ on:
- Redeploy - Redeploy
- Dry Run - Dry Run
snap_publish: snap_publish:
description: 'Publish to snap store' description: 'Publish to Snap store'
required: true required: true
default: true default: true
type: boolean type: boolean
choco_publish: choco_publish:
description: 'Publish to chocolatey store' description: 'Publish to Chocolatey store'
required: true required: true
default: true default: true
type: boolean type: boolean
@ -38,12 +38,12 @@ defaults:
jobs: jobs:
setup: setup:
name: Setup name: Setup
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
outputs: outputs:
release-version: ${{ steps.version.outputs.version }} release-version: ${{ steps.version.outputs.version }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Branch check - name: Branch check
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
@ -57,7 +57,7 @@ jobs:
- name: Check Release Version - name: Check Release Version
id: version id: version
uses: bitwarden/gh-actions/release-version-check@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/release-version-check@main
with: with:
release-type: ${{ github.event.inputs.release_type }} release-type: ${{ github.event.inputs.release_type }}
project-type: ts project-type: ts
@ -67,7 +67,7 @@ jobs:
- name: Create GitHub deployment - name: Create GitHub deployment
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: chrnorm/deployment-action@d42cde7132fcec920de534fffc3be83794335c00 # v2.0.5 uses: chrnorm/deployment-action@55729fcebec3d284f60f5bcabbd8376437d696b1 # v2.0.7
id: deployment id: deployment
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
@ -78,7 +78,7 @@ jobs:
- name: Download all Release artifacts - name: Download all Release artifacts
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-cli.yml workflow: build-cli.yml
path: apps/cli path: apps/cli
@ -87,16 +87,16 @@ jobs:
- name: Dry Run - Download all artifacts - name: Dry Run - Download all artifacts
if: ${{ github.event.inputs.release_type == 'Dry Run' }} if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-cli.yml workflow: build-cli.yml
path: apps/cli path: apps/cli
workflow_conclusion: success workflow_conclusion: success
branch: master branch: main
- name: Create release - name: Create release
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: ncipollo/release-action@a2e71bdd4e7dab70ca26a852f29600c98b33153e # v1.12.0 uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0
env: env:
PKG_VERSION: ${{ steps.version.outputs.version }} PKG_VERSION: ${{ steps.version.outputs.version }}
with: with:
@ -118,7 +118,7 @@ jobs:
- name: Update deployment status to Success - name: Update deployment status to Success
if: ${{ github.event.inputs.release_type != 'Dry Run' && success() }} if: ${{ github.event.inputs.release_type != 'Dry Run' && success() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
state: 'success' state: 'success'
@ -126,7 +126,7 @@ jobs:
- name: Update deployment status to Failure - name: Update deployment status to Failure
if: ${{ github.event.inputs.release_type != 'Dry Run' && failure() }} if: ${{ github.event.inputs.release_type != 'Dry Run' && failure() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
state: 'failure' state: 'failure'
@ -134,35 +134,33 @@ jobs:
snap: snap:
name: Deploy Snap name: Deploy Snap
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
needs: setup needs: setup
if: inputs.snap_publish if: inputs.snap_publish
env: env:
_PKG_VERSION: ${{ needs.setup.outputs.release-version }} _PKG_VERSION: ${{ needs.setup.outputs.release-version }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Login to Azure - name: Login to Azure
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "snapcraft-store-token" secrets: "snapcraft-store-token"
- name: Install Snap - name: Install Snap
uses: samuelmeuli/action-snapcraft@d33c176a9b784876d966f80fb1b461808edc0641 # v2.1.1 uses: samuelmeuli/action-snapcraft@d33c176a9b784876d966f80fb1b461808edc0641 # v2.1.1
with:
snapcraft_token: ${{ steps.retrieve-secrets.outputs.snapcraft-store-token }}
- name: Download artifacts - name: Download artifacts
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-cli.yml workflow: build-cli.yml
path: apps/cli path: apps/cli
@ -172,39 +170,41 @@ jobs:
- name: Dry Run - Download artifacts - name: Dry Run - Download artifacts
if: ${{ github.event.inputs.release_type == 'Dry Run' }} if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-cli.yml workflow: build-cli.yml
path: apps/cli path: apps/cli
workflow_conclusion: success workflow_conclusion: success
branch: master branch: main
artifacts: bw_${{ env._PKG_VERSION }}_amd64.snap artifacts: bw_${{ env._PKG_VERSION }}_amd64.snap
- name: Publish Snap & logout - name: Publish Snap & logout
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ steps.retrieve-secrets.outputs.snapcraft-store-token }}
run: | run: |
snapcraft push bw_${{ env._PKG_VERSION }}_amd64.snap --release stable snapcraft upload bw_${{ env._PKG_VERSION }}_amd64.snap --release stable
snapcraft logout snapcraft logout
choco: choco:
name: Deploy Choco name: Deploy Choco
runs-on: windows-2019 runs-on: windows-2022
needs: setup needs: setup
if: inputs.choco_publish if: inputs.choco_publish
env: env:
_PKG_VERSION: ${{ needs.setup.outputs.release-version }} _PKG_VERSION: ${{ needs.setup.outputs.release-version }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Login to Azure - name: Login to Azure
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "cli-choco-api-key" secrets: "cli-choco-api-key"
@ -220,7 +220,7 @@ jobs:
- name: Download artifacts - name: Download artifacts
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-cli.yml workflow: build-cli.yml
path: apps/cli/dist path: apps/cli/dist
@ -230,12 +230,12 @@ jobs:
- name: Dry Run - Download artifacts - name: Dry Run - Download artifacts
if: ${{ github.event.inputs.release_type == 'Dry Run' }} if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-cli.yml workflow: build-cli.yml
path: apps/cli/dist path: apps/cli/dist
workflow_conclusion: success workflow_conclusion: success
branch: master branch: main
artifacts: bitwarden-cli.${{ env._PKG_VERSION }}.nupkg artifacts: bitwarden-cli.${{ env._PKG_VERSION }}.nupkg
- name: Push to Chocolatey - name: Push to Chocolatey
@ -247,30 +247,30 @@ jobs:
npm: npm:
name: Publish NPM name: Publish NPM
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
needs: setup needs: setup
if: inputs.npm_publish if: inputs.npm_publish
env: env:
_PKG_VERSION: ${{ needs.setup.outputs.release-version }} _PKG_VERSION: ${{ needs.setup.outputs.release-version }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Login to Azure - name: Login to Azure
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "npm-api-key" secrets: "npm-api-key"
- name: Download artifacts - name: Download artifacts
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-cli.yml workflow: build-cli.yml
path: apps/cli/build path: apps/cli/build
@ -280,12 +280,12 @@ jobs:
- name: Dry Run - Download artifacts - name: Dry Run - Download artifacts
if: ${{ github.event.inputs.release_type == 'Dry Run' }} if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-cli.yml workflow: build-cli.yml
path: apps/cli/build path: apps/cli/build
workflow_conclusion: success workflow_conclusion: success
branch: master branch: main
artifacts: bitwarden-cli-${{ env._PKG_VERSION }}-npm-build.zip artifacts: bitwarden-cli-${{ env._PKG_VERSION }}-npm-build.zip
- name: Setup NPM - name: Setup NPM

View File

@ -15,21 +15,22 @@ defaults:
jobs: jobs:
setup: setup:
name: Setup name: Setup
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
outputs: outputs:
release-version: ${{ steps.version.outputs.version }} release-version: ${{ steps.version.outputs.version }}
release-channel: ${{ steps.release-channel.outputs.channel }} release-channel: ${{ steps.release-channel.outputs.channel }}
branch-name: ${{ steps.branch.outputs.branch-name }} branch-name: ${{ steps.branch.outputs.branch-name }}
build_number: ${{ steps.increment-version.outputs.build_number }} build_number: ${{ steps.increment-version.outputs.build_number }}
node_version: ${{ steps.retrieve-node-version.outputs.node_version }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Branch check - name: Branch check
run: | run: |
if [[ "$GITHUB_REF" != "refs/heads/master" ]] && [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then if [[ "$GITHUB_REF" != "refs/heads/main" ]] && [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then
echo "===================================" echo "==================================="
echo "[!] Can only release from the 'master', 'rc' or 'hotfix-rc' branches" echo "[!] Can only release from the 'main', 'rc' or 'hotfix-rc' branches"
echo "===================================" echo "==================================="
exit 1 exit 1
fi fi
@ -47,7 +48,7 @@ jobs:
- name: Check Release Version - name: Check Release Version
id: version id: version
uses: bitwarden/gh-actions/release-version-check@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/release-version-check@main
with: with:
release-type: 'Initial Release' release-type: 'Initial Release'
project-type: ts project-type: ts
@ -104,35 +105,36 @@ jobs:
echo "branch-name=$branch_name" >> $GITHUB_OUTPUT echo "branch-name=$branch_name" >> $GITHUB_OUTPUT
- name: Get Node Version
id: retrieve-node-version
run: |
NODE_NVMRC=$(cat .nvmrc)
NODE_VERSION=${NODE_NVMRC/v/''}
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
linux: linux:
name: Linux Build name: Linux Build
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
needs: setup needs: setup
env: env:
_PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }} _PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }}
_NODE_VERSION: ${{ needs.setup.outputs.node_version }}
NODE_OPTIONS: --max_old_space_size=4096
defaults: defaults:
run: run:
working-directory: apps/desktop working-directory: apps/desktop
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with: with:
ref: ${{ needs.setup.outputs.branch-name }} ref: ${{ needs.setup.outputs.branch-name }}
- name: Set up Node - name: Set up Node
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with: with:
cache: 'npm' cache: 'npm'
cache-dependency-path: '**/package-lock.json' cache-dependency-path: '**/package-lock.json'
node-version: '18' node-version: ${{ env._NODE_VERSION }}
- name: Set Node options
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
- name: Install node-gyp
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Set up environment - name: Set up environment
run: | run: |
@ -157,42 +159,42 @@ jobs:
run: npm run dist:lin run: npm run dist:lin
- name: Upload .deb artifact - name: Upload .deb artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden-${{ env._PACKAGE_VERSION }}-amd64.deb name: Bitwarden-${{ env._PACKAGE_VERSION }}-amd64.deb
path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-amd64.deb path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-amd64.deb
if-no-files-found: error if-no-files-found: error
- name: Upload .rpm artifact - name: Upload .rpm artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.rpm name: Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.rpm
path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.rpm path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.rpm
if-no-files-found: error if-no-files-found: error
- name: Upload .freebsd artifact - name: Upload .freebsd artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64.freebsd name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64.freebsd
path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64.freebsd path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64.freebsd
if-no-files-found: error if-no-files-found: error
- name: Upload .snap artifact - name: Upload .snap artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bitwarden_${{ env._PACKAGE_VERSION }}_amd64.snap name: bitwarden_${{ env._PACKAGE_VERSION }}_amd64.snap
path: apps/desktop/dist/bitwarden_${{ env._PACKAGE_VERSION }}_amd64.snap path: apps/desktop/dist/bitwarden_${{ env._PACKAGE_VERSION }}_amd64.snap
if-no-files-found: error if-no-files-found: error
- name: Upload .AppImage artifact - name: Upload .AppImage artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.AppImage name: Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.AppImage path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
if-no-files-found: error if-no-files-found: error
- name: Upload auto-update artifact - name: Upload auto-update artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: ${{ needs.setup.outputs.release-channel }}-linux.yml name: ${{ needs.setup.outputs.release-channel }}-linux.yml
path: apps/desktop/dist/${{ needs.setup.outputs.release-channel }}-linux.yml path: apps/desktop/dist/${{ needs.setup.outputs.release-channel }}-linux.yml
@ -201,7 +203,7 @@ jobs:
windows: windows:
name: Windows Build name: Windows Build
runs-on: windows-2019 runs-on: windows-2022
needs: setup needs: setup
defaults: defaults:
run: run:
@ -209,29 +211,23 @@ jobs:
working-directory: apps/desktop working-directory: apps/desktop
env: env:
_PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }} _PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }}
_NODE_VERSION: ${{ needs.setup.outputs.node_version }}
NODE_OPTIONS: --max_old_space_size=4096
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with: with:
ref: ${{ needs.setup.outputs.branch-name }} ref: ${{ needs.setup.outputs.branch-name }}
- name: Set up Node - name: Set up Node
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with: with:
cache: 'npm' cache: 'npm'
cache-dependency-path: '**/package-lock.json' cache-dependency-path: '**/package-lock.json'
node-version: '18' node-version: ${{ env._NODE_VERSION }}
- name: Set Node options
run: echo "NODE_OPTIONS=--max_old_space_size=4096" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: Install node-gyp
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Install AST - name: Install AST
uses: bitwarden/gh-actions/install-ast@a30e9c3d658dc97c4c2e61ec749fdab64b83386c run: dotnet tool install --global AzureSignTool --version 4.0.1
- name: Set up environment - name: Set up environment
run: choco install checksum --no-progress run: choco install checksum --no-progress
@ -243,13 +239,13 @@ jobs:
choco --version choco --version
- name: Login to Azure - name: Login to Azure
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "code-signing-vault-url, secrets: "code-signing-vault-url,
@ -304,91 +300,91 @@ jobs:
-NewName bitwarden-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z -NewName bitwarden-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z
- name: Upload portable exe artifact - name: Upload portable exe artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden-Portable-${{ env._PACKAGE_VERSION }}.exe name: Bitwarden-Portable-${{ env._PACKAGE_VERSION }}.exe
path: apps/desktop/dist/Bitwarden-Portable-${{ env._PACKAGE_VERSION }}.exe path: apps/desktop/dist/Bitwarden-Portable-${{ env._PACKAGE_VERSION }}.exe
if-no-files-found: error if-no-files-found: error
- name: Upload installer exe artifact - name: Upload installer exe artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden-Installer-${{ env._PACKAGE_VERSION }}.exe name: Bitwarden-Installer-${{ env._PACKAGE_VERSION }}.exe
path: apps/desktop/dist/nsis-web/Bitwarden-Installer-${{ env._PACKAGE_VERSION }}.exe path: apps/desktop/dist/nsis-web/Bitwarden-Installer-${{ env._PACKAGE_VERSION }}.exe
if-no-files-found: error if-no-files-found: error
- name: Upload appx ia32 artifact - name: Upload appx ia32 artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.appx name: Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.appx
path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.appx
if-no-files-found: error if-no-files-found: error
- name: Upload store appx ia32 artifact - name: Upload store appx ia32 artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden-${{ env._PACKAGE_VERSION }}-ia32-store.appx name: Bitwarden-${{ env._PACKAGE_VERSION }}-ia32-store.appx
path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32-store.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32-store.appx
if-no-files-found: error if-no-files-found: error
- name: Upload NSIS ia32 artifact - name: Upload NSIS ia32 artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bitwarden-${{ env._PACKAGE_VERSION }}-ia32.nsis.7z name: bitwarden-${{ env._PACKAGE_VERSION }}-ia32.nsis.7z
path: apps/desktop/dist/nsis-web/bitwarden-${{ env._PACKAGE_VERSION }}-ia32.nsis.7z path: apps/desktop/dist/nsis-web/bitwarden-${{ env._PACKAGE_VERSION }}-ia32.nsis.7z
if-no-files-found: error if-no-files-found: error
- name: Upload appx x64 artifact - name: Upload appx x64 artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64.appx name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64.appx
path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64.appx
if-no-files-found: error if-no-files-found: error
- name: Upload store appx x64 artifact - name: Upload store appx x64 artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64-store.appx name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64-store.appx
path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64-store.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64-store.appx
if-no-files-found: error if-no-files-found: error
- name: Upload NSIS x64 artifact - name: Upload NSIS x64 artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bitwarden-${{ env._PACKAGE_VERSION }}-x64.nsis.7z name: bitwarden-${{ env._PACKAGE_VERSION }}-x64.nsis.7z
path: apps/desktop/dist/nsis-web/bitwarden-${{ env._PACKAGE_VERSION }}-x64.nsis.7z path: apps/desktop/dist/nsis-web/bitwarden-${{ env._PACKAGE_VERSION }}-x64.nsis.7z
if-no-files-found: error if-no-files-found: error
- name: Upload appx ARM64 artifact - name: Upload appx ARM64 artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.appx name: Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.appx
path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.appx
if-no-files-found: error if-no-files-found: error
- name: Upload store appx ARM64 artifact - name: Upload store appx ARM64 artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden-${{ env._PACKAGE_VERSION }}-arm64-store.appx name: Bitwarden-${{ env._PACKAGE_VERSION }}-arm64-store.appx
path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64-store.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64-store.appx
if-no-files-found: error if-no-files-found: error
- name: Upload NSIS ARM64 artifact - name: Upload NSIS ARM64 artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bitwarden-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z name: bitwarden-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z
path: apps/desktop/dist/nsis-web/bitwarden-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z path: apps/desktop/dist/nsis-web/bitwarden-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z
if-no-files-found: error if-no-files-found: error
- name: Upload nupkg artifact - name: Upload nupkg artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bitwarden.${{ env._PACKAGE_VERSION }}.nupkg name: bitwarden.${{ env._PACKAGE_VERSION }}.nupkg
path: apps/desktop/dist/chocolatey/bitwarden.${{ env._PACKAGE_VERSION }}.nupkg path: apps/desktop/dist/chocolatey/bitwarden.${{ env._PACKAGE_VERSION }}.nupkg
if-no-files-found: error if-no-files-found: error
- name: Upload auto-update artifact - name: Upload auto-update artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: ${{ needs.setup.outputs.release-channel }}.yml name: ${{ needs.setup.outputs.release-channel }}.yml
path: apps/desktop/dist/nsis-web/${{ needs.setup.outputs.release-channel }}.yml path: apps/desktop/dist/nsis-web/${{ needs.setup.outputs.release-channel }}.yml
@ -397,33 +393,30 @@ jobs:
macos-build: macos-build:
name: MacOS Build name: MacOS Build
# Note, this workflow is running on macOS 11 to maintain compatibility with macOS 10.15 Catalina,
# as the newer versions will case the native modules to be incompatible with older macOS systems
# This version should stay pinned until we drop support for macOS 10.15, or we drop the native modules
runs-on: macos-11 runs-on: macos-11
needs: setup needs: setup
env: env:
_PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }} _PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }}
_NODE_VERSION: ${{ needs.setup.outputs.node_version }}
NODE_OPTIONS: --max_old_space_size=4096
defaults: defaults:
run: run:
working-directory: apps/desktop working-directory: apps/desktop
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with: with:
ref: ${{ needs.setup.outputs.branch-name }} ref: ${{ needs.setup.outputs.branch-name }}
- name: Set up Node - name: Set up Node
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with: with:
cache: 'npm' cache: 'npm'
cache-dependency-path: '**/package-lock.json' cache-dependency-path: '**/package-lock.json'
node-version: '18' node-version: ${{ env._NODE_VERSION }}
- name: Set Node options
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
- name: Install node-gyp
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Print environment - name: Print environment
run: | run: |
@ -434,70 +427,78 @@ jobs:
- name: Cache Build - name: Cache Build
id: build-cache id: build-cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4.0.1
with: with:
path: apps/desktop/build path: apps/desktop/build
key: ${{ runner.os }}-${{ github.run_id }}-build key: ${{ runner.os }}-${{ github.run_id }}-build
- name: Cache Safari - name: Cache Safari
id: safari-cache id: safari-cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4.0.1
with: with:
path: apps/browser/dist/Safari path: apps/browser/dist/Safari
key: ${{ runner.os }}-${{ github.run_id }}-safari-extension key: ${{ runner.os }}-${{ github.run_id }}-safari-extension
- name: Decrypt secrets - name: Download Provisioning Profiles secrets
env: env:
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} ACCOUNT_NAME: bitwardenci
CONTAINER_NAME: profiles
run: | run: |
mkdir -p $HOME/secrets mkdir -p $HOME/secrets
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/bitwarden-desktop-key.p12" \ az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
"$GITHUB_WORKSPACE/.github/secrets/bitwarden-desktop-key.p12.gpg" --name bitwarden_desktop_appstore.provisionprofile \
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ --file $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \
--output "$HOME/secrets/appstore-app-cert.p12" \ --output none
"$GITHUB_WORKSPACE/.github/secrets/appstore-app-cert.p12.gpg"
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - name: Get certificates
--output "$HOME/secrets/appstore-installer-cert.p12" \ run: |
"$GITHUB_WORKSPACE/.github/secrets/appstore-installer-cert.p12.gpg" mkdir -p $HOME/certificates
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/devid-app-cert.p12" \ az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/bitwarden-desktop-key |
"$GITHUB_WORKSPACE/.github/secrets/devid-app-cert.p12.gpg" jq -r .value | base64 -d > $HOME/certificates/bitwarden-desktop-key.p12
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/devid-installer-cert.p12" \ az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/appstore-app-cert |
"$GITHUB_WORKSPACE/.github/secrets/devid-installer-cert.p12.gpg" jq -r .value | base64 -d > $HOME/certificates/appstore-app-cert.p12
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/macdev-cert.p12" \ az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/appstore-installer-cert |
"$GITHUB_WORKSPACE/.github/secrets/macdev-cert.p12.gpg" jq -r .value | base64 -d > $HOME/certificates/appstore-installer-cert.p12
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/bitwarden_desktop_appstore.provisionprofile" \ az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-app-cert |
"$GITHUB_WORKSPACE/.github/secrets/bitwarden_desktop_appstore.provisionprofile.gpg" jq -r .value | base64 -d > $HOME/certificates/devid-app-cert.p12
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-installer-cert |
jq -r .value | base64 -d > $HOME/certificates/devid-installer-cert.p12
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/macdev-cert |
jq -r .value | base64 -d > $HOME/certificates/macdev-cert.p12
- name: Set up keychain - name: Set up keychain
env: env:
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
DESKTOP_KEY_PASSWORD: ${{ secrets.DESKTOP_KEY_PASSWORD }}
DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_PASSWORD }}
APPSTORE_CERT_PASSWORD: ${{ secrets.APPSTORE_CERT_PASSWORD }}
MACDEV_CERT_PASSWORD: ${{ secrets.MACDEV_CERT_PASSWORD }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
run: | run: |
security create-keychain -p $KEYCHAIN_PASSWORD build.keychain security create-keychain -p $KEYCHAIN_PASSWORD build.keychain
security default-keychain -s build.keychain security default-keychain -s build.keychain
security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain
security set-keychain-settings -lut 1200 build.keychain security set-keychain-settings -lut 1200 build.keychain
security import "$HOME/secrets/bitwarden-desktop-key.p12" -k build.keychain -P $DESKTOP_KEY_PASSWORD \ security import "$HOME/certificates/bitwarden-desktop-key.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/devid-app-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \
security import "$HOME/certificates/devid-app-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/devid-installer-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \
security import "$HOME/certificates/devid-installer-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/appstore-app-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \
security import "$HOME/certificates/appstore-app-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/appstore-installer-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \
security import "$HOME/certificates/appstore-installer-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/macdev-cert.p12" -k build.keychain -P $MACDEV_CERT_PASSWORD \
security import "$HOME/certificates/macdev-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain
- name: Set up provisioning profiles - name: Set up provisioning profiles
@ -524,35 +525,32 @@ jobs:
macos-package-github: macos-package-github:
name: MacOS Package GitHub Release Assets name: MacOS Package GitHub Release Assets
# Note, this workflow is running on macOS 11 to maintain compatibility with macOS 10.15 Catalina,
# as the newer versions will case the native modules to be incompatible with older macOS systems
# This version should stay pinned until we drop support for macOS 10.15, or we drop the native modules
runs-on: macos-11 runs-on: macos-11
needs: needs:
- setup - setup
- macos-build - macos-build
env: env:
_PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }} _PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }}
_NODE_VERSION: ${{ needs.setup.outputs.node_version }}
NODE_OPTIONS: --max_old_space_size=4096
defaults: defaults:
run: run:
working-directory: apps/desktop working-directory: apps/desktop
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with: with:
ref: ${{ needs.setup.outputs.branch-name }} ref: ${{ needs.setup.outputs.branch-name }}
- name: Set up Node - name: Set up Node
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with: with:
cache: 'npm' cache: 'npm'
cache-dependency-path: '**/package-lock.json' cache-dependency-path: '**/package-lock.json'
node-version: '18' node-version: ${{ env._NODE_VERSION }}
- name: Set Node options
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
- name: Install node-gyp
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Print environment - name: Print environment
run: | run: |
@ -563,70 +561,84 @@ jobs:
- name: Get Build Cache - name: Get Build Cache
id: build-cache id: build-cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4.0.1
with: with:
path: apps/desktop/build path: apps/desktop/build
key: ${{ runner.os }}-${{ github.run_id }}-build key: ${{ runner.os }}-${{ github.run_id }}-build
- name: Setup Safari Cache - name: Setup Safari Cache
id: safari-cache id: safari-cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4.0.1
with: with:
path: apps/browser/dist/Safari path: apps/browser/dist/Safari
key: ${{ runner.os }}-${{ github.run_id }}-safari-extension key: ${{ runner.os }}-${{ github.run_id }}-safari-extension
- name: Decrypt secrets - name: Login to Azure
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Download Provisioning Profiles secrets
env: env:
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} ACCOUNT_NAME: bitwardenci
CONTAINER_NAME: profiles
run: | run: |
mkdir -p $HOME/secrets mkdir -p $HOME/secrets
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/bitwarden-desktop-key.p12" \ az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
"$GITHUB_WORKSPACE/.github/secrets/bitwarden-desktop-key.p12.gpg" --name bitwarden_desktop_appstore.provisionprofile \
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ --file $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \
--output "$HOME/secrets/appstore-app-cert.p12" \ --output none
"$GITHUB_WORKSPACE/.github/secrets/appstore-app-cert.p12.gpg"
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - name: Get certificates
--output "$HOME/secrets/appstore-installer-cert.p12" \ run: |
"$GITHUB_WORKSPACE/.github/secrets/appstore-installer-cert.p12.gpg" mkdir -p $HOME/certificates
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/devid-app-cert.p12" \ az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/bitwarden-desktop-key |
"$GITHUB_WORKSPACE/.github/secrets/devid-app-cert.p12.gpg" jq -r .value | base64 -d > $HOME/certificates/bitwarden-desktop-key.p12
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/devid-installer-cert.p12" \ az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/appstore-app-cert |
"$GITHUB_WORKSPACE/.github/secrets/devid-installer-cert.p12.gpg" jq -r .value | base64 -d > $HOME/certificates/appstore-app-cert.p12
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/macdev-cert.p12" \ az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/appstore-installer-cert |
"$GITHUB_WORKSPACE/.github/secrets/macdev-cert.p12.gpg" jq -r .value | base64 -d > $HOME/certificates/appstore-installer-cert.p12
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/bitwarden_desktop_appstore.provisionprofile" \ az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-app-cert |
"$GITHUB_WORKSPACE/.github/secrets/bitwarden_desktop_appstore.provisionprofile.gpg" jq -r .value | base64 -d > $HOME/certificates/devid-app-cert.p12
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-installer-cert |
jq -r .value | base64 -d > $HOME/certificates/devid-installer-cert.p12
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/macdev-cert |
jq -r .value | base64 -d > $HOME/certificates/macdev-cert.p12
- name: Set up keychain - name: Set up keychain
env: env:
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
DESKTOP_KEY_PASSWORD: ${{ secrets.DESKTOP_KEY_PASSWORD }}
DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_PASSWORD }}
APPSTORE_CERT_PASSWORD: ${{ secrets.APPSTORE_CERT_PASSWORD }}
MACDEV_CERT_PASSWORD: ${{ secrets.MACDEV_CERT_PASSWORD }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
run: | run: |
security create-keychain -p $KEYCHAIN_PASSWORD build.keychain security create-keychain -p $KEYCHAIN_PASSWORD build.keychain
security default-keychain -s build.keychain security default-keychain -s build.keychain
security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain
security set-keychain-settings -lut 1200 build.keychain security set-keychain-settings -lut 1200 build.keychain
security import "$HOME/secrets/bitwarden-desktop-key.p12" -k build.keychain -P $DESKTOP_KEY_PASSWORD \
security import "$HOME/certificates/bitwarden-desktop-key.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/devid-app-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \
security import "$HOME/certificates/devid-app-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/devid-installer-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \
security import "$HOME/certificates/devid-installer-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/appstore-app-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \
security import "$HOME/certificates/appstore-app-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/appstore-installer-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \
security import "$HOME/certificates/appstore-installer-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/macdev-cert.p12" -k build.keychain -P $MACDEV_CERT_PASSWORD \
security import "$HOME/certificates/macdev-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain
- name: Set up provisioning profiles - name: Set up provisioning profiles
@ -653,7 +665,7 @@ jobs:
- name: Download artifact from hotfix-rc - name: Download artifact from hotfix-rc
if: github.ref == 'refs/heads/hotfix-rc' if: github.ref == 'refs/heads/hotfix-rc'
uses: dawidd6/action-download-artifact@246dbf436b23d7c49e21a7ab8204ca9ecd1fe615 # v2.27.0 uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
with: with:
workflow: build-browser.yml workflow: build-browser.yml
workflow_conclusion: success workflow_conclusion: success
@ -662,20 +674,20 @@ jobs:
- name: Download artifact from rc - name: Download artifact from rc
if: github.ref == 'refs/heads/rc' if: github.ref == 'refs/heads/rc'
uses: dawidd6/action-download-artifact@246dbf436b23d7c49e21a7ab8204ca9ecd1fe615 # v2.27.0 uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
with: with:
workflow: build-browser.yml workflow: build-browser.yml
workflow_conclusion: success workflow_conclusion: success
branch: rc branch: rc
path: ${{ github.workspace }}/browser-build-artifacts path: ${{ github.workspace }}/browser-build-artifacts
- name: Download artifact from master - name: Download artifacts from main
if: ${{ github.ref != 'refs/heads/rc' && github.ref != 'refs/heads/hotfix-rc' }} if: ${{ github.ref != 'refs/heads/rc' && github.ref != 'refs/heads/hotfix-rc' }}
uses: dawidd6/action-download-artifact@246dbf436b23d7c49e21a7ab8204ca9ecd1fe615 # v2.27.0 uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
with: with:
workflow: build-browser.yml workflow: build-browser.yml
workflow_conclusion: success workflow_conclusion: success
branch: master branch: main
path: ${{ github.workspace }}/browser-build-artifacts path: ${{ github.workspace }}/browser-build-artifacts
- name: Unzip Safari artifact - name: Unzip Safari artifact
@ -696,28 +708,28 @@ jobs:
run: npm run pack:mac run: npm run pack:mac
- name: Upload .zip artifact - name: Upload .zip artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal-mac.zip name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal-mac.zip
path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal-mac.zip path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal-mac.zip
if-no-files-found: error if-no-files-found: error
- name: Upload .dmg artifact - name: Upload .dmg artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg
path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg
if-no-files-found: error if-no-files-found: error
- name: Upload .dmg blockmap artifact - name: Upload .dmg blockmap artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg.blockmap name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg.blockmap
path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg.blockmap path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg.blockmap
if-no-files-found: error if-no-files-found: error
- name: Upload auto-update artifact - name: Upload auto-update artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: ${{ needs.setup.outputs.release-channel }}-mac.yml name: ${{ needs.setup.outputs.release-channel }}-mac.yml
path: apps/desktop/dist/${{ needs.setup.outputs.release-channel }}-mac.yml path: apps/desktop/dist/${{ needs.setup.outputs.release-channel }}-mac.yml
@ -726,35 +738,32 @@ jobs:
macos-package-mas: macos-package-mas:
name: MacOS Package Prod Release Asset name: MacOS Package Prod Release Asset
# Note, this workflow is running on macOS 11 to maintain compatibility with macOS 10.15 Catalina,
# as the newer versions will case the native modules to be incompatible with older macOS systems
# This version should stay pinned until we drop support for macOS 10.15, or we drop the native modules
runs-on: macos-11 runs-on: macos-11
needs: needs:
- setup - setup
- macos-build - macos-build
env: env:
_PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }} _PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }}
_NODE_VERSION: ${{ needs.setup.outputs.node_version }}
NODE_OPTIONS: --max_old_space_size=4096
defaults: defaults:
run: run:
working-directory: apps/desktop working-directory: apps/desktop
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with: with:
ref: ${{ needs.setup.outputs.branch-name }} ref: ${{ needs.setup.outputs.branch-name }}
- name: Set up Node - name: Set up Node
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with: with:
cache: 'npm' cache: 'npm'
cache-dependency-path: '**/package-lock.json' cache-dependency-path: '**/package-lock.json'
node-version: '18' node-version: ${{ env._NODE_VERSION }}
- name: Set Node options
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
- name: Install node-gyp
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Print environment - name: Print environment
run: | run: |
@ -765,70 +774,79 @@ jobs:
- name: Get Build Cache - name: Get Build Cache
id: build-cache id: build-cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4.0.1
with: with:
path: apps/desktop/build path: apps/desktop/build
key: ${{ runner.os }}-${{ github.run_id }}-build key: ${{ runner.os }}-${{ github.run_id }}-build
- name: Setup Safari Cache - name: Setup Safari Cache
id: safari-cache id: safari-cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4.0.1
with: with:
path: apps/browser/dist/Safari path: apps/browser/dist/Safari
key: ${{ runner.os }}-${{ github.run_id }}-safari-extension key: ${{ runner.os }}-${{ github.run_id }}-safari-extension
- name: Decrypt secrets - name: Download Provisioning Profiles secrets
env: env:
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} ACCOUNT_NAME: bitwardenci
CONTAINER_NAME: profiles
run: | run: |
mkdir -p $HOME/secrets mkdir -p $HOME/secrets
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/bitwarden-desktop-key.p12" \ az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
"$GITHUB_WORKSPACE/.github/secrets/bitwarden-desktop-key.p12.gpg" --name bitwarden_desktop_appstore.provisionprofile \
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ --file $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \
--output "$HOME/secrets/appstore-app-cert.p12" \ --output none
"$GITHUB_WORKSPACE/.github/secrets/appstore-app-cert.p12.gpg"
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - name: Get certificates
--output "$HOME/secrets/appstore-installer-cert.p12" \ run: |
"$GITHUB_WORKSPACE/.github/secrets/appstore-installer-cert.p12.gpg" mkdir -p $HOME/certificates
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/devid-app-cert.p12" \ az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/bitwarden-desktop-key |
"$GITHUB_WORKSPACE/.github/secrets/devid-app-cert.p12.gpg" jq -r .value | base64 -d > $HOME/certificates/bitwarden-desktop-key.p12
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/devid-installer-cert.p12" \ az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/appstore-app-cert |
"$GITHUB_WORKSPACE/.github/secrets/devid-installer-cert.p12.gpg" jq -r .value | base64 -d > $HOME/certificates/appstore-app-cert.p12
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/macdev-cert.p12" \ az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/appstore-installer-cert |
"$GITHUB_WORKSPACE/.github/secrets/macdev-cert.p12.gpg" jq -r .value | base64 -d > $HOME/certificates/appstore-installer-cert.p12
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/bitwarden_desktop_appstore.provisionprofile" \ az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-app-cert |
"$GITHUB_WORKSPACE/.github/secrets/bitwarden_desktop_appstore.provisionprofile.gpg" jq -r .value | base64 -d > $HOME/certificates/devid-app-cert.p12
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-installer-cert |
jq -r .value | base64 -d > $HOME/certificates/devid-installer-cert.p12
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/macdev-cert |
jq -r .value | base64 -d > $HOME/certificates/macdev-cert.p12
- name: Set up keychain - name: Set up keychain
env: env:
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
DESKTOP_KEY_PASSWORD: ${{ secrets.DESKTOP_KEY_PASSWORD }}
DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_PASSWORD }}
APPSTORE_CERT_PASSWORD: ${{ secrets.APPSTORE_CERT_PASSWORD }}
MACDEV_CERT_PASSWORD: ${{ secrets.MACDEV_CERT_PASSWORD }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
run: | run: |
security create-keychain -p $KEYCHAIN_PASSWORD build.keychain security create-keychain -p $KEYCHAIN_PASSWORD build.keychain
security default-keychain -s build.keychain security default-keychain -s build.keychain
security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain
security set-keychain-settings -lut 1200 build.keychain security set-keychain-settings -lut 1200 build.keychain
security import "$HOME/secrets/bitwarden-desktop-key.p12" -k build.keychain -P $DESKTOP_KEY_PASSWORD \
security import "$HOME/certificates/bitwarden-desktop-key.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/devid-app-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \
security import "$HOME/certificates/devid-app-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/devid-installer-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \
security import "$HOME/certificates/devid-installer-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/appstore-app-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \
security import "$HOME/certificates/appstore-app-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/appstore-installer-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \
security import "$HOME/certificates/appstore-installer-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/secrets/macdev-cert.p12" -k build.keychain -P $MACDEV_CERT_PASSWORD \
security import "$HOME/certificates/macdev-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain
- name: Set up provisioning profiles - name: Set up provisioning profiles
@ -855,7 +873,7 @@ jobs:
- name: Download artifact from hotfix-rc - name: Download artifact from hotfix-rc
if: github.ref == 'refs/heads/hotfix-rc' if: github.ref == 'refs/heads/hotfix-rc'
uses: dawidd6/action-download-artifact@246dbf436b23d7c49e21a7ab8204ca9ecd1fe615 # v2.27.0 uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
with: with:
workflow: build-browser.yml workflow: build-browser.yml
workflow_conclusion: success workflow_conclusion: success
@ -864,20 +882,20 @@ jobs:
- name: Download artifact from rc - name: Download artifact from rc
if: github.ref == 'refs/heads/rc' if: github.ref == 'refs/heads/rc'
uses: dawidd6/action-download-artifact@246dbf436b23d7c49e21a7ab8204ca9ecd1fe615 # v2.27.0 uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
with: with:
workflow: build-browser.yml workflow: build-browser.yml
workflow_conclusion: success workflow_conclusion: success
branch: rc branch: rc
path: ${{ github.workspace }}/browser-build-artifacts path: ${{ github.workspace }}/browser-build-artifacts
- name: Download artifact from master - name: Download artifact from main
if: ${{ github.ref != 'refs/heads/rc' && github.ref != 'refs/heads/hotfix-rc' }} if: ${{ github.ref != 'refs/heads/rc' && github.ref != 'refs/heads/hotfix-rc' }}
uses: dawidd6/action-download-artifact@246dbf436b23d7c49e21a7ab8204ca9ecd1fe615 # v2.27.0 uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
with: with:
workflow: build-browser.yml workflow: build-browser.yml
workflow_conclusion: success workflow_conclusion: success
branch: master branch: main
path: ${{ github.workspace }}/browser-build-artifacts path: ${{ github.workspace }}/browser-build-artifacts
- name: Unzip Safari artifact - name: Unzip Safari artifact
@ -898,7 +916,7 @@ jobs:
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
- name: Upload .pkg artifact - name: Upload .pkg artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.pkg name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.pkg
path: apps/desktop/dist/mas-universal/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.pkg path: apps/desktop/dist/mas-universal/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.pkg
@ -906,7 +924,7 @@ jobs:
release: release:
name: Release beta channel to S3 name: Release beta channel to S3
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
needs: needs:
- setup - setup
- linux - linux
@ -916,7 +934,7 @@ jobs:
- macos-package-mas - macos-package-mas
steps: steps:
- name: Create GitHub deployment - name: Create GitHub deployment
uses: chrnorm/deployment-action@d42cde7132fcec920de534fffc3be83794335c00 # v2.0.5 uses: chrnorm/deployment-action@55729fcebec3d284f60f5bcabbd8376437d696b1 # v2.0.7
id: deployment id: deployment
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
@ -926,13 +944,13 @@ jobs:
task: release task: release
- name: Login to Azure - name: Login to Azure
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "aws-electron-access-id, secrets: "aws-electron-access-id,
@ -944,7 +962,7 @@ jobs:
cf-prod-account" cf-prod-account"
- name: Download all artifacts - name: Download all artifacts
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4
with: with:
path: apps/desktop/artifacts path: apps/desktop/artifacts
@ -983,7 +1001,7 @@ jobs:
- name: Update deployment status to Success - name: Update deployment status to Success
if: ${{ success() }} if: ${{ success() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
state: 'success' state: 'success'
@ -991,7 +1009,7 @@ jobs:
- name: Update deployment status to Failure - name: Update deployment status to Failure
if: ${{ failure() }} if: ${{ failure() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
state: 'failure' state: 'failure'
@ -999,7 +1017,7 @@ jobs:
remove-branch: remove-branch:
name: Remove branch name: Remove branch
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
if: always() if: always()
needs: needs:
- setup - setup
@ -1011,7 +1029,7 @@ jobs:
- release - release
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup git config - name: Setup git config
run: | run: |

View File

@ -30,12 +30,12 @@ on:
default: true default: true
type: boolean type: boolean
electron_publish: electron_publish:
description: 'Publish electron to S3 bucket' description: 'Publish Electron to S3 bucket'
required: true required: true
default: true default: true
type: boolean type: boolean
github_release: github_release:
description: 'Publish github release' description: 'Publish GitHub release'
required: true required: true
default: true default: true
type: boolean type: boolean
@ -47,13 +47,13 @@ defaults:
jobs: jobs:
setup: setup:
name: Setup name: Setup
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
outputs: outputs:
release-version: ${{ steps.version.outputs.version }} release-version: ${{ steps.version.outputs.version }}
release-channel: ${{ steps.release-channel.outputs.channel }} release-channel: ${{ steps.release-channel.outputs.channel }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Branch check - name: Branch check
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
@ -67,9 +67,9 @@ jobs:
- name: Check Release Version - name: Check Release Version
id: version id: version
uses: bitwarden/gh-actions/release-version-check@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/release-version-check@main
with: with:
release-type: ${{ github.event.inputs.release_type }} release-type: ${{ inputs.release_type }}
project-type: ts project-type: ts
file: apps/desktop/src/package.json file: apps/desktop/src/package.json
monorepo: true monorepo: true
@ -94,7 +94,7 @@ jobs:
- name: Create GitHub deployment - name: Create GitHub deployment
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: chrnorm/deployment-action@d42cde7132fcec920de534fffc3be83794335c00 # v2.0.5 uses: chrnorm/deployment-action@55729fcebec3d284f60f5bcabbd8376437d696b1 # v2.0.7
id: deployment id: deployment
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
@ -104,13 +104,13 @@ jobs:
task: release task: release
- name: Login to Azure - name: Login to Azure
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "aws-electron-access-id, secrets: "aws-electron-access-id,
@ -123,7 +123,7 @@ jobs:
- name: Download all artifacts - name: Download all artifacts
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-desktop.yml workflow: build-desktop.yml
workflow_conclusion: success workflow_conclusion: success
@ -132,11 +132,11 @@ jobs:
- name: Dry Run - Download all artifacts - name: Dry Run - Download all artifacts
if: ${{ github.event.inputs.release_type == 'Dry Run' }} if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-desktop.yml workflow: build-desktop.yml
workflow_conclusion: success workflow_conclusion: success
branch: master branch: main
path: apps/desktop/artifacts path: apps/desktop/artifacts
- name: Rename .pkg to .pkg.archive - name: Rename .pkg to .pkg.archive
@ -146,17 +146,17 @@ jobs:
run: mv Bitwarden-${{ env.PKG_VERSION }}-universal.pkg Bitwarden-${{ env.PKG_VERSION }}-universal.pkg.archive run: mv Bitwarden-${{ env.PKG_VERSION }}-universal.pkg Bitwarden-${{ env.PKG_VERSION }}-universal.pkg.archive
- name: Set staged rollout percentage - name: Set staged rollout percentage
if: ${{ github.event.inputs.electron_publish }} if: ${{ github.event.inputs.electron_publish == 'true' }}
env: env:
RELEASE_CHANNEL: ${{ steps.release-channel.outputs.channel }} RELEASE_CHANNEL: ${{ steps.release-channel.outputs.channel }}
ROLLOUT_PCT: ${{ github.event.inputs.rollout_percentage }} ROLLOUT_PCT: ${{ inputs.rollout_percentage }}
run: | run: |
echo "stagingPercentage: ${ROLLOUT_PCT}" >> apps/desktop/artifacts/${RELEASE_CHANNEL}.yml echo "stagingPercentage: ${ROLLOUT_PCT}" >> apps/desktop/artifacts/${RELEASE_CHANNEL}.yml
echo "stagingPercentage: ${ROLLOUT_PCT}" >> apps/desktop/artifacts/${RELEASE_CHANNEL}-linux.yml echo "stagingPercentage: ${ROLLOUT_PCT}" >> apps/desktop/artifacts/${RELEASE_CHANNEL}-linux.yml
echo "stagingPercentage: ${ROLLOUT_PCT}" >> apps/desktop/artifacts/${RELEASE_CHANNEL}-mac.yml echo "stagingPercentage: ${ROLLOUT_PCT}" >> apps/desktop/artifacts/${RELEASE_CHANNEL}-mac.yml
- name: Publish artifacts to S3 - name: Publish artifacts to S3
if: ${{ github.event.inputs.release_type != 'Dry Run' && github.event.inputs.electron_publish }} if: ${{ github.event.inputs.release_type != 'Dry Run' && github.event.inputs.electron_publish == 'true' }}
env: env:
AWS_ACCESS_KEY_ID: ${{ steps.retrieve-secrets.outputs.aws-electron-access-id }} AWS_ACCESS_KEY_ID: ${{ steps.retrieve-secrets.outputs.aws-electron-access-id }}
AWS_SECRET_ACCESS_KEY: ${{ steps.retrieve-secrets.outputs.aws-electron-access-key }} AWS_SECRET_ACCESS_KEY: ${{ steps.retrieve-secrets.outputs.aws-electron-access-key }}
@ -170,7 +170,7 @@ jobs:
--quiet --quiet
- name: Publish artifacts to R2 - name: Publish artifacts to R2
if: ${{ github.event.inputs.release_type != 'Dry Run' && github.event.inputs.electron_publish }} if: ${{ github.event.inputs.release_type != 'Dry Run' && github.event.inputs.electron_publish == 'true' }}
env: env:
AWS_ACCESS_KEY_ID: ${{ steps.retrieve-secrets.outputs.r2-electron-access-id }} AWS_ACCESS_KEY_ID: ${{ steps.retrieve-secrets.outputs.r2-electron-access-id }}
AWS_SECRET_ACCESS_KEY: ${{ steps.retrieve-secrets.outputs.r2-electron-access-key }} AWS_SECRET_ACCESS_KEY: ${{ steps.retrieve-secrets.outputs.r2-electron-access-key }}
@ -185,14 +185,14 @@ jobs:
--endpoint-url https://${CF_ACCOUNT}.r2.cloudflarestorage.com --endpoint-url https://${CF_ACCOUNT}.r2.cloudflarestorage.com
- name: Get checksum files - name: Get checksum files
uses: bitwarden/gh-actions/get-checksum@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-checksum@main
with: with:
packages_dir: "apps/desktop/artifacts" packages_dir: "apps/desktop/artifacts"
file_path: "apps/desktop/artifacts/sha256-checksums.txt" file_path: "apps/desktop/artifacts/sha256-checksums.txt"
- name: Create Release - name: Create Release
uses: ncipollo/release-action@a2e71bdd4e7dab70ca26a852f29600c98b33153e # v1.12.0 uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0
if: ${{ steps.release-channel.outputs.channel == 'latest' && github.event.inputs.release_type != 'Dry Run' && inputs.github_release }} if: ${{ steps.release-channel.outputs.channel == 'latest' && github.event.inputs.release_type != 'Dry Run' && github.event.inputs.github_release == 'true' }}
env: env:
PKG_VERSION: ${{ steps.version.outputs.version }} PKG_VERSION: ${{ steps.version.outputs.version }}
RELEASE_CHANNEL: ${{ steps.release-channel.outputs.channel }} RELEASE_CHANNEL: ${{ steps.release-channel.outputs.channel }}
@ -231,7 +231,7 @@ jobs:
- name: Update deployment status to Success - name: Update deployment status to Success
if: ${{ github.event.inputs.release_type != 'Dry Run' && success() }} if: ${{ github.event.inputs.release_type != 'Dry Run' && success() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
state: 'success' state: 'success'
@ -239,7 +239,7 @@ jobs:
- name: Update deployment status to Failure - name: Update deployment status to Failure
if: ${{ github.event.inputs.release_type != 'Dry Run' && failure() }} if: ${{ github.event.inputs.release_type != 'Dry Run' && failure() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
state: 'failure' state: 'failure'
@ -247,31 +247,29 @@ jobs:
snap: snap:
name: Deploy Snap name: Deploy Snap
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
needs: setup needs: setup
if: inputs.snap_publish if: ${{ github.event.inputs.snap_publish == 'true' }}
env: env:
_PKG_VERSION: ${{ needs.setup.outputs.release-version }} _PKG_VERSION: ${{ needs.setup.outputs.release-version }}
steps: steps:
- name: Checkout Repo - name: Checkout Repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Login to Azure - name: Login to Azure
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "snapcraft-store-token" secrets: "snapcraft-store-token"
- name: Install Snap - name: Install Snap
uses: samuelmeuli/action-snapcraft@d33c176a9b784876d966f80fb1b461808edc0641 # v2.1.1 uses: samuelmeuli/action-snapcraft@d33c176a9b784876d966f80fb1b461808edc0641 # v2.1.1
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ steps.retrieve-secrets.outputs.snapcraft-store-token }}
- name: Setup - name: Setup
run: mkdir dist run: mkdir dist
@ -279,7 +277,7 @@ jobs:
- name: Download Snap artifact - name: Download Snap artifact
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-desktop.yml workflow: build-desktop.yml
workflow_conclusion: success workflow_conclusion: success
@ -289,11 +287,11 @@ jobs:
- name: Dry Run - Download Snap artifact - name: Dry Run - Download Snap artifact
if: ${{ github.event.inputs.release_type == 'Dry Run' }} if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-desktop.yml workflow: build-desktop.yml
workflow_conclusion: success workflow_conclusion: success
branch: master branch: main
artifacts: bitwarden_${{ env._PKG_VERSION }}_amd64.snap artifacts: bitwarden_${{ env._PKG_VERSION }}_amd64.snap
path: apps/desktop/dist path: apps/desktop/dist
@ -302,20 +300,20 @@ jobs:
env: env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ steps.retrieve-secrets.outputs.snapcraft-store-token }} SNAPCRAFT_STORE_CREDENTIALS: ${{ steps.retrieve-secrets.outputs.snapcraft-store-token }}
run: | run: |
/snap/bin/snapcraft upload bitwarden_${{ env._PKG_VERSION }}_amd64.snap --release stable snapcraft upload bitwarden_${{ env._PKG_VERSION }}_amd64.snap --release stable
/snap/bin/snapcraft logout snapcraft logout
working-directory: apps/desktop/dist working-directory: apps/desktop/dist
choco: choco:
name: Deploy Choco name: Deploy Choco
runs-on: windows-2019 runs-on: windows-2022
needs: setup needs: setup
if: inputs.choco_publish if: ${{ github.event.inputs.choco_publish == 'true' }}
env: env:
_PKG_VERSION: ${{ needs.setup.outputs.release-version }} _PKG_VERSION: ${{ needs.setup.outputs.release-version }}
steps: steps:
- name: Checkout Repo - name: Checkout Repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Print Environment - name: Print Environment
run: | run: |
@ -323,13 +321,13 @@ jobs:
dotnet nuget --version dotnet nuget --version
- name: Login to Azure - name: Login to Azure
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "cli-choco-api-key" secrets: "cli-choco-api-key"
@ -347,7 +345,7 @@ jobs:
- name: Download choco artifact - name: Download choco artifact
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-desktop.yml workflow: build-desktop.yml
workflow_conclusion: success workflow_conclusion: success
@ -357,11 +355,11 @@ jobs:
- name: Dry Run - Download choco artifact - name: Dry Run - Download choco artifact
if: ${{ github.event.inputs.release_type == 'Dry Run' }} if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-desktop.yml workflow: build-desktop.yml
workflow_conclusion: success workflow_conclusion: success
branch: master branch: main
artifacts: bitwarden.${{ env._PKG_VERSION }}.nupkg artifacts: bitwarden.${{ env._PKG_VERSION }}.nupkg
path: apps/desktop/dist path: apps/desktop/dist

View File

@ -15,16 +15,19 @@ on:
- Redeploy - Redeploy
- Dry Run - Dry Run
env:
_AZ_REGISTRY: bitwardenprod.azurecr.io
jobs: jobs:
setup: setup:
name: Setup name: Setup
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
outputs: outputs:
release_version: ${{ steps.version.outputs.version }} release_version: ${{ steps.version.outputs.version }}
tag_version: ${{ steps.version.outputs.tag }} tag_version: ${{ steps.version.outputs.tag }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Branch check - name: Branch check
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
@ -38,7 +41,7 @@ jobs:
- name: Check Release Version - name: Check Release Version
id: version id: version
uses: bitwarden/gh-actions/release-version-check@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/release-version-check@main
with: with:
release-type: ${{ github.event.inputs.release_type }} release-type: ${{ github.event.inputs.release_type }}
project-type: ts project-type: ts
@ -46,10 +49,9 @@ jobs:
monorepo: true monorepo: true
monorepo-project: web monorepo-project: web
self-host: self-host:
name: Release self-host docker name: Release self-host docker
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
needs: setup needs: setup
env: env:
_BRANCH_NAME: ${{ github.ref_name }} _BRANCH_NAME: ${{ github.ref_name }}
@ -65,195 +67,74 @@ jobs:
echo "Github Release Option: $_RELEASE_OPTION" echo "Github Release Option: $_RELEASE_OPTION"
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
########## DockerHub ##########
- name: Setup DCT
id: setup-dct
uses: bitwarden/gh-actions/setup-docker-trust@a30e9c3d658dc97c4c2e61ec749fdab64b83386c
with:
azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
azure-keyvault-name: "bitwarden-ci"
- name: Pull branch image
run: |
if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then
docker pull bitwarden/web:latest
else
docker pull bitwarden/web:$_BRANCH_NAME
fi
- name: Docker Tag version
run: |
if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then
docker tag bitwarden/web:latest bitwarden/web:$_RELEASE_VERSION
else
docker tag bitwarden/web:$_BRANCH_NAME bitwarden/web:$_RELEASE_VERSION
fi
- name: Docker Push version
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
env:
DOCKER_CONTENT_TRUST: 1
DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ steps.setup-dct.outputs.dct-delegate-repo-passphrase }}
run: docker push bitwarden/web:$_RELEASE_VERSION
- name: Log out of Docker and disable Docker Notary
run: |
docker logout
echo "DOCKER_CONTENT_TRUST=0" >> $GITHUB_ENV
########## ACR ########## ########## ACR ##########
- name: Login to Azure - PROD Subscription - name: Login to Azure - PROD Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
- name: Login to Azure ACR - name: Login to Azure ACR
run: az acr login -n bitwardenprod run: az acr login -n bitwardenprod
- name: Tag version - name: Pull branch image
env:
REGISTRY: bitwardenprod.azurecr.io
run: | run: |
if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then
docker tag bitwarden/web:latest $REGISTRY/web:$_RELEASE_VERSION docker pull $_AZ_REGISTRY/web:latest
docker tag bitwarden/web:latest $REGISTRY/web-sh:$_RELEASE_VERSION
else else
docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web:$_RELEASE_VERSION docker pull $_AZ_REGISTRY/web:$_BRANCH_NAME
fi
docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web-sh:$_RELEASE_VERSION - name: Tag version
run: |
if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then
docker tag $_AZ_REGISTRY/web:latest $_AZ_REGISTRY/web:dryrun
docker tag $_AZ_REGISTRY/web:latest $_AZ_REGISTRY/web-sh:dryrun
else
docker tag $_AZ_REGISTRY/web:$_BRANCH_NAME $_AZ_REGISTRY/web:$_RELEASE_VERSION
docker tag $_AZ_REGISTRY/web:$_BRANCH_NAME $_AZ_REGISTRY/web-sh:$_RELEASE_VERSION
docker tag $_AZ_REGISTRY/web:$_BRANCH_NAME $_AZ_REGISTRY/web:latest
docker tag $_AZ_REGISTRY/web:$_BRANCH_NAME $_AZ_REGISTRY/web-sh:latest
fi fi
- name: Push version - name: Push version
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
env:
REGISTRY: bitwardenprod.azurecr.io
run: | run: |
docker push $REGISTRY/web:$_RELEASE_VERSION if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then
docker push $_AZ_REGISTRY/web:dryrun
docker push $REGISTRY/web-sh:$_RELEASE_VERSION docker push $_AZ_REGISTRY/web-sh:dryrun
else
docker push $_AZ_REGISTRY/web:$_RELEASE_VERSION
docker push $_AZ_REGISTRY/web-sh:$_RELEASE_VERSION
docker push $_AZ_REGISTRY/web:latest
docker push $_AZ_REGISTRY/web-sh:latest
fi
- name: Log out of Docker - name: Log out of Docker
run: docker logout run: docker logout
ghpages-deploy:
name: Deploy to GitHub Pages
runs-on: ubuntu-20.04
needs:
- setup
env:
_RELEASE_VERSION: ${{ needs.setup.outputs.release_version }}
_TAG_VERSION: ${{ needs.setup.outputs.tag_version }}
_BRANCH: "v${{ needs.setup.outputs.release_version }}-deploy"
steps:
- name: Login to Azure - CI Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve bot secrets
id: retrieve-bot-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c
with:
keyvault: bitwarden-ci
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
- name: Checkout GH pages repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
with:
repository: bitwarden/web-vault-pages
path: ghpages-deployment
token: ${{ steps.retrieve-bot-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
- name: Download latest cloud asset
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c
with:
workflow: build-web.yml
path: assets
workflow_conclusion: success
branch: ${{ github.ref_name }}
artifacts: web-*-cloud-COMMERCIAL.zip
- name: Dry Run - Download latest cloud asset
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c
with:
workflow: build-web.yml
path: assets
workflow_conclusion: success
branch: master
artifacts: web-*-cloud-COMMERCIAL.zip
- name: Unzip build asset
working-directory: assets
run: unzip web-*-cloud-COMMERCIAL.zip
- name: Create new branch
run: |
cd ${{ github.workspace }}/ghpages-deployment
git config user.name = "GitHub Action Bot"
git config user.email = "<>"
git config --global url."https://github.com/".insteadOf ssh://git@github.com/
git config --global url."https://".insteadOf ssh://
git checkout -b ${_BRANCH}
- name: Copy build files
run: |
rm -rf ${{ github.workspace }}/ghpages-deployment/*
cp -Rf ${{ github.workspace }}/assets/build/* ghpages-deployment/
- name: Commit and push changes
working-directory: ghpages-deployment
run: |
git add .
git commit -m "Deploy Web v${_RELEASE_VERSION} to GitHub Pages"
git push --set-upstream origin ${_BRANCH} --force
- name: Create GitHub Pages Deploy PR
working-directory: ghpages-deployment
env:
GITHUB_TOKEN: ${{ steps.retrieve-bot-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
run: |
if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then
gh pr create --title "Deploy v${_RELEASE_VERSION} to GitHub Pages" \
--draft \
--body "Deploying v${_RELEASE_VERSION}" \
--base master \
--head "${_BRANCH}"
else
gh pr create --title "Deploy v${_RELEASE_VERSION} to GitHub Pages" \
--body "Deploying v${_RELEASE_VERSION}" \
--base master \
--head "${_BRANCH}"
fi
release: release:
name: Create GitHub Release name: Create GitHub Release
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
needs: needs:
- setup - setup
- self-host - self-host
- ghpages-deploy
steps: steps:
- name: Create GitHub deployment - name: Create GitHub deployment
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: chrnorm/deployment-action@d42cde7132fcec920de534fffc3be83794335c00 # v2.0.5 uses: chrnorm/deployment-action@55729fcebec3d284f60f5bcabbd8376437d696b1 # v2.0.7
id: deployment id: deployment
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
initial-status: 'in_progress' initial-status: 'in_progress'
environment-url: http://vault.bitwarden.com environment-url: http://vault.bitwarden.com
environment: 'Web Vault - Production' environment: 'Web Vault - US Production Cloud'
description: 'Deployment ${{ needs.setup.outputs.release_version }} from branch ${{ github.ref_name }}' description: 'Deployment ${{ needs.setup.outputs.release_version }} from branch ${{ github.ref_name }}'
task: release task: release
- name: Download latest build artifacts - name: Download latest build artifacts
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-web.yml workflow: build-web.yml
path: apps/web/artifacts path: apps/web/artifacts
@ -264,12 +145,12 @@ jobs:
- name: Dry Run - Download latest build artifacts - name: Dry Run - Download latest build artifacts
if: ${{ github.event.inputs.release_type == 'Dry Run' }} if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-web.yml workflow: build-web.yml
path: apps/web/artifacts path: apps/web/artifacts
workflow_conclusion: success workflow_conclusion: success
branch: master branch: main
artifacts: "web-*-selfhosted-COMMERCIAL.zip, artifacts: "web-*-selfhosted-COMMERCIAL.zip,
web-*-selfhosted-open-source.zip" web-*-selfhosted-open-source.zip"
@ -281,7 +162,7 @@ jobs:
- name: Create release - name: Create release
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: ncipollo/release-action@a2e71bdd4e7dab70ca26a852f29600c98b33153e # v1.12.0 uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0
with: with:
name: "Web v${{ needs.setup.outputs.release_version }}" name: "Web v${{ needs.setup.outputs.release_version }}"
commit: ${{ github.sha }} commit: ${{ github.sha }}
@ -294,7 +175,7 @@ jobs:
- name: Update deployment status to Success - name: Update deployment status to Success
if: ${{ github.event.inputs.release_type != 'Dry Run' && success() }} if: ${{ github.event.inputs.release_type != 'Dry Run' && success() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
environment-url: http://vault.bitwarden.com environment-url: http://vault.bitwarden.com
@ -303,7 +184,7 @@ jobs:
- name: Update deployment status to Failure - name: Update deployment status to Failure
if: ${{ github.event.inputs.release_type != 'Dry Run' && failure() }} if: ${{ github.event.inputs.release_type != 'Dry Run' && failure() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
environment-url: http://vault.bitwarden.com environment-url: http://vault.bitwarden.com

78
.github/workflows/scan.yml vendored Normal file
View File

@ -0,0 +1,78 @@
name: Scan
on:
workflow_dispatch:
push:
branches:
- "main"
- "rc"
- "hotfix-rc"
pull_request_target:
types: [opened, synchronize]
jobs:
check-run:
name: Check PR run
uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main
sast:
name: SAST scan
runs-on: ubuntu-22.04
needs: check-run
permissions:
contents: read
pull-requests: write
security-events: write
steps:
- name: Check out repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Scan with Checkmarx
uses: checkmarx/ast-github-action@749fec53e0db0f6404a97e2e0807c3e80e3583a7 #2.0.23
env:
INCREMENTAL: "${{ contains(github.event_name, 'pull_request') && '--sast-incremental' || '' }}"
with:
project_name: ${{ github.repository }}
cx_tenant: ${{ secrets.CHECKMARX_TENANT }}
base_uri: https://ast.checkmarx.net/
cx_client_id: ${{ secrets.CHECKMARX_CLIENT_ID }}
cx_client_secret: ${{ secrets.CHECKMARX_SECRET }}
additional_params: |
--report-format sarif \
--filter "state=TO_VERIFY;PROPOSED_NOT_EXPLOITABLE;CONFIRMED;URGENT" \
--output-path . ${{ env.INCREMENTAL }}
- name: Upload Checkmarx results to GitHub
uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9
with:
sarif_file: cx_result.sarif
quality:
name: Quality scan
runs-on: ubuntu-22.04
needs: check-run
permissions:
contents: read
pull-requests: write
steps:
- name: Check out repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- name: Scan with SonarCloud
uses: sonarsource/sonarcloud-github-action@49e6cd3b187936a73b8280d59ffd9da69df63ec9 # v2.1.1
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
args: >
-Dsonar.organization=${{ github.repository_owner }}
-Dsonar.projectKey=${{ github.repository_owner }}_${{ github.event.repository.name }}
-Dsonar.test.inclusions=**/*.spec.ts
-Dsonar.tests=.

View File

@ -20,13 +20,13 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: Login to Azure - name: Login to Azure
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "aws-electron-access-id, secrets: "aws-electron-access-id,

View File

@ -8,10 +8,10 @@ on:
jobs: jobs:
stale: stale:
name: 'Check for stale issues and PRs' name: 'Check for stale issues and PRs'
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
steps: steps:
- name: 'Run stale action' - name: 'Run stale action'
uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0 uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0
with: with:
stale-issue-label: 'needs-reply' stale-issue-label: 'needs-reply'
stale-pr-label: 'needs-changes' stale-pr-label: 'needs-changes'
@ -27,4 +27,4 @@ jobs:
If youre still working on this, please respond here after youve made the changes weve requested and our team will re-open it for further review. If youre still working on this, please respond here after youve made the changes weve requested and our team will re-open it for further review.
Please make sure to resolve any conflicts with the master branch before requesting another review. Please make sure to resolve any conflicts with the main branch before requesting another review.

View File

@ -3,17 +3,12 @@ name: Run tests
on: on:
workflow_dispatch: workflow_dispatch:
push:
branches:
- "main"
- "rc"
- "hotfix-rc-*"
pull_request: pull_request:
branches-ignore:
- 'l10n_master'
- 'cf-pages'
paths:
- 'apps/**'
- 'libs/**'
- '*'
- '!*.md'
- '!*.txt'
- '.github/workflows/test.yml'
defaults: defaults:
run: run:
@ -25,14 +20,21 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Get Node Version
id: retrieve-node-version
run: |
NODE_NVMRC=$(cat .nvmrc)
NODE_VERSION=${NODE_NVMRC/v/''}
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
- name: Set up Node - name: Set up Node
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with: with:
cache: 'npm' cache: 'npm'
cache-dependency-path: '**/package-lock.json' cache-dependency-path: '**/package-lock.json'
node-version: '18' node-version: ${{ steps.retrieve-node-version.outputs.node_version }}
- name: Print environment - name: Print environment
run: | run: |
@ -46,13 +48,13 @@ jobs:
# Tests in apps/ are typechecked when their app is built, so we just do it here for libs/ # Tests in apps/ are typechecked when their app is built, so we just do it here for libs/
# See https://bitwarden.atlassian.net/browse/EC-497 # See https://bitwarden.atlassian.net/browse/EC-497
- name: Run typechecking - name: Run typechecking
run: npm run test:types run: npm run test:types --coverage
- name: Run tests - name: Run tests
run: npm run test run: npm run test --coverage
- name: Report test results - name: Report test results
uses: dorny/test-reporter@c9b3d0e2bd2a4e96aaf424dbaa31c46b42318226 # v1.6.0 uses: dorny/test-reporter@eaa763f6ffc21c7a37837f56cd5f9737f27fc6c8 # v1.8.0
if: always() if: always()
with: with:
name: Test Results name: Test Results
@ -60,6 +62,11 @@ jobs:
reporter: jest-junit reporter: jest-junit
fail-on-error: true fail-on-error: true
- name: Upload to codecov.io
uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # v4.1.0
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
rust: rust:
name: rust - ${{ matrix.os }} name: rust - ${{ matrix.os }}
runs-on: ${{ matrix.os || 'ubuntu-latest' }} runs-on: ${{ matrix.os || 'ubuntu-latest' }}
@ -82,7 +89,7 @@ jobs:
sudo apt-get install -y gnome-keyring dbus-x11 sudo apt-get install -y gnome-keyring dbus-x11
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Build - name: Build
working-directory: ./apps/desktop/desktop_native working-directory: ./apps/desktop/desktop_native

View File

@ -1,49 +1,35 @@
--- ---
name: Version Auto Bump name: Auto Bump Desktop Version
on: on:
push: push:
tags: tags:
- desktop-v** - desktop-v**
defaults:
run:
shell: bash
jobs: jobs:
setup: bump-version:
name: "Setup" name: Bump Desktop Version
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
outputs:
version_number: ${{ steps.version.outputs.new-version }}
steps: steps:
- name: Checkout Branch - name: Login to Azure - CI Subscription
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Calculate bumped version - name: Retrieve bot secrets
id: version id: retrieve-bot-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: bitwarden-ci
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
- name: Trigger Version Bump workflow
env: env:
RELEASE_TAG: ${{ github.ref }} GH_TOKEN: ${{ steps.retrieve-bot-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
run: | run: |
CURR_MAJOR=$(echo $RELEASE_TAG | sed -r 's/refs\/tags\/[a-z]*-v([0-9]{4}\.[0-9]{1,2})\.([0-9]{1,2})/\1/') echo '{"cut_rc_branch": "false", \
CURR_PATCH=$(echo $RELEASE_TAG | sed -r 's/refs\/tags\/[a-z]*-v([0-9]{4}\.[0-9]{1,2})\.([0-9]{1,2})/\2/') "bump_browser": "false", \
echo "Current Major: $CURR_MAJOR" "bump_cli": "false", \
echo "Current Patch: $CURR_PATCH" "bump_desktop": "true", \
"bump_web": "false"}' | \
NEW_PATCH=$((CURR_PATCH+1)) gh workflow run version-bump.yml --json --repo bitwarden/clients
echo "New patch: $NEW_PATCH"
NEW_VER=$CURR_MAJOR.$NEW_PATCH
echo "New Version: $NEW_VER"
echo "new-version=$NEW_VER" >> $GITHUB_OUTPUT
trigger_version_bump:
name: Bump version to ${{ needs.setup.outputs.version_number }}
needs: setup
uses: ./.github/workflows/version-bump.yml
secrets:
AZURE_PROD_KV_CREDENTIALS: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
with:
version_number: ${{ needs.setup.outputs.version_number }}
client: "Desktop"

View File

@ -4,141 +4,391 @@ name: Version Bump
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
client: bump_browser:
description: "Client Project" description: "Bump Browser?"
required: true type: boolean
type: choice default: false
options: bump_cli:
- Browser description: "Bump CLI?"
- CLI type: boolean
- Desktop default: false
- Web bump_desktop:
- All description: "Bump Desktop?"
version_number: type: boolean
description: "New Version" default: false
required: true bump_web:
description: "Bump Web?"
workflow_call: type: boolean
inputs: default: false
version_number: version_number_override:
required: true description: "New version override (leave blank for automatic calculation, example: '2024.1.0')"
required: false
type: string type: string
client: cut_rc_branch:
required: true description: "Cut RC branch?"
type: string default: true
secrets: type: boolean
AZURE_PROD_KV_CREDENTIALS:
required: true
defaults:
run:
shell: bash
jobs: jobs:
bump_version: bump_version:
name: "Bump ${{ github.event.inputs.client }} Version" name: Bump Version
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
outputs:
version_browser: ${{ steps.set-final-version-output.outputs.version_browser }}
version_cli: ${{ steps.set-final-version-output.outputs.version_cli }}
version_desktop: ${{ steps.set-final-version-output.outputs.version_desktop }}
version_web: ${{ steps.set-final-version-output.outputs.version_web }}
steps: steps:
- name: Checkout Branch - name: Validate version input
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 if: ${{ inputs.version_number_override != '' }}
uses: bitwarden/gh-actions/version-check@main
- name: Login to Azure - Prod Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} version: ${{ inputs.version_number_override }}
- name: Checkout Branch
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: main
- name: Check if RC branch exists
if: ${{ inputs.cut_rc_branch == true }}
run: |
remote_rc_branch_check=$(git ls-remote --heads origin rc | wc -l)
if [[ "${remote_rc_branch_check}" -gt 0 ]]; then
echo "Remote RC branch exists."
echo "Please delete current RC branch before running again."
exit 1
fi
- name: Login to Azure - CI Subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "github-gpg-private-key, github-gpg-private-key-passphrase" secrets: "github-gpg-private-key,
github-gpg-private-key-passphrase,
github-pat-bitwarden-devops-bot-repo-scope"
- name: Import GPG key - name: Import GPG key
uses: crazy-max/ghaction-import-gpg@72b6676b71ab476b77e676928516f6982eef7a41 # v5.3.0 uses: crazy-max/ghaction-import-gpg@01dd5d3ca463c7f10f7f4f7b4f177225ac661ee4 # v6.1.0
with: with:
gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }} gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }}
passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }} passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }}
git_user_signingkey: true git_user_signingkey: true
git_commit_gpgsign: true git_commit_gpgsign: true
- name: Create Version Branch - name: Setup git
id: branch
env:
CLIENT_NAME: ${{ github.event.inputs.client }}
VERSION: ${{ github.event.inputs.version_number }}
run: | run: |
CLIENT=$(python -c "print('$CLIENT_NAME'.lower())") git config --local user.email "106330231+bitwarden-devops-bot@users.noreply.github.com"
echo "client=$CLIENT" >> $GITHUB_OUTPUT git config --local user.name "bitwarden-devops-bot"
git switch -c ${CLIENT}_version_bump_${VERSION} - name: Create Version Branch
id: create-branch
run: |
CLIENTS=()
if [[ ${{ inputs.bump_browser }} == true ]]; then
CLIENTS+=("browser")
fi
if [[ ${{ inputs.bump_cli }} == true ]]; then
CLIENTS+=("cli")
fi
if [[ ${{ inputs.bump_desktop }} == true ]]; then
CLIENTS+=("desktop")
fi
if [[ ${{ inputs.bump_web }} == true ]]; then
CLIENTS+=("web")
fi
printf -v joined '%s,' "${CLIENTS[@]}"
echo "client=${joined%,}" >> $GITHUB_OUTPUT
NAME=version_bump_${{ github.ref_name }}_$(date +"%Y-%m-%d")
git switch -c $NAME
echo "name=$NAME" >> $GITHUB_OUTPUT
######################## ########################
# VERSION BUMP SECTION # # VERSION BUMP SECTION #
######################## ########################
### Browser ### Browser
- name: Bump Browser Version - name: Get current Browser version
if: ${{ github.event.inputs.client == 'Browser' || github.event.inputs.client == 'All' }} if: ${{ inputs.bump_browser == true }}
id: current-browser-version
run: |
CURRENT_VERSION=$(cat package.json | jq -r '.version')
echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
working-directory: apps/browser
- name: Browser - Verify input version
if: ${{ inputs.bump_browser == true && inputs.version_number_override != '' }}
env: env:
VERSION: ${{ github.event.inputs.version_number }} CURRENT_VERSION: ${{ steps.current-browser-version.outputs.version }}
run: npm version --workspace=@bitwarden/browser ${VERSION} NEW_VERSION: ${{ inputs.version_number_override }}
run: |
# Error if version has not changed.
if [[ "$NEW_VERSION" == "$CURRENT_VERSION" ]]; then
echo "Version has not changed."
exit 1
fi
- name: Bump Browser Version - Manifest # Check if version is newer.
if: ${{ github.event.inputs.client == 'Browser' || github.event.inputs.client == 'All' }} printf '%s\n' "${CURRENT_VERSION}" "${NEW_VERSION}" | sort -C -V
uses: bitwarden/gh-actions/version-bump@a30e9c3d658dc97c4c2e61ec749fdab64b83386c if [ $? -eq 0 ]; then
echo "Version check successful."
else
echo "Version check failed."
exit 1
fi
working-directory: apps/browser
- name: Calculate next Browser release version
if: ${{ inputs.bump_browser == true && inputs.version_number_override == '' }}
id: calculate-next-browser-version
uses: bitwarden/gh-actions/version-next@main
with:
version: ${{ steps.current-browser-version.outputs.version }}
- name: Bump Browser Version - Version Override
if: ${{ inputs.bump_browser == true && inputs.version_number_override != '' }}
id: bump-browser-version-override
run: npm version --workspace=@bitwarden/browser ${{ inputs.version_number_override }}
- name: Bump Browser Version - Automatic Calculation
if: ${{ inputs.bump_browser == true && inputs.version_number_override == '' }}
id: bump-browser-version-automatic
env:
VERSION: ${{ steps.calculate-next-browser-version.outputs.version }}
run: npm version --workspace=@bitwarden/browser $VERSION
- name: Bump Browser Version - Manifest - Version Override
if: ${{ inputs.bump_browser == true && inputs.version_number_override != '' }}
uses: bitwarden/gh-actions/version-bump@main
with: with:
version: ${{ github.event.inputs.version_number }}
file_path: "apps/browser/src/manifest.json" file_path: "apps/browser/src/manifest.json"
version: ${{ inputs.version_number_override }}
- name: Bump Browser Version - Manifest v3 - name: Bump Browser Version - Manifest - Automatic Calculation
if: ${{ github.event.inputs.client == 'Browser' || github.event.inputs.client == 'All' }} if: ${{ inputs.bump_browser == true && inputs.version_number_override == '' }}
uses: bitwarden/gh-actions/version-bump@a30e9c3d658dc97c4c2e61ec749fdab64b83386c uses: bitwarden/gh-actions/version-bump@main
with:
file_path: "apps/browser/src/manifest.json"
version: ${{ steps.calculate-next-browser-version.outputs.version }}
- name: Bump Browser Version - Manifest v3 - Version Override
if: ${{ inputs.bump_browser == true && inputs.version_number_override != '' }}
uses: bitwarden/gh-actions/version-bump@main
with: with:
version: ${{ github.event.inputs.version_number }}
file_path: "apps/browser/src/manifest.v3.json" file_path: "apps/browser/src/manifest.v3.json"
version: ${{ inputs.version_number_override }}
- name: Bump Browser Version - Manifest v3 - Automatic Calculation
if: ${{ inputs.bump_browser == true && inputs.version_number_override == '' }}
uses: bitwarden/gh-actions/version-bump@main
with:
file_path: "apps/browser/src/manifest.v3.json"
version: ${{ steps.calculate-next-browser-version.outputs.version }}
- name: Run Prettier after Browser Version Bump - name: Run Prettier after Browser Version Bump
if: ${{ github.event.inputs.client == 'Browser' || github.event.inputs.client == 'All' }} if: ${{ inputs.bump_browser == true }}
run: | run: |
npm install -g prettier npm install -g prettier
prettier --write apps/browser/src/manifest.json prettier --write apps/browser/src/manifest.json
prettier --write apps/browser/src/manifest.v3.json prettier --write apps/browser/src/manifest.v3.json
### CLI ### CLI
- name: Bump CLI Version - name: Get current CLI version
if: ${{ github.event.inputs.client == 'CLI' || github.event.inputs.client == 'All' }} if: ${{ inputs.bump_cli == true }}
id: current-cli-version
run: |
CURRENT_VERSION=$(cat package.json | jq -r '.version')
echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
working-directory: apps/cli
- name: CLI - Verify input version
if: ${{ inputs.bump_cli == true && inputs.version_number_override != '' }}
env: env:
VERSION: ${{ github.event.inputs.version_number }} CURRENT_VERSION: ${{ steps.current-cli-version.outputs.version }}
run: npm version --workspace=@bitwarden/cli ${VERSION} NEW_VERSION: ${{ inputs.version_number_override }}
run: |
# Error if version has not changed.
if [[ "$NEW_VERSION" == "$CURRENT_VERSION" ]]; then
echo "Version has not changed."
exit 1
fi
# Check if version is newer.
printf '%s\n' "${CURRENT_VERSION}" "${NEW_VERSION}" | sort -C -V
if [ $? -eq 0 ]; then
echo "Version check successful."
else
echo "Version check failed."
exit 1
fi
working-directory: apps/cli
- name: Calculate next CLI release version
if: ${{ inputs.bump_cli == true && inputs.version_number_override == '' }}
id: calculate-next-cli-version
uses: bitwarden/gh-actions/version-next@main
with:
version: ${{ steps.current-cli-version.outputs.version }}
- name: Bump CLI Version - Version Override
if: ${{ inputs.bump_cli == true && inputs.version_number_override != '' }}
id: bump-cli-version-override
run: npm version --workspace=@bitwarden/cli ${{ inputs.version_number_override }}
- name: Bump CLI Version - Automatic Calculation
if: ${{ inputs.bump_cli == true && inputs.version_number_override == '' }}
id: bump-cli-version-automatic
env:
VERSION: ${{ steps.calculate-next-cli-version.outputs.version }}
run: npm version --workspace=@bitwarden/cli $VERSION
### Desktop ### Desktop
- name: Bump Desktop Version - Root - name: Get current Desktop version
if: ${{ github.event.inputs.client == 'Desktop' || github.event.inputs.client == 'All' }} if: ${{ inputs.bump_desktop == true }}
env: id: current-desktop-version
VERSION: ${{ github.event.inputs.version_number }} run: |
run: npm version --workspace=@bitwarden/desktop ${VERSION} CURRENT_VERSION=$(cat package.json | jq -r '.version')
echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
working-directory: apps/desktop
- name: Bump Desktop Version - App - name: Desktop - Verify input version
if: ${{ github.event.inputs.client == 'Desktop' || github.event.inputs.client == 'All' }} if: ${{ inputs.bump_desktop == true && inputs.version_number_override != '' }}
env: env:
VERSION: ${{ github.event.inputs.version_number }} CURRENT_VERSION: ${{ steps.current-desktop-version.outputs.version }}
run: npm version ${VERSION} NEW_VERSION: ${{ inputs.version_number_override }}
run: |
# Error if version has not changed.
if [[ "$NEW_VERSION" == "$CURRENT_VERSION" ]]; then
echo "Version has not changed."
exit 1
fi
# Check if version is newer.
printf '%s\n' "${CURRENT_VERSION}" "${NEW_VERSION}" | sort -C -V
if [ $? -eq 0 ]; then
echo "Version check successful."
else
echo "Version check failed."
exit 1
fi
working-directory: apps/desktop
- name: Calculate next Desktop release version
if: ${{ inputs.bump_desktop == true && inputs.version_number_override == '' }}
id: calculate-next-desktop-version
uses: bitwarden/gh-actions/version-next@main
with:
version: ${{ steps.current-desktop-version.outputs.version }}
- name: Bump Desktop Version - Root - Version Override
if: ${{ inputs.bump_desktop == true && inputs.version_number_override != '' }}
id: bump-desktop-version-override
run: npm version --workspace=@bitwarden/desktop ${{ inputs.version_number_override }}
- name: Bump Desktop Version - Root - Automatic Calculation
if: ${{ inputs.bump_desktop == true && inputs.version_number_override == '' }}
id: bump-desktop-version-automatic
env:
VERSION: ${{ steps.calculate-next-desktop-version.outputs.version }}
run: npm version --workspace=@bitwarden/desktop $VERSION
- name: Bump Desktop Version - App - Version Override
if: ${{ inputs.bump_desktop == true && inputs.version_number_override != '' }}
run: npm version ${{ inputs.version_number_override }}
working-directory: "apps/desktop/src"
- name: Bump Desktop Version - App - Automatic Calculation
if: ${{ inputs.bump_desktop == true && inputs.version_number_override == '' }}
env:
VERSION: ${{ steps.calculate-next-desktop-version.outputs.version }}
run: npm version $VERSION
working-directory: "apps/desktop/src" working-directory: "apps/desktop/src"
### Web ### Web
- name: Bump Web Version - name: Get current Web version
if: ${{ github.event.inputs.client == 'Web' || github.event.inputs.client == 'All' }} if: ${{ inputs.bump_web == true }}
id: current-web-version
run: |
CURRENT_VERSION=$(cat package.json | jq -r '.version')
echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
working-directory: apps/web
- name: Web - Verify input version
if: ${{ inputs.bump_web == true && inputs.version_number_override != '' }}
env: env:
VERSION: ${{ github.event.inputs.version_number }} CURRENT_VERSION: ${{ steps.current-web-version.outputs.version }}
run: npm version --workspace=@bitwarden/web-vault ${VERSION} NEW_VERSION: ${{ inputs.version_number_override }}
run: |
# Error if version has not changed.
if [[ "$NEW_VERSION" == "$CURRENT_VERSION" ]]; then
echo "Version has not changed."
exit 1
fi
# Check if version is newer.
printf '%s\n' "${CURRENT_VERSION}" "${NEW_VERSION}" | sort -C -V
if [ $? -eq 0 ]; then
echo "Version check successful."
else
echo "Version check failed."
exit 1
fi
working-directory: apps/web
- name: Calculate next Web release version
if: ${{ inputs.bump_web == true && inputs.version_number_override == '' }}
id: calculate-next-web-version
uses: bitwarden/gh-actions/version-next@main
with:
version: ${{ steps.current-web-version.outputs.version }}
- name: Bump Web Version - Version Override
if: ${{ inputs.bump_web == true && inputs.version_number_override != '' }}
id: bump-web-version-override
run: npm version --workspace=@bitwarden/web-vault ${{ inputs.version_number_override }}
- name: Bump Web Version - Automatic Calculation
if: ${{ inputs.bump_web == true && inputs.version_number_override == '' }}
id: bump-web-version-automatic
env:
VERSION: ${{ steps.calculate-next-web-version.outputs.version }}
run: npm version --workspace=@bitwarden/web-vault $VERSION
######################## ########################
- name: Setup git - name: Set final version output
id: set-final-version-output
run: | run: |
git config --local user.email "106330231+bitwarden-devops-bot@users.noreply.github.com" if [[ "${{ steps.bump-browser-version-override.outcome }}" = "success" ]]; then
git config --local user.name "bitwarden-devops-bot" echo "version_browser=${{ inputs.version_number_override }}" >> $GITHUB_OUTPUT
elif [[ "${{ steps.bump-browser-version-automatic.outcome }}" = "success" ]]; then
echo "version_browser=${{ steps.calculate-next-browser-version.outputs.version }}" >> $GITHUB_OUTPUT
fi
if [[ "${{ steps.bump-cli-version-override.outcome }}" = "success" ]]; then
echo "version_cli=${{ inputs.version_number_override }}" >> $GITHUB_OUTPUT
elif [[ "${{ steps.bump-cli-version-automatic.outcome }}" = "success" ]]; then
echo "version_cli=${{ steps.calculate-next-cli-version.outputs.version }}" >> $GITHUB_OUTPUT
fi
if [[ "${{ steps.bump-desktop-version-override.outcome }}" = "success" ]]; then
echo "version_desktop=${{ inputs.version_number_override }}" >> $GITHUB_OUTPUT
elif [[ "${{ steps.bump-desktop-version-automatic.outcome }}" = "success" ]]; then
echo "version_desktop=${{ steps.calculate-next-desktop-version.outputs.version }}" >> $GITHUB_OUTPUT
fi
if [[ "${{ steps.bump-web-version-override.outcome }}" = "success" ]]; then
echo "version_web=${{ inputs.version_number_override }}" >> $GITHUB_OUTPUT
elif [[ "${{ steps.bump-web-version-automatic.outcome }}" = "success" ]]; then
echo "version_web=${{ steps.calculate-next-web-version.outputs.version }}" >> $GITHUB_OUTPUT
fi
- name: Check if version changed - name: Check if version changed
id: version-changed id: version-changed
@ -153,27 +403,26 @@ jobs:
- name: Commit files - name: Commit files
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
env: env:
CLIENT: ${{ steps.branch.outputs.client }} CLIENT: ${{ steps.create-branch.outputs.client }}
VERSION: ${{ github.event.inputs.version_number }} VERSION: ${{ steps.set-final-version-output.outputs.version }}
run: git commit -m "Bumped ${CLIENT} version to ${VERSION}" -a run: git commit -m "Bumped ${CLIENT} version to ${VERSION}" -a
- name: Push changes - name: Push changes
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
env: env:
CLIENT: ${{ steps.branch.outputs.client }} PR_BRANCH: ${{ steps.create-branch.outputs.name }}
VERSION: ${{ github.event.inputs.version_number }} run: git push -u origin $PR_BRANCH
run: git push -u origin ${CLIENT}_version_bump_${VERSION}
- name: Create Bump Version PR - name: Create Version PR
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
id: create-pr
env: env:
PR_BRANCH: "${{ steps.branch.outputs.client }}_version_bump_${{ github.event.inputs.version_number }}" GH_TOKEN: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" PR_BRANCH: ${{ steps.create-branch.outputs.name }}
BASE_BRANCH: master TITLE: "Bump ${{ steps.create-branch.outputs.client }} version to ${{ steps.set-final-version-output.outputs.version }}"
TITLE: "Bump ${{ github.event.inputs.client }} version to ${{ github.event.inputs.version_number }}"
run: | run: |
gh pr create --title "$TITLE" \ PR_URL=$(gh pr create --title "$TITLE" \
--base "$BASE" \ --base "main" \
--head "$PR_BRANCH" \ --head "$PR_BRANCH" \
--label "version update" \ --label "version update" \
--label "automated pr" \ --label "automated pr" \
@ -186,5 +435,107 @@ jobs:
- [X] Other - [X] Other
## Objective ## Objective
Automated ${{ github.event.inputs.client }} version bump to ${{ github.event.inputs.version_number }}" Automated ${{ steps.create-branch.outputs.client }} version bump to ${{ steps.set-final-version-output.outputs.version }}")
echo "pr_number=${PR_URL##*/}" >> $GITHUB_OUTPUT
- name: Approve PR
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }}
run: gh pr review $PR_NUMBER --approve
- name: Merge PR
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
env:
GH_TOKEN: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }}
run: gh pr merge $PR_NUMBER --squash --auto --delete-branch
cut_rc:
name: Cut RC branch
if: ${{ inputs.cut_rc_branch == true }}
needs: bump_version
runs-on: ubuntu-22.04
steps:
- name: Checkout Branch
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: main
### Browser
- name: Browser - Verify version has been updated
if: ${{ inputs.bump_browser == true }}
env:
NEW_VERSION: ${{ needs.bump_version.outputs.version_browser }}
run: |
# Wait for version to change.
while : ; do
echo "Waiting for version to be updated..."
git pull --force
CURRENT_VERSION=$(cat package.json | jq -r '.version')
# If the versions don't match we continue the loop, otherwise we break out of the loop.
[[ "$NEW_VERSION" != "$CURRENT_VERSION" ]] || break
sleep 10
done
working-directory: apps/browser
### CLI
- name: CLI - Verify version has been updated
if: ${{ inputs.bump_cli == true }}
env:
NEW_VERSION: ${{ needs.bump_version.outputs.version_cli }}
run: |
# Wait for version to change.
while : ; do
echo "Waiting for version to be updated..."
git pull --force
CURRENT_VERSION=$(cat package.json | jq -r '.version')
# If the versions don't match we continue the loop, otherwise we break out of the loop.
[[ "$NEW_VERSION" != "$CURRENT_VERSION" ]] || break
sleep 10
done
working-directory: apps/cli
### Desktop
- name: Desktop - Verify version has been updated
if: ${{ inputs.bump_desktop == true }}
env:
NEW_VERSION: ${{ needs.bump_version.outputs.version_desktop }}
run: |
# Wait for version to change.
while : ; do
echo "Waiting for version to be updated..."
git pull --force
CURRENT_VERSION=$(cat package.json | jq -r '.version')
# If the versions don't match we continue the loop, otherwise we break out of the loop.
[[ "$NEW_VERSION" != "$CURRENT_VERSION" ]] || break
sleep 10
done
working-directory: apps/desktop
### Web
- name: Web - Verify version has been updated
if: ${{ inputs.bump_web == true }}
env:
NEW_VERSION: ${{ needs.bump_version.outputs.version_web }}
run: |
# Wait for version to change.
while : ; do
echo "Waiting for version to be updated..."
git pull --force
CURRENT_VERSION=$(cat package.json | jq -r '.version')
# If the versions don't match we continue the loop, otherwise we break out of the loop.
[[ "$NEW_VERSION" != "$CURRENT_VERSION" ]] || break
sleep 10
done
working-directory: apps/web
- name: Cut RC branch
run: |
git switch --quiet --create rc
git push --quiet --set-upstream origin rc

View File

@ -1,11 +0,0 @@
---
name: Workflow Linter
on:
pull_request:
paths:
- .github/workflows/**
jobs:
call-workflow:
uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@a30e9c3d658dc97c4c2e61ec749fdab64b83386c

3
.gitignore vendored
View File

@ -42,3 +42,6 @@ junit.xml
documentation.json documentation.json
.eslintcache .eslintcache
storybook-static storybook-static
# Local app configuration
apps/**/config/local.json

View File

@ -1,4 +1 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged npx lint-staged

View File

@ -9,7 +9,6 @@ storybook-static
# External libraries / auto synced locales # External libraries / auto synced locales
apps/browser/src/_locales apps/browser/src/_locales
apps/browser/src/auth/scripts/duo.js apps/browser/src/auth/scripts/duo.js
apps/browser/src/autofill/content/autofill.js
apps/browser/src/safari apps/browser/src/safari
apps/desktop/src/locales apps/desktop/src/locales

View File

@ -4,6 +4,7 @@ import remarkGfm from "remark-gfm";
const config: StorybookConfig = { const config: StorybookConfig = {
stories: [ stories: [
"../libs/auth/src/**/*.stories.@(js|jsx|ts|tsx)",
"../libs/components/src/**/*.mdx", "../libs/components/src/**/*.mdx",
"../libs/components/src/**/*.stories.@(js|jsx|ts|tsx)", "../libs/components/src/**/*.stories.@(js|jsx|ts|tsx)",
"../apps/web/src/**/*.mdx", "../apps/web/src/**/*.mdx",
@ -15,6 +16,8 @@ const config: StorybookConfig = {
"@storybook/addon-links", "@storybook/addon-links",
"@storybook/addon-essentials", "@storybook/addon-essentials",
"@storybook/addon-a11y", "@storybook/addon-a11y",
"@storybook/addon-designs",
"@storybook/addon-interactions",
{ {
name: "@storybook/addon-docs", name: "@storybook/addon-docs",
options: { options: {
@ -35,9 +38,7 @@ const config: StorybookConfig = {
}, },
env: (config) => ({ env: (config) => ({
...config, ...config,
FLAGS: JSON.stringify({ FLAGS: JSON.stringify({}),
secretsManager: true,
}),
}), }),
webpackFinal: async (config, { configType }) => { webpackFinal: async (config, { configType }) => {
if (config.resolve) { if (config.resolve) {

63
.storybook/manager.js Normal file
View File

@ -0,0 +1,63 @@
import { addons } from "@storybook/addons";
import { create } from "@storybook/theming/create";
const lightTheme = create({
base: "light",
//logo and Title
brandTitle: "Bitwarden Component Library",
brandUrl: "/",
brandImage:
"https://github.com/bitwarden/brand/blob/51942f8d6e55e96a078a524e0f739efbf1997bcf/logos/logo-horizontal-blue.png?raw=true",
brandTarget: "_self",
//Colors
colorPrimary: "#6D757E",
colorSecondary: "#175DDC",
// UI
appBg: "#f9fBff",
appContentBg: "#ffffff",
appBorderColor: "#CED4DC",
// Text colors
textColor: "#212529",
textInverseColor: "#ffffff",
// Toolbar default and active colors
barTextColor: "#6D757E",
barSelectedColor: "#175DDC",
barBg: "#ffffff",
// Form colors
inputBg: "#ffffff",
inputBorder: "#6D757E",
inputTextColor: "#6D757E",
});
const darkTheme = create({
base: "dark",
//logo and Title
brandTitle: "Bitwarden Component Library",
brandUrl: "/",
brandImage:
"https://github.com/bitwarden/brand/blob/51942f8d6e55e96a078a524e0f739efbf1997bcf/logos/logo-horizontal-white.png?raw=true",
brandTarget: "_self",
//Colors
colorSecondary: "#6A99F0",
barSelectedColor: "#6A99F0",
});
export const getPreferredColorScheme = () => {
if (!globalThis || !globalThis.matchMedia) return "light";
const isDarkThemePreferred = globalThis.matchMedia("(prefers-color-scheme: dark)").matches;
if (isDarkThemePreferred) return "dark";
return "light";
};
addons.setConfig({
theme: getPreferredColorScheme() === "dark" ? darkTheme : lightTheme,
});

View File

@ -48,7 +48,7 @@ const decorator = componentWrapperDecorator(
}, },
({ globals }) => { ({ globals }) => {
return { theme: `${globals["theme"]}` }; return { theme: `${globals["theme"]}` };
} },
); );
const preview: Preview = { const preview: Preview = {

View File

@ -1,3 +1,9 @@
{ {
"cSpell.words": ["Csprng", "decryptable", "Popout", "Reprompt", "takeuntil"] "cSpell.words": ["Csprng", "decryptable", "Popout", "Reprompt", "takeuntil"],
"search.exclude": {
"**/locales/[^e]*/messages.json": true,
"**/locales/*[^n]/messages.json": true,
"**/_locales/[^e]*/messages.json": true,
"**/_locales/*[^n]/messages.json": true
}
} }

View File

@ -1,22 +1,12 @@
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/apps-combo-logo.png" alt="Bitwarden" /> <img src="https://raw.githubusercontent.com/bitwarden/brand/main/screenshots/apps-combo-logo.png" alt="Bitwarden" />
</p> </p>
<p align="center"> <p align="center">
<a href="https://github.com/bitwarden/clients/actions/workflows/build-browser.yml?query=branch:master" target="_blank"> <a href="https://github.com/bitwarden/clients/actions/workflows/build-browser.yml?query=branch:main" target="_blank"><img src="https://github.com/bitwarden/clients/actions/workflows/build-browser.yml/badge.svg?branch=main" alt="GitHub Workflow browser build on main" /></a>
<img src="https://github.com/bitwarden/clients/actions/workflows/build-browser.yml/badge.svg?branch=master" alt="Github Workflow browser build on master" /> <a href="https://github.com/bitwarden/clients/actions/workflows/build-cli.yml?query=branch:main" target="_blank"><img src="https://github.com/bitwarden/clients/actions/workflows/build-cli.yml/badge.svg?branch=main" alt="GitHub Workflow CLI build on main" /></a>
</a> <a href="https://github.com/bitwarden/clients/actions/workflows/build-desktop.yml?query=branch:main" target="_blank"><img src="https://github.com/bitwarden/clients/actions/workflows/build-desktop.yml/badge.svg?branch=main" alt="GitHub Workflow desktop build on main" /></a>
<a href="https://github.com/bitwarden/clients/actions/workflows/build-cli.yml?query=branch:master" target="_blank"> <a href="https://github.com/bitwarden/clients/actions/workflows/build-web.yml?query=branch:main" target="_blank"><img src="https://github.com/bitwarden/clients/actions/workflows/build-web.yml/badge.svg?branch=main" alt="GitHub Workflow web build on main" /></a>
<img src="https://github.com/bitwarden/clients/actions/workflows/build-cli.yml/badge.svg?branch=master" alt="Github Workflow CLI build on master" /> <a href="https://gitter.im/bitwarden/Lobby" target="_blank"><img src="https://badges.gitter.im/bitwarden/Lobby.svg" alt="gitter chat" /></a>
</a>
<a href="https://github.com/bitwarden/clients/actions/workflows/build-desktop.yml?query=branch:master" target="_blank">
<img src="https://github.com/bitwarden/clients/actions/workflows/build-desktop.yml/badge.svg?branch=master" alt="Github Workflow desktop build on master" />
</a>
<a href="https://github.com/bitwarden/clients/actions/workflows/build-web.yml?query=branch:master" target="_blank">
<img src="https://github.com/bitwarden/clients/actions/workflows/build-web.yml/badge.svg?branch=master" alt="Github Workflow web build on master" />
</a>
<a href="https://gitter.im/bitwarden/Lobby" target="_blank">
<img src="https://badges.gitter.im/bitwarden/Lobby.svg" alt="gitter chat" />
</a>
</p> </p>
--- ---
@ -39,6 +29,6 @@ Interested in contributing in a big way? Consider joining our team! We're hiring
# Contribute # Contribute
Code contributions are welcome! Please commit any pull requests against the `master` branch. Learn more about how to contribute by reading the [Contributing Guidelines](https://contributing.bitwarden.com/contributing/). Check out the [Contributing Documentation](https://contributing.bitwarden.com/) for how to get started with your first contribution. Code contributions are welcome! Please commit any pull requests against the `main` branch. Learn more about how to contribute by reading the [Contributing Guidelines](https://contributing.bitwarden.com/contributing/). Check out the [Contributing Documentation](https://contributing.bitwarden.com/) for how to get started with your first contribution.
Security audits and feedback are welcome. Please open an issue or email us privately if the report is sensitive in nature. You can read our security policy in the [`SECURITY.md`](SECURITY.md) file. Security audits and feedback are welcome. Please open an issue or email us privately if the report is sensitive in nature. You can read our security policy in the [`SECURITY.md`](SECURITY.md) file.

View File

@ -0,0 +1,26 @@
{
"env": {
"browser": true,
"webextensions": true
},
"overrides": [
{
"files": ["src/**/*.ts"],
"excludedFiles": [
"src/**/{content,popup,spec}/**/*.ts",
"src/**/autofill/{notification,overlay}/**/*.ts",
"src/**/autofill/**/{autofill-overlay-content,collect-autofill-content,dom-element-visibility,insert-autofill-content}.service.ts",
"src/**/*.spec.ts"
],
"rules": {
"no-restricted-globals": [
"error",
{
"name": "window",
"message": "The `window` object is not available in service workers and may not be available within the background script. Consider using `self`, `globalThis`, or another global property instead."
}
]
}
}
]
}

View File

@ -1,3 +1,5 @@
config/local.json
# Safari # Safari
dist-safari dist-safari
!src/safari/safari/app/popup/index.html !src/safari/safari/app/popup/index.html

View File

@ -4,13 +4,13 @@
# Bitwarden Browser Extension # Bitwarden Browser Extension
<a href="https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb" target="_blank"><img src="https://imgur.com/3C4iKO0.png" width="64" height="64"></a> <a href="https://chromewebstore.google.com/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb" target="_blank"><img src="https://imgur.com/3C4iKO0.png" width="64" height="64"></a>
<a href="https://addons.mozilla.org/firefox/addon/bitwarden-password-manager/" target="_blank"><img src="https://imgur.com/ihXsdDO.png" width="64" height="64"></a> <a href="https://addons.mozilla.org/firefox/addon/bitwarden-password-manager/" target="_blank"><img src="https://imgur.com/ihXsdDO.png" width="64" height="64"></a>
<a href="https://microsoftedge.microsoft.com/addons/detail/bitwarden-free-password/jbkfoedolllekgbhcbcoahefnbanhhlh" target="_blank"><img src="https://imgur.com/vMcaXaw.png" width="64" height="64"></a> <a href="https://microsoftedge.microsoft.com/addons/detail/bitwarden-free-password/jbkfoedolllekgbhcbcoahefnbanhhlh" target="_blank"><img src="https://imgur.com/vMcaXaw.png" width="64" height="64"></a>
<a href="https://addons.opera.com/extensions/details/bitwarden-free-password-manager/" target="_blank"><img src="https://imgur.com/nSJ9htU.png" width="64" height="64"></a> <a href="https://addons.opera.com/extensions/details/bitwarden-free-password-manager/" target="_blank"><img src="https://imgur.com/nSJ9htU.png" width="64" height="64"></a>
<a href="https://bitwarden.com/download/" target="_blank"><img src="https://imgur.com/ENbaWUu.png" width="64" height="64"></a> <a href="https://bitwarden.com/download/" target="_blank"><img src="https://imgur.com/ENbaWUu.png" width="64" height="64"></a>
<a href="https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb" target="_blank"><img src="https://imgur.com/EuDp4vP.png" width="64" height="64"></a> <a href="https://chromewebstore.google.com/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb" target="_blank"><img src="https://imgur.com/EuDp4vP.png" width="64" height="64"></a>
<a href="https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb" target="_blank"><img src="https://imgur.com/z8yjLZ2.png" width="64" height="64"></a> <a href="https://chromewebstore.google.com/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb" target="_blank"><img src="https://imgur.com/z8yjLZ2.png" width="64" height="64"></a>
<a href="https://addons.mozilla.org/firefox/addon/bitwarden-password-manager/" target="_blank"><img src="https://imgur.com/MQYBSrD.png" width="64" height="64"></a> <a href="https://addons.mozilla.org/firefox/addon/bitwarden-password-manager/" target="_blank"><img src="https://imgur.com/MQYBSrD.png" width="64" height="64"></a>
The Bitwarden browser extension is written using the Web Extension API and Angular. The Bitwarden browser extension is written using the Web Extension API and Angular.

View File

@ -1,6 +1,8 @@
{ {
"dev_flags": {}, "dev_flags": {},
"flags": { "flags": {
"showPasswordless": true "showPasswordless": true,
"enableCipherKeyEncryption": false,
"accountSwitching": false
} }
} }

View File

@ -6,6 +6,8 @@
} }
}, },
"flags": { "flags": {
"showPasswordless": true "showPasswordless": true,
"enableCipherKeyEncryption": false,
"accountSwitching": true
} }
} }

View File

@ -1,3 +1,6 @@
{ {
"flags": {} "flags": {
"enableCipherKeyEncryption": false,
"accountSwitching": true
}
} }

View File

@ -1,13 +1,11 @@
const child = require("child_process"); const child = require("child_process");
const fs = require("fs"); const fs = require("fs");
const del = require("del"); const { rimraf } = require("rimraf");
const gulp = require("gulp"); const gulp = require("gulp");
const filter = require("gulp-filter");
const gulpif = require("gulp-if"); const gulpif = require("gulp-if");
const jeditor = require("gulp-json-editor"); const jeditor = require("gulp-json-editor");
const replace = require("gulp-replace"); const replace = require("gulp-replace");
const zip = require("gulp-zip");
const manifest = require("./src/manifest.json"); const manifest = require("./src/manifest.json");
@ -47,7 +45,10 @@ function distFileName(browserName, ext) {
return `dist-${browserName}${buildString()}.${ext}`; return `dist-${browserName}${buildString()}.${ext}`;
} }
function dist(browserName, manifest) { async function dist(browserName, manifest) {
const { default: zip } = await import("gulp-zip");
const { default: filter } = await import("gulp-filter");
return gulp return gulp
.src(paths.build + "**/*") .src(paths.build + "**/*")
.pipe(filter(["**"].concat(filters.fonts).concat(filters.safari))) .pipe(filter(["**"].concat(filters.fonts).concat(filters.safari)))
@ -60,6 +61,10 @@ function dist(browserName, manifest) {
function distFirefox() { function distFirefox() {
return dist("firefox", (manifest) => { return dist("firefox", (manifest) => {
delete manifest.storage; delete manifest.storage;
delete manifest.sandbox;
manifest.optional_permissions = manifest.optional_permissions.filter(
(permission) => permission !== "privacy",
);
return manifest; return manifest;
}); });
} }
@ -123,13 +128,13 @@ function distSafariApp(cb, subBuildPath) {
"--sign", "--sign",
subBuildPath === "mas" subBuildPath === "mas"
? "3rd Party Mac Developer Application: Bitwarden Inc" ? "3rd Party Mac Developer Application: Bitwarden Inc"
: "E661AB6249AEB60B0F47ABBD7326B2877D2575B0", : "E7C9978F6FBCE0553429185C405E61F5380BE8EB",
"--entitlements", "--entitlements",
entitlementsPath, entitlementsPath,
]; ];
} }
return del([buildPath + "**/*"]) return rimraf([buildPath + "**/*"], { glob: true })
.then(() => safariCopyAssets(paths.safari + "**/*", buildPath)) .then(() => safariCopyAssets(paths.safari + "**/*", buildPath))
.then(() => safariCopyBuild(paths.build + "**/*", buildPath + "safari/app")) .then(() => safariCopyBuild(paths.build + "**/*", buildPath + "safari/app"))
.then(() => { .then(() => {
@ -143,7 +148,9 @@ function distSafariApp(cb, subBuildPath) {
stdOutProc(proc); stdOutProc(proc);
return new Promise((resolve) => proc.on("close", resolve)); return new Promise((resolve) => proc.on("close", resolve));
}) })
.then(() => { .then(async () => {
const { default: filter } = await import("gulp-filter");
const libs = fs const libs = fs
.readdirSync(builtAppexFrameworkPath) .readdirSync(builtAppexFrameworkPath)
.filter((p) => p.endsWith(".dylib")) .filter((p) => p.endsWith(".dylib"))
@ -167,7 +174,7 @@ function distSafariApp(cb, subBuildPath) {
}, },
() => { () => {
return cb; return cb;
} },
); );
} }
@ -178,7 +185,7 @@ function safariCopyAssets(source, dest) {
.on("error", reject) .on("error", reject)
.pipe(gulpif("safari/Info.plist", replace("0.0.1", manifest.version))) .pipe(gulpif("safari/Info.plist", replace("0.0.1", manifest.version)))
.pipe( .pipe(
gulpif("safari/Info.plist", replace("0.0.2", process.env.BUILD_NUMBER || manifest.version)) gulpif("safari/Info.plist", replace("0.0.2", process.env.BUILD_NUMBER || manifest.version)),
) )
.pipe(gulpif("desktop.xcodeproj/project.pbxproj", replace("../../../build", "../safari/app"))) .pipe(gulpif("desktop.xcodeproj/project.pbxproj", replace("../../../build", "../safari/app")))
.pipe(gulp.dest(dest)) .pipe(gulp.dest(dest))
@ -186,7 +193,9 @@ function safariCopyAssets(source, dest) {
}); });
} }
function safariCopyBuild(source, dest) { async function safariCopyBuild(source, dest) {
const { default: filter } = await import("gulp-filter");
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
gulp gulp
.src(source) .src(source)
@ -202,8 +211,8 @@ function safariCopyBuild(source, dest) {
delete manifest.optional_permissions; delete manifest.optional_permissions;
manifest.permissions.push("nativeMessaging"); manifest.permissions.push("nativeMessaging");
return manifest; return manifest;
}) }),
) ),
) )
.pipe(gulp.dest(dest)) .pipe(gulp.dest(dest))
.on("end", resolve); .on("end", resolve);
@ -215,7 +224,10 @@ function stdOutProc(proc) {
proc.stderr.on("data", (data) => console.error(data.toString())); proc.stderr.on("data", (data) => console.error(data.toString()));
} }
function ciCoverage(cb) { async function ciCoverage(cb) {
const { default: zip } = await import("gulp-zip");
const { default: filter } = await import("gulp-filter");
return gulp return gulp
.src(paths.coverage + "**/*") .src(paths.coverage + "**/*")
.pipe(filter(["**", "!coverage/coverage*.zip"])) .pipe(filter(["**", "!coverage/coverage*.zip"]))

View File

@ -9,7 +9,10 @@ module.exports = {
...sharedConfig, ...sharedConfig,
preset: "jest-preset-angular", preset: "jest-preset-angular",
setupFilesAfterEnv: ["<rootDir>/test.setup.ts"], setupFilesAfterEnv: ["<rootDir>/test.setup.ts"],
moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, { moduleNameMapper: pathsToModuleNameMapper(
prefix: "<rootDir>/", { "@bitwarden/common/spec": ["../../libs/common/spec"], ...(compilerOptions?.paths ?? {}) },
}), {
prefix: "<rootDir>/",
},
),
}; };

View File

@ -1,12 +1,11 @@
{ {
"name": "@bitwarden/browser", "name": "@bitwarden/browser",
"version": "2023.7.1", "version": "2024.4.1",
"scripts": { "scripts": {
"build": "webpack", "build": "webpack",
"build:mv3": "cross-env MANIFEST_VERSION=3 webpack", "build:mv3": "cross-env MANIFEST_VERSION=3 webpack",
"build:watch": "webpack --watch", "build:watch": "webpack --watch",
"build:watch:mv3": "cross-env MANIFEST_VERSION=3 webpack --watch", "build:watch:mv3": "cross-env MANIFEST_VERSION=3 webpack --watch",
"build:watch:autofill": "cross-env AUTOFILL_VERSION=2 webpack --watch",
"build:prod": "cross-env NODE_ENV=production webpack", "build:prod": "cross-env NODE_ENV=production webpack",
"build:prod:watch": "cross-env NODE_ENV=production webpack --watch", "build:prod:watch": "cross-env NODE_ENV=production webpack --watch",
"dist": "npm run build:prod && gulp dist", "dist": "npm run build:prod && gulp dist",
@ -19,6 +18,7 @@
"dist:safari:masdev": "npm run build:prod && gulp dist:safari:masdev", "dist:safari:masdev": "npm run build:prod && gulp dist:safari:masdev",
"dist:safari:dmg": "npm run build:prod && gulp dist:safari:dmg", "dist:safari:dmg": "npm run build:prod && gulp dist:safari:dmg",
"test": "jest", "test": "jest",
"test:coverage": "jest --coverage --coverageDirectory=coverage",
"test:watch": "jest --watch", "test:watch": "jest --watch",
"test:watch:all": "jest --watchAll" "test:watch:all": "jest --watchAll"
} }

View File

@ -0,0 +1,29 @@
import { mockDeep } from "jest-mock-extended";
/**
* Mocks a chrome.runtime.Port set up to send messages through `postMessage` to `onMessage.addListener` callbacks.
* @param name - The name of the port.
* @param immediateOnConnectExecution - Whether to immediately execute the onConnect callbacks against the new port.
* Defaults to false. If true, the creator of the port will not have had a chance to set up listeners yet.
* @returns a mock chrome.runtime.Port
*/
export function mockPorts() {
// notify listeners of a new port
(chrome.runtime.connect as jest.Mock).mockImplementation((portInfo) => {
const port = mockDeep<chrome.runtime.Port>();
port.name = portInfo.name;
// set message broadcast
(port.postMessage as jest.Mock).mockImplementation((message) => {
(port.onMessage.addListener as jest.Mock).mock.calls.forEach(([callbackFn]) => {
callbackFn(message, port);
});
});
(chrome.runtime.onConnect.addListener as jest.Mock).mock.calls.forEach(([callbackFn]) => {
callbackFn(port);
});
return port;
});
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -91,6 +91,15 @@
"autoFill": { "autoFill": {
"message": "Auto-fill" "message": "Auto-fill"
}, },
"autoFillLogin": {
"message": "Auto-fill login"
},
"autoFillCard": {
"message": "Auto-fill card"
},
"autoFillIdentity": {
"message": "Auto-fill identity"
},
"generatePasswordCopied": { "generatePasswordCopied": {
"message": "Generate password (copied)" "message": "Generate password (copied)"
}, },
@ -100,6 +109,21 @@
"noMatchingLogins": { "noMatchingLogins": {
"message": "No matching logins" "message": "No matching logins"
}, },
"noCards": {
"message": "No cards"
},
"noIdentities": {
"message": "No identities"
},
"addLoginMenu": {
"message": "Add login"
},
"addCardMenu": {
"message": "Add card"
},
"addIdentityMenu": {
"message": "Add identity"
},
"unlockVaultMenu": { "unlockVaultMenu": {
"message": "Unlock your vault" "message": "Unlock your vault"
}, },
@ -244,6 +268,9 @@
"length": { "length": {
"message": "Length" "message": "Length"
}, },
"passwordMinLength": {
"message": "Minimum password length"
},
"uppercase": { "uppercase": {
"message": "Uppercase (A-Z)" "message": "Uppercase (A-Z)"
}, },
@ -299,6 +326,9 @@
"password": { "password": {
"message": "Password" "message": "Password"
}, },
"totp": {
"message": "Authenticator secret"
},
"passphrase": { "passphrase": {
"message": "Passphrase" "message": "Passphrase"
}, },
@ -338,6 +368,12 @@
"other": { "other": {
"message": "Other" "message": "Other"
}, },
"unlockMethodNeededToChangeTimeoutActionDesc": {
"message": "Set up an unlock method to change your vault timeout action."
},
"unlockMethodNeeded": {
"message": "Set up an unlock method in Settings"
},
"rateExtension": { "rateExtension": {
"message": "Rate the extension" "message": "Rate the extension"
}, },
@ -378,6 +414,9 @@
"lockNow": { "lockNow": {
"message": "Lock now" "message": "Lock now"
}, },
"lockAll": {
"message": "Lock all"
},
"immediately": { "immediately": {
"message": "Immediately" "message": "Immediately"
}, },
@ -454,6 +493,12 @@
"newAccountCreated": { "newAccountCreated": {
"message": "Your new account has been created! You may now log in." "message": "Your new account has been created! You may now log in."
}, },
"youSuccessfullyLoggedIn": {
"message": "You successfully logged in"
},
"youMayCloseThisWindow": {
"message": "You may close this window"
},
"masterPassSent": { "masterPassSent": {
"message": "We've sent you an email with your master password hint." "message": "We've sent you an email with your master password hint."
}, },
@ -476,6 +521,18 @@
"autofillError": { "autofillError": {
"message": "Unable to auto-fill the selected item on this page. Copy and paste the information instead." "message": "Unable to auto-fill the selected item on this page. Copy and paste the information instead."
}, },
"totpCaptureError": {
"message": "Unable to scan QR code from the current webpage"
},
"totpCaptureSuccess": {
"message": "Authenticator key added"
},
"totpCapture": {
"message": "Scan authenticator QR code from current webpage"
},
"copyTOTP": {
"message": "Copy Authenticator key (TOTP)"
},
"loggedOut": { "loggedOut": {
"message": "Logged out" "message": "Logged out"
}, },
@ -592,6 +649,9 @@
"addLoginNotificationDesc": { "addLoginNotificationDesc": {
"message": "Ask to add an item if one isn't found in your vault." "message": "Ask to add an item if one isn't found in your vault."
}, },
"addLoginNotificationDescAlt": {
"message": "Ask to add an item if one isn't found in your vault. Applies to all logged in accounts."
},
"showCardsCurrentTab": { "showCardsCurrentTab": {
"message": "Show cards on Tab page" "message": "Show cards on Tab page"
}, },
@ -624,6 +684,15 @@
"changedPasswordNotificationDesc": { "changedPasswordNotificationDesc": {
"message": "Ask to update a login's password when a change is detected on a website." "message": "Ask to update a login's password when a change is detected on a website."
}, },
"changedPasswordNotificationDescAlt": {
"message": "Ask to update a login's password when a change is detected on a website. Applies to all logged in accounts."
},
"enableUsePasskeys": {
"message": "Ask to save and use passkeys"
},
"usePasskeysDesc": {
"message": "Ask to save new passkeys or log in with passkeys stored in your vault. Applies to all logged in accounts."
},
"notificationChangeDesc": { "notificationChangeDesc": {
"message": "Do you want to update this password in Bitwarden?" "message": "Do you want to update this password in Bitwarden?"
}, },
@ -640,7 +709,10 @@
"message": "Show context menu options" "message": "Show context menu options"
}, },
"contextMenuItemDesc": { "contextMenuItemDesc": {
"message": "Use a secondary click to access password generation and matching logins for the website. " "message": "Use a secondary click to access password generation and matching logins for the website."
},
"contextMenuItemDescAlt": {
"message": "Use a secondary click to access password generation and matching logins for the website. Applies to all logged in accounts."
}, },
"defaultUriMatchDetection": { "defaultUriMatchDetection": {
"message": "Default URI match detection", "message": "Default URI match detection",
@ -655,6 +727,9 @@
"themeDesc": { "themeDesc": {
"message": "Change the application's color theme." "message": "Change the application's color theme."
}, },
"themeDescAlt": {
"message": "Change the application's color theme. Applies to all logged in accounts."
},
"dark": { "dark": {
"message": "Dark", "message": "Dark",
"description": "Dark color" "description": "Dark color"
@ -768,8 +843,8 @@
"featureUnavailable": { "featureUnavailable": {
"message": "Feature unavailable" "message": "Feature unavailable"
}, },
"updateKey": { "encryptionKeyMigrationRequired": {
"message": "You cannot use this feature until you update your encryption key." "message": "Encryption key migration required. Please login through the web vault to update your encryption key."
}, },
"premiumMembership": { "premiumMembership": {
"message": "Premium membership" "message": "Premium membership"
@ -792,8 +867,8 @@
"ppremiumSignUpStorage": { "ppremiumSignUpStorage": {
"message": "1 GB encrypted storage for file attachments." "message": "1 GB encrypted storage for file attachments."
}, },
"ppremiumSignUpTwoStep": { "premiumSignUpTwoStepOptions": {
"message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." "message": "Proprietary two-step login options such as YubiKey and Duo."
}, },
"ppremiumSignUpReports": { "ppremiumSignUpReports": {
"message": "Password hygiene, account health, and data breach reports to keep your vault safe." "message": "Password hygiene, account health, and data breach reports to keep your vault safe."
@ -975,6 +1050,31 @@
"environmentSaved": { "environmentSaved": {
"message": "Environment URLs saved" "message": "Environment URLs saved"
}, },
"showAutoFillMenuOnFormFields": {
"message": "Show auto-fill menu on form fields",
"description": "Represents the message for allowing the user to enable the auto-fill overlay"
},
"showAutoFillMenuOnFormFieldsDescAlt": {
"message": "Applies to all logged in accounts."
},
"turnOffBrowserBuiltInPasswordManagerSettings": {
"message": "Turn off your browsers built in password manager settings to avoid conflicts."
},
"turnOffBrowserBuiltInPasswordManagerSettingsLink": {
"message": "Edit browser settings."
},
"autofillOverlayVisibilityOff": {
"message": "Off",
"description": "Overlay setting select option for disabling autofill overlay"
},
"autofillOverlayVisibilityOnFieldFocus": {
"message": "When field is selected (on focus)",
"description": "Overlay appearance select option for showing the field on focus of the input element"
},
"autofillOverlayVisibilityOnButtonClick": {
"message": "When auto-fill icon is selected",
"description": "Overlay appearance select option for showing the field on click of the overlay icon"
},
"enableAutoFillOnPageLoad": { "enableAutoFillOnPageLoad": {
"message": "Auto-fill on page load" "message": "Auto-fill on page load"
}, },
@ -1067,6 +1167,9 @@
"faviconDesc": { "faviconDesc": {
"message": "Show a recognizable image next to each login." "message": "Show a recognizable image next to each login."
}, },
"faviconDescAlt": {
"message": "Show a recognizable image next to each login. Applies to all logged in accounts."
},
"enableBadgeCounter": { "enableBadgeCounter": {
"message": "Show badge counter" "message": "Show badge counter"
}, },
@ -1396,6 +1499,9 @@
"invalidPin": { "invalidPin": {
"message": "Invalid PIN code." "message": "Invalid PIN code."
}, },
"tooManyInvalidPinEntryAttemptsLoggingOut": {
"message": "Too many invalid PIN entry attempts. Logging out."
},
"unlockWithBiometrics": { "unlockWithBiometrics": {
"message": "Unlock with biometrics" "message": "Unlock with biometrics"
}, },
@ -1446,9 +1552,6 @@
"restoreItem": { "restoreItem": {
"message": "Restore item" "message": "Restore item"
}, },
"restoreItemConfirmation": {
"message": "Are you sure you want to restore this item?"
},
"restoredItem": { "restoredItem": {
"message": "Item restored" "message": "Item restored"
}, },
@ -1605,6 +1708,12 @@
"biometricsNotSupportedDesc": { "biometricsNotSupportedDesc": {
"message": "Browser biometrics is not supported on this device." "message": "Browser biometrics is not supported on this device."
}, },
"biometricsFailedTitle": {
"message": "Biometrics failed"
},
"biometricsFailedDesc": {
"message": "Biometrics cannot be completed, consider using a master password or logging out. If this persists, please contact Bitwarden support."
},
"nativeMessaginPermissionErrorTitle": { "nativeMessaginPermissionErrorTitle": {
"message": "Permission not provided" "message": "Permission not provided"
}, },
@ -1623,18 +1732,24 @@
"personalOwnershipPolicyInEffect": { "personalOwnershipPolicyInEffect": {
"message": "An organization policy is affecting your ownership options." "message": "An organization policy is affecting your ownership options."
}, },
"personalOwnershipPolicyInEffectImports": {
"message": "An organization policy has blocked importing items into your individual vault."
},
"excludedDomains": { "excludedDomains": {
"message": "Excluded domains" "message": "Excluded domains"
}, },
"excludedDomainsDesc": { "excludedDomainsDesc": {
"message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect."
}, },
"excludedDomainsDescAlt": {
"message": "Bitwarden will not ask to save login details for these domains for all logged in accounts. You must refresh the page for changes to take effect."
},
"excludedDomainsInvalidDomain": { "excludedDomainsInvalidDomain": {
"message": "$DOMAIN$ is not a valid domain", "message": "$DOMAIN$ is not a valid domain",
"placeholders": { "placeholders": {
"domain": { "domain": {
"content": "$1", "content": "$1",
"example": "googlecom" "example": "google.com"
} }
} }
}, },
@ -1889,8 +2004,21 @@
"selectFolder": { "selectFolder": {
"message": "Select folder..." "message": "Select folder..."
}, },
"ssoCompleteRegistration": { "noFoldersFound": {
"message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." "message": "No folders found",
"description": "Used as a message within the notification bar when no folders are found"
},
"orgPermissionsUpdatedMustSetPassword": {
"message": "Your organization permissions were updated, requiring you to set a master password.",
"description": "Used as a card title description on the set password page to explain why the user is there"
},
"orgRequiresYouToSetPassword": {
"message": "Your organization requires you to set a master password.",
"description": "Used as a card title description on the set password page to explain why the user is there"
},
"verificationRequired" : {
"message": "Verification required",
"description": "Default title for the user verification dialog."
}, },
"hours": { "hours": {
"message": "Hours" "message": "Hours"
@ -1985,8 +2113,8 @@
"exportingPersonalVaultTitle": { "exportingPersonalVaultTitle": {
"message": "Exporting individual vault" "message": "Exporting individual vault"
}, },
"exportingPersonalVaultDescription": { "exportingIndividualVaultDescription": {
"message": "Only the individual vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", "message": "Only the individual vault items associated with $EMAIL$ will be exported. Organization vault items will not be included. Only vault item information will be exported and will not include associated attachments.",
"placeholders": { "placeholders": {
"email": { "email": {
"content": "$1", "content": "$1",
@ -2086,8 +2214,8 @@
"serverVersion": { "serverVersion": {
"message": "Server version" "message": "Server version"
}, },
"selfHosted": { "selfHostedServer": {
"message": "Self-hosted" "message": "self-hosted"
}, },
"thirdParty": { "thirdParty": {
"message": "Third-party" "message": "Third-party"
@ -2146,8 +2274,8 @@
"notificationSentDevice": { "notificationSentDevice": {
"message": "A notification has been sent to your device." "message": "A notification has been sent to your device."
}, },
"logInInitiated": { "loginInitiated": {
"message": "Log in initiated" "message": "Login initiated"
}, },
"exposedMasterPassword": { "exposedMasterPassword": {
"message": "Exposed Master Password" "message": "Exposed Master Password"
@ -2186,7 +2314,7 @@
"message": "How to auto-fill" "message": "How to auto-fill"
}, },
"autofillSelectInfoWithCommand": { "autofillSelectInfoWithCommand": {
"message": "Select an item from this page or use the shortcut: $COMMAND$", "message": "Select an item from this screen, use the shortcut $COMMAND$, or explore other options in settings.",
"placeholders": { "placeholders": {
"command": { "command": {
"content": "$1", "content": "$1",
@ -2195,7 +2323,7 @@
} }
}, },
"autofillSelectInfoWithoutCommand": { "autofillSelectInfoWithoutCommand": {
"message": "Select an item from this page or set a shortcut in settings." "message": "Select an item from this screen, or explore other options in settings."
}, },
"gotIt": { "gotIt": {
"message": "Got it" "message": "Got it"
@ -2233,11 +2361,30 @@
"opensInANewWindow": { "opensInANewWindow": {
"message": "Opens in a new window" "message": "Opens in a new window"
}, },
"usDomain": { "deviceApprovalRequired": {
"message": "bitwarden.com" "message": "Device approval required. Select an approval option below:"
}, },
"euDomain": { "rememberThisDevice": {
"message": "bitwarden.eu" "message": "Remember this device"
},
"uncheckIfPublicDevice": {
"message": "Uncheck if using a public device"
},
"approveFromYourOtherDevice": {
"message": "Approve from your other device"
},
"requestAdminApproval": {
"message": "Request admin approval"
},
"approveWithMasterPassword": {
"message": "Approve with master password"
},
"ssoIdentifierRequired": {
"message": "Organization SSO identifier is required."
},
"eu": {
"message": "EU",
"description": "European Union"
}, },
"accessDenied": { "accessDenied": {
"message": "Access denied. You do not have permission to view this page." "message": "Access denied. You do not have permission to view this page."
@ -2247,5 +2394,622 @@
}, },
"display": { "display": {
"message": "Display" "message": "Display"
},
"accountSuccessfullyCreated": {
"message": "Account successfully created!"
},
"adminApprovalRequested": {
"message": "Admin approval requested"
},
"adminApprovalRequestSentToAdmins": {
"message": "Your request has been sent to your admin."
},
"youWillBeNotifiedOnceApproved": {
"message": "You will be notified once approved."
},
"troubleLoggingIn": {
"message": "Trouble logging in?"
},
"loginApproved": {
"message": "Login approved"
},
"userEmailMissing": {
"message": "User email missing"
},
"deviceTrusted": {
"message": "Device trusted"
},
"inputRequired": {
"message": "Input is required."
},
"required": {
"message": "required"
},
"search": {
"message": "Search"
},
"inputMinLength": {
"message": "Input must be at least $COUNT$ characters long.",
"placeholders": {
"count": {
"content": "$1",
"example": "8"
}
}
},
"inputMaxLength": {
"message": "Input must not exceed $COUNT$ characters in length.",
"placeholders": {
"count": {
"content": "$1",
"example": "20"
}
}
},
"inputForbiddenCharacters": {
"message": "The following characters are not allowed: $CHARACTERS$",
"placeholders": {
"characters": {
"content": "$1",
"example": "@, #, $, %"
}
}
},
"inputMinValue": {
"message": "Input value must be at least $MIN$.",
"placeholders": {
"min": {
"content": "$1",
"example": "8"
}
}
},
"inputMaxValue": {
"message": "Input value must not exceed $MAX$.",
"placeholders": {
"max": {
"content": "$1",
"example": "100"
}
}
},
"multipleInputEmails": {
"message": "1 or more emails are invalid"
},
"inputTrimValidator": {
"message": "Input must not contain only whitespace.",
"description": "Notification to inform the user that a form's input can't contain only whitespace."
},
"inputEmail": {
"message": "Input is not an email address."
},
"fieldsNeedAttention": {
"message": "$COUNT$ field(s) above need your attention.",
"placeholders": {
"count": {
"content": "$1",
"example": "4"
}
}
},
"selectPlaceholder": {
"message": "-- Select --"
},
"multiSelectPlaceholder": {
"message": "-- Type to filter --"
},
"multiSelectLoading": {
"message": "Retrieving options..."
},
"multiSelectNotFound": {
"message": "No items found"
},
"multiSelectClearAll": {
"message": "Clear all"
},
"plusNMore": {
"message": "+ $QUANTITY$ more",
"placeholders": {
"quantity": {
"content": "$1",
"example": "5"
}
}
},
"submenu": {
"message": "Submenu"
},
"toggleCollapse": {
"message": "Toggle collapse",
"description": "Toggling an expand/collapse state."
},
"filelessImport": {
"message": "Import your data to Bitwarden?",
"description": "Default notification title for triggering a fileless import."
},
"lpFilelessImport": {
"message": "Protect your LastPass data and import to Bitwarden?",
"description": "LastPass specific notification title for triggering a fileless import."
},
"lpCancelFilelessImport": {
"message": "Save as unencrypted file",
"description": "LastPass specific notification button text for cancelling a fileless import."
},
"startFilelessImport": {
"message": "Import to Bitwarden",
"description": "Notification button text for starting a fileless import."
},
"importing": {
"message": "Importing...",
"description": "Notification message for when an import is in progress."
},
"dataSuccessfullyImported": {
"message": "Data successfully imported!",
"description": "Notification message for when an import has completed successfully."
},
"dataImportFailed": {
"message": "Error importing. Check console for details.",
"description": "Notification message for when an import has failed."
},
"importNetworkError": {
"message": "Network error encountered during import.",
"description": "Notification message for when an import has failed due to a network error."
},
"aliasDomain": {
"message": "Alias domain"
},
"passwordRepromptDisabledAutofillOnPageLoad": {
"message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.",
"description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load."
},
"autofillOnPageLoadSetToDefault": {
"message": "Auto-fill on page load set to use default setting.",
"description": "Toast message for informing the user that auto-fill on page load has been set to the default setting."
},
"turnOffMasterPasswordPromptToEditField": {
"message": "Turn off master password re-prompt to edit this field",
"description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item."
},
"skipToContent": {
"message": "Skip to content"
},
"bitwardenOverlayButton": {
"message": "Bitwarden auto-fill menu button",
"description": "Page title for the iframe containing the overlay button"
},
"toggleBitwardenVaultOverlay": {
"message": "Toggle Bitwarden auto-fill menu",
"description": "Screen reader and tool tip label for the overlay button"
},
"bitwardenVault": {
"message": "Bitwarden auto-fill menu",
"description": "Page title in overlay"
},
"unlockYourAccountToViewMatchingLogins": {
"message": "Unlock your account to view matching logins",
"description": "Text to display in overlay when the account is locked."
},
"unlockAccount": {
"message": "Unlock account",
"description": "Button text to display in overlay when the account is locked."
},
"fillCredentialsFor": {
"message": "Fill credentials for",
"description": "Screen reader text for when overlay item is in focused"
},
"partialUsername" : {
"message": "Partial username",
"description": "Screen reader text for when a login item is focused where a partial username is displayed. SR will announce this phrase before reading the text of the partial username"
},
"noItemsToShow": {
"message": "No items to show",
"description": "Text to show in overlay if there are no matching items"
},
"newItem": {
"message": "New item",
"description": "Button text to display in overlay when there are no matching items"
},
"addNewVaultItem": {
"message": "Add new vault item",
"description": "Screen reader text (aria-label) for new item button in overlay"
},
"bitwardenOverlayMenuAvailable": {
"message": "Bitwarden auto-fill menu available. Press the down arrow key to select.",
"description": "Screen reader text for announcing when the overlay opens on the page"
},
"turnOn": {
"message": "Turn on"
},
"ignore": {
"message": "Ignore"
},
"importData": {
"message": "Import data",
"description": "Used for the header of the import dialog, the import button and within the file-password-prompt"
},
"importError": {
"message": "Import error"
},
"importErrorDesc": {
"message": "There was a problem with the data you tried to import. Please resolve the errors listed below in your source file and try again."
},
"resolveTheErrorsBelowAndTryAgain": {
"message": "Resolve the errors below and try again."
},
"description": {
"message": "Description"
},
"importSuccess": {
"message": "Data successfully imported"
},
"importSuccessNumberOfItems": {
"message": "A total of $AMOUNT$ items were imported.",
"placeholders": {
"amount": {
"content": "$1",
"example": "2"
}
}
},
"tryAgain": {
"message": "Try again"
},
"verificationRequiredForActionSetPinToContinue": {
"message": "Verification required for this action. Set a PIN to continue."
},
"setPin": {
"message": "Set PIN"
},
"verifyWithBiometrics": {
"message": "Verify with biometrics"
},
"awaitingConfirmation": {
"message": "Awaiting confirmation"
},
"couldNotCompleteBiometrics": {
"message": "Could not complete biometrics."
},
"needADifferentMethod": {
"message": "Need a different method?"
},
"useMasterPassword": {
"message": "Use master password"
},
"usePin": {
"message": "Use PIN"
},
"useBiometrics": {
"message": "Use biometrics"
},
"enterVerificationCodeSentToEmail": {
"message": "Enter the verification code that was sent to your email."
},
"resendCode": {
"message": "Resend code"
},
"total": {
"message": "Total"
},
"importWarning": {
"message": "You are importing data to $ORGANIZATION$. Your data may be shared with members of this organization. Do you want to proceed?",
"placeholders": {
"organization": {
"content": "$1",
"example": "My Org Name"
}
}
},
"launchDuoAndFollowStepsToFinishLoggingIn": {
"message": "Launch Duo and follow the steps to finish logging in."
},
"duoRequiredForAccount": {
"message": "Duo two-step login is required for your account."
},
"popoutTheExtensionToCompleteLogin": {
"message": "Popout the extension to complete login."
},
"popoutExtension": {
"message": "Popout extension"
},
"launchDuo": {
"message": "Launch Duo"
},
"importFormatError": {
"message": "Data is not formatted correctly. Please check your import file and try again."
},
"importNothingError": {
"message": "Nothing was imported."
},
"importEncKeyError": {
"message": "Error decrypting the exported file. Your encryption key does not match the encryption key used export the data."
},
"invalidFilePassword": {
"message": "Invalid file password, please use the password you entered when you created the export file."
},
"importDestination": {
"message": "Import destination"
},
"learnAboutImportOptions": {
"message": "Learn about your import options"
},
"selectImportFolder": {
"message": "Select a folder"
},
"selectImportCollection": {
"message": "Select a collection"
},
"importTargetHint": {
"message": "Select this option if you want the imported file contents moved to a $DESTINATION$",
"description": "Located as a hint under the import target. Will be appended by either folder or collection, depending if the user is importing into an individual or an organizational vault.",
"placeholders": {
"destination": {
"content": "$1",
"example": "folder or collection"
}
}
},
"importUnassignedItemsError": {
"message": "File contains unassigned items."
},
"selectFormat": {
"message": "Select the format of the import file"
},
"selectImportFile": {
"message": "Select the import file"
},
"chooseFile": {
"message": "Choose File"
},
"noFileChosen": {
"message": "No file chosen"
},
"orCopyPasteFileContents": {
"message": "or copy/paste the import file contents"
},
"instructionsFor": {
"message": "$NAME$ Instructions",
"description": "The title for the import tool instructions.",
"placeholders": {
"name": {
"content": "$1",
"example": "LastPass (csv)"
}
}
},
"confirmVaultImport": {
"message": "Confirm vault import"
},
"confirmVaultImportDesc": {
"message": "This file is password-protected. Please enter the file password to import data."
},
"confirmFilePassword": {
"message": "Confirm file password"
},
"typePasskey": {
"message": "Passkey"
},
"passkeyNotCopied": {
"message": "Passkey will not be copied"
},
"passkeyNotCopiedAlert": {
"message": "The passkey will not be copied to the cloned item. Do you want to continue cloning this item?"
},
"passkeyFeatureIsNotImplementedForAccountsWithoutMasterPassword": {
"message": "Verification required by the initiating site. This feature is not yet implemented for accounts without master password."
},
"logInWithPasskey": {
"message": "Log in with passkey?"
},
"passkeyAlreadyExists": {
"message": "A passkey already exists for this application."
},
"noPasskeysFoundForThisApplication": {
"message": "No passkeys found for this application."
},
"noMatchingPasskeyLogin": {
"message": "You do not have a matching login for this site."
},
"confirm": {
"message": "Confirm"
},
"savePasskey": {
"message": "Save passkey"
},
"savePasskeyNewLogin": {
"message": "Save passkey as new login"
},
"choosePasskey": {
"message": "Choose a login to save this passkey to"
},
"passkeyItem": {
"message": "Passkey Item"
},
"overwritePasskey": {
"message": "Overwrite passkey?"
},
"overwritePasskeyAlert": {
"message": "This item already contains a passkey. Are you sure you want to overwrite the current passkey?"
},
"featureNotSupported": {
"message": "Feature not yet supported"
},
"yourPasskeyIsLocked": {
"message": "Authentication required to use passkey. Verify your identity to continue."
},
"multifactorAuthenticationCancelled": {
"message": "Multifactor authentication cancelled"
},
"noLastPassDataFound": {
"message": "No LastPass data found"
},
"incorrectUsernameOrPassword": {
"message": "Incorrect username or password"
},
"incorrectPassword": {
"message": "Incorrect password"
},
"incorrectCode": {
"message": "Incorrect code"
},
"incorrectPin": {
"message": "Incorrect PIN"
},
"multifactorAuthenticationFailed": {
"message": "Multifactor authentication failed"
},
"includeSharedFolders": {
"message": "Include shared folders"
},
"lastPassEmail": {
"message": "LastPass Email"
},
"importingYourAccount": {
"message": "Importing your account..."
},
"lastPassMFARequired": {
"message": "LastPass multifactor authentication required"
},
"lastPassMFADesc": {
"message": "Enter your one-time passcode from your authentication app"
},
"lastPassOOBDesc": {
"message": "Approve the login request in your authentication app or enter a one-time passcode."
},
"passcode": {
"message": "Passcode"
},
"lastPassMasterPassword": {
"message": "LastPass master password"
},
"lastPassAuthRequired": {
"message": "LastPass authentication required"
},
"awaitingSSO": {
"message": "Awaiting SSO authentication"
},
"awaitingSSODesc": {
"message": "Please continue to log in using your company credentials."
},
"seeDetailedInstructions": {
"message": "See detailed instructions on our help site at",
"description": "This is followed a by a hyperlink to the help website."
},
"importDirectlyFromLastPass": {
"message": "Import directly from LastPass"
},
"importFromCSV": {
"message": "Import from CSV"
},
"lastPassTryAgainCheckEmail": {
"message": "Try again or look for an email from LastPass to verify it's you."
},
"collection": {
"message": "Collection"
},
"lastPassYubikeyDesc": {
"message": "Insert the YubiKey associated with your LastPass account into your computer's USB port, then touch its button."
},
"switchAccount": {
"message": "Switch account"
},
"switchAccounts": {
"message": "Switch accounts"
},
"switchToAccount": {
"message": "Switch to account"
},
"activeAccount": {
"message": "Active account"
},
"availableAccounts": {
"message": "Available accounts"
},
"accountLimitReached": {
"message": "Account limit reached. Log out of an account to add another."
},
"active": {
"message": "active"
},
"locked": {
"message": "locked"
},
"unlocked": {
"message": "unlocked"
},
"server": {
"message": "server"
},
"hostedAt": {
"message": "hosted at"
},
"useDeviceOrHardwareKey": {
"message": "Use your device or hardware key"
},
"justOnce": {
"message": "Just once"
},
"alwaysForThisSite": {
"message": "Always for this site"
},
"domainAddedToExcludedDomains": {
"message": "$DOMAIN$ added to excluded domains.",
"placeholders": {
"domain": {
"content": "$1",
"example": "google.com"
}
}
},
"commonImportFormats": {
"message": "Common formats",
"description": "Label indicating the most common import formats"
},
"overrideDefaultBrowserAutofillTitle": {
"message": "Make Bitwarden your default password manager?",
"description": "Dialog title facilitating the ability to override a chrome browser's default autofill behavior"
},
"overrideDefaultBrowserAutofillDescription": {
"message": "Ignoring this option may cause conflicts between the Bitwarden auto-fill menu and your browser's.",
"description": "Dialog message facilitating the ability to override a chrome browser's default autofill behavior"
},
"overrideDefaultBrowserAutoFillSettings": {
"message": "Make Bitwarden your default password manager",
"description": "Label for the setting that allows overriding the default browser autofill settings"
},
"privacyPermissionAdditionNotGrantedTitle": {
"message": "Unable to set Bitwarden as the default password manager",
"description": "Title for the dialog that appears when the user has not granted the extension permission to set privacy settings"
},
"privacyPermissionAdditionNotGrantedDescription": {
"message": "You must grant browser privacy permissions to Bitwarden to set it as the default password manager.",
"description": "Description for the dialog that appears when the user has not granted the extension permission to set privacy settings"
},
"makeDefault": {
"message": "Make default",
"description": "Button text for the setting that allows overriding the default browser autofill settings"
},
"saveCipherAttemptSuccess": {
"message": "Credentials saved successfully!",
"description": "Notification message for when saving credentials has succeeded."
},
"updateCipherAttemptSuccess": {
"message": "Credentials updated successfully!",
"description": "Notification message for when updating credentials has succeeded."
},
"saveCipherAttemptFailed": {
"message": "Error saving credentials. Check console for details.",
"description": "Notification message for when saving credentials has failed."
},
"removePasskey": {
"message": "Remove passkey"
},
"passkeyRemoved": {
"message": "Passkey removed"
},
"unassignedItemsBanner": {
"message": "Notice: Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible."
},
"unassignedItemsBannerSelfHost": {
"message": "Notice: On May 2, 2024, unassigned organization items will no longer be visible in the All Vaults view and will only be accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible."
} }
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More