Skip to content

Commit a746661

Browse files
rkolesnikovDXRoman KolesnikovCopilot
authored
deps: Lodash upgrade to 4.18.1 (#2882)
* test: fix session storage mock initialization Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3aafafb2-5e0b-49a1-b15d-ca56d5dd535e * build: update lodash to 4.18.1 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3aafafb2-5e0b-49a1-b15d-ca56d5dd535e * ci: pin validation to Node 20 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3aafafb2-5e0b-49a1-b15d-ca56d5dd535e * fix: load static data webpack configs asynchronously * fix: handle undefined ARM_TOKEN in authenticators for tests * refactor: deduplicate static data copy patterns * fix: skip ARM token fetch in static data build to fix CI failure webpack.staticData.js calls webpack.publisher.js which previously always fetched an ARM token via getArmToken(). In CI there is no AZURE_CLIENT_SECRET set, so it fell back to interactive browser auth which fails with AuthenticationRequiredError. The static data build does not need a real ARM token — startup.publish.ts uses a hardcoded StaticSettingsProvider when NODE_ENV === staticDataEnvironment, and StaticAuthenticator already handles undefined/empty ARM_TOKEN gracefully. - Add optional skipArmToken parameter to webpack.publisher.js - Pass { skipArmToken: true } from webpack.staticData.js * fix: await async publisher webpack configs * fix: set isLocalRun=true and root=http://localhost:8080 in config.validate.json to fix end2end-tests CI * fix: use nullish coalescing for skipArmToken option in webpack.publisher.js * fix: restore managementApiUrl fallback in MapiClient.setBaseUrl and static settings for mock publishing mode * fix: remove redundant 'products/' prefix in getProduct calls in product-subscribe components * fix: improve error message in MapiClient.setBaseUrl to reflect all config sources * fix: pre-seed sessionStorage mock and add --exit to mocha to fix test failures and stuck process --------- Co-authored-by: Roman Kolesnikov <rokolesnikov@microsoft.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent f5e0234 commit a746661

16 files changed

Lines changed: 124 additions & 100 deletions

.github/workflows/mainCI.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@ jobs:
1818
security-events: write
1919

2020
steps:
21-
- name: Use Node.js 20.x
21+
- name: Checkout code
2222
uses: actions/checkout@v2
23+
24+
- name: Setup Node.js 20
25+
uses: actions/setup-node@v4
2326
with:
24-
node-version: 20.x
27+
node-version: 20
2528

2629
- name: Install
2730
run: npm install

.github/workflows/test.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ jobs:
1313
- name: Checkout code
1414
uses: actions/checkout@v3
1515

16+
- name: Setup Node.js 20
17+
uses: actions/setup-node@v4
18+
with:
19+
node-version: 20
20+
1621
- name: Install
1722
run: npm install
1823

package-lock.json

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"build-publisher": "webpack --config webpack.publisher.js",
1818
"build-runtime": "webpack --config webpack.runtime.js",
1919
"build-function": "webpack --config webpack.function.js",
20-
"test": "node node_modules/mocha/bin/_mocha -r mocha.js src/**/*.spec.ts",
20+
"test": "node node_modules/mocha/bin/_mocha -r mocha.js --exit src/**/*.spec.ts",
2121
"deploy-function": "npm run build-function && cd dist/function && func azure functionapp publish < function app name >",
2222
"publish": "webpack --config webpack.publisher.js && node dist/publisher/index.js && npm run serve-website",
2323
"serve-website": "webpack serve --open --static ./dist/website --no-stats",
@@ -116,6 +116,7 @@
116116
"knockout-mapping": "^2.6.0",
117117
"knockout.validation": "^2.0.4",
118118
"liquidjs": "^10.9.2",
119+
"lodash": "4.18.1",
119120
"lunr": "^2.3.9",
120121
"mime": "^3.0.0",
121122
"moment": "^2.29.4",

src/authentication/authenticatorResolver.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { ArmAuthenticator } from "./armAuthenticator";
66
import { IAuthenticator } from "./IAuthenticator";
77
import { IEditorSettings } from "./IEditorSettings";
88

9+
declare const ARM_TOKEN: string | undefined;
10+
911
export class AuthenticatorResolver {
1012
private loadPromise: Promise<IAuthenticator>;
1113

src/authentication/staticAuthenticator.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { IAuthenticator, AccessToken } from ".";
22

3+
declare const ARM_TOKEN: string | undefined;
4+
35
/**
46
* Static implementation of the IAuthenticator interface to mimic actual authentication in publish time.
57
*/
@@ -11,7 +13,7 @@ export class StaticAuthenticator implements IAuthenticator {
1113
* The ARM token injected acquired in build-time. It's used in on local development only.
1214
* TODO: Static authenticator is used in production publishing, therefore it's safer to introduce dedicated implementation.
1315
*/
14-
if (!ARM_TOKEN) {
16+
if (typeof ARM_TOKEN === "undefined" || !ARM_TOKEN) {
1517
return;
1618
}
1719

src/clients/mapiClient.spec.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,18 @@ describe("Mapi Client", async () => {
2121

2222
global.sessionStorage = {
2323
_values: new Map<string, string>(),
24-
length: global.sessionStorage._values.size,
24+
get length() { return this._values.size; },
2525
key: (index: number) => { return null; },
2626
getItem: (key: string) => { return global.sessionStorage._values.get(key); },
2727
setItem: (key: string, value: string) => { global.sessionStorage._values.set(key, value); },
2828
removeItem: (key: string) => { global.sessionStorage._values.delete(key); },
2929
clear: () => { global.sessionStorage._values.clear(); }
3030
}
3131

32+
// Pre-seed a valid non-expired SAS token so ArmAuthenticator.getAccessToken() returns from
33+
// sessionStorage cache and never calls authenticate(), which relies on browser-only `location`.
34+
global.sessionStorage.setItem("armAccessToken", createMockToken());
35+
3236
const settingsProvider = new StaticSettingsProvider({
3337
managementApiUrl: "https://contoso.management.azure-api.net",
3438
backendUrl: "https://contoso.developer.azure-api.net",

src/clients/mapiClient.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import * as Constants from "../constants";
77
import ApiClient from "./apiClient";
88
import { IRetryStrategy } from "./retryStrategy/retryStrategy";
99
import { SettingNames } from "../constants";
10+
import { Utils } from "../utils";
1011

1112
export class MapiClient extends ApiClient {
1213
constructor(
@@ -22,25 +23,29 @@ export class MapiClient extends ApiClient {
2223

2324
protected override async setBaseUrl() {
2425
const settings = await this.settingsProvider.getSettings();
25-
26+
27+
const managementApiUrl = settings[Constants.SettingNames.managementApiUrl];
28+
if (managementApiUrl) {
29+
this.baseUrl = managementApiUrl;
30+
return;
31+
}
32+
2633
const serviceName = settings[Constants.SettingNames.serviceName];
2734
const subscriptionId = settings[Constants.SettingNames.subscriptionId];
2835
const resourceGroupName = settings[Constants.SettingNames.resourceGroupName];
2936

30-
if (!serviceName) {
31-
throw new Error("Service name setting is missing.");
37+
if (serviceName && subscriptionId && resourceGroupName) {
38+
this.baseUrl = `https://management.azure.com/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.ApiManagement/service/${serviceName}`;
39+
return;
3240
}
3341

34-
if (!subscriptionId) {
35-
throw new Error("Subscription ID setting is missing.");
42+
const backendUrl = settings[Constants.SettingNames.backendUrl];
43+
if (backendUrl) {
44+
this.baseUrl = Utils.getBaseUrlWithMapiSuffix(backendUrl);
45+
return;
3646
}
3747

38-
if (!resourceGroupName) {
39-
throw new Error("Resource Group name setting is missing.");
40-
}
41-
42-
this.baseUrl = `https://management.azure.com/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.ApiManagement/service/${serviceName}`;
43-
48+
throw new Error("Unable to determine management API URL: no valid configuration found (managementApiUrl, serviceName/subscriptionId/resourceGroupName, or backendUrl must be set).");
4449
}
4550

4651
public async getTenantArmUriAsync(): Promise<string> {

src/components/products/product-subscribe/ko/runtime/product-subscribe.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export class ProductSubscribe {
8181
return;
8282
}
8383

84-
const product = await this.productService.getProduct(`products/${productName}`);
84+
const product = await this.productService.getProduct(productName);
8585

8686
if (!product) {
8787
return;

src/components/products/product-subscribe/react/runtime/ProductSubscribeRuntime.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ type ProductSubscribeRuntimeFCProps = ProductSubscribeRuntimeProps & {
2727
const loadProduct = async (usersService: UsersService, delegationService: IDelegationService, productService: ProductService, productName: string) => {
2828
const promises = [
2929
await delegationService.isSubscriptionDelegationEnabled(),
30-
await productService.getProduct(`products/${productName}`),
30+
await productService.getProduct(productName),
3131
await usersService.getCurrentUserId(),
3232
] as const;
3333
const [isDelegationEnabled, product, userId] = await Promise.all(promises);

0 commit comments

Comments
 (0)