Skip to content

Commit

Permalink
Merge branch 'main' into pm-12242/fix-default-region-urls
Browse files Browse the repository at this point in the history
  • Loading branch information
fedemkr committed Sep 17, 2024
2 parents bdefb92 + a91c7f6 commit e58e73a
Show file tree
Hide file tree
Showing 19 changed files with 439 additions and 29 deletions.
113 changes: 113 additions & 0 deletions .github/workflows/_version.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
---
name: Calculate Version Name and Number


on:
workflow_dispatch:
inputs:
base_version_number:
description: "Base version number to use for version calculation"
type: number
default: 0
version_name:
description: "Overrides version name calculation"
distinct_id:
description: "Unique ID for this dispatch, used by dispatch-and-download.yml"
skip_checkout:
description: "Skip checking out the repository"
type: boolean
repository_dispatch:

env:
BASE_VERSION_NUMBER: ${{ inputs.base_version_number || 0 }}

jobs:
calculate-version:
name: Calculate Version Name and Number
runs-on: ubuntu-latest
steps:
- name: Log inputs to job summary
run: |
echo "<details><summary>Workflow Inputs</summary>" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo '```json' >> $GITHUB_STEP_SUMMARY
echo '${{ toJson(inputs) }}' >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "</details>" >> $GITHUB_STEP_SUMMARY
- name: Echo distinct ID ${{ github.event.inputs.distinct_id }}
run: echo ${{ github.event.inputs.distinct_id }}

- name: Check out repository
if: ${{ !inputs.skip_checkout || false }}
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
fetch-depth: 0

- name: Calculate version name
id: calc-version-name
run: |
output() {
local version_name=$1
echo "version_name=$version_name" >> $GITHUB_OUTPUT
}
# override version name if provided
if [[ ! -z "${{ inputs.version_name }}" ]]; then
echo -e "\nApplying version override"
version_name=${{ inputs.version_name }}
echo "::warning::Override applied: $version_name"
output "$version_name"
exit 0
fi
current_year=$(date +%Y)
current_month=$(date +%-m)
latest_tag_version=$(git tag --sort=committerdate --list | tail -1)
if [[ -z "$latest_tag_version" ]]; then
version_name="${current_year}.${current_month}.0"
echo "::warning::No tags found, did you checkout? Calculating version from current date: $version_name"
output "$version_name"
exit 0
fi
# Git tag was found, calculate version from latest tag
latest_version=${latest_tag_version:1} # remove 'v' from tag version
latest_major_version=$(echo $latest_version | cut -d "." -f 1)
latest_minor_version=$(echo $latest_version | cut -d "." -f 2)
latest_patch_version=$(echo $latest_version | cut -d "." -f 3)
if [[ "$current_year" == "$latest_major_version" && "$current_month" == "$latest_minor_version" ]]; then
version_name="${latest_major_version}.${latest_minor_version}.$(($latest_patch_version + 1))"
else
version_name="${current_year}.${current_month}.0"
fi
output "$version_name"
- name: Calculate version number
id: calc-version-number
run: |
version_number=$(($GITHUB_RUN_NUMBER + ${{ env.BASE_VERSION_NUMBER }}))
echo "version_number=$version_number" >> $GITHUB_OUTPUT
- name: Create version info JSON
run: |
json='{
"version_number": "${{ steps.calc-version-number.outputs.version_number }}",
"version_name": "${{ steps.calc-version-name.outputs.version_name }}"
}'
echo "$json" > version_info.json
echo "## version-info.json" >> $GITHUB_STEP_SUMMARY
echo '```json' >> $GITHUB_STEP_SUMMARY
echo "$json" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
- name: Upload version info artifact
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
name: version-info
path: version_info.json
69 changes: 69 additions & 0 deletions .github/workflows/dispatch-and-download/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Dispatch Workflow and Download Artifacts
description: 'Dispatches a workflow, waits for completion, and downloads artifacts'
inputs:
token:
description: GitHub Personal Access Token for making API requests.
required: true
workflow:
description: The workflow to dispatch, can be a filename or ID
required: true
ref:
description: The branch or tag to dispatch the workflow on
default: 'main'
repo:
description: Repository of the action to dispatch.
default: ${{ github.repository }}
owner:
description: Owner of the given repository.
default: ${{ github.repository_owner }}
workflow_timeout_seconds:
description: Time until giving up waiting for the start of the workflow run.
default: 120
workflow_inputs:
description: A flat JSON object, only supports strings, numbers, and booleans (as per workflow inputs API).
distinct_id:
description: Specify a static string to use instead of a random distinct ID.
runs:
using: "composite"
steps:
- name: Log inputs to job summary
run: |
echo "<details><summary>Workflow Inputs</summary>" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo '```json' >> $GITHUB_STEP_SUMMARY
echo '${{ toJson(inputs) }}' >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "</details>" >> $GITHUB_STEP_SUMMARY
- name: Dispatch an action and get the run ID and URL
uses: codex-/return-dispatch@bcb9c46cb8ee849d5e6cca0ba9c8529d620ae006 # v1.15.0
id: return_dispatch
with:
token: ${{ inputs.token }}
ref: ${{ inputs.ref }}
repo: ${{ inputs.repo }}
owner: ${{ inputs.owner }}
workflow: ${{ inputs.workflow }}
workflow_timeout_seconds: ${{ inputs.workflow_timeout_seconds }}
workflow_inputs: ${{ inputs.workflow_inputs }}
distinct_id: ${{ inputs.distinct_id }}

- name: Use the output run ID and URL
shell: bash
run: |
echo ${{steps.return_dispatch.outputs.run_id}}
echo ${{steps.return_dispatch.outputs.run_url}}
- name: Download all artifacts
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
id: download
with:
run-id: ${{steps.return_dispatch.outputs.run_id}}
github-token: ${{ inputs.token }}

- name: Debug artifact download
shell: bash
run: |
echo "Run ID: ${{steps.return_dispatch.outputs.run_id}}"
echo "Artifacts path: ${{ steps.download.outputs.download-path }}"
ls -laR ${{ steps.download.outputs.download-path }}
41 changes: 41 additions & 0 deletions BitwardenShared/Core/Platform/Services/StateService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,13 @@ protocol StateService: AnyObject {
///
func getMasterPasswordHash(userId: String?) async throws -> String?

/// Gets whether the user needs to set up vault unlock methods.
///
/// - Parameter userId: The user ID associated with the value.
/// - Returns: Whether the user needs to set up vault unlock methods.
///
func getNeedsVaultUnlockSetup(userId: String?) async throws -> Bool

/// Gets the last notifications registration date for a user ID.
///
/// - Parameter userId: The user ID of the account. Defaults to the active account if `nil`.
Expand Down Expand Up @@ -464,6 +471,14 @@ protocol StateService: AnyObject {
///
func setMasterPasswordHash(_ hash: String?, userId: String?) async throws

/// Sets whether the user needs to set up vault unlock methods.
///
/// - Parameters:
/// - needsVaultUnlockSetup: Whether the user needs to set up vault unlock methods.
/// - userId: The user ID associated with the value.
///
func setNeedsVaultUnlockSetup(_ needsVaultUnlockSetup: Bool, userId: String?) async throws

/// Sets the last notifications registration date for a user ID.
///
/// - Parameters:
Expand Down Expand Up @@ -750,6 +765,14 @@ extension StateService {
try await getMasterPasswordHash(userId: nil)
}

/// Gets whether the active account needs to set up vault unlock methods.
///
/// - Returns: Whether the user needs to set up vault unlock methods.
///
func getNeedsVaultUnlockSetup() async throws -> Bool {
try await getNeedsVaultUnlockSetup(userId: nil)
}

/// Gets the last notifications registration date for the active account.
///
/// - Returns: The last notifications registration date for the active account.
Expand Down Expand Up @@ -936,6 +959,14 @@ extension StateService {
try await setMasterPasswordHash(hash, userId: nil)
}

/// Sets whether the active account needs to set up vault unlock methods.
///
/// - Parameter needsVaultUnlockSetup: Whether the user needs to set up vault unlock methods.
///
func setNeedsVaultUnlockSetup(_ needsVaultUnlockSetup: Bool) async throws {
try await setNeedsVaultUnlockSetup(needsVaultUnlockSetup, userId: nil)
}

/// Sets the last notifications registration date for the active account.
///
/// - Parameter date: The last notifications registration date.
Expand Down Expand Up @@ -1240,6 +1271,11 @@ actor DefaultStateService: StateService { // swiftlint:disable:this type_body_le
return appSettingsStore.masterPasswordHash(userId: userId)
}

func getNeedsVaultUnlockSetup(userId: String?) async throws -> Bool {
let userId = try userId ?? getActiveAccountUserId()
return appSettingsStore.needsVaultUnlockSetup(userId: userId)
}

func getNotificationsLastRegistrationDate(userId: String?) async throws -> Date? {
let userId = try userId ?? getActiveAccountUserId()
return appSettingsStore.notificationsLastRegistrationDate(userId: userId)
Expand Down Expand Up @@ -1461,6 +1497,11 @@ actor DefaultStateService: StateService { // swiftlint:disable:this type_body_le
appSettingsStore.setMasterPasswordHash(hash, userId: userId)
}

func setNeedsVaultUnlockSetup(_ needsVaultUnlockSetup: Bool, userId: String?) async throws {
let userId = try userId ?? getActiveAccountUserId()
appSettingsStore.setNeedsVaultUnlockSetup(needsVaultUnlockSetup, userId: userId)
}

func setNotificationsLastRegistrationDate(_ date: Date?, userId: String?) async throws {
let userId = try userId ?? getActiveAccountUserId()
appSettingsStore.setNotificationsLastRegistrationDate(date, userId: userId)
Expand Down
30 changes: 30 additions & 0 deletions BitwardenShared/Core/Platform/Services/StateServiceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,25 @@ class StateServiceTests: BitwardenTestCase { // swiftlint:disable:this type_body
}
}

/// `getNeedsVaultUnlockSetup()` returns whether the user needs to set up vault unlock methods.
func test_getNeedsVaultUnlockSetup() async throws {
await subject.addAccount(.fixture(profile: .fixture(userId: "1")))

let initialValue = try await subject.getNeedsVaultUnlockSetup()
XCTAssertFalse(initialValue)

appSettingsStore.needsVaultUnlockSetup["1"] = true
let needsVaultUnlockSetup = try await subject.getNeedsVaultUnlockSetup()
XCTAssertTrue(needsVaultUnlockSetup)
}

/// `getNeedsVaultUnlockSetup()` throws an error if there isn't an active account.
func test_getNeedsVaultUnlockSetup_noAccount() async throws {
await assertAsyncThrows(error: StateServiceError.noActiveAccount) {
_ = try await subject.getNeedsVaultUnlockSetup()
}
}

/// `getNotificationsLastRegistrationDate()` returns the user's last notifications registration date.
func test_getNotificationsLastRegistrationDate() async throws {
await subject.addAccount(.fixture(profile: .fixture(userId: "1")))
Expand Down Expand Up @@ -1535,6 +1554,17 @@ class StateServiceTests: BitwardenTestCase { // swiftlint:disable:this type_body
XCTAssertEqual(appSettingsStore.masterPasswordHashes, ["1": "1234"])
}

/// `setNeedsVaultUnlockSetup(_:)` sets whether the user needs to set up vault unlock methods.
func test_setNeedsVaultUnlockSetup() async throws {
await subject.addAccount(.fixture(profile: .fixture(userId: "1")))

try await subject.setNeedsVaultUnlockSetup(true)
XCTAssertEqual(appSettingsStore.needsVaultUnlockSetup, ["1": true])

try await subject.setNeedsVaultUnlockSetup(false, userId: "1")
XCTAssertEqual(appSettingsStore.needsVaultUnlockSetup, ["1": false])
}

/// `setNotificationsLastRegistrationDate(_:)` sets the last notifications registration date for a user.
func test_setNotificationsLastRegistrationDate() async throws {
await subject.addAccount(.fixture(profile: .fixture(userId: "1")))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,13 @@ protocol AppSettingsStore: AnyObject {
///
func masterPasswordHash(userId: String) -> String?

/// Gets whether the user needs to set up vault unlock methods.
///
/// - Parameter userId: The user ID associated with the value.
/// - Returns: Whether the user needs to set up vault unlock methods.
///
func needsVaultUnlockSetup(userId: String) -> Bool

/// Gets the last date the user successfully registered for push notifications.
///
/// - Parameter userId: The user ID associated with the last notifications registration date.
Expand Down Expand Up @@ -305,6 +312,14 @@ protocol AppSettingsStore: AnyObject {
///
func setMasterPasswordHash(_ hash: String?, userId: String)

/// Sets whether the user needs to set up vault unlock methods.
///
/// - Parameters:
/// - needsVaultUnlockSetup: Whether the user needs to set up vault unlock methods.
/// - userId: The user ID associated with the value.
///
func setNeedsVaultUnlockSetup(_ needsVaultUnlockSetup: Bool, userId: String)

/// Sets the last notifications registration date for a user ID.
///
/// - Parameters:
Expand Down Expand Up @@ -587,6 +602,7 @@ extension DefaultAppSettingsStore: AppSettingsStore {
case loginRequest
case masterPasswordHash(userId: String)
case migrationVersion
case needsVaultUnlockSetup(userId: String)
case notificationsLastRegistrationDate(userId: String)
case passwordGenerationOptions(userId: String)
case pinProtectedUserKey(userId: String)
Expand Down Expand Up @@ -656,6 +672,8 @@ extension DefaultAppSettingsStore: AppSettingsStore {
key = "keyHash_\(userId)"
case .migrationVersion:
key = "migrationVersion"
case let .needsVaultUnlockSetup(userId):
key = "needsVaultUnlockSetup_\(userId)"
case let .notificationsLastRegistrationDate(userId):
key = "pushLastRegistrationDate_\(userId)"
case let .passwordGenerationOptions(userId):
Expand Down Expand Up @@ -836,6 +854,10 @@ extension DefaultAppSettingsStore: AppSettingsStore {
fetch(for: .masterPasswordHash(userId: userId))
}

func needsVaultUnlockSetup(userId: String) -> Bool {
fetch(for: .needsVaultUnlockSetup(userId: userId))
}

func notificationsLastRegistrationDate(userId: String) -> Date? {
fetch(for: .notificationsLastRegistrationDate(userId: userId)).map { Date(timeIntervalSince1970: $0) }
}
Expand Down Expand Up @@ -914,6 +936,10 @@ extension DefaultAppSettingsStore: AppSettingsStore {
store(hash, for: .masterPasswordHash(userId: userId))
}

func setNeedsVaultUnlockSetup(_ needsVaultUnlockSetup: Bool, userId: String) {
store(needsVaultUnlockSetup, for: .needsVaultUnlockSetup(userId: userId))
}

func setNotificationsLastRegistrationDate(_ date: Date?, userId: String) {
store(date?.timeIntervalSince1970, for: .notificationsLastRegistrationDate(userId: userId))
}
Expand Down
Loading

0 comments on commit e58e73a

Please sign in to comment.