Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 52 additions & 28 deletions tasks/tags/createTags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
*--------------------------------------------------------------------------------------------*/

import * as fs from 'fs';
import { spawnSync } from 'child_process';
import minimist from 'minimist';
import { Octokit } from '@octokit/rest';
import { allNugetPackages, NugetPackageInfo, platformSpecificPackages } from '../packaging/offlinePackagingTasks';
import { PlatformInformation } from '../../src/shared/platform';
import path from 'path';
import { runTask } from '../runTask';
import { rootPath } from '../projectPaths';

runTask(createTags);

Expand All @@ -34,8 +36,8 @@ async function createTagsRoslyn(): Promise<void> {
options,
'dotnet',
'roslyn',
async (releaseCommit: string, githubPAT: string) =>
getCommitFromNugetAsync(allNugetPackages.roslyn, releaseCommit, githubPAT),
async (releaseCommit: string, _githubPAT: string) =>
getCommitFromNugetAsync(allNugetPackages.roslyn, releaseCommit),
(releaseVersion: string, isPrerelease: boolean): [string, string] => {
const prereleaseText = isPrerelease ? '-prerelease' : '';
return [
Expand Down Expand Up @@ -183,32 +185,9 @@ function logError(message: string): void {
console.log(`##vso[task.logissue type=error]${message}`);
}

async function getCommitFromNugetAsync(
packageInfo: NugetPackageInfo,
releaseCommit: string,
githubPAT: string
): Promise<string | null> {
// Fetch package.json from dotnet/vscode-csharp GitHub repo at the specific commit
const packageJsonUrl = `https://raw.githubusercontent.com/dotnet/vscode-csharp/${releaseCommit}/package.json`;

console.log(`Fetching package.json from ${packageJsonUrl}`);

let packageJson: { defaults?: { [key: string]: string } };
try {
const response = await fetch(packageJsonUrl, {
headers: {
Authorization: `token ${githubPAT}`,
Accept: 'application/vnd.github.v3.raw',
},
});
if (!response.ok) {
logError(`Failed to fetch package.json from ${packageJsonUrl}: ${response.status} ${response.statusText}`);
return null;
}
const packageJsonString = await response.text();
packageJson = JSON.parse(packageJsonString);
} catch (error) {
logError(`Error fetching package.json from GitHub: ${error}`);
async function getCommitFromNugetAsync(packageInfo: NugetPackageInfo, releaseCommit: string): Promise<string | null> {
const packageJson = getPackageJsonFromReleaseCommit(releaseCommit);
if (!packageJson) {
return null;
}

Expand Down Expand Up @@ -258,3 +237,48 @@ async function getCommitFromNugetAsync(
console.log(`commitNumber is ${commitNumber}`);
return commitNumber;
}

function getPackageJsonFromReleaseCommit(releaseCommit: string): { defaults?: { [key: string]: string } } | null {
const packageJsonPath = 'package.json';

try {
// Read the committed package.json at the release commit directly from the local git object
// database. The release pipeline fetches full history (fetchDepth: 0) and checks out the
// release commit, so the object is always present. Reading the committed blob (rather than the
// working tree) ensures the tag references exactly what was released.
console.log(`Reading package.json from local git object ${releaseCommit}:${packageJsonPath}`);
const packageJsonString = getGitOutput(['show', `${releaseCommit}:${packageJsonPath}`]);
Comment thread
dibarbet marked this conversation as resolved.
if (!packageJsonString) {
logError(
`Failed to read package.json from local git commit ${releaseCommit}. Ensure the release commit is fetched or checked out.`
);
return null;
}

return JSON.parse(packageJsonString);
} catch (error) {
logError(`Error reading package.json for commit ${releaseCommit}: ${error}`);
return null;
}
}

function getGitOutput(args: string[]): string | null {
const gitCommand = `git ${args.join(' ')}`;
const cwd = rootPath;
const result = spawnSync('git', args, { encoding: 'utf8', cwd });

if (result.error) {
logError(`Failed to run '${gitCommand}' from '${cwd}': ${result.error.message}`);
return null;
}

if (result.status !== 0) {
const stderr = result.stderr.trim();
const stdout = result.stdout.trim();
const failureDetails = stderr || stdout || `Exited with status ${result.status}.`;
logError(`Command '${gitCommand}' failed from '${cwd}': ${failureDetails}`);
return null;
}

return result.stdout.trim();
}