Merge remote-tracking branch 'clients/master' into PS-589-add-2fa-new-device-login-settings-flag

# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
This commit is contained in:
Federico Andrés Maccaroni 2022-06-06 15:18:42 -03:00
commit c6919f3484
1695 changed files with 449253 additions and 14063 deletions

View File

@ -7,6 +7,7 @@ root = true
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
# Set default charset
[*.{js,ts,scss,html}]

19
.eslintignore Normal file
View File

@ -0,0 +1,19 @@
**/build
**/dist
**/node_modules
**/webpack.*.js
**/jest.config.js
**/gulpfile.js
apps/browser/src/content/autofill.js
apps/browser/src/scripts/duo.js
apps/desktop/desktop_native
apps/desktop/src/scripts/duo.js
apps/web/config.js
apps/web/scripts/*.js
apps/web/src/theme.js
apps/web/tailwind.config.js

55
.eslintrc.json Normal file
View File

@ -0,0 +1,55 @@
{
"root": true,
"env": {
"browser": true,
"webextensions": true
},
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:import/recommended",
"plugin:import/typescript",
"prettier"
],
"rules": {
"@typescript-eslint/no-explicit-any": "off", // TODO: This should be re-enabled
"@typescript-eslint/no-unused-vars": ["warn", { "args": "none" }],
"@typescript-eslint/explicit-member-accessibility": [
"error",
{
"accessibility": "no-public"
}
],
"@typescript-eslint/no-this-alias": [
"error",
{
"allowedNames": ["self"]
}
],
"no-console": "warn",
"import/no-unresolved": "off", // TODO: Look into turning off once each package is an actual package.
"import/order": [
"error",
{
"alphabetize": {
"order": "asc"
},
"newlines-between": "always",
"pathGroups": [
{
"pattern": "jslib-*/**",
"group": "external",
"position": "after"
},
{
"pattern": "src/**/*",
"group": "parent",
"position": "before"
}
],
"pathGroupsExcludedImportTypes": ["builtin"]
}
]
}
}

24
.git-blame-ignore-revs Normal file
View File

@ -0,0 +1,24 @@
# Browser: Apply Prettier https://github.com/bitwarden/browser/pull/2238
8fe821b9a3f9728bcb02d607ca75add468d380c1
# Browser: Monorepository https://github.com/bitwarden/browser/pull/2531
7fe51f83daa38df15a105f4a917abd01d94eddd1
# Desktop: Apply Prettier https://github.com/bitwarden/desktop/pull/1202
521feae535d83166e620c3c28dfc3e7b0314a00e
# Browser: Monorepository https://github.com/bitwarden/clients/commit/7712ca6fa505c4b80b168258a7fc6a02c13160fd
28bc4113b9bbae4dba2b5af14d460764fce79acf
# CLI: Apply Prettier https://github.com/bitwarden/cli/pull/426
910b4a24e649f21acbf4da5b2d422b121d514bd5
# CLI: Monorepository https://github.com/bitwarden/clients/commit/980429f4bdcb178d8d92d8202cbdacfaa45c917e
980429f4bdcb178d8d92d8202cbdacfaa45c917e
# Web: Apply Prettier https://github.com/bitwarden/web/pull/1347
56477eb39cfd8a73c9920577d24d75fed36e2cf5
# Web: Monorepository https://github.com/bitwarden/clients/commit/02fe7159034b04d763a61fcf0200869e3209fa33
02fe7159034b04d763a61fcf0200869e3209fa33
# Jslib: Apply Prettier https://github.com/bitwarden/jslib/pull/581
193434461dbd9c48fe5dcbad95693470aec422ac
# Jslib: Monorepository https://github.com/bitwarden/clients/pull/2824/commits/d7492e3cf320410e74ebd0e0675ab994e64bd01a
d7492e3cf320410e74ebd0e0675ab994e64bd01a

93
.github/ISSUE_TEMPLATE/browser.yml vendored Normal file
View File

@ -0,0 +1,93 @@
name: Browser Bug Report
description: File a bug report
labels: [bug, browser]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
Please do not submit feature requests. The [Community Forums](https://community.bitwarden.com) has a section for submitting, voting for, and discussing product feature requests.
- type: textarea
id: reproduce
attributes:
label: Steps To Reproduce
description: How can we reproduce the behavior.
value: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. Click on '...'
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected Result
description: A clear and concise description of what you expected to happen.
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual Result
description: A clear and concise description of what is happening.
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: Screenshots or Videos
description: If applicable, add screenshots and/or a short video to help explain your problem.
- type: textarea
id: additional-context
attributes:
label: Additional Context
description: Add any other context about the problem here.
- type: dropdown
id: os
attributes:
label: Operating System
description: What operating system are you seeing the problem on?
multiple: true
options:
- Windows
- macOS
- Linux
- Android
- iOS
validations:
required: true
- type: input
id: os-version
attributes:
label: Operating System Version
description: What version of the operating system(s) are you seeing the problem on?
- type: dropdown
id: browsers
attributes:
label: Web Browser
description: What browser(s) are you seeing the problem on?
multiple: true
options:
- Chrome
- Safari
- Microsoft Edge
- Firefox
- Opera
- Brave
- Vivaldi
validations:
required: true
- type: input
id: browser-version
attributes:
label: Browser Version
description: What version of the browser(s) are you seeing the problem on?
- type: input
id: version
attributes:
label: Build Version
description: What version of our software are you running? (go to "Settings" → "About" in the extension)
validations:
required: true

82
.github/ISSUE_TEMPLATE/cli.yml vendored Normal file
View File

@ -0,0 +1,82 @@
name: CLI Bug Report
description: File a bug report
labels: [bug, cli]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
Please do not submit feature requests. The [Community Forums](https://community.bitwarden.com) has a section for submitting, voting for, and discussing product feature requests.
- type: textarea
id: reproduce
attributes:
label: Steps To Reproduce
description: How can we reproduce the behavior.
value: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. Click on '...'
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected Result
description: A clear and concise description of what you expected to happen.
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual Result
description: A clear and concise description of what is happening.
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: Screenshots or Videos
description: If applicable, add screenshots and/or a short video to help explain your problem.
- type: textarea
id: additional-context
attributes:
label: Additional Context
description: Add any other context about the problem here.
- type: dropdown
id: os
attributes:
label: Operating System
description: What operating system are you seeing the problem on?
multiple: true
options:
- Windows
- macOS
- Linux
validations:
required: true
- type: input
id: os-version
attributes:
label: Operating System Version
description: What version of the operating system(s) are you seeing the problem on?
- type: dropdown
id: shell
attributes:
label: Shell
description: What shell(s) are you seeing the problem on?
multiple: true
options:
- Bash
- Zsh
- PowerShell
validations:
required: true
- type: input
id: version
attributes:
label: Build Version
description: What version of our software are you running? (run `bw --version`)
validations:
required: true

20
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,20 @@
blank_issues_enabled: false
contact_links:
- name: Report failure of prompt to save credentials in browser
url: https://docs.google.com/forms/d/e/1FAIpQLSeG-Dtpn2xnr9N7oF04NyY6ETUM-JF8pagFfAv8mW7bgcMVxA/viewform
about: We are aware of many sites' login forms where the Bitwarden browser extension either on a single platform/browser or multiple will not prompt the user to save a new password or update an existing password. This is something the Bitwarden team is actively working on but need your help as a community and active Bitwarden users!
- name: Report autofill failure in browser
url: https://docs.google.com/forms/d/e/1FAIpQLSfkxh1w6vK8fLYwAbAAEVhvhMAJwfFNDtYtPUVk1y5WTHvJmQ/viewform
about: We are aware of many sites' login forms, payment gateways, identity forms, etc. where the Bitwarden browser extension either on a single platform/browser or multiple will not autofill information. This is something the Bitwarden team is actively working on but need your help as a community and active Bitwarden users!
- name: Feature Requests
url: https://community.bitwarden.com/c/feature-requests/
about: Request new features using the Community Forums. Please search existing feature requests before making a new one.
- name: Bitwarden Community Forums
url: https://community.bitwarden.com
about: Please visit the community forums for general community discussion, support and the development roadmap.
- name: Customer Support
url: https://bitwarden.com/contact/
about: Please contact our customer support for account issues and general customer support.
- name: Security Issues
url: https://hackerone.com/bitwarden
about: We use HackerOne to manage security disclosures.

85
.github/ISSUE_TEMPLATE/desktop.yml vendored Normal file
View File

@ -0,0 +1,85 @@
name: Desktop Bug Report
description: File a bug report
labels: [bug, desktop]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
Please do not submit feature requests. The [Community Forums](https://community.bitwarden.com) has a section for submitting, voting for, and discussing product feature requests.
- type: textarea
id: reproduce
attributes:
label: Steps To Reproduce
description: How can we reproduce the behavior.
value: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. Click on '...'
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected Result
description: A clear and concise description of what you expected to happen.
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual Result
description: A clear and concise description of what is happening.
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: Screenshots or Videos
description: If applicable, add screenshots and/or a short video to help explain your problem.
- type: textarea
id: additional-context
attributes:
label: Additional Context
description: Add any other context about the problem here.
- type: dropdown
id: os
attributes:
label: Operating System
description: What operating system are you seeing the problem on?
multiple: true
options:
- Windows
- macOS
- Linux
validations:
required: true
- type: input
id: os-version
attributes:
label: Operating System Version
description: What version of the operating system(s) are you seeing the problem on?
- type: dropdown
id: install-method
attributes:
label: Installation method
multiple: true
options:
- Direct Download (from bitwarden.com)
- Mac App Store
- Microsoft Store
- Homebrew
- Chocolatey
- Snap
- Other
validations:
required: true
- type: input
id: version
attributes:
label: Build Version
description: What version of our software are you running? (go to "Help" → "About Bitwarden" in the app)
validations:
required: true

View File

@ -1,6 +1,6 @@
name: Bug Report
name: Web Bug Report
description: File a bug report
labels: [bug]
labels: [bug, web]
body:
- type: markdown
attributes:

View File

@ -24,5 +24,6 @@
## Before you submit
- [ ] I have checked for **linting** errors (`npm run lint`) (required)
- [ ] I have added **unit tests** where it makes sense to do so (encouraged but not required)
- [ ] This change requires a **documentation update** (notify the documentation team)
- [ ] This change has particular **deployment requirements** (notify the DevOps team)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
.github/secrets/devid-app-cert.p12.gpg vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
.github/secrets/macdev-cert.p12.gpg vendored Normal file

Binary file not shown.

433
.github/workflows/build-browser.yml vendored Normal file
View File

@ -0,0 +1,433 @@
---
name: Build Browser
on:
pull_request:
branches-ignore:
- 'l10n_master'
- 'gh-pages'
paths:
- 'apps/browser/**'
- '.github/workflows/build-browser.yml'
push:
branches:
- 'master'
- 'rc'
- 'hotfix-rc/**'
paths:
- 'apps/browser/**'
- '.github/workflows/build-browser.yml'
workflow_dispatch:
inputs: {}
defaults:
run:
shell: bash
jobs:
cloc:
name: CLOC
runs-on: ubuntu-20.04
steps:
- name: Checkout repo
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0
- 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:
name: Setup
runs-on: ubuntu-20.04
outputs:
repo_url: ${{ steps.gen_vars.outputs.repo_url }}
adj_build_number: ${{ steps.gen_vars.outputs.adj_build_number }}
steps:
- name: Get Package Version
id: gen_vars
run: |
repo_url=https://github.com/$GITHUB_REPOSITORY.git
adj_build_num=${GITHUB_SHA:0:7}
echo "::set-output name=repo_url::$repo_url"
echo "::set-output name=adj_build_number::$adj_build_num"
locales-test:
name: Locales Test
runs-on: ubuntu-20.04
needs:
- setup
defaults:
run:
working-directory: apps/browser
steps:
- name: Checkout repo
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0
- name: Testing locales - extName length
run: |
found_error=false
echo "Locales Test"
echo "============"
echo "extName string must be 40 characters or less"
echo
for locale in $(ls src/_locales/); do
string_length=$(jq '.extName.message | length' src/_locales/$locale/messages.json)
if [[ $string_length -gt 40 ]]; then
echo "$locale: $string_length"
found_error=true
fi
done
if $found_error; then
echo
echo "Please fix 'extName' for the locales listed above."
exit 1
else
echo "Test passed!"
fi
build:
name: Build
runs-on: windows-2019
needs:
- setup
- locales-test
env:
_BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }}
defaults:
run:
working-directory: apps/browser
steps:
- name: Checkout repo
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0
- name: Set up Node
uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '16'
- name: Install node-gyp
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Print environment
run: |
node --version
npm --version
- name: NPM setup
run: npm ci
working-directory: ./
- name: Build & Test
run: |
npm run dist
npm run test
- name: Gulp
run: gulp ci
- name: Build sources for reviewers
shell: cmd
run: |
mkdir dist\Source
call git clone %GITHUB_SERVER_URL%/%GITHUB_REPOSITORY% dist\Source
cd dist\Source
call git checkout %GITHUB_SHA%
call git submodule update --init --recursive
cd ../
del /S/Q "Source\.git\objects\pack\*"
call 7z a browser-source.zip "Source\*"
- name: Upload Opera artifact
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
with:
name: dist-opera-${{ env._BUILD_NUMBER }}.zip
path: apps/browser/dist/dist-opera.zip
if-no-files-found: error
- name: Upload Chrome artifact
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
with:
name: dist-chrome-${{ env._BUILD_NUMBER }}.zip
path: apps/browser/dist/dist-chrome.zip
if-no-files-found: error
- name: Upload Firefox artifact
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
with:
name: dist-firefox-${{ env._BUILD_NUMBER }}.zip
path: apps/browser/dist/dist-firefox.zip
if-no-files-found: error
- name: Upload Edge artifact
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
with:
name: dist-edge-${{ env._BUILD_NUMBER }}.zip
path: apps/browser/dist/dist-edge.zip
if-no-files-found: error
- name: Upload browser source
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
with:
name: browser-source-${{ env._BUILD_NUMBER }}.zip
path: apps/browser/dist/browser-source.zip
if-no-files-found: error
- name: Upload coverage artifact
if: false
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
with:
name: coverage-${{ env._BUILD_NUMBER }}.zip
path: apps/browser/coverage/coverage-${{ env._BUILD_NUMBER }}.zip
if-no-files-found: error
build-safari:
name: Build Safari
runs-on: macos-11
needs:
- setup
- locales-test
env:
_BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }}
steps:
- name: Checkout repo
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0
- name: Set up Node
uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '16'
- name: Print environment
run: |
node --version
npm --version
- name: Decrypt secrets
env:
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }}
run: |
mkdir -p $HOME/secrets
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/bitwarden-desktop-key.p12" \
"$GITHUB_WORKSPACE/.github/secrets/bitwarden-desktop-key.p12.gpg"
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/appstore-app-cert.p12" \
"$GITHUB_WORKSPACE/.github/secrets/appstore-app-cert.p12.gpg"
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/appstore-installer-cert.p12" \
"$GITHUB_WORKSPACE/.github/secrets/appstore-installer-cert.p12.gpg"
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/devid-app-cert.p12" \
"$GITHUB_WORKSPACE/.github/secrets/devid-app-cert.p12.gpg"
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/devid-installer-cert.p12" \
"$GITHUB_WORKSPACE/.github/secrets/devid-installer-cert.p12.gpg"
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/macdev-cert.p12" \
"$GITHUB_WORKSPACE/.github/secrets/macdev-cert.p12.gpg"
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output "$HOME/secrets/bitwarden_desktop_appstore.provisionprofile" \
"$GITHUB_WORKSPACE/.github/secrets/bitwarden_desktop_appstore.provisionprofile.gpg"
- name: Set up keychain
env:
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: |
security create-keychain -p $KEYCHAIN_PASSWORD build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p $KEYCHAIN_PASSWORD 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 \
-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 \
-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 \
-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 \
-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 \
-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 \
-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
- name: NPM setup
run: npm ci
working-directory: ./
- name: Build Safari extension
run: npm run dist:safari
working-directory: apps/browser
- name: Zip Safari build artifact
run: |
cd apps/browser/dist
zip dist-safari.zip ./Safari/**/build/Release/safari.appex -r
pwd
ls -la
- name: Upload Safari artifact
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
with:
name: dist-safari-${{ env._BUILD_NUMBER }}.zip
path: apps/browser/dist/dist-safari.zip
if-no-files-found: error
crowdin-push:
name: Crowdin Push
if: github.ref == 'refs/heads/master'
runs-on: ubuntu-20.04
needs:
- build
- build-safari
steps:
- name: Checkout repo
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0
- name: Login to Azure
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf
with:
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
- name: Retrieve secrets
id: retrieve-secrets
uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f
with:
keyvault: "bitwarden-prod-kv"
secrets: "crowdin-api-token"
- name: Upload Sources
uses: crowdin/github-action@ecd7eb0ef6f3cfa16293c79e9cbc4bc5b5fd9c49 # v1.4.9
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
CROWDIN_PROJECT_ID: "268134"
with:
config: apps/browser/crowdin.yml
crowdin_branch_name: master
upload_sources: true
upload_translations: false
trigger-desktop-build:
name: Trigger desktop build
if: ${{ (github.ref == 'refs/heads/master') || (github.ref == 'refs/heads/rc') || contains(github.ref, 'hotfix-rc') }}
runs-on: ubuntu-20.04
needs:
- build
- build-safari
steps:
- name: Login to Azure
uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010
with:
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
- name: Retrieve secrets
id: retrieve-secrets
uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f
with:
keyvault: "bitwarden-prod-kv"
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
- name: Extract branch name
id: extract_branch
shell: bash
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
- name: Call GitHub API to trigger desktop build workflow
env:
TOKEN: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
BRANCH_NAME: ${{ steps.extract_branch.outputs.branch }}
run: |
JSON_STRING=$(printf '{"ref":"%s"}' "$BRANCH_NAME")
curl \
-X POST \
-i -u bitwarden-devops-bot:$TOKEN \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/bitwarden/clients/actions/workflows/build-desktop.yml/dispatches \
-d $JSON_STRING
check-failures:
name: Check for failures
if: always()
runs-on: ubuntu-20.04
needs:
- cloc
- setup
- locales-test
- build
- build-safari
- crowdin-push
- trigger-desktop-build
steps:
- name: Check if any job failed
if: ${{ (github.ref == 'refs/heads/master') || (github.ref == 'refs/heads/rc') }}
env:
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 }}
TRIGGER_DESKTOP_BUILD_STATUS: ${{ needs.trigger-desktop-build.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
elif [ "$TRIGGER_DESKTOP_BUILD_STATUS" = "failure" ]; then
exit 1
fi
- name: Login to Azure - Prod Subscription
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf
if: failure()
with:
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
- name: Retrieve secrets
id: retrieve-secrets
uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f
if: failure()
with:
keyvault: "bitwarden-prod-kv"
secrets: "devops-alerts-slack-webhook-url"
- name: Notify Slack on failure
uses: act10ns/slack@da3191ebe2e67f49b46880b4633f5591a96d1d33 # v1.5.0
if: failure()
env:
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}
with:
status: ${{ job.status }}

370
.github/workflows/build-cli.yml vendored Normal file
View File

@ -0,0 +1,370 @@
---
name: Build CLI
on:
pull_request:
branches-ignore:
- 'l10n_master'
- 'gh-pages'
paths:
- 'apps/cli/**'
- '.github/workflows/build-cli.yml'
push:
branches:
- 'master'
- 'rc'
- 'hotfix-rc/**'
paths:
- 'apps/cli/**'
- '.github/workflows/build-cli.yml'
workflow_dispatch:
inputs: {}
defaults:
run:
working-directory: apps/cli
jobs:
cloc:
name: CLOC
runs-on: ubuntu-20.04
steps:
- name: Checkout repo
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- 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:
name: Setup
runs-on: ubuntu-20.04
outputs:
package_version: ${{ steps.retrieve-version.outputs.package_version }}
steps:
- name: Checkout repo
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Get Package Version
id: retrieve-version
run: |
PKG_VERSION=$(jq -r .version package.json)
echo "::set-output name=package_version::$PKG_VERSION"
cli:
name: Build CLI
runs-on: windows-2019
needs:
- setup
env:
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
_WIN_PKG_FETCH_VERSION: 16.15.0
_WIN_PKG_VERSION: 3.4
steps:
- name: Checkout repo
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Setup Windows builder
run: |
choco install checksum --no-progress
choco install reshack --no-progress
choco install nasm --no-progress
- name: Set up Node
uses: actions/setup-node@17f8bd926464a1afa4c6a11669539e9c1ba77048 # v3.2.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '16'
- name: Install node-gyp
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Get pkg-fetch
shell: pwsh
run: |
cd $HOME
$fetchedUrl = "https://github.com/vercel/pkg-fetch/releases/download/v$env:_WIN_PKG_VERSION/node-v$env:_WIN_PKG_FETCH_VERSION-win-x64"
New-Item -ItemType directory -Path .\.pkg-cache
New-Item -ItemType directory -Path .\.pkg-cache\v$env:_WIN_PKG_VERSION
Invoke-RestMethod -Uri $fetchedUrl `
-OutFile ".\.pkg-cache\v$env:_WIN_PKG_VERSION\fetched-v$env:_WIN_PKG_FETCH_VERSION-win-x64"
- name: Setup Version Info
shell: pwsh
run: |
$major,$minor,$patch = $env:_PACKAGE_VERSION.split('.')
$versionInfo = @"
1 VERSIONINFO
FILEVERSION $major,$minor,$patch,0
PRODUCTVERSION $major,$minor,$patch,0
FILEOS 0x40004
FILETYPE 0x1
{
BLOCK "StringFileInfo"
{
BLOCK "040904b0"
{
VALUE "CompanyName", "Bitwarden Inc."
VALUE "ProductName", "Bitwarden"
VALUE "FileDescription", "Bitwarden CLI"
VALUE "FileVersion", "$env:_PACKAGE_VERSION"
VALUE "ProductVersion", "$env:_PACKAGE_VERSION"
VALUE "OriginalFilename", "bw.exe"
VALUE "InternalName", "bw"
VALUE "LegalCopyright", "Copyright Bitwarden Inc."
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409 0x04B0
}
}
"@
$versionInfo | Out-File ./version-info.rc
# https://github.com/vercel/pkg-fetch/issues/188
- name: Resource Hacker
shell: cmd
run: |
set PATH=%PATH%;C:\Program Files (x86)\Resource Hacker
set WIN_PKG=C:\Users\runneradmin\.pkg-cache\v%_WIN_PKG_VERSION%\fetched-v%_WIN_PKG_FETCH_VERSION%-win-x64
set WIN_PKG_BUILT=C:\Users\runneradmin\.pkg-cache\v%_WIN_PKG_VERSION%\built-v%_WIN_PKG_FETCH_VERSION%-win-x64
copy %WIN_PKG% %WIN_PKG_BUILT%
ResourceHacker -open %WIN_PKG_BUILT% -save %WIN_PKG_BUILT% -action delete -mask ICONGROUP,1,
ResourceHacker -open version-info.rc -save version-info.res -action compile
ResourceHacker -open %WIN_PKG_BUILT% -save %WIN_PKG_BUILT% -action addoverwrite -resource version-info.res
- name: Install
run: npm ci
working-directory: ./
- name: Run tests
run: npm run test
- name: Build & Package
run: npm run dist --quiet
- name: Package Chocolatey
shell: pwsh
run: |
Copy-Item -Path stores/chocolatey -Destination dist/chocolatey -Recurse
Copy-Item dist/windows/bw.exe -Destination dist/chocolatey/tools
Copy-Item ${{ github.workspace }}/LICENSE.txt -Destination dist/chocolatey/tools
choco pack dist/chocolatey/bitwarden-cli.nuspec --version ${{ env._PACKAGE_VERSION }} --out dist/chocolatey
- name: Zip
shell: cmd
run: |
7z a ./dist/bw-windows-%_PACKAGE_VERSION%.zip ./dist/windows/bw.exe
7z a ./dist/bw-macos-%_PACKAGE_VERSION%.zip ./dist/macos/bw
7z a ./dist/bw-linux-%_PACKAGE_VERSION%.zip ./dist/linux/bw
- name: Version Test
run: |
dir ./dist/
Expand-Archive -Path "./dist/bw-windows-${env:_PACKAGE_VERSION}.zip" -DestinationPath "./test/windows"
$testVersion = Invoke-Expression '& ./test/windows/bw.exe -v'
echo "version: $env:_PACKAGE_VERSION"
echo "testVersion: $testVersion"
if($testVersion -ne $env:_PACKAGE_VERSION) {
Throw "Version test failed."
}
- name: Create checksums
run: |
checksum -f="./dist/bw-windows-${env:_PACKAGE_VERSION}.zip" `
-t sha256 | Out-File -Encoding ASCII ./dist/bw-windows-sha256-${env:_PACKAGE_VERSION}.txt
checksum -f="./dist/bw-macos-${env:_PACKAGE_VERSION}.zip" `
-t sha256 | Out-File -Encoding ASCII ./dist/bw-macos-sha256-${env:_PACKAGE_VERSION}.txt
checksum -f="./dist/bw-linux-${env:_PACKAGE_VERSION}.zip" `
-t sha256 | Out-File -Encoding ASCII ./dist/bw-linux-sha256-${env:_PACKAGE_VERSION}.txt
- name: Upload windows zip asset
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
with:
name: bw-windows-${{ env._PACKAGE_VERSION }}.zip
path: apps/cli/dist/bw-windows-${{ env._PACKAGE_VERSION }}.zip
if-no-files-found: error
- name: Upload windows checksum asset
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
with:
name: bw-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
path: apps/cli/dist/bw-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
if-no-files-found: error
- name: Upload macos zip asset
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
with:
name: bw-macos-${{ env._PACKAGE_VERSION }}.zip
path: apps/cli/dist/bw-macos-${{ env._PACKAGE_VERSION }}.zip
if-no-files-found: error
- name: Upload macos checksum asset
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
with:
name: bw-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
path: apps/cli/dist/bw-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
if-no-files-found: error
- name: Upload linux zip asset
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
with:
name: bw-linux-${{ env._PACKAGE_VERSION }}.zip
path: apps/cli/dist/bw-linux-${{ env._PACKAGE_VERSION }}.zip
if-no-files-found: error
- name: Upload linux checksum asset
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
with:
name: bw-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
path: apps/cli/dist/bw-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
if-no-files-found: error
- name: Upload Chocolatey asset
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
with:
name: bitwarden-cli.${{ env._PACKAGE_VERSION }}.nupkg
path: apps/cli/dist/chocolatey/bitwarden-cli.${{ env._PACKAGE_VERSION }}.nupkg
if-no-files-found: error
- name: Upload NPM Build Directory asset
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
with:
name: bitwarden-cli-${{ env._PACKAGE_VERSION }}-npm-build.zip
path: apps/cli/build
if-no-files-found: error
snap:
name: Build Snap
runs-on: ubuntu-20.04
needs: [setup, cli]
env:
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
steps:
- name: Checkout repo
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Print environment
run: |
whoami
echo "GitHub ref: $GITHUB_REF"
echo "GitHub event: $GITHUB_EVENT"
echo "BW Package Version: $_PACKAGE_VERSION"
- name: Get bw linux cli
uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741
with:
name: bw-linux-${{ env._PACKAGE_VERSION }}.zip
path: apps/cli/dist/snap
- name: Setup Snap Package
run: |
cp -r stores/snap/* -t dist/snap
sed -i s/__version__/${{ env._PACKAGE_VERSION }}/g dist/snap/snapcraft.yaml
cd dist/snap
ls -alth
- name: Build snap
uses: snapcore/action-build@ea14cdeb353272f75977040488ca191880509a8c # v1.1.0
with:
path: apps/cli/dist/snap
- name: Create checksum
run: |
cd dist/snap
ls -alth
sha256sum bw_${{ env._PACKAGE_VERSION }}_amd64.snap \
| awk '{split($0, a); print a[1]}' > bw-snap-sha256-${{ env._PACKAGE_VERSION }}.txt
- name: Install Snap
run: sudo snap install dist/snap/bw*.snap --dangerous
- name: Test Snap
shell: pwsh
run: |
$testVersion = Invoke-Expression '& bw -v'
if($testVersion -ne $env:_PACKAGE_VERSION) {
Throw "Version test failed."
}
env:
BITWARDENCLI_APPDATA_DIR: "/home/runner/snap/bw/x1/.config/Bitwarden CLI"
- name: Cleanup Test & Update Snap for Publish
shell: pwsh
run: sudo snap remove bw
- name: Upload snap asset
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
with:
name: bw_${{ env._PACKAGE_VERSION }}_amd64.snap
path: apps/cli/dist/snap/bw_${{ env._PACKAGE_VERSION }}_amd64.snap
if-no-files-found: error
- name: Upload snap checksum asset
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
with:
name: bw-snap-sha256-${{ env._PACKAGE_VERSION }}.txt
path: apps/cli/dist/snap/bw-snap-sha256-${{ env._PACKAGE_VERSION }}.txt
if-no-files-found: error
check-failures:
name: Check for failures
if: always()
runs-on: ubuntu-20.04
needs:
- cloc
- setup
- cli
- snap
steps:
- name: Check if any job failed
working-directory: ${{ github.workspace }}
if: ${{ (github.ref == 'refs/heads/master') || (github.ref == 'refs/heads/rc') }}
env:
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
uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010 # v1.1
if: failure()
with:
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
- name: Retrieve secrets
id: retrieve-secrets
uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f
if: failure()
with:
keyvault: "bitwarden-prod-kv"
secrets: "devops-alerts-slack-webhook-url"
- name: Notify Slack on failure
uses: act10ns/slack@da3191ebe2e67f49b46880b4633f5591a96d1d33
if: failure()
env:
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}
with:
status: ${{ job.status }}

1193
.github/workflows/build-desktop.yml vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,24 @@
---
name: Build
name: Build Web
on:
workflow_dispatch:
inputs:
custom_tag_extension:
description: "Custom image tag extension"
required: false
push:
pull_request:
branches-ignore:
- "l10n_master"
- "gh-pages"
- "deploy"
paths-ignore:
- '.github/workflows/**'
- 'l10n_master'
- 'gh-pages'
paths:
- 'apps/web/**'
- '.github/workflows/build-web.yml'
push:
branches:
- 'master'
- 'rc'
- 'hotfix-rc/**'
paths:
- 'apps/web/**'
- '.github/workflows/build-web.yml'
workflow_dispatch:
inputs: {}
jobs:
cloc:
@ -22,7 +26,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Set up cloc
run: |
@ -30,30 +34,10 @@ jobs:
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
lint:
name: Lint
runs-on: ubuntu-20.04
steps:
- name: Checkout repo
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
- name: Cache npm
id: npm-cache
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353 # v2.1.6
with:
path: "~/.npm"
key: ${{ runner.os }}-npm-lint-${{ hashFiles('**/package-lock.json') }}
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
setup:
name: Setup
runs-on: ubuntu-20.04
@ -61,7 +45,7 @@ jobs:
version: ${{ steps.version.outputs.value }}
steps:
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Get GitHub sha as version
id: version
@ -73,15 +57,14 @@ jobs:
runs-on: ubuntu-20.04
needs:
- setup
- lint
env:
_VERSION: ${{ needs.setup.outputs.version }}
steps:
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Set up Node
uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0
uses: actions/setup-node@56337c425554a6be30cdef71bf441f15be286854 # v3.1.1
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
@ -101,15 +84,16 @@ jobs:
run: npm ci
- name: Build OSS selfhost
working-directory: apps/web
run: |
npm run dist:oss:selfhost
zip -r web-$_VERSION-selfhosted-open-source.zip build
- name: Upload build artifact
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
with:
name: web-${{ env._VERSION }}-selfhosted-open-source.zip
path: ./web-${{ env._VERSION }}-selfhosted-open-source.zip
path: apps/web/web-${{ env._VERSION }}-selfhosted-open-source.zip
if-no-files-found: error
@ -118,15 +102,14 @@ jobs:
runs-on: ubuntu-20.04
needs:
- setup
- lint
env:
_VERSION: ${{ needs.setup.outputs.version }}
steps:
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Set up Node
uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0
uses: actions/setup-node@56337c425554a6be30cdef71bf441f15be286854 # v3.1.1
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
@ -146,15 +129,16 @@ jobs:
run: npm ci
- name: Build Cloud
working-directory: apps/web
run: |
npm run dist:bit:cloud
zip -r web-$_VERSION-cloud-COMMERCIAL.zip build
- name: Upload build artifact
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
with:
name: web-${{ env._VERSION }}-cloud-COMMERCIAL.zip
path: ./web-${{ env._VERSION }}-cloud-COMMERCIAL.zip
path: apps/web/web-${{ env._VERSION }}-cloud-COMMERCIAL.zip
if-no-files-found: error
@ -163,15 +147,14 @@ jobs:
runs-on: ubuntu-20.04
needs:
- setup
- lint
env:
_VERSION: ${{ needs.setup.outputs.version }}
steps:
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Set up Node
uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0
uses: actions/setup-node@56337c425554a6be30cdef71bf441f15be286854 # v3.1.1
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
@ -199,6 +182,7 @@ jobs:
run: npm ci
- name: Build
working-directory: apps/web
run: |
echo -e "# Building Web\n"
echo "Building app"
@ -208,13 +192,14 @@ jobs:
zip -r web-$_VERSION-selfhosted-COMMERCIAL.zip build
- name: Upload build artifact
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
with:
name: web-${{ env._VERSION }}-selfhosted-COMMERCIAL.zip
path: ./web-${{ env._VERSION }}-selfhosted-COMMERCIAL.zip
path: apps/web/web-${{ env._VERSION }}-selfhosted-COMMERCIAL.zip
if-no-files-found: error
- name: Build Docker image
working-directory: apps/web
run: |
echo -e "\nBuilding Docker image"
docker --version
@ -264,7 +249,7 @@ jobs:
echo "DOCKER_CONTENT_TRUST=0" >> $GITHUB_ENV
- name: Login to Azure - QA Subscription
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a
uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010 # v1.1
with:
creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }}
@ -292,13 +277,12 @@ jobs:
runs-on: ubuntu-20.04
needs:
- setup
- lint
steps:
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Set up Node
uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0
uses: actions/setup-node@56337c425554a6be30cdef71bf441f15be286854 # v3.1.1
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
@ -315,7 +299,7 @@ jobs:
echo "GitHub event: $GITHUB_EVENT"
- name: Login to Azure
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a
uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010 # v1.1
with:
creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }}
@ -326,6 +310,7 @@ jobs:
run: npm ci
- name: Build
working-directory: apps/web
run: |
echo -e "# Building Web\n"
echo "Building app"
@ -377,44 +362,6 @@ jobs:
- name: Log out of Docker
run: docker logout
windows:
name: Test code on Windows
runs-on: windows-2019
steps:
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
- name: Set up NuGet
uses: nuget/setup-nuget@04b0c2b8d1b97922f67eca497d7cf0bf17b8ffe1
with:
nuget-version: "latest"
- name: Set up Node
uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: "16"
- name: Print environment
run: |
nuget help | grep Version
node --version
npm --version
echo "GitHub ref: $GITHUB_REF"
echo "GitHub event: $GITHUB_EVENT"
env:
GITHUB_REF: ${{ github.ref }}
GITHUB_EVENT: ${{ github.event_name }}
- name: Install dependencies
run: npm ci
- name: NPM build
run: npm run build:bit:cloud
crowdin-push:
name: Crowdin Push
if: github.ref == 'refs/heads/master'
@ -428,27 +375,27 @@ jobs:
_CROWDIN_PROJECT_ID: "308189"
steps:
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 # v2.3.4
- name: Login to Azure
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a
uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010 # v1.1
with:
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
- name: Retrieve secrets
id: retrieve-secrets
uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403
uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f # v1.0.0
with:
keyvault: "bitwarden-prod-kv"
secrets: "crowdin-api-token"
- name: Upload Sources
uses: crowdin/github-action@e39093fd75daae7859c68eded4b43d42ec78d8ea # v1.3.2
uses: crowdin/github-action@a3160b9e5a9e00739392c23da5e580c6cabe526d # v1.4.8
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
with:
config: crowdin.yml
config: apps/web/crowdin.yml
crowdin_branch_name: master
upload_sources: true
upload_translations: false
@ -461,31 +408,25 @@ jobs:
needs:
- cloc
- setup
- lint
- build-oss-selfhost
- build-cloud
- build-commercial-selfhost
- build-qa
- crowdin-push
- windows
steps:
- name: Check if any job failed
if: ${{ (github.ref == 'refs/heads/master') || (github.ref == 'refs/heads/rc') }}
env:
CLOC_STATUS: ${{ needs.cloc.result }}
LINT_STATUS: ${{ needs.lint.result }}
SETUP_STATUS: ${{ needs.setup.result }}
BUILD_OSS_SELFHOST_STATUS: ${{ needs.build-oss-selfhost.result }}
BUILD_CLOUD_STATUS: ${{ needs.build-cloud.result }}
BUILD_COMMERCIAL_SELFHOST_STATUS: ${{ needs.build-commercial-selfhost.result }}
BUILD_QA_STATUS: ${{ needs.build-qa.result }}
CROWDIN_PUSH_STATUS: ${{ needs.crowdin-push.result }}
WINDOWS_STATUS: ${{ needs.windows.result }}
run: |
if [ "$CLOC_STATUS" = "failure" ]; then
exit 1
elif [ "$LINT_STATUS" = "failure" ]; then
exit 1
elif [ "$SETUP_STATUS" = "failure" ]; then
exit 1
elif [ "$BUILD_OSS_SELFHOST_STATUS" = "failure" ]; then
@ -498,26 +439,24 @@ jobs:
exit 1
elif [ "$CROWDIN_PUSH_STATUS" = "failure" ]; then
exit 1
elif [ "$WINDOWS_STATUS" = "failure" ]; then
exit 1
fi
- name: Login to Azure - Prod Subscription
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a
uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010 # v1.1
if: failure()
with:
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
- name: Retrieve secrets
id: retrieve-secrets
uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403
uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f # v1.0.0
if: failure()
with:
keyvault: "bitwarden-prod-kv"
secrets: "devops-alerts-slack-webhook-url"
- name: Notify Slack on failure
uses: act10ns/slack@e4e71685b9b239384b0f676a63c32367f59c2522 # v1.2.2
uses: act10ns/slack@da3191ebe2e67f49b46880b4633f5591a96d1d33 # v1.5.1
if: failure()
env:
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}

View File

@ -1,18 +1,24 @@
---
name: Crowdin Pull
name: Crowdin Sync
on:
workflow_dispatch:
inputs: {}
schedule:
- cron: "0 0 * * 5"
- cron: '0 0 * * 5'
jobs:
crowdin-pull:
name: Pull
crowdin-sync:
name: Autosync
runs-on: ubuntu-20.04
env:
_CROWDIN_PROJECT_ID: "308189"
strategy:
fail-fast: false
matrix:
include:
- app_name: browser
crowdin_project_id: "268134"
- app_name: desktop
crowdin_project_id: "299360"
steps:
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
@ -30,10 +36,11 @@ jobs:
secrets: "crowdin-api-token"
- name: Download translations
uses: crowdin/github-action@e39093fd75daae7859c68eded4b43d42ec78d8ea # v1.3.2
uses: bitwarden/gh-actions/crowdin@05052c5c575ceb09ceea397fe241879e199ed44b
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
CROWDIN_PROJECT_ID: ${{ matrix.crowdin_project_id }}
with:
config: crowdin.yml
crowdin_branch_name: master
@ -43,7 +50,8 @@ jobs:
github_user_name: "github-actions"
github_user_email: "<>"
commit_message: "Autosync the updated translations"
localization_branch_name: crowdin-auto-sync
localization_branch_name: crowdin-auto-sync-${{ matrix.app_name }}
create_pull_request: true
pull_request_title: "Autosync Crowdin Translations"
pull_request_title: "Autosync Crowdin Translations for ${{ matrix.app_name }}"
pull_request_body: "Autosync the updated translations"
working_directory: apps/${{ matrix.app_name }}

View File

@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Enforce Label
uses: yogevbd/enforce-label-action@8d1e1709b1011e6d90400a0e6cf7c0b77aa5efeb
uses: yogevbd/enforce-label-action@8d1e1709b1011e6d90400a0e6cf7c0b77aa5efeb # v2.1.0
with:
BANNED_LABELS: "hold"
BANNED_LABELS_DESCRIPTION: "PRs on hold cannot be merged"

36
.github/workflows/lint.yml vendored Normal file
View File

@ -0,0 +1,36 @@
---
name: Lint
on:
push:
branches-ignore:
- 'l10n_master'
- 'gh-pages'
paths-ignore:
- '.github/workflows/**'
workflow_dispatch:
inputs: {}
defaults:
run:
shell: bash
jobs:
lint:
name: Lint
runs-on: ubuntu-20.04
steps:
- name: Checkout repo
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0
- name: Set up Node
uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '16'
- name: Run linter
run: |
npm ci
npm run lint

136
.github/workflows/release-browser.yml vendored Normal file
View File

@ -0,0 +1,136 @@
---
name: Release Browser
on:
workflow_dispatch:
inputs:
release_type:
description: 'Release Options'
required: true
default: 'Initial Release'
type: choice
options:
- Initial Release
- Redeploy
- Dry Run
defaults:
run:
shell: bash
jobs:
setup:
name: Setup
runs-on: ubuntu-20.04
outputs:
release-version: ${{ steps.version.outputs.version }}
branch-name: ${{ steps.branch.outputs.branch-name }}
steps:
- name: Branch check
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
run: |
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ $GITHUB_REF != refs/heads/hotfix-rc/* ]]; then
echo "==================================="
echo "[!] Can only release from the 'rc' or 'hotfix-rc/*' branches"
echo "==================================="
exit 1
fi
- name: Checkout repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Check Release Version
id: version
uses: bitwarden/gh-actions/release-version-check@ea9fab01d76940267b4147cc1c4542431246b9f6
with:
release-type: ${{ github.event.inputs.release_type }}
project-type: ts
file: apps/browser/src/manifest.json
monorepo: true
monorepo-project: browser
- name: Get branch name
id: branch
run: |
BRANCH_NAME=$(basename ${{ github.ref }})
echo "::set-output name=branch-name::$BRANCH_NAME"
locales-test:
name: Locales Test
runs-on: ubuntu-20.04
needs: setup
steps:
- name: Checkout repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Testing locales - extName length
run: |
found_error=false
echo "Locales Test"
echo "============"
echo "extName string must be 40 characters or less"
echo
for locale in $(ls src/_locales/); do
string_length=$(jq '.extName.message | length' src/_locales/$locale/messages.json)
if [[ $string_length -gt 40 ]]; then
echo "$locale: $string_length"
found_error=true
fi
done
if $found_error; then
echo
echo "Please fix 'extName' for the locales listed above."
exit 1
else
echo "Test passed!"
fi
working-directory: apps/browser
release:
name: Create GitHub Release
runs-on: ubuntu-20.04
needs:
- setup
- locales-test
steps:
- name: Download latest RC build artifacts
uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8
with:
workflow: build-browser.yml
workflow_conclusion: success
branch: ${{ needs.setup.outputs.branch-name }}
artifacts: 'browser-source-*.zip,
dist-chrome-*.zip,
dist-opera-*.zip,
dist-firefox-*.zip,
dist-edge-*.zip'
- name: Rename build artifacts
env:
PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }}
run: |
mv browser-source.zip browser-source-$PACKAGE_VERSION.zip
mv dist-chrome.zip dist-chrome-$PACKAGE_VERSION.zip
mv dist-opera.zip dist-opera-$PACKAGE_VERSION.zip
mv dist-firefox.zip dist-firefox-$PACKAGE_VERSION.zip
mv dist-edge.zip dist-edge-$PACKAGE_VERSION.zip
- name: Create release
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: ncipollo/release-action@40bb172bd05f266cf9ba4ff965cb61e9ee5f6d01
with:
artifacts: 'browser-source-${{ needs.setup.outputs.release-version }}.zip,
dist-chrome-${{ needs.setup.outputs.release-version }}.zip,
dist-opera-${{ needs.setup.outputs.release-version }}.zip,
dist-firefox-${{ needs.setup.outputs.release-version }}.zip,
dist-edge-${{ needs.setup.outputs.release-version }}.zip'
commit: ${{ github.sha }}
tag: "browser-v${{ needs.setup.outputs.release-version }}"
name: "Browser v${{ needs.setup.outputs.release-version }}"
body: "<insert release notes here>"
token: ${{ secrets.GITHUB_TOKEN }}
draft: true

196
.github/workflows/release-cli.yml vendored Normal file
View File

@ -0,0 +1,196 @@
---
name: Release CLI
on:
workflow_dispatch:
inputs:
release_type:
description: 'Release Options'
required: true
default: 'Initial Release'
type: choice
options:
- Initial Release
- Redeploy
- Dry Run
defaults:
run:
working-directory: apps/cli
jobs:
setup:
name: Setup
runs-on: ubuntu-20.04
outputs:
release-version: ${{ steps.version.outputs.version }}
branch-name: ${{ steps.branch.outputs.branch-name }}
steps:
- name: Branch check
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
run: |
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ $GITHUB_REF != refs/heads/hotfix-rc/* ]]; then
echo "==================================="
echo "[!] Can only release from the 'rc' or 'hotfix-rc/*' branches"
echo "==================================="
exit 1
fi
- name: Checkout repo
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Check Release Version
id: version
uses: bitwarden/gh-actions/release-version-check@ea9fab01d76940267b4147cc1c4542431246b9f6
with:
release-type: ${{ github.event.inputs.release_type }}
project-type: ts
file: apps/cli/package.json
monorepo: true
monorepo-project: cli
- name: Get branch name
id: branch
run: |
BRANCH_NAME=$(basename ${{ github.ref }})
echo "::set-output name=branch-name::$BRANCH_NAME"
- name: Download all artifacts
uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8
with:
workflow: build-cli.yml
path: apps/cli
workflow_conclusion: success
branch: ${{ steps.branch.outputs.branch-name }}
- name: Create release
uses: ncipollo/release-action@58ae73b360456532aafd58ee170c045abbeaee37 # v1.10.0
env:
PKG_VERSION: ${{ steps.version.outputs.version }}
with:
artifacts: "apps/cli/bw-windows-${{ env.PKG_VERSION }}.zip,
apps/cli/bw-windows-sha256-${{ env.PKG_VERSION }}.txt,
apps/cli/bw-macos-${{ env.PKG_VERSION }}.zip,
apps/cli/bw-macos-sha256-${{ env.PKG_VERSION }}.txt,
apps/cli/bw-linux-${{ env.PKG_VERSION }}.zip,
apps/cli/bw-linux-sha256-${{ env.PKG_VERSION }}.txt,
apps/cli/bitwarden-cli.${{ env.PKG_VERSION }}.nupkg,
apps/cli/bw_${{ env.PKG_VERSION }}_amd64.snap,
apps/cli/bw-snap-sha256-${{ env.PKG_VERSION }}.txt"
commit: ${{ github.sha }}
tag: cli-v${{ env.PKG_VERSION }}
name: CLI v${{ env.PKG_VERSION }}
body: "<insert release notes here>"
token: ${{ secrets.GITHUB_TOKEN }}
draft: true
snap:
name: Deploy Snap
runs-on: ubuntu-20.04
needs: setup
env:
_PKG_VERSION: ${{ needs.setup.outputs.release-version }}
steps:
- name: Checkout repo
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Login to Azure
uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010 # v1.1
with:
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
- name: Retrieve secrets
id: retrieve-secrets
uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f
with:
keyvault: "bitwarden-prod-kv"
secrets: "snapcraft-store-token"
- name: Install Snap
uses: samuelmeuli/action-snapcraft@10d7d0a84d9d86098b19f872257df314b0bd8e2d # v1.2.0
with:
snapcraft_token: ${{ steps.retrieve-secrets.outputs.snapcraft-store-token }}
- name: Download artifacts
uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8
with:
workflow: build-cli.yml
path: apps/cli
workflow_conclusion: success
branch: ${{ needs.setup.outputs.branch-name }}
artifacts: bw_${{ env._PKG_VERSION }}_amd64.snap
- name: Publish Snap & logout
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
run: |
snapcraft push bw_${{ env._PKG_VERSION }}_amd64.snap --release stable
snapcraft logout
choco:
name: Deploy Choco
runs-on: windows-2019
needs: setup
env:
_PKG_VERSION: ${{ needs.setup.outputs.release-version }}
steps:
- name: Checkout repo
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Setup Chocolatey
run: choco apikey --key $env:CHOCO_API_KEY --source https://push.chocolatey.org/
env:
CHOCO_API_KEY: ${{ secrets.CHOCO_API_KEY }}
- name: Make dist dir
shell: pwsh
run: New-Item -ItemType directory -Path ./dist
- name: Download artifacts
uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8
with:
workflow: build-cli.yml
path: apps/cli
workflow_conclusion: success
branch: ${{ needs.setup.outputs.branch-name }}
artifacts: bitwarden-cli.${{ env._PKG_VERSION }}.nupkg
- name: Push to Chocolatey
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
shell: pwsh
run: |
cd dist
choco push
npm:
name: Publish NPM
runs-on: ubuntu-20.04
needs: setup
env:
_PKG_VERSION: ${{ needs.setup.outputs.release-version }}
steps:
- name: Checkout repo
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Download artifacts
uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8
with:
workflow: build-cli.yml
path: apps/cli
workflow_conclusion: success
branch: ${{ needs.setup.outputs.branch-name }}
artifacts: bitwarden-cli-${{ env._PKG_VERSION }}-npm-build.zip
- name: Setup NPM
run: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > .npmrc
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Install Husky
run: npm install -g husky
- name: Publish NPM
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
run: npm publish --access public

209
.github/workflows/release-desktop.yml vendored Normal file
View File

@ -0,0 +1,209 @@
---
name: Release Desktop
on:
workflow_dispatch:
inputs:
release_type:
description: 'Release Options'
required: true
default: 'Initial Release'
type: choice
options:
- Initial Release
- Redeploy
- Dry Run
defaults:
run:
shell: bash
jobs:
setup:
name: Setup
runs-on: ubuntu-20.04
outputs:
release-version: ${{ steps.version.outputs.version }}
branch-name: ${{ steps.branch.outputs.branch-name }}
steps:
- name: Branch check
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
run: |
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ $GITHUB_REF != refs/heads/hotfix-rc/* ]]; then
echo "==================================="
echo "[!] Can only release from the 'rc' or 'hotfix-rc/*' branches"
echo "==================================="
exit 1
fi
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
- name: Check Release Version
id: version
uses: bitwarden/gh-actions/release-version-check@ea9fab01d76940267b4147cc1c4542431246b9f6
with:
release-type: ${{ github.event.inputs.release_type }}
project-type: ts
file: apps/desktop/src/package.json
monorepo: true
monorepo-project: desktop
- name: Get branch name
id: branch
run: |
BRANCH_NAME=$(basename ${{ github.ref }})
echo "::set-output name=branch-name::$BRANCH_NAME"
- name: Login to Azure
uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010
with:
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
- name: Retrieve secrets
id: retrieve-secrets
uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f
with:
keyvault: "bitwarden-prod-kv"
secrets: "aws-electron-access-id, aws-electron-access-key, aws-electron-bucket-name"
- name: Download all artifacts
uses: bitwarden/gh-actions/download-artifacts@23433be15ed6fd046ce12b6889c5184a8d9c8783
with:
workflow: build-desktop.yml
workflow_conclusion: success
branch: ${{ steps.branch.outputs.branch-name }}
path: apps/desktop/artifacts
- name: Rename .pkg to .pkg.archive
env:
PKG_VERSION: ${{ steps.version.outputs.version }}
working-directory: apps/desktop/artifacts
run: mv Bitwarden-${{ env.PKG_VERSION }}-universal.pkg Bitwarden-${{ env.PKG_VERSION }}-universal.pkg.archive
- name: Publish artifacts to S3
env:
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_DEFAULT_REGION: 'us-west-2'
AWS_S3_BUCKET_NAME: ${{ steps.retrieve-secrets.outputs.aws-electron-bucket-name }}
working-directory: apps/desktop/artifacts
run: |
aws s3 cp ./ $AWS_S3_BUCKET_NAME/desktop/ \
--acl "public-read" \
--recursive \
--quiet
- name: Create release
uses: ncipollo/release-action@95215a3cb6e6a1908b3c44e00b4fdb15548b1e09 # v2.8.5
env:
PKG_VERSION: ${{ steps.version.outputs.version }}
with:
artifacts: "apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-amd64.deb,
apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-x86_64.rpm,
apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-x64.freebsd,
apps/desktop/artifacts/bitwarden_${{ env.PKG_VERSION }}_amd64.snap,
apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-x86_64.AppImage,
apps/desktop/artifacts/Bitwarden-Portable-${{ env.PKG_VERSION }}.exe,
apps/desktop/artifacts/Bitwarden-Installer-${{ env.PKG_VERSION }}.exe,
apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-ia32-store.appx,
apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-ia32.appx,
apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-ia32.nsis.7z,
apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-x64-store.appx,
apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-x64.appx,
apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-x64.nsis.7z,
apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-arm64-store.appx,
apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-arm64.appx,
apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-arm64.nsis.7z,
apps/desktop/artifacts/bitwarden.${{ env.PKG_VERSION }}.nupkg,
apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-universal-mac.zip,
apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-universal.dmg,
apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-universal.dmg.blockmap,
apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-universal.pkg.archive"
commit: ${{ github.sha }}
tag: desktop-v${{ env.PKG_VERSION }}
name: Desktop v${{ env.PKG_VERSION }}
body: "<insert release notes here>"
token: ${{ secrets.GITHUB_TOKEN }}
draft: true
snap:
name: Deploy Snap
runs-on: ubuntu-20.04
needs: setup
env:
_PKG_VERSION: ${{ needs.setup.outputs.release-version }}
steps:
- name: Checkout Repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
- name: Login to Azure
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a
with:
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
- name: Retrieve secrets
id: retrieve-secrets
uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403
with:
keyvault: "bitwarden-prod-kv"
secrets: "snapcraft-store-token"
- name: Install Snap
uses: samuelmeuli/action-snapcraft@10d7d0a84d9d86098b19f872257df314b0bd8e2d # v1.2.0
with:
snapcraft_token: ${{ steps.retrieve-secrets.outputs.snapcraft-store-token }}
- name: Setup
run: mkdir dist
working-directory: apps/desktop
- name: Download Snap artifact
uses: bitwarden/gh-actions/download-artifacts@23433be15ed6fd046ce12b6889c5184a8d9c8783
with:
workflow: build-desktop.yml
workflow_conclusion: success
branch: ${{ needs.setup.outputs.branch-name }}
artifacts: bitwarden_${{ env._PKG_VERSION }}_amd64.snap
path: apps/desktop/dist
- name: Deploy to Snap Store
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
run: |
snapcraft upload bitwarden_${{ env._PKG_VERSION }}_amd64.snap --release stable
snapcraft logout
working-directory: apps/desktop/dist
choco:
name: Deploy Choco
runs-on: windows-2019
needs: setup
env:
_PKG_VERSION: ${{ needs.setup.outputs.release-version }}
steps:
- name: Checkout Repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
- name: Setup Chocolatey
run: choco apikey --key $env:CHOCO_API_KEY --source https://push.chocolatey.org/
env:
CHOCO_API_KEY: ${{ secrets.CHOCO_API_KEY }}
- name: Make dist dir
shell: pwsh
run: New-Item -ItemType directory -Path ./dist
working-directory: apps/desktop
- name: Download choco artifact
uses: bitwarden/gh-actions/download-artifacts@23433be15ed6fd046ce12b6889c5184a8d9c8783
with:
workflow: build-desktop.yml
workflow_conclusion: success
branch: ${{ needs.setup.outputs.branch-name }}
artifacts: bitwarden.${{ env._PKG_VERSION }}.nupkg
path: apps/desktop/dist
- name: Push to Chocolatey
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
shell: pwsh
run: choco push
working-directory: apps/desktop/dist

View File

@ -1,5 +1,5 @@
---
name: Release
name: Release Web
on:
workflow_dispatch:
@ -20,29 +20,31 @@ jobs:
runs-on: ubuntu-20.04
outputs:
release_version: ${{ steps.version.outputs.version }}
tag_version: ${{ steps.version.outputs.version }}
tag_version: ${{ steps.version.outputs.tag }}
branch_name: ${{ steps.branch.outputs.branch_name }}
steps:
- name: Branch check
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
run: |
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ $GITHUB_REF != refs/heads/hotfix-rc/* ]]; then
echo "==================================="
echo "[!] Can only release from the 'rc' or 'hotfix-rc' branches"
echo "[!] Can only release from the 'rc' or 'hotfix-rc/*' branches"
echo "==================================="
exit 1
fi
- name: Checkout repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # 2.4.0
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Check Release Version
id: version
uses: bitwarden/gh-actions/release-version-check@ea9fab01d76940267b4147cc1c4542431246b9f6
uses: bitwarden/gh-actions/release-version-check@8f055ef543c7433c967a1b9b04a0f230923233bb
with:
release-type: ${{ github.event.inputs.release_type }}
project-type: ts
file: package.json
file: apps/web/package.json
monorepo: true
monorepo-project: web
- name: Get branch name
id: branch
@ -69,7 +71,7 @@ jobs:
echo "Github Release Option: $_RELEASE_OPTION"
- name: Checkout repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
########## DockerHub ##########
- name: Setup DCT
@ -87,16 +89,12 @@ jobs:
docker pull bitwarden/web:$_BRANCH_NAME
fi
- name: Tag version and latest
- name: Docker Tag version and latest image
run: |
if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then
docker tag bitwarden/web:latest bitwarden/web:dryrun
else
docker tag bitwarden/web:$_BRANCH_NAME bitwarden/web:$_RELEASE_VERSION
docker tag bitwarden/web:$_BRANCH_NAME bitwarden/web:latest
fi
docker tag bitwarden/web:$_BRANCH_NAME bitwarden/web:$_RELEASE_VERSION
docker tag bitwarden/web:$_BRANCH_NAME bitwarden/web:latest
- name: Push version and latest image
- name: Docker Push version and latest image
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
env:
DOCKER_CONTENT_TRUST: 1
@ -112,7 +110,7 @@ jobs:
########## ACR ##########
- name: Login to Azure - QA Subscription
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a
uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010 # v1.1
with:
creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }}
@ -123,15 +121,11 @@ jobs:
env:
REGISTRY: bitwardenqa.azurecr.io
run: |
if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then
docker tag bitwarden/web:latest $REGISTRY/web:dryrun
else
docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web:$_RELEASE_VERSION
docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web:latest
docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web:$_RELEASE_VERSION
docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web:latest
docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web-sh:$_RELEASE_VERSION
docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web-sh:latest
fi
docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web-sh:$_RELEASE_VERSION
docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web-sh:latest
- name: Push version and latest image
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
@ -159,7 +153,7 @@ jobs:
_TAG_VERSION: ${{ needs.setup.outputs.tag_version }}
steps:
- name: Checkout Repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2.4.0
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 # v2.4.0
with:
ref: gh-pages
@ -169,7 +163,7 @@ jobs:
git push -u origin gh-pages-deploy-$_TAG_VERSION
- name: Checkout Repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2.4.0
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 # v2.4.0
- name: Setup git config
run: |
@ -181,22 +175,24 @@ jobs:
- name: Download latest cloud asset
uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8
with:
workflow: build.yml
workflow: build-web.yml
path: apps/web
workflow_conclusion: success
branch: ${{ needs.setup.outputs.branch_name }}
artifacts: web-*-cloud-COMMERCIAL.zip
# This should result in a build directory in the current working directory
- name: Unzip build asset
working-directory: apps/web
run: unzip web-*-cloud-COMMERCIAL.zip
- name: Deploy GitHub Pages
uses: crazy-max/ghaction-github-pages@a117e4aa1fb4854d021546d2abdfac95be568a3a # v2.6.0
uses: crazy-max/ghaction-github-pages@eb08c35b9fab86751edfff4e55cd5cde35ff0e52 # v3.0.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
target_branch: gh-pages-deploy-${{ needs.setup.outputs.tag_version }}
build_dir: build
build_dir: apps/web/build
keep_history: true
commit_message: "Staging deploy ${{ needs.setup.outputs.release_version }}"
dry_run: ${{ github.event.inputs.release_type == 'Dry Run' }}
@ -224,22 +220,24 @@ jobs:
_TAG_VERSION: ${{ needs.setup.outputs.tag_version }}
steps:
- name: Checkout Repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2.4.0
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Download latest cloud asset
uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8
with:
workflow: build.yml
workflow: build-web.yml
path: apps/web
workflow_conclusion: success
branch: ${{ needs.setup.outputs.branch_name }}
artifacts: web-*-cloud-COMMERCIAL.zip
# This should result in a build directory in the current working directory
- name: Unzip build asset
working-directory: apps/web
run: unzip web-*-cloud-COMMERCIAL.zip
- name: Checkout Repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2.4.0
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
with:
ref: deploy
path: deployment
@ -254,7 +252,7 @@ jobs:
- name: Deploy CloudFlare Pages
run: |
rm -rf ./*
cp -R ../build/* .
cp -R apps/web/build/* .
working-directory: deployment
- name: Create cf-pages-deploy branch
@ -263,7 +261,7 @@ jobs:
git add .
git commit -m "Staging deploy ${{ needs.setup.outputs.release_version }}"
git push -u origin cf-pages-deploy-$_TAG_VERSION
working-directory: deployment
working-directory: deployment
- name: Create CloudFlare Pages Deploy PR
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
@ -287,29 +285,31 @@ jobs:
- cfpages-deploy
steps:
- name: Download latest build artifacts
uses: bitwarden/gh-actions/download-artifacts@23433be15ed6fd046ce12b6889c5184a8d9c8783
uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8
with:
workflow: build.yml
workflow: build-web.yml
path: apps/web/artifacts
workflow_conclusion: success
branch: ${{ needs.setup.outputs.branch_name }}
artifacts: "web-*-selfhosted-COMMERCIAL.zip,
web-*-selfhosted-open-source.zip"
- name: Rename assets
working-directory: apps/web/artifacts
run: |
mv web-*-selfhosted-COMMERCIAL.zip web-${{ needs.setup.outputs.release_version }}-selfhosted-COMMERCIAL.zip
mv web-*-selfhosted-open-source.zip web-${{ needs.setup.outputs.release_version }}-selfhosted-open-source.zip
- name: Create release
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: ncipollo/release-action@40bb172bd05f266cf9ba4ff965cb61e9ee5f6d01
uses: ncipollo/release-action@58ae73b360456532aafd58ee170c045abbeaee37 # v1.10.0
with:
name: "Version ${{ needs.setup.outputs.release_version }}"
name: "Version v${{ needs.setup.outputs.release_version }}"
commit: ${{ github.sha }}
tag: "${{ needs.setup.outputs.tag_version }}"
body: "<insert release notes here>"
artifacts: "web-${{ needs.setup.outputs.release_version }}-selfhosted-COMMERCIAL.zip,
web-${{ needs.setup.outputs.release_version }}-selfhosted-open-source.zip"
artifacts: "apps/web/artifacts/web-${{ needs.setup.outputs.release_version }}-selfhosted-COMMERCIAL.zip,
apps/web/artifacts/web-${{ needs.setup.outputs.release_version }}-selfhosted-open-source.zip"
token: ${{ secrets.GITHUB_TOKEN }}
draft: true
@ -325,7 +325,7 @@ jobs:
- release
steps:
- name: Checkout repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # 2.4.0
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Remove gh-pages-deploy branch
run: git push origin --delete gh-pages-deploy-$_TAG_VERSION

140
.github/workflows/version-bump.yml vendored Normal file
View File

@ -0,0 +1,140 @@
---
name: Version Bump
on:
workflow_dispatch:
inputs:
client:
description: "Client Project"
required: true
type: choice
options:
- Browser
- CLI
- Desktop
- Web
version_number:
description: "New Version"
required: true
defaults:
run:
shell: bash
jobs:
bump_version:
name: "Bump ${{ github.event.inputs.client }} Version"
runs-on: ubuntu-20.04
steps:
- name: Checkout Branch
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Create Version Branch
id: branch
env:
CLIENT_NAME: ${{ github.event.inputs.client }}
run: |
CLIENT=$(python -c "print('$CLIENT_NAME'.lower())")
echo "::set-output name=client::$CLIENT"
git switch -c ${CLIENT}_version_bump_${{ github.event.inputs.version_number }}
git push -u origin ${CLIENT}_version_bump_${{ github.event.inputs.version_number }}
- name: Checkout Version Branch
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
with:
ref: ${{ steps.branch.outputs.client }}_version_bump_${{ github.event.inputs.version_number }}
########################
# VERSION BUMP SECTION #
########################
### Browser
- name: Bump Browser Version - Manifest
if: ${{ github.event.inputs.client == 'Browser' }}
uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
with:
version: ${{ github.event.inputs.version_number }}
file_path: "apps/browser/src/manifest.json"
- name: Run Prettier after Browser Version Bump
if: ${{ github.event.inputs.client == 'Browser' }}
run: |
npm install -g prettier
prettier --write apps/browser/src/manifest.json
### CLI
- name: Bump CLI Version - Package
if: ${{ github.event.inputs.client == 'CLI' }}
uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
with:
version: ${{ github.event.inputs.version_number }}
file_path: "apps/cli/package.json"
- name: Bump CLI Version - Package-lock
if: ${{ github.event.inputs.client == 'CLI' }}
uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
with:
version: ${{ github.event.inputs.version_number }}
file_path: "apps/cli/package-lock.json"
### Desktop
- name: Bump Desktop Version - Package
if: ${{ github.event.inputs.client == 'Desktop' }}
uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
with:
version: ${{ github.event.inputs.version_number }}
file_path: "apps/desktop/src/package.json"
### Web
- name: Bump Web Version - package.json
if: ${{ github.event.inputs.client == 'Web' }}
uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
with:
version: ${{ github.event.inputs.version_number }}
file_path: "apps/web/package.json"
- name: Bump Web Version - package-lock.json
if: ${{ github.event.inputs.client == 'Web' }}
uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
with:
version: ${{ github.event.inputs.version_number }}
file_path: "apps/web/package-lock.json"
########################
- name: Commit files
env:
CLIENT: ${{ steps.branch.outputs.client }}
run: |
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git commit -m "Bumped ${CLIENT} version to ${{ github.event.inputs.version_number }}" -a
- name: Push changes
env:
CLIENT: ${{ steps.branch.outputs.client }}
run: git push -u origin ${CLIENT}_version_bump_${{ github.event.inputs.version_number }}
- name: Create Bump Version PR
env:
PR_BRANCH: "${{ steps.branch.outputs.client }}_version_bump_${{ github.event.inputs.version_number }}"
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
BASE_BRANCH: master
TITLE: "Bump ${{ github.event.inputs.client }} version to ${{ github.event.inputs.version_number }}"
run: |
gh pr create --title "$TITLE" \
--base "$BASE" \
--head "$PR_BRANCH" \
--label "version update" \
--label "automated pr" \
--body "
## Type of change
- [ ] Bug fix
- [ ] New feature development
- [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc)
- [ ] Build/deploy pipeline (DevOps)
- [X] Other
## Objective
Automated ${{ github.event.inputs.client }} version bump to ${{ github.event.inputs.version_number }}"

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
node_modules/
**/coverage/
.github/workflows/act

1
.husky/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
_

1
.nvmrc Normal file
View File

@ -0,0 +1 @@
v16.13.1

27
.prettierignore Normal file
View File

@ -0,0 +1,27 @@
# Build directories
**/build
**/dist
**/coverage
# External libraries / auto synced locales
apps/browser/src/_locales
apps/browser/src/scripts/duo.js
apps/browser/src/content/autofill.js
apps/browser/src/safari
apps/desktop/src/locales
apps/desktop/dist-safari
apps/desktop/desktop_native
apps/desktop/src/scripts/duo.js
apps/cli/src/locales
apps/cli/.github
apps/web/.github
apps/web/src/404/bootstrap.min.css
apps/web/src/locales
libs/.github
# Github Workflows
.github/workflows

View File

@ -11,11 +11,11 @@ Here is how you can get involved:
- **Report a bug or submit a bugfix:** Use Github issues and pull requests
- **Write documentation:** Submit a pull request to the [Bitwarden help repository](https://github.com/bitwarden/help)
- **Help other users:** Go to the [Ask the Bitwarden Community category](https://community.bitwarden.com/c/support/) on the Community Forums
- **Translate:** See the localization (l10n) section below
- **Translate:** See the localization (i10n) section below
## Contributor Agreement
Please sign the [Contributor Agreement](https://cla-assistant.io/bitwarden/web) if you intend on contributing to any Github repository. Pull requests cannot be accepted and merged unless the author has signed the Contributor Agreement.
Please sign the [Contributor Agreement](https://cla-assistant.io/bitwarden/clients) if you intend on contributing to any Github repository. Pull requests cannot be accepted and merged unless the author has signed the Contributor Agreement.
## Pull Request Guidelines
@ -25,11 +25,13 @@ Please sign the [Contributor Agreement](https://cla-assistant.io/bitwarden/web)
# Localization (l10n)
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/bitwarden-web/localized.svg)](https://crowdin.com/project/bitwarden-web)
We use a translation tool called [Crowdin](https://crowdin.com) to help manage our localization efforts across many different languages.
If you are interested in helping translate the Bitwarden web vault into another language (or make a translation correction), please register an account at Crowdin and join our project here: https://crowdin.com/project/bitwarden-web
If you are interested in helping translate the Bitwarden applications into another language (or make a translation correction), please register an account at Crowdin and join our projects here:
- https://crowdin.com/project/bitwarden-web
- https://crowdin.com/project/bitwarden-desktop
- https://crowdin.com/project/bitwarden-browser
If the language that you are interested in translating is not already listed, create a new account on Crowdin, join the project, and contact the project owner (https://crowdin.com/profile/dwbit).

134
README.md Normal file
View File

@ -0,0 +1,134 @@
<p align="center">
<img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/apps-combo-logo.png" alt="Bitwarden" />
</p>
<p align="center">
<a href="https://github.com/bitwarden/clients/actions/workflows/build-browser.yml?query=branch:master" target="_blank">
<img src="https://github.com/bitwarden/clients/actions/workflows/build-browser.yml/badge.svg?branch=master" alt="Github Workflow browser build on master" />
</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://gitter.im/bitwarden/Lobby" target="_blank">
<img src="https://badges.gitter.im/bitwarden/Lobby.svg" alt="gitter chat" />
</a>
</p>
---
# Bitwarden Client Applications
This repository houses all Bitwarden client applications except the [Mobile application](https://github.com/bitwarden/mobile).
Please check the readmes for each application under `apps` for instructions on how to build the different applications.
## Related projects:
- [bitwarden/server](https://github.com/bitwarden/server): The core infrastructure backend (API, database, Docker, etc).
- [bitwarden/mobile](https://github.com/bitwarden/mobile): The mobile app vault (iOS and Android).
- [bitwarden/directory-connector](https://github.com/bitwarden/directory-connector): A tool for syncing a directory (AD, LDAP, Azure, G Suite, Okta) to an organization.
# We're Hiring!
Interested in contributing in a big way? Consider joining our team! We're hiring for many positions. Please take a look at our [Careers page](https://bitwarden.com/careers/) to see what opportunities are currently open as well as what it's like to work at Bitwarden.
# Contribute
Code contributions are welcome! Please commit any pull requests against the `master` branch. Learn more about how to contribute by reading the [`CONTRIBUTING.md`](CONTRIBUTING.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.
## Git blame
We recommend that you configure git to ignore specific revision using:
```bash
git config blame.ignoreRevsFile .git-blame-ignore-revs
```
## Migrate PRs from old repositories
We recently migrated from individual client repositories. And some PRs were unfortunately left behind in the old repositories. Luckily it's fairly straightforward to sync them up again. Please follow all the instructions below in order to avoid most merge conflicts.
### Desktop
```
# Merge master
git merge master
# Merge branch mono-repo-prep
git merge 28bc4113b9bbae4dba2b5af14d460764fce79acf
# Verify files are placed in apps/desktop
# Add remote
git remote add clients git@github.com:bitwarden/clients.git
# Merge against clients master
git fetch clients
git merge clients/master
# Push to clients or your own fork
```
### CLI
```
# Merge master
git merge master
# Merge branch mono-repo-prep
git merge 980429f4bdcb178d8d92d8202cbdacfaa45c917e
# Verify files are placed in apps/cli
# Add remote
git remote add clients git@github.com:bitwarden/clients.git
# Merge against clients master
git fetch clients
git merge clients/master
# Push to clients or your own fork
```
### Web
```
# Merge master
git merge master
# Merge branch mono-repo-prep
git merge 02fe7159034b04d763a61fcf0200869e3209fa33
# Verify files are placed in apps/web
# Add remote
git remote add clients git@github.com:bitwarden/clients.git
# Merge against clients master
git fetch clients
git merge clients/master
# Push to clients or your own fork
```
### Jslib
```
# Merge master
git merge master
# Merge branch mono-repo
git merge d7492e3cf320410e74ebd0e0675ab994e64bd01a
# Verify files are placed in libs
# Add remote
git remote add clients git@github.com:bitwarden/clients.git
# Merge against clients master
git fetch clients
git merge clients/master
# Push to clients or your own fork
```

20
apps/browser/.gitignore vendored Normal file
View File

@ -0,0 +1,20 @@
.vs
.vscode
.idea
.DS_Store
node_modules
npm-debug.log
vwd.webinfo
css/
dist/
dist-safari/
webfonts/
*.crx
*.pem
*.zip
build/
build.safariextension/
xcuserdata/
*.hmap
!src/safari/safari/app/popup/index.html
src/safari/safari/app/

52
apps/browser/README.md Normal file
View File

@ -0,0 +1,52 @@
[![Github Workflow build browser on master](https://github.com/bitwarden/clients/actions/workflows/build-browser.yml/badge.svg?branch=master)](https://github.com/bitwarden/clients/actions/workflows/build-browser.yml?query=branch:master)
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/bitwarden-browser/localized.svg)](https://crowdin.com/project/bitwarden-browser)
[![Join the chat at https://gitter.im/bitwarden/Lobby](https://badges.gitter.im/bitwarden/Lobby.svg)](https://gitter.im/bitwarden/Lobby)
# 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://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://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://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://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://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.
![My Vault](https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/browser-chrome.png)
# Build/Run
**Requirements**
- [Node.js](https://nodejs.org) v16.13.1 or greater
- NPM v8
- [Gulp](https://gulpjs.com/) (`npm install --global gulp-cli`)
- Chrome (preferred), Opera, or Firefox browser
**Run the app**
```
npm install
npm run build:watch
```
You can now load the extension into your browser through the browser's extension tools page:
- Chrome/Opera:
1. Type `chrome://extensions` in your address bar to bring up the extensions page.
2. Enable developer mode (toggle switch)
3. Click the "Load unpacked extension" button, navigate to the `build` folder of your local extension instance, and click "Ok".
- Firefox
1. Type `about:debugging` in your address bar to bring up the add-ons page.
2. Click the `Load Temporary Add-on` button, navigate to the `build/manifest.json` file, and "Open".
**Desktop communication**
Native Messaging (communication between the desktop application and browser extension) works by having the browser start a lightweight proxy baked into our desktop application.
Out of the box, the desktop application can only communicate with the production browser extension. When you enable browser integration in the desktop application, the application generates manifests which contain the production IDs of the browser extensions. To enable communication between the desktop application and development versions of browser extensions, add the development IDs to the `allowed_extensions` section of the corresponding manifests.
Manifests are located in the `browser` subdirectory of the Bitwarden configuration directory. For instance, on Windows the manifests are located at `C:\Users\<user>\AppData\Roaming\Bitwarden\browsers` and on macOS these are in `Application Support` for various browsers ([for example](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_manifests#manifest_location)). Note that disabling the desktop integration will delete the manifests, and the files will need to be updated again.

28
apps/browser/crowdin.yml Normal file
View File

@ -0,0 +1,28 @@
project_id_env: CROWDIN_PROJECT_ID
api_token_env: CROWDIN_API_TOKEN
preserve_hierarchy: true
files:
- source: /src/_locales/en/messages.json
dest: /src/_locales/en/%original_file_name%
translation: /src/_locales/%two_letters_code%/%original_file_name%
update_option: update_as_unapproved
languages_mapping:
two_letters_code:
pt-PT: pt_PT
pt-BR: pt_BR
zh-CN: zh_CN
zh-TW: zh_TW
en-GB: en_GB
en-IN: en_IN
- source: /store/locales/en/copy.resx
dest: /store/locales/en/%original_file_name%
translation: /store/locales/%two_letters_code%/%original_file_name%
update_option: update_as_unapproved
languages_mapping:
two_letters_code:
pt-PT: pt_PT
pt-BR: pt_BR
zh-CN: zh_CN
zh-TW: zh_TW
en-GB: en_GB
en-IN: en_IN

245
apps/browser/gulpfile.js Normal file
View File

@ -0,0 +1,245 @@
const child = require("child_process");
const fs = require("fs");
const del = require("del");
const gulp = require("gulp");
const filter = require("gulp-filter");
const gulpif = require("gulp-if");
const jeditor = require("gulp-json-editor");
const replace = require("gulp-replace");
const zip = require("gulp-zip");
const manifest = require("./src/manifest.json");
const paths = {
build: "./build/",
dist: "./dist/",
coverage: "./coverage/",
node_modules: "./node_modules/",
popupDir: "./src/popup/",
cssDir: "./src/popup/css/",
safari: "./src/safari/",
};
const filters = {
fonts: [
"!build/popup/fonts/*",
"build/popup/fonts/Open_Sans*.woff",
"build/popup/fonts/bwi-font.woff2",
"build/popup/fonts/bwi-font.woff",
"build/popup/fonts/bwi-font.ttf",
],
safari: ["!build/safari/**/*"],
};
function buildString() {
var build = "";
if (process.env.BUILD_NUMBER && process.env.BUILD_NUMBER !== "") {
build = `-${process.env.BUILD_NUMBER}`;
}
return build;
}
function distFileName(browserName, ext) {
return `dist-${browserName}${buildString()}.${ext}`;
}
function dist(browserName, manifest) {
return gulp
.src(paths.build + "**/*")
.pipe(filter(["**"].concat(filters.fonts).concat(filters.safari)))
.pipe(gulpif("popup/index.html", replace("__BROWSER__", "browser_" + browserName)))
.pipe(gulpif("manifest.json", jeditor(manifest)))
.pipe(zip(distFileName(browserName, "zip")))
.pipe(gulp.dest(paths.dist));
}
function distFirefox() {
return dist("firefox", (manifest) => {
delete manifest.content_security_policy;
removeShortcuts(manifest);
return manifest;
});
}
function distOpera() {
return dist("opera", (manifest) => {
delete manifest.applications;
delete manifest.content_security_policy;
removeShortcuts(manifest);
return manifest;
});
}
function distChrome() {
return dist("chrome", (manifest) => {
delete manifest.applications;
delete manifest.content_security_policy;
delete manifest.sidebar_action;
delete manifest.commands._execute_sidebar_action;
return manifest;
});
}
function distEdge() {
return dist("edge", (manifest) => {
delete manifest.applications;
delete manifest.content_security_policy;
delete manifest.sidebar_action;
delete manifest.commands._execute_sidebar_action;
return manifest;
});
}
function removeShortcuts(manifest) {
if (manifest.content_scripts && manifest.content_scripts.length > 1) {
const shortcutsScript = manifest.content_scripts[1];
if (shortcutsScript.js.indexOf("content/shortcuts.js") > -1) {
manifest.content_scripts.splice(1, 1);
}
}
}
function distSafariMas(cb) {
return distSafariApp(cb, "mas");
}
function distSafariMasDev(cb) {
return distSafariApp(cb, "masdev");
}
function distSafariDmg(cb) {
return distSafariApp(cb, "dmg");
}
function distSafariApp(cb, subBuildPath) {
const buildPath = paths.dist + "Safari/" + subBuildPath + "/";
const builtAppexPath = buildPath + "build/Release/safari.appex";
const builtAppexFrameworkPath = buildPath + "build/Release/safari.appex/Contents/Frameworks/";
const entitlementsPath = paths.safari + "safari/safari.entitlements";
var args = [
"--verbose",
"--force",
"-o",
"runtime",
"--sign",
"Developer ID Application: 8bit Solutions LLC",
"--entitlements",
entitlementsPath,
];
if (subBuildPath !== "dmg") {
args = [
"--verbose",
"--force",
"--sign",
subBuildPath === "mas"
? "3rd Party Mac Developer Application: 8bit Solutions LLC"
: "6B287DD81FF922D86FD836128B0F62F358B38726",
"--entitlements",
entitlementsPath,
];
}
return del([buildPath + "**/*"])
.then(() => safariCopyAssets(paths.safari + "**/*", buildPath))
.then(() => safariCopyBuild(paths.build + "**/*", buildPath + "safari/app"))
.then(() => {
const proc = child.spawn("xcodebuild", [
"-project",
buildPath + "desktop.xcodeproj",
"-alltargets",
"-configuration",
"Release",
]);
stdOutProc(proc);
return new Promise((resolve) => proc.on("close", resolve));
})
.then(() => {
const libs = fs
.readdirSync(builtAppexFrameworkPath)
.filter((p) => p.endsWith(".dylib"))
.map((p) => builtAppexFrameworkPath + p);
const libPromises = [];
libs.forEach((i) => {
const proc = child.spawn("codesign", args.concat([i]));
stdOutProc(proc);
libPromises.push(new Promise((resolve) => proc.on("close", resolve)));
});
return Promise.all(libPromises);
})
.then(() => {
const proc = child.spawn("codesign", args.concat([builtAppexPath]));
stdOutProc(proc);
return new Promise((resolve) => proc.on("close", resolve));
})
.then(
() => {
return cb;
},
() => {
return cb;
}
);
}
function safariCopyAssets(source, dest) {
return new Promise((resolve, reject) => {
gulp
.src(source)
.on("error", reject)
.pipe(gulpif("safari/Info.plist", replace("0.0.1", manifest.version)))
.pipe(
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(gulp.dest(dest))
.on("end", resolve);
});
}
function safariCopyBuild(source, dest) {
return new Promise((resolve, reject) => {
gulp
.src(source)
.on("error", reject)
.pipe(filter(["**"].concat(filters.fonts)))
.pipe(gulpif("popup/index.html", replace("__BROWSER__", "browser_safari")))
.pipe(
gulpif(
"manifest.json",
jeditor((manifest) => {
delete manifest.optional_permissions;
manifest.permissions.push("nativeMessaging");
return manifest;
})
)
)
.pipe(gulp.dest(dest))
.on("end", resolve);
});
}
function stdOutProc(proc) {
proc.stdout.on("data", (data) => console.log(data.toString()));
proc.stderr.on("data", (data) => console.error(data.toString()));
}
function ciCoverage(cb) {
return gulp
.src(paths.coverage + "**/*")
.pipe(filter(["**", "!coverage/coverage*.zip"]))
.pipe(zip(`coverage${buildString()}.zip`))
.pipe(gulp.dest(paths.coverage));
}
exports["dist:firefox"] = distFirefox;
exports["dist:chrome"] = distChrome;
exports["dist:opera"] = distOpera;
exports["dist:edge"] = distEdge;
exports["dist:safari"] = gulp.parallel(distSafariMas, distSafariMasDev, distSafariDmg);
exports["dist:safari:mas"] = distSafariMas;
exports["dist:safari:masdev"] = distSafariMasDev;
exports["dist:safari:dmg"] = distSafariDmg;
exports.dist = gulp.parallel(distFirefox, distChrome, distOpera, distEdge);
exports["ci:coverage"] = ciCoverage;
exports.ci = ciCoverage;

View File

@ -0,0 +1,13 @@
const { pathsToModuleNameMapper } = require("ts-jest");
const { compilerOptions } = require("./tsconfig");
module.exports = {
collectCoverage: true,
coverageReporters: ["html", "lcov"],
coverageDirectory: "coverage",
preset: "jest-preset-angular",
moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, {
prefix: "<rootDir>/",
}),
};

20
apps/browser/package.json Normal file
View File

@ -0,0 +1,20 @@
{
"name": "@bitwarden/browser",
"version": "0.0.0",
"scripts": {
"build": "webpack",
"build:watch": "webpack --watch",
"build:prod": "cross-env NODE_ENV=production webpack",
"build:prod:watch": "cross-env NODE_ENV=production webpack --watch",
"dist": "npm run build:prod && gulp dist",
"dist:firefox": "npm run build:prod && gulp dist:firefox",
"dist:opera": "npm run build:prod && gulp dist:opera",
"dist:safari": "npm run build:prod && gulp dist:safari",
"dist:safari:mas": "npm run build:prod && gulp dist:safari:mas",
"dist:safari:masdev": "npm run build:prod && gulp dist:safari:masdev",
"dist:safari:dmg": "npm run build:prod && gulp dist:safari:dmg",
"test": "jest",
"test:watch": "jest --watch",
"test:watch:all": "jest --watchAll"
}
}

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

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

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