Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate GitHub Actions summary #442

Merged
merged 5 commits into from
May 3, 2023
Merged
Show file tree
Hide file tree
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
8 changes: 7 additions & 1 deletion .github/workflows/update-dotnet-sdk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ on:
required: false
type: string
default: ''
generate-step-summary:
description: 'If true, will output a summary of any .NET SDK update to $GITHUB_STEP_SUMMARY.'
required: false
type: boolean
default: true
global-json-file:
description: 'The optional path to the global.json file to update.'
required: false
Expand Down Expand Up @@ -158,12 +163,13 @@ jobs:
# for the same release channel as the SDK specified in global.json.
- name: Update .NET SDK
id: update-dotnet-sdk
uses: martincostello/update-dotnet-sdk@bba9c5d796cf9e84046ae0cb42f7dd33bde568f3 # v2.1.4
uses: martincostello/update-dotnet-sdk@c2b0eab1ae1000f7f9b7357c85f0957ce54e0a21 # v2.2.0
with:
branch-name: ${{ inputs.branch-name }}
channel: ${{ inputs.channel }}
commit-message: ${{ inputs.commit-message }}
dry-run: ${{ inputs.dry-run }}
generate-step-summary: ${{ inputs.generate-step-summary }}
global-json-file: ${{ inputs.global-json-file }}
labels: ${{ inputs.labels }}
repo-token: ${{ steps.assign-token.outputs.access-token }}
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ jobs:
| `branch-name` | The optional Git branch name to use. | - |
| `channel` | The optional .NET release channel to download the SDK for (3.1, 6.0, etc.). | The channel derived from the current SDK version. |
| `commit-message` | The optional Git commit message to use. | - |
| `generate-step-summary` | If true, will output a summary of any .NET SDK update to `$GITHUB_STEP_SUMMARY`. | `true` |
| `global-json-file` | The optional path to the global.json file to update the SDK for. | `./global.json` |
| `labels` | The optional comma-separated label(s) to apply to Pull Requests generated by the action. | - |
| `user-email` | The optional email address to use for the Git commit. | `github-actions[bot]@users.noreply.github.com` |
Expand Down
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ inputs:
description: 'The optional Git commit message to use.'
required: false
default: ''
generate-step-summary:
description: 'If true, will output a summary of any .NET SDK update to $GITHUB_STEP_SUMMARY.'
required: false
default: true
global-json-file:
description: 'The optional path to the global.json file to update.'
required: false
Expand Down
4 changes: 2 additions & 2 deletions dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "update-dotnet-sdk",
"version": "2.1.5",
"version": "2.2.0",
"private": true,
"description": "A GitHub Action that updates the .NET SDK.",
"main": "lib/main.js",
Expand Down
51 changes: 48 additions & 3 deletions src/DotNetSdkUpdater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export class DotNetSdkUpdater {
return messageLines.join('\n');
}

public static generatePullRequestBody(update: SdkVersions, options: UpdateOptions): string {
public static generatePullRequestBody(update: SdkVersions, options: UpdateOptions, isGitHubEnterprise: boolean): string {
let body = `Updates the .NET SDK to version \`${update.latest.sdkVersion}\`, `;

if (update.latest.runtimeVersion === update.current.runtimeVersion) {
Expand All @@ -106,7 +106,7 @@ export class DotNetSdkUpdater {
if (update.security && update.securityIssues.length > 0) {
body += `\n\nThis release includes fixes for the following security issue(s):`;
for (const issue of update.securityIssues) {
body += `\n * [${issue.id}](${issue.url})`;
body += `\n- ${isGitHubEnterprise ? `[${issue.id}](${issue.url})` : issue.id}`;
}
}

Expand All @@ -115,6 +115,44 @@ export class DotNetSdkUpdater {
return body;
}

public static async generateSummary(update: SdkVersions, today: Date): Promise<string> {
const daysSinceRelease = Math.floor((today.getTime() - update.latest.releaseDate.getTime()) / (24 * 60 * 60 * 1000));
const daysUnit = daysSinceRelease === 1 ? 'day' : 'days';
const iso8601Date = update.latest.releaseDate.toISOString().split('T')[0];

let summary = core.summary
.addHeading(`.NET SDK ${update.latest.sdkVersion}`, 1)
.addRaw(`An update from version ${update.current.sdkVersion} to ${update.latest.sdkVersion} of the .NET SDK is available.`)
.addBreak()
.addBreak()
.addRaw(`This version of the .NET SDK was released on ${iso8601Date} (${daysSinceRelease} ${daysUnit} ago).`)
.addBreak()
.addBreak()
.addLink(`Release notes`, update.latest.releaseNotes);

if (update.security) {
summary = summary
.addHeading('Security Issues', 2)
.addRaw('This update includes fixes for the following security issues:')
.addBreak()
.addBreak()
.addList(
update.securityIssues.map((p) => p.id),
false
);
}

const result = summary.stringify();

if (process.env['GITHUB_STEP_SUMMARY']) {
await summary.write();
}

summary.emptyBuffer();

return result;
}

public async tryUpdateSdk(): Promise<UpdateResult> {
const globalJson: GlobalJson = JSON.parse(fs.readFileSync(this.options.globalJsonPath, { encoding: 'utf8' }));

Expand Down Expand Up @@ -166,6 +204,10 @@ export class DotNetSdkUpdater {
result.security = update.security;
result.updated = true;
result.version = update.latest.sdkVersion;

if (this.options.generateStepSummary) {
await DotNetSdkUpdater.generateSummary(update, new Date());
}
}
} else {
core.info('The current .NET SDK version is up-to-date');
Expand All @@ -176,7 +218,8 @@ export class DotNetSdkUpdater {

private async createPullRequest(base: string, update: SdkVersions): Promise<PullRequest> {
const title = `Update .NET SDK to ${update.latest.sdkVersion}`;
const body = DotNetSdkUpdater.generatePullRequestBody(update, this.options);
const isGitHubEnterprise = this.options.serverUrl !== 'https://github.com';
const body = DotNetSdkUpdater.generatePullRequestBody(update, this.options, isGitHubEnterprise);

const options = {
baseUrl: this.options.apiUrl,
Expand Down Expand Up @@ -327,6 +370,7 @@ export class DotNetSdkUpdater {
const release = releasesForSdk[0];

const result = {
releaseDate: new Date(release['release-date']),
releaseNotes: release['release-notes'],
runtimeVersion: release.runtime.version,
sdkVersion: foundSdk.version,
Expand Down Expand Up @@ -433,6 +477,7 @@ interface PullRequest {
}

interface ReleaseInfo {
releaseDate: Date;
releaseNotes: string;
runtimeVersion: string;
sdkVersion: string;
Expand Down
1 change: 1 addition & 0 deletions src/UpdateOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface UpdateOptions {
channel: string;
commitMessage: string;
dryRun: boolean;
generateStepSummary: boolean;
globalJsonPath: string;
labels: string;
repo?: string;
Expand Down
1 change: 1 addition & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export async function run(): Promise<void> {
channel: core.getInput('channel', { required: false }),
commitMessage: core.getInput('commit-message', { required: false }),
dryRun: core.getInput('dry-run', { required: false }) === 'true',
generateStepSummary: core.getInput('generate-step-summary', { required: false }) === 'true',
globalJsonPath,
labels: core.getInput('labels', { required: false }) ?? '',
repo: process.env.GITHUB_REPOSITORY,
Expand Down
28 changes: 25 additions & 3 deletions tests/DotNetSdkUpdater.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,10 @@ describe('DotNetSdkUpdater tests', () => {
expect(actual).toContain(`update-type: version-update:semver-${expected}`);
});

test('Sorts the CVEs in the pull request description', () => {
test.each([
[false, '\n- CVE-2022-41089\n- CVE-2023-21808'],
[true, '\n- [CVE-2022-41089](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-41089)\n- [CVE-2023-21808](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-21808)']
])('Sorts the CVEs in the pull request description', (isGitHubEnterprise, expected) => {
const channel = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'tests', 'releases-7.0.json'), {encoding: 'utf8'}));
const versions = updater.DotNetSdkUpdater.getLatestRelease('7.0.100', channel);
const options: UpdateOptions = {
Expand All @@ -192,12 +195,31 @@ describe('DotNetSdkUpdater tests', () => {
channel: '7.0',
commitMessage: '',
dryRun: false,
generateStepSummary: false,
globalJsonPath: '',
labels: '',
userEmail: '',
userName: '',
};
const actual = updater.DotNetSdkUpdater.generatePullRequestBody(versions, options);
expect(actual).toContain('\n * [CVE-2022-41089](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-41089)\n * [CVE-2023-21808](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-21808)');
const actual = updater.DotNetSdkUpdater.generatePullRequestBody(versions, options, isGitHubEnterprise);
expect(actual).toContain(expected);
});

test.each([
['3.1', '3.1.403', '2023-05-02', '3.1.404', '903 days'],
['5.0', '5.0.102', '2023-05-02', '5.0.200', '791 days'],
['6.0', '6.0.407', '2023-05-02', '6.0.408', '21 days'],
['7.0', '7.0.201', '2023-03-14', '7.0.202', '0 days'],
['7.0', '7.0.201', '2023-03-15', '7.0.202', '1 day'],
['7.0', '7.0.201', '2023-03-16', '7.0.202', '2 days'],
['7.0', '7.0.201', '2023-05-02', '7.0.202', '49 days'],
['8.0', '8.0.100-preview.2.23157.25', '2023-05-02', '8.0.100-preview.3.23178.7', '21 days']
])('Generates correct GitHub step summary for %s from %s on %s', async (channelVersion, sdkVersion, date, expectedSdkVersion, expectedDaysAgo) => {
const today = new Date(date);
const channel = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'tests', `releases-${channelVersion}.json`), {encoding: 'utf8'}));
const versions = updater.DotNetSdkUpdater.getLatestRelease(sdkVersion, channel);
const actual = await updater.DotNetSdkUpdater.generateSummary(versions, today);
expect(actual).toContain(`<h1>.NET SDK ${expectedSdkVersion}</h1>`);
expect(actual).toContain(`(${expectedDaysAgo} ago)`);
});
});
5 changes: 4 additions & 1 deletion tests/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ import {afterEach, beforeEach, describe, expect, jest, test} from '@jest/globals

const tempDir = path.join(os.tmpdir(), 'update-dotnet-sdk-temp');
const globalJsonPath = path.join(tempDir, 'global.json');
const githubStepSummary = path.join(tempDir, 'github-step-summary.md');

describe('update-dotnet-sdk tests', () => {
const inputs = {
'GITHUB_API_URL': 'https://github.local/api/v3',
'GITHUB_REPOSITORY': '',
'GITHUB_SERVER_URL': 'https://github.local',
'GITHUB_STEP_SUMMARY': githubStepSummary,
'INPUT_GLOBAL-JSON-FILE': globalJsonPath,
'INPUT_LABELS': 'foo,bar',
'INPUT_REPO-TOKEN': 'my-token',
Expand All @@ -42,7 +44,8 @@ describe('update-dotnet-sdk tests', () => {

afterEach(async () => {
try {
await io.rmRF(path.join(tempDir, 'global.json'));
await io.rmRF(globalJsonPath);
await io.rmRF(githubStepSummary);
await io.rmRF(tempDir);
} catch {
console.log('Failed to remove test directories');
Expand Down