Skip to content

Commit 025dd35

Browse files
authored
chore: kickoff release
2 parents 1368007 + 7d9e3da commit 025dd35

File tree

24 files changed

+1841
-8
lines changed

24 files changed

+1841
-8
lines changed

.github/workflows/dependency-review.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ jobs:
2222
- name: Dependency Review
2323
uses: actions/dependency-review-action@7d90b4f05fea31dde1c4a1fb3fa787e197ea93ab # v3.0.7
2424
with:
25-
config-file: aws-amplify/amplify-ci-support/.github/dependency-review-config.yml@main
25+
config-file: amazon-ospo/dependency-review-config/default/dependency-review-config.yml@main

.github/workflows/integ_test.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,8 @@ jobs:
6464
needs: prepare-for-test
6565
uses: ./.github/workflows/integ_test_storage.yml
6666
secrets: inherit
67+
68+
logging-test:
69+
needs: prepare-for-test
70+
uses: ./.github/workflows/integ_test_logging.yml
71+
secrets: inherit
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
name: Integration Tests | Logging
2+
on:
3+
workflow_dispatch:
4+
workflow_call:
5+
6+
permissions:
7+
id-token: write
8+
contents: read
9+
10+
jobs:
11+
logging-integration-test-iOS:
12+
runs-on: macos-12
13+
environment: IntegrationTest
14+
steps:
15+
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
16+
with:
17+
persist-credentials: false
18+
19+
- name: Make directory
20+
run: mkdir -p ~/.aws-amplify/amplify-ios/testconfiguration/
21+
22+
- name: Copy integration test resouces
23+
uses: ./.github/composite_actions/download_test_configuration
24+
with:
25+
resource_subfolder: logging
26+
aws_role_to_assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
27+
aws_region: ${{ secrets.AWS_REGION }}
28+
aws_s3_bucket: ${{ secrets.AWS_S3_BUCKET_INTEG_V2 }}
29+
30+
- name: Run Integration test
31+
uses: ./.github/composite_actions/run_xcodebuild_test
32+
with:
33+
project_path: ./AmplifyPlugins/Logging/Tests/AWSCloudWatchLoggingPluginHostApp
34+
scheme: AWSCloudWatchLoggingPluginIntegrationTests
35+
36+
logging-integration-test-tvOS:
37+
runs-on: macos-13
38+
environment: IntegrationTest
39+
steps:
40+
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
41+
with:
42+
persist-credentials: false
43+
44+
- name: Make directory
45+
run: mkdir -p ~/.aws-amplify/amplify-ios/testconfiguration/
46+
47+
- name: Copy integration test resouces
48+
uses: ./.github/composite_actions/download_test_configuration
49+
with:
50+
resource_subfolder: logging
51+
aws_role_to_assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
52+
aws_region: ${{ secrets.AWS_REGION }}
53+
aws_s3_bucket: ${{ secrets.AWS_S3_BUCKET_INTEG_V2 }}
54+
55+
- name: Run Integration test
56+
uses: ./.github/composite_actions/run_xcodebuild_test
57+
with:
58+
project_path: ./AmplifyPlugins/Logging/Tests/AWSCloudWatchLoggingPluginHostApp
59+
scheme: AWSCloudWatchLoggingPluginIntegrationTests
60+
destination: platform=tvOS Simulator,name=Apple TV 4K (3rd generation),OS=latest
61+
sdk: appletvsimulator
62+
xcode_path: '/Applications/Xcode_14.3.app'
63+
64+
logging-integration-test-watchOS:
65+
runs-on: macos-13
66+
environment: IntegrationTest
67+
steps:
68+
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
69+
with:
70+
persist-credentials: false
71+
72+
- name: Make directory
73+
run: mkdir -p ~/.aws-amplify/amplify-ios/testconfiguration/
74+
75+
- name: Copy integration test resouces
76+
uses: ./.github/composite_actions/download_test_configuration
77+
with:
78+
resource_subfolder: logging
79+
aws_role_to_assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
80+
aws_region: ${{ secrets.AWS_REGION }}
81+
aws_s3_bucket: ${{ secrets.AWS_S3_BUCKET_INTEG_V2 }}
82+
83+
- name: Run Integration test
84+
uses: ./.github/composite_actions/run_xcodebuild_test
85+
with:
86+
project_path: ./AmplifyPlugins/Logging/Tests/AWSCloudWatchLoggingPluginHostApp
87+
scheme: AWSCloudWatchLoggingPluginIntegrationTestsWatch
88+
destination: platform=watchOS Simulator,name=Apple Watch Series 8 (45mm),OS=latest
89+
sdk: watchsimulator
90+
xcode_path: '/Applications/Xcode_14.3.app'

AmplifyPlugins/DataStore/Sources/AWSDataStorePlugin/Sync/InitialSync/InitialSyncOperation.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,13 @@ final class InitialSyncOperation: AsynchronousOperation {
130130
switch result {
131131
case .failure(let apiError):
132132
if self.isAuthSignedOutError(apiError: apiError) {
133-
self.dataStoreConfiguration.errorHandler(DataStoreError.api(apiError))
133+
self.log.error("Sync for \(self.modelSchema.name) failed due to signed out error \(apiError.errorDescription)")
134134
}
135+
135136
// TODO: Retry query on error
136-
self.finish(result: .failure(DataStoreError.api(apiError)))
137+
let error = DataStoreError.api(apiError)
138+
self.dataStoreConfiguration.errorHandler(error)
139+
self.finish(result: .failure(error))
137140
case .success(let graphQLResult):
138141
self.handleQueryResults(lastSyncTime: lastSyncTime, graphQLResult: graphQLResult)
139142
}

AmplifyPlugins/DataStore/Sources/AWSDataStorePlugin/Sync/InitialSync/InitialSyncOrchestrator.swift

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ final class AWSInitialSyncOrchestrator: InitialSyncOrchestrator {
164164
allMessages.joined(separator: "\n"),
165165
underlyingError
166166
)
167+
167168
return .failure(syncError)
168169
}
169170

@@ -208,7 +209,7 @@ extension AWSInitialSyncOrchestrator {
208209
return errorTypeValue
209210
}
210211

211-
private func isUnauthorizedError(_ error: DataStoreError) -> Bool {
212+
func isUnauthorizedError(_ error: DataStoreError) -> Bool {
212213
guard case let .sync(_, _, underlyingError) = error,
213214
let datastoreError = underlyingError as? DataStoreError
214215
else {
@@ -245,6 +246,22 @@ extension AWSInitialSyncOrchestrator {
245246
case .unauthorized = AppSyncErrorType(errorTypeValue) {
246247
return true
247248
}
249+
250+
// Check is API error is of unauthorized type
251+
if case let .api(amplifyError, _) = datastoreError,
252+
let apiError = amplifyError as? APIError {
253+
if case .operationError(let errorDescription, _, _) = apiError,
254+
errorDescription.range(of: "Unauthorized",
255+
options: .caseInsensitive) != nil {
256+
return true
257+
}
258+
259+
if case .httpStatusError(let statusCode, _) = apiError,
260+
(statusCode == 401 || statusCode == 403) {
261+
return true
262+
}
263+
}
264+
248265
return false
249266
}
250267

AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/InitialSyncOrchestratorTests.swift

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77

88
import XCTest
9+
import Foundation
910

1011
@testable import Amplify
1112
@testable import AmplifyTestCommon
@@ -101,7 +102,7 @@ class InitialSyncOrchestratorTests: XCTestCase {
101102
Amplify.Hub.removeListener(hubListener)
102103
sink.cancel()
103104
}
104-
105+
105106
/// - Given: An InitialSyncOrchestrator with a model dependency graph, API is expected to return an error for certain models
106107
/// - When:
107108
/// - The orchestrator starts up
@@ -200,7 +201,7 @@ class InitialSyncOrchestratorTests: XCTestCase {
200201
Amplify.Hub.removeListener(hubListener)
201202
sink.cancel()
202203
}
203-
204+
204205
/// - Given: An InitialSyncOrchestrator with a model dependency graph containing no associations
205206
/// - When:
206207
/// - The orchestrator starts up
@@ -409,4 +410,47 @@ class InitialSyncOrchestratorTests: XCTestCase {
409410
sink.cancel()
410411
}
411412

413+
/// - Given:
414+
/// An InitialSyncOrchestrator with a model dependency graph
415+
/// - When:
416+
/// isUnauthorized() is called with an API Error with status code 401, 403 or "Unauthorized" description
417+
/// and return false for other cases
418+
/// - Then:
419+
/// - It should return true for unauthorized cases and false for other cases
420+
func testIsUnauthorized() {
421+
let apiPlugin = MockAPICategoryPlugin()
422+
let storageAdapter = MockSQLiteStorageEngineAdapter()
423+
let reconciliationQueue = MockReconciliationQueue()
424+
425+
let orchestrator =
426+
AWSInitialSyncOrchestrator(dataStoreConfiguration: .default,
427+
authModeStrategy: AWSDefaultAuthModeStrategy(),
428+
api: apiPlugin,
429+
reconciliationQueue: reconciliationQueue,
430+
storageAdapter: storageAdapter)
431+
432+
let error1 = DataStoreError.api(APIError.httpStatusError(401, HTTPURLResponse(url: URL(string: "https://aws.amazon.com")!,
433+
statusCode: 401,
434+
httpVersion: nil,
435+
headerFields: nil)!))
436+
XCTAssertTrue(orchestrator.isUnauthorizedError(DataStoreError.sync("", "", error1)))
437+
438+
let error2 = DataStoreError.api(APIError.httpStatusError(403, HTTPURLResponse(url: URL(string: "https://aws.amazon.com")!,
439+
statusCode: 403,
440+
httpVersion: nil,
441+
headerFields: nil)!))
442+
XCTAssertTrue(orchestrator.isUnauthorizedError(DataStoreError.sync("", "", error2)))
443+
444+
let error3 = DataStoreError.api(APIError.httpStatusError(404, HTTPURLResponse(url: URL(string: "https://aws.amazon.com")!,
445+
statusCode: 404,
446+
httpVersion: nil,
447+
headerFields: nil)!))
448+
XCTAssertFalse(orchestrator.isUnauthorizedError(DataStoreError.sync("", "", error3)))
449+
450+
let error4 = DataStoreError.api(APIError.operationError("Unauthorized error", "", nil))
451+
XCTAssertTrue(orchestrator.isUnauthorizedError(DataStoreError.sync("", "", error4)))
452+
453+
let error5 = DataStoreError.api(APIError.operationError("An error occurred", "", nil))
454+
XCTAssertFalse(orchestrator.isUnauthorizedError(DataStoreError.sync("", "", error5)))
455+
}
412456
}

AmplifyPlugins/Logging/Sources/AWSCloudWatchLoggingPlugin/AWSCloudWatchLoggingPlugin.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public class AWSCloudWatchLoggingPlugin: LoggingCategoryPlugin {
155155
localStore.reset()
156156
}
157157

158-
DispatchQueue.main.async {
158+
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {
159159
self.loggingClient.takeUserIdentifierFromCurrentUser()
160160
}
161161
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//
2+
// Copyright Amazon.com Inc. or its affiliates.
3+
// All Rights Reserved.
4+
//
5+
// SPDX-License-Identifier: Apache-2.0
6+
//
7+
8+
import Foundation
9+
import AWSCloudWatchLogs
10+
11+
class AWSCloudWatchClientHelper {
12+
static func getFilterLogEventCount(client: CloudWatchLogsClientProtocol?, filterPattern: String?, startTime: Date?, endTime: Date?, logGroupName: String?) async throws -> [CloudWatchLogsClientTypes.FilteredLogEvent]? {
13+
let filterEventInput = FilterLogEventsInput(endTime: endTime?.epochMilliseconds, filterPattern: filterPattern, logGroupName: logGroupName, startTime: startTime?.epochMilliseconds)
14+
let response = try await client?.filterLogEvents(input: filterEventInput)
15+
return response?.events
16+
}
17+
}
18+
19+
extension Date {
20+
var epochMilliseconds: Int {
21+
Int(self.timeIntervalSince1970 * 1_000)
22+
}
23+
}

0 commit comments

Comments
 (0)