Skip to content

Commit 5671568

Browse files
[tsp-client] Fix writing additional directory (#8662)
* account for non-list additional dir * unify tsp-location.yaml creation * docs * add test * add read test * release prep * update release date --------- Co-authored-by: Catalina Peralta <caperal@microsoft.com>
1 parent f6cb995 commit 5671568

8 files changed

Lines changed: 89 additions & 21 deletions

File tree

tools/tsp-client/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Release
22

3+
## 2024-07-23 - 0.9.4
4+
5+
- Fixed issue where one additional directory entry is treated as a string instead of an array. (#8551)
6+
37
## 2024-07-15 - 0.9.3
48

59
- Add autorest and plugins as dependencies, and run the packages from their install folders, to guarantee the versions don't change after install.

tools/tsp-client/package-lock.json

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

tools/tsp-client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@azure-tools/typespec-client-generator-cli",
3-
"version": "0.9.3",
3+
"version": "0.9.4",
44
"description": "A tool to generate Azure SDKs from TypeSpec",
55
"main": "dist/index.js",
66
"homepage": "https://github.com/Azure/azure-sdk-tools/tree/main/tools/tsp-client#readme",

tools/tsp-client/src/fs.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,13 @@ export async function readTspLocation(rootDir: string): Promise<TspLocation> {
3535

3636
// Normalize the directory path and remove trailing slash
3737
tspLocation.directory = normalizeDirectory(tspLocation.directory);
38-
tspLocation.additionalDirectories = tspLocation.additionalDirectories.map(normalizeDirectory);
38+
if (typeof tspLocation.additionalDirectories === "string") {
39+
tspLocation.additionalDirectories = [normalizeDirectory(tspLocation.additionalDirectories)];
40+
} else {
41+
// List of additional directories
42+
tspLocation.additionalDirectories =
43+
tspLocation.additionalDirectories.map(normalizeDirectory);
44+
}
3945

4046
return tspLocation;
4147
}
@@ -46,10 +52,9 @@ export async function readTspLocation(rootDir: string): Promise<TspLocation> {
4652
}
4753
}
4854

49-
5055
export async function getEmitterFromRepoConfig(emitterPath: string): Promise<string> {
5156
await access(emitterPath);
52-
const data = await readFile(emitterPath, 'utf8');
57+
const data = await readFile(emitterPath, "utf8");
5358
const obj = JSON.parse(data);
5459
if (!obj || !obj.dependencies) {
5560
throw new Error("Invalid emitter-package.json");
@@ -66,6 +71,6 @@ export async function getEmitterFromRepoConfig(emitterPath: string): Promise<str
6671
}
6772

6873
export function normalizeDirectory(directory: string): string {
69-
const normalizedDir = normalizePath(directory);
70-
return normalizedDir.endsWith("/") ? normalizedDir.slice(0, -1) : normalizedDir;
74+
const normalizedDir = normalizePath(directory);
75+
return normalizedDir.endsWith("/") ? normalizedDir.slice(0, -1) : normalizedDir;
7176
}

tools/tsp-client/src/index.ts

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ import { createTempDirectory, removeDirectory, readTspLocation, getEmitterFromRe
33
import { Logger, printBanner, enableDebug, printVersion } from "./log.js";
44
import { TspLocation, compileTsp, discoverMainFile, resolveTspConfigUrl } from "./typespec.js";
55
import { getOptions } from "./options.js";
6-
import { mkdir, writeFile, cp, readFile, stat, rename, unlink } from "node:fs/promises";
6+
import { mkdir, cp, readFile, stat, rename, unlink } from "node:fs/promises";
77
import { addSpecFiles, checkoutCommit, cloneRepo, getRepoRoot, sparseCheckout } from "./git.js";
88
import { doesFileExist } from "./network.js";
99
import { parse as parseYaml } from "yaml";
1010
import { joinPaths, normalizePath, resolvePath } from "@typespec/compiler";
11-
import { formatAdditionalDirectories, getAdditionalDirectoryName, getPathToDependency, getServiceDir, makeSparseSpecDir } from "./utils.js";
11+
import { getAdditionalDirectoryName, getPathToDependency, getServiceDir, makeSparseSpecDir, writeTspLocationYaml } from "./utils.js";
1212
import { resolve } from "node:path";
1313
import { config as dotenvConfig } from "dotenv";
1414

@@ -58,10 +58,13 @@ async function sdkInit(
5858
}
5959
const newPackageDir = joinPaths(outputDir, serviceDir, packageDir!)
6060
await mkdir(newPackageDir, { recursive: true });
61-
const additionalDirOutput = formatAdditionalDirectories(configYaml?.parameters?.dependencies?.additionalDirectories);
62-
await writeFile(
63-
joinPaths(newPackageDir, "tsp-location.yaml"),
64-
`directory: ${resolvedConfigUrl.path}\ncommit: ${resolvedConfigUrl.commit}\nrepo: ${resolvedConfigUrl.repo}\nadditionalDirectories:${additionalDirOutput}\n`);
61+
const tspLocationData: TspLocation = {
62+
directory: resolvedConfigUrl.path,
63+
commit: resolvedConfigUrl.commit,
64+
repo: resolvedConfigUrl.repo,
65+
additionalDirectories: configYaml?.parameters?.dependencies?.additionalDirectories,
66+
};
67+
await writeTspLocationYaml(tspLocationData, newPackageDir);
6568
Logger.debug(`Removing sparse-checkout directory ${cloneDir}`);
6669
await removeDirectory(cloneDir);
6770
return newPackageDir;
@@ -81,7 +84,6 @@ async function sdkInit(
8184
}
8285
const configYaml = parseYaml(data);
8386
const serviceDir = getServiceDir(configYaml, emitter);
84-
const additionalDirOutput = formatAdditionalDirectories(configYaml?.parameters?.dependencies?.additionalDirectories);
8587
const packageDir = configYaml?.options?.[emitter]?.["package-dir"];
8688
if (!packageDir) {
8789
throw new Error(`Missing package-dir in ${emitter} options of tspconfig.yaml. Please refer to https://github.com/Azure/azure-rest-api-specs/blob/main/specification/contosowidgetmanager/Contoso.WidgetManager/tspconfig.yaml for the right schema.`);
@@ -96,8 +98,13 @@ async function sdkInit(
9698
directory = matchRes.groups!["path"]!;
9799
}
98100
}
99-
writeFile(joinPaths(newPackageDir, "tsp-location.yaml"),
100-
`directory: ${directory}\ncommit: ${commit}\nrepo: ${repo}\nadditionalDirectories:${additionalDirOutput}\n`);
101+
const tspLocationData: TspLocation = {
102+
directory: directory,
103+
commit: commit ?? "",
104+
repo: repo ?? "",
105+
additionalDirectories: configYaml?.parameters?.dependencies?.additionalDirectories,
106+
};
107+
await writeTspLocationYaml(tspLocationData, newPackageDir);
101108
return newPackageDir;
102109
}
103110
}
@@ -321,13 +328,13 @@ async function main() {
321328
const tspLocation: TspLocation = await readTspLocation(rootUrl);
322329
tspLocation.commit = options.commit ?? tspLocation.commit;
323330
tspLocation.repo = options.repo ?? tspLocation.repo;
324-
await writeFile(joinPaths(rootUrl, "tsp-location.yaml"), `directory: ${tspLocation.directory}\ncommit: ${tspLocation.commit}\nrepo: ${tspLocation.repo}\nadditionalDirectories: ${tspLocation.additionalDirectories}`);
331+
await writeTspLocationYaml(tspLocation, rootUrl);
325332
} else if (options.tspConfig) {
326333
const tspLocation: TspLocation = await readTspLocation(rootUrl);
327334
const tspConfig = resolveTspConfigUrl(options.tspConfig);
328335
tspLocation.commit = tspConfig.commit ?? tspLocation.commit;
329336
tspLocation.repo = tspConfig.repo ?? tspLocation.repo;
330-
await writeFile(joinPaths(rootUrl, "tsp-location.yaml"), `directory: ${tspLocation.directory}\ncommit: ${tspLocation.commit}\nrepo: ${tspLocation.repo}\nadditionalDirectories: ${tspLocation.additionalDirectories}`);
337+
await writeTspLocationYaml(tspLocation, rootUrl);
331338
}
332339
await syncTspFiles(rootUrl, options.localSpecRepo);
333340
await generate({ rootUrl, noCleanup: options.noCleanup, additionalEmitterOptions: options.emitterOptions});

tools/tsp-client/src/utils.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { joinPaths, normalizeSlashes } from "@typespec/compiler";
22
import { randomUUID } from "node:crypto";
3-
import { access, constants, mkdir } from "node:fs/promises";
3+
import { access, constants, mkdir, writeFile } from "node:fs/promises";
44
import { dirname, join } from "node:path";
55
import { fileURLToPath } from "node:url";
66
import { Logger } from "./log.js";
7+
import { TspLocation } from "./typespec.js";
78

89
export function formatAdditionalDirectories(additionalDirectories?: string[]): string {
910
let additionalDirOutput = "";
@@ -77,3 +78,19 @@ export async function getPathToDependency(dependency: string): Promise<string> {
7778
}
7879
}
7980
}
81+
82+
/**
83+
* Writes tsp-location.yaml file at the given projectPath. Ensures additional directories are formatted correctly.
84+
*
85+
* @param tspLocation TspLocation object containing tsp location information.
86+
* @param projectPath Path to the project.
87+
*/
88+
export async function writeTspLocationYaml(
89+
tspLocation: TspLocation,
90+
projectPath: string,
91+
): Promise<void> {
92+
await writeFile(
93+
joinPaths(projectPath, "tsp-location.yaml"),
94+
`directory: ${tspLocation.directory}\ncommit: ${tspLocation.commit}\nrepo: ${tspLocation.repo}\nadditionalDirectories: ${formatAdditionalDirectories(tspLocation.additionalDirectories)}`,
95+
);
96+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
directory: specification/contosowidgetmanager/Contoso.WidgetManager
2+
commit: 1234567
3+
repo: foo
4+
additionalDirectories:
5+
- specification/contosowidgetmanager/Contoso.WidgetManager.Shared

tools/tsp-client/test/tspLocation.spec.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { assert } from "chai";
22
import { normalizeDirectory, readTspLocation } from "../src/fs.js";
33
import { describe, it } from "node:test";
4+
import { writeTspLocationYaml } from "../src/utils.js";
5+
import { stat } from "node:fs/promises";
46

5-
describe("Parse tsp-location.yaml", function () {
7+
describe("Verify tsp-location.yaml", function () {
68
it("Normalize tsp-location.yaml directories", async function () {
79
const tspLocation = await readTspLocation("./test/examples/sdk/badtsplocation");
810
const directory = normalizeDirectory(tspLocation.directory);
@@ -20,4 +22,32 @@ describe("Parse tsp-location.yaml", function () {
2022
);
2123
}
2224
});
25+
26+
it("Write tsp-location.yaml", async function () {
27+
const tspLocation = {
28+
directory: "specification/contosowidgetmanager/Contoso.WidgetManager",
29+
commit: "1234567",
30+
repo: "foo",
31+
additionalDirectories: [
32+
"specification/contosowidgetmanager/Contoso.WidgetManager.Shared",
33+
],
34+
};
35+
await writeTspLocationYaml(tspLocation, "./test/examples/");
36+
37+
const tspLocationFile = await stat("./test/examples/tsp-location.yaml");
38+
assert.isTrue(tspLocationFile.isFile());
39+
});
40+
41+
it("Verify read tsp-location.yaml", async function () {
42+
const tspLocation = await readTspLocation("./test/examples/");
43+
assert.equal(tspLocation.directory, "specification/contosowidgetmanager/Contoso.WidgetManager");
44+
assert.equal(tspLocation.commit, "1234567");
45+
assert.equal(tspLocation.repo, "foo");
46+
assert.typeOf(tspLocation.additionalDirectories, "array");
47+
assert.equal(tspLocation.additionalDirectories?.length, 1);
48+
assert.equal(
49+
tspLocation.additionalDirectories?.[0],
50+
"specification/contosowidgetmanager/Contoso.WidgetManager.Shared",
51+
);
52+
});
2353
});

0 commit comments

Comments
 (0)