Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7230886a12 |
@@ -1,79 +0,0 @@
|
||||
name: Bug Report - Language Service
|
||||
description: Create a bug report for IntelliSense, code editing, code navigation, code completion, code formatting, semantic colorization, etc.
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
### Is there an existing issue for this?
|
||||
Please search our [existing issues](https://github.com/microsoft/vscode-cpptools/issues) to see if an issue already exists for the bug you encountered.
|
||||
|
||||
Please also review our [documentation](https://code.visualstudio.com/docs/languages/cpp) and [FAQs](https://code.visualstudio.com/docs/cpp/faq-cpp).
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Environment
|
||||
description: |
|
||||
Please provide the information for the following:
|
||||
- OS and Version
|
||||
- VS Code Version
|
||||
- C/C++ Extension Version
|
||||
- If using SSH remote, specify OS of remote machine
|
||||
value: |
|
||||
- OS and Version:
|
||||
- VS Code Version:
|
||||
- C/C++ Extension Version:
|
||||
- If using SSH remote, specify OS of remote machine:
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Bug Summary and Steps to Reproduce
|
||||
description: |
|
||||
Please describe the language service issue or language service feature that is not working as expected. Include information about the actual workspace project (for example, is the workspace a single project or multiple projects, size of the project, etc).
|
||||
|
||||
Include clear steps on how to reproduce the issue and a description of what you expected to happen.
|
||||
value: |
|
||||
Bug Summary:
|
||||
|
||||
|
||||
Steps to reproduce:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
Expected behavior:
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Configuration and Logs
|
||||
description: |
|
||||
Please provide your c_cpp_properties.json and logs:
|
||||
- Configurations in `c_cpp_properties.json`
|
||||
- Logs from running `C/C++: Log Diagnostics` from the VS Code command palette
|
||||
- Logs from [the language server logging](https://code.visualstudio.com/docs/cpp/enable-logging-cpp#_enable-logging-for-the-language-server)
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Other Extensions
|
||||
description: If applicable, please list other extensions installed and if the issue persists after disabling other extensions.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: |
|
||||
Optionally provide other information that will give us more context about the issue you are encountering, such as code sample, screenshots, screen recording of the issue, call stacks, etc.
|
||||
|
||||
Providing call stacks:
|
||||
For bugs like crashes, deadlocks, infinite loops, etc. that we are not able to repro and for which the call stack may be useful, please attach a debugger and/or create a dmp and provide the call stacks. Windows binaries have symbols available in VS Code by setting your "symbolSearchPath" to "https://msdl.microsoft.com/download/symbols".
|
||||
|
||||
Instructions for attaching debugger to language service process:
|
||||
https://github.com/microsoft/vscode-cpptools/wiki/Attaching-debugger-to-cpptools-or-cpptools%E2%80%90srv.
|
||||
|
||||
Performance analysis:
|
||||
For a performance issue see instructions at https://github.com/microsoft/vscode-cpptools/wiki/Troubleshooting-Performance-Issues.
|
||||
validations:
|
||||
required: false
|
||||
@@ -1,78 +0,0 @@
|
||||
name: Bug Report - Debugger
|
||||
description: Create a bug report for debugging such as call stack, breakpoints, watch window, launching or attaching to a debuggee.
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
### Is there an existing issue for this?
|
||||
Please search our [existing issues](https://github.com/microsoft/vscode-cpptools/issues) to see if an issue already exists for the bug you encountered.
|
||||
|
||||
Please also review our [documentation](https://code.visualstudio.com/docs/languages/cpp) and [FAQs](https://code.visualstudio.com/docs/cpp/faq-cpp).
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Environment
|
||||
description: |
|
||||
Please provide the information for the following:
|
||||
- OS and version
|
||||
- VS Code version
|
||||
- C/C++ extension version
|
||||
- OS and version of remote machine (if applicable)
|
||||
- GDB / LLDB version
|
||||
value: |
|
||||
- OS and version:
|
||||
- VS Code:
|
||||
- C/C++ extension:
|
||||
- OS and version of remote machine (if applicable):
|
||||
- GDB / LLDB version:
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Bug Summary and Steps to Reproduce
|
||||
description: |
|
||||
Please describe the debugging issue or debugger feature that is not working as expected.
|
||||
|
||||
Include clear steps on how to reproduce the issue.
|
||||
value: |
|
||||
Bug Summary:
|
||||
|
||||
|
||||
Steps to reproduce:
|
||||
1. In this environment...
|
||||
2. With this config...
|
||||
3. Do '...'
|
||||
4. See error...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Debugger Configurations
|
||||
description: Please provide the debugger configurations from the **tasks.json** and **launch.json** files.
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Debugger Logs
|
||||
description: |
|
||||
If applicable, please include [logging for the debugger adapter](https://code.visualstudio.com/docs/cpp/enable-logging-cpp#_enable-logging-for-the-debug-adapter) by adding `"logging": { "engineLogging": true, "trace": true, "traceResponse": true }` in the **launch.json** file.
|
||||
|
||||
Include logs or error messages from the Debug Console or Output windows.
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Other Extensions
|
||||
description: If applicable, please list other extensions installed and if the issue persists after disabling other extensions.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional Information
|
||||
description: |
|
||||
Optionally provide other information that will give us more context about the issue you are encountering, such as a code sample, screenshots, or screen recording of the issue.
|
||||
|
||||
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
||||
validations:
|
||||
required: false
|
||||
@@ -1,15 +0,0 @@
|
||||
name: Feature Request
|
||||
description: Suggest an idea for the C/C++ extension.
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
### Is there an existing request for this feature?
|
||||
Prior to creating a new feature request, please review our [existing feature requests](https://github.com/microsoft/vscode-cpptools/issues?q=is%3Aopen+is%3Aissue+label%3A%22Feature+Request%22) to avoid duplicates.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Feature Request
|
||||
description: |
|
||||
Describe the feature you'd like.
|
||||
validations:
|
||||
required: true
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
name: Bug Report - Debugger
|
||||
about: Create a bug report for debugging such as call stack, breakpoints, watch window,
|
||||
launching or attaching to a debuggee.
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Bug type: Debugger
|
||||
|
||||
<!-- Prior to creating a bug report, please review:
|
||||
📝 Existing issues at https://github.com/Microsoft/vscode-cpptools/issues
|
||||
📜 Our documentation at https://code.visualstudio.com/docs/languages/cpp
|
||||
📙 FAQs at https://code.visualstudio.com/docs/cpp/faq-cpp
|
||||
-->
|
||||
|
||||
|
||||
**Describe the bug**
|
||||
- OS and Version:
|
||||
- VS Code Version:
|
||||
- C/C++ Extension Version:
|
||||
- Other extensions you installed (and if the issue persists after disabling them):
|
||||
- A clear and concise description of what the bug is.
|
||||
|
||||
|
||||
**To Reproduce**
|
||||
*Please include a code sample and `launch.json` configuration.*
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
|
||||
**Additional context**
|
||||
*If applicable, please include logging by adding "logging": { "engineLogging": true, "trace": true, "traceResponse": true } in your `launch.json`*
|
||||
Add any other context about the problem here including log or error messages in your Debug Console or Output windows.
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: Suggest an idea for this extension.
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Type: Feature Request
|
||||
|
||||
<!-- Prior to creating a feature request, please review
|
||||
existing issues at https://github.com/Microsoft/vscode-cpptools/issues
|
||||
to avoid creating duplicates.
|
||||
-->
|
||||
|
||||
<!-- Describe the feature you'd like. -->
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
name: Bug Report - General Extension
|
||||
about: Create a bug report for downloading, installing, or building the extension.
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Bug type: General
|
||||
|
||||
<!-- Prior to creating a bug report, please review:
|
||||
📝 Existing issues at https://github.com/Microsoft/vscode-cpptools/issues
|
||||
📜 Our documentation at https://code.visualstudio.com/docs/languages/cpp
|
||||
📙 FAQs at https://code.visualstudio.com/docs/cpp/faq-cpp
|
||||
-->
|
||||
|
||||
|
||||
**Describe the bug**
|
||||
- OS and Version:
|
||||
- VS Code Version:
|
||||
- C/C++ Extension Version:
|
||||
- Other extensions you installed (and if the issue persists after disabling them):
|
||||
- A clear and concise description of what the bug is.
|
||||
|
||||
|
||||
**To Reproduce**
|
||||
*Please include code sample and `task.json` files.*
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
|
||||
**Expected behavior**
|
||||
<!-- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
|
||||
**Screenshots**
|
||||
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||
|
||||
|
||||
**Additional context**
|
||||
<!-- Add any other context about the problem here including log messages from the Output window. -->
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
name: Bug Report - Language Service
|
||||
about: 'Create a bug report for IntelliSense, autocomplete, code editing, code navigation, etc.'
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Bug type: Language Service
|
||||
|
||||
<!-- Prior to creating a bug report, please review:
|
||||
📝 Existing issues at https://github.com/Microsoft/vscode-cpptools/issues
|
||||
📜 Our documentation at https://code.visualstudio.com/docs/languages/cpp
|
||||
📙 FAQs at https://code.visualstudio.com/docs/cpp/faq-cpp
|
||||
-->
|
||||
|
||||
|
||||
**Describe the bug**
|
||||
- OS and Version:
|
||||
- VS Code Version:
|
||||
- C/C++ Extension Version:
|
||||
- Other extensions you installed (and if the issue persists after disabling them):
|
||||
- If using SSH remote, specify OS of remote machine:
|
||||
- A clear and concise description of what the bug is, including information about the workspace (i.e. is the workspace a single project or multiple projects, size of the project, etc).
|
||||
|
||||
|
||||
**Steps to reproduce**
|
||||
<!-- Provide clear steps to reproduce the bug: -->
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
|
||||
**Expected behavior**
|
||||
<!-- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
|
||||
**Code sample and logs**
|
||||
<!-- Please provide code sample, your c_cpp_properties.json and logs. -->
|
||||
- Code sample
|
||||
|
||||
- Configurations in `c_cpp_properties.json`
|
||||
|
||||
- Logs from running `C/C++: Log Diagnostics` from the VS Code command palette
|
||||
|
||||
- Logs from [the language server logging](https://code.visualstudio.com/docs/cpp/enable-logging-cpp#_enable-logging-for-the-language-server)
|
||||
|
||||
|
||||
**Screenshots**
|
||||
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||
|
||||
|
||||
**Additional context**
|
||||
<!--
|
||||
Providing call stacks:
|
||||
For bugs like crashes, deadlocks, infinite loops, etc. that we are not able to repro and for which the call stack may be useful, please attach a debugger and/or create a dmp and provide the call stacks. Windows binaries have symbols available in VS Code by setting your "symbolSearchPath" to "https://msdl.microsoft.com/download/symbols".
|
||||
|
||||
Instructions for attaching debugger to language service process:
|
||||
https://github.com/microsoft/vscode-cpptools/wiki/Attaching-debugger-to-cpptools-or-cpptools%E2%80%90srv.
|
||||
|
||||
Performance analysis:
|
||||
For a performance issue see instructions at https://github.com/microsoft/vscode-cpptools/wiki/Troubleshooting-Performance-Issues.
|
||||
-->
|
||||
@@ -1,4 +0,0 @@
|
||||
registry=https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/
|
||||
always-auth=true
|
||||
# Disable postinstall scripts for supply chain security. Allowlist exceptions with npm trust: https://docs.npmjs.com/cli/v11/commands/npm-trust
|
||||
ignore-scripts=true
|
||||
@@ -1,86 +0,0 @@
|
||||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AddComment = void 0;
|
||||
const ActionBase_1 = require("../common/ActionBase");
|
||||
const utils_1 = require("../common/utils");
|
||||
class AddComment extends ActionBase_1.ActionBase {
|
||||
constructor(github, createdAfter, afterDays, labels, addComment, addLabels, removeLabels, setMilestoneId, milestoneName, milestoneId, ignoreLabels, ignoreMilestoneNames, ignoreMilestoneIds, minimumVotes, maximumVotes, involves) {
|
||||
super(labels, milestoneName, milestoneId, ignoreLabels, ignoreMilestoneNames, ignoreMilestoneIds, minimumVotes, maximumVotes, involves);
|
||||
this.github = github;
|
||||
this.createdAfter = createdAfter;
|
||||
this.afterDays = afterDays;
|
||||
this.addComment = addComment;
|
||||
this.addLabels = addLabels;
|
||||
this.removeLabels = removeLabels;
|
||||
this.setMilestoneId = setMilestoneId;
|
||||
}
|
||||
async run() {
|
||||
const updatedTimestamp = this.afterDays ? (0, utils_1.daysAgoToHumanReadbleDate)(this.afterDays) : undefined;
|
||||
const query = this.buildQuery((updatedTimestamp ? `updated:<${updatedTimestamp} ` : "") +
|
||||
(this.createdAfter ? `created:>${this.createdAfter} ` : "") +
|
||||
"is:open is:unlocked");
|
||||
const addLabelsSet = this.addLabels ? this.addLabels.split(',') : [];
|
||||
const removeLabelsSet = this.removeLabels ? this.removeLabels.split(',') : [];
|
||||
for await (const page of this.github.query({ q: query })) {
|
||||
for (const issue of page) {
|
||||
const hydrated = await issue.getIssue();
|
||||
if (hydrated.open && this.validateIssue(hydrated)
|
||||
// TODO: Verify updated timestamp
|
||||
) {
|
||||
// Don't add a comment if already commented on by an action.
|
||||
let foundActionComment = false;
|
||||
for await (const commentBatch of issue.getComments()) {
|
||||
for (const comment of commentBatch) {
|
||||
if (comment.author.isGitHubApp) {
|
||||
foundActionComment = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (foundActionComment)
|
||||
break;
|
||||
}
|
||||
if (foundActionComment) {
|
||||
(0, utils_1.safeLog)(`Issue ${hydrated.number} already commented on by an action. Ignoring.`);
|
||||
continue;
|
||||
}
|
||||
if (this.addComment) {
|
||||
(0, utils_1.safeLog)(`Posting comment on issue ${hydrated.number}`);
|
||||
await issue.postComment(this.addComment);
|
||||
}
|
||||
if (removeLabelsSet.length > 0) {
|
||||
for (const removeLabel of removeLabelsSet) {
|
||||
if (removeLabel && removeLabel.length > 0) {
|
||||
(0, utils_1.safeLog)(`Removing label on issue ${hydrated.number}: ${removeLabel}`);
|
||||
await issue.removeLabel(removeLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (addLabelsSet.length > 0) {
|
||||
for (const addLabel of addLabelsSet) {
|
||||
if (addLabel && addLabel.length > 0) {
|
||||
(0, utils_1.safeLog)(`Adding label on issue ${hydrated.number}: ${addLabel}`);
|
||||
await issue.addLabel(addLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.setMilestoneId != undefined) {
|
||||
(0, utils_1.safeLog)(`Setting milestone of issue ${hydrated.number} to id ${+this.setMilestoneId}`);
|
||||
await issue.setMilestone(+this.setMilestoneId);
|
||||
}
|
||||
(0, utils_1.safeLog)(`Processing issue ${hydrated.number}.`);
|
||||
}
|
||||
else {
|
||||
if (!hydrated.open) {
|
||||
(0, utils_1.safeLog)(`Issue ${hydrated.number} is not open. Ignoring`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.AddComment = AddComment;
|
||||
//# sourceMappingURL=AddComment.js.map
|
||||
@@ -1,98 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { GitHub } from '../api/api';
|
||||
import { ActionBase } from '../common/ActionBase';
|
||||
import { daysAgoToHumanReadbleDate, daysAgoToTimestamp, safeLog } from '../common/utils';
|
||||
|
||||
export class AddComment extends ActionBase {
|
||||
constructor(
|
||||
private github: GitHub,
|
||||
private createdAfter: string | undefined,
|
||||
private afterDays: number,
|
||||
labels: string,
|
||||
private addComment: string,
|
||||
private addLabels?: string,
|
||||
private removeLabels?: string,
|
||||
private setMilestoneId?: string,
|
||||
milestoneName?: string,
|
||||
milestoneId?: string,
|
||||
ignoreLabels?: string,
|
||||
ignoreMilestoneNames?: string,
|
||||
ignoreMilestoneIds?: string,
|
||||
minimumVotes?: number,
|
||||
maximumVotes?: number,
|
||||
involves?: string
|
||||
) {
|
||||
super(labels, milestoneName, milestoneId, ignoreLabels, ignoreMilestoneNames, ignoreMilestoneIds, minimumVotes, maximumVotes, involves);
|
||||
}
|
||||
|
||||
async run() {
|
||||
const updatedTimestamp = this.afterDays ? daysAgoToHumanReadbleDate(this.afterDays) : undefined;
|
||||
const query = this.buildQuery(
|
||||
(updatedTimestamp ? `updated:<${updatedTimestamp} ` : "") +
|
||||
(this.createdAfter ? `created:>${this.createdAfter} ` : "") +
|
||||
"is:open is:unlocked");
|
||||
|
||||
const addLabelsSet = this.addLabels ? this.addLabels.split(',') : [];
|
||||
const removeLabelsSet = this.removeLabels ? this.removeLabels.split(',') : [];
|
||||
|
||||
for await (const page of this.github.query({ q: query })) {
|
||||
for (const issue of page) {
|
||||
const hydrated = await issue.getIssue();
|
||||
if (hydrated.open && this.validateIssue(hydrated)
|
||||
// TODO: Verify updated timestamp
|
||||
) {
|
||||
// Don't add a comment if already commented on by an action.
|
||||
let foundActionComment = false;
|
||||
for await (const commentBatch of issue.getComments()) {
|
||||
for (const comment of commentBatch) {
|
||||
if (comment.author.isGitHubApp) {
|
||||
foundActionComment = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (foundActionComment)
|
||||
break;
|
||||
}
|
||||
if (foundActionComment) {
|
||||
safeLog(`Issue ${hydrated.number} already commented on by an action. Ignoring.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.addComment) {
|
||||
safeLog(`Posting comment on issue ${hydrated.number}`);
|
||||
await issue.postComment(this.addComment);
|
||||
}
|
||||
if (removeLabelsSet.length > 0) {
|
||||
for (const removeLabel of removeLabelsSet) {
|
||||
if (removeLabel && removeLabel.length > 0) {
|
||||
safeLog(`Removing label on issue ${hydrated.number}: ${removeLabel}`);
|
||||
await issue.removeLabel(removeLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (addLabelsSet.length > 0) {
|
||||
for (const addLabel of addLabelsSet) {
|
||||
if (addLabel && addLabel.length > 0) {
|
||||
safeLog(`Adding label on issue ${hydrated.number}: ${addLabel}`);
|
||||
await issue.addLabel(addLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.setMilestoneId != undefined) {
|
||||
safeLog(`Setting milestone of issue ${hydrated.number} to id ${+this.setMilestoneId}`);
|
||||
await issue.setMilestone(+this.setMilestoneId);
|
||||
}
|
||||
safeLog(`Processing issue ${hydrated.number}.`);
|
||||
} else {
|
||||
if (!hydrated.open) {
|
||||
safeLog(`Issue ${hydrated.number} is not open. Ignoring`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
name: Add Comment and Label
|
||||
description: Add comment (etc) to issues that are marked with a specified label (etc)
|
||||
inputs:
|
||||
token:
|
||||
description: GitHub token with issue, comment, and label read/write permissions
|
||||
default: ${{ github.token }}
|
||||
createdAfter:
|
||||
description: Creation date after which to be considered.
|
||||
required: false
|
||||
afterDays:
|
||||
description: Days to wait before performing this action (may be 0).
|
||||
required: false
|
||||
addComment:
|
||||
description: Comment to add
|
||||
labels:
|
||||
description: items with these labels will be considered. May be "*".
|
||||
required: true
|
||||
milestoneName:
|
||||
description: items with these milestones will be considered (name only, must match ID)
|
||||
milestoneId:
|
||||
description: items with these milestones will be considered (id only, must match name)
|
||||
ignoreLabels:
|
||||
description: items with these labels will not be considered
|
||||
ignoreMilestoneNames:
|
||||
description: items with these milestones will not be considered (names only, must match IDs). May be "*".
|
||||
ignoreMilestoneIds:
|
||||
description: items with these milestones will not be considered (IDs only, must match names)
|
||||
addLabels:
|
||||
description: Labels to add to issue.
|
||||
removeLabels:
|
||||
description: Labels to remove from issue.
|
||||
minimumVotes:
|
||||
descriptions: Only issues with at least this many votes will be considered.
|
||||
maximumVotes:
|
||||
descriptions: Only issues fewer or equal to this many votes will be considered.
|
||||
involves:
|
||||
descriptions: Qualifier to find issues that in some way involve a certain user either as an author, assignee, or mentions.
|
||||
readonly:
|
||||
description: If true, changes are not applied.
|
||||
runs:
|
||||
using: 'node24'
|
||||
main: 'index.js'
|
||||
@@ -1,20 +0,0 @@
|
||||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const utils_1 = require("../common/utils");
|
||||
const AddComment_1 = require("./AddComment");
|
||||
const Action_1 = require("../common/Action");
|
||||
class AddCommentAction extends Action_1.Action {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.id = 'AddComment';
|
||||
}
|
||||
async onTriggered(github) {
|
||||
await new AddComment_1.AddComment(github, (0, utils_1.getInput)('createdAfter') || undefined, +((0, utils_1.getInput)('afterDays') || 0), (0, utils_1.getRequiredInput)('labels'), (0, utils_1.getInput)('addComment') || '', (0, utils_1.getInput)('addLabels') || undefined, (0, utils_1.getInput)('removeLabels') || undefined, (0, utils_1.getInput)('setMilestoneId') || undefined, (0, utils_1.getInput)('milestoneName') || undefined, (0, utils_1.getInput)('milestoneId') || undefined, (0, utils_1.getInput)('ignoreLabels') || undefined, (0, utils_1.getInput)('ignoreMilestoneNames') || undefined, (0, utils_1.getInput)('ignoreMilestoneIds') || undefined, +((0, utils_1.getInput)('minimumVotes') || 0), +((0, utils_1.getInput)('maximumVotes') || 9999999), (0, utils_1.getInput)('involves') || undefined).run();
|
||||
}
|
||||
}
|
||||
new AddCommentAction().run(); // eslint-disable-line
|
||||
//# sourceMappingURL=index.js.map
|
||||
@@ -1,36 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { OctoKit } from '../api/octokit'
|
||||
import { getInput, getRequiredInput } from '../common/utils'
|
||||
import { AddComment } from './AddComment'
|
||||
import { Action } from '../common/Action'
|
||||
|
||||
class AddCommentAction extends Action {
|
||||
id = 'AddComment';
|
||||
|
||||
async onTriggered(github: OctoKit) {
|
||||
await new AddComment(
|
||||
github,
|
||||
getInput('createdAfter') || undefined,
|
||||
+(getInput('afterDays') || 0),
|
||||
getRequiredInput('labels'),
|
||||
getInput('addComment') || '',
|
||||
getInput('addLabels') || undefined,
|
||||
getInput('removeLabels') || undefined,
|
||||
getInput('setMilestoneId') || undefined,
|
||||
getInput('milestoneName') || undefined,
|
||||
getInput('milestoneId') || undefined,
|
||||
getInput('ignoreLabels') || undefined,
|
||||
getInput('ignoreMilestoneNames') || undefined,
|
||||
getInput('ignoreMilestoneIds') || undefined,
|
||||
+(getInput('minimumVotes') || 0),
|
||||
+(getInput('maximumVotes') || 9999999),
|
||||
getInput('involves') || undefined
|
||||
).run();
|
||||
}
|
||||
}
|
||||
|
||||
new AddCommentAction().run(); // eslint-disable-line
|
||||
@@ -15,8 +15,8 @@ class Locker extends ActionBase_1.ActionBase {
|
||||
this.daysSinceUpdate = daysSinceUpdate;
|
||||
}
|
||||
async run() {
|
||||
const closedTimestamp = (0, utils_1.daysAgoToHumanReadbleDate)(this.daysSinceClose);
|
||||
const updatedTimestamp = (0, utils_1.daysAgoToHumanReadbleDate)(this.daysSinceUpdate);
|
||||
const closedTimestamp = utils_1.daysAgoToHumanReadbleDate(this.daysSinceClose);
|
||||
const updatedTimestamp = utils_1.daysAgoToHumanReadbleDate(this.daysSinceUpdate);
|
||||
const query = this.buildQuery((this.daysSinceClose ? `closed:<${closedTimestamp} ` : "") + (this.daysSinceUpdate ? `updated:<${updatedTimestamp} ` : "") + "is:closed is:unlocked");
|
||||
for await (const page of this.github.query({ q: query })) {
|
||||
await Promise.all(page.map(async (issue) => {
|
||||
@@ -24,15 +24,15 @@ class Locker extends ActionBase_1.ActionBase {
|
||||
if (!hydrated.locked && hydrated.open === false && this.validateIssue(hydrated)
|
||||
// TODO: Verify closed and updated timestamps
|
||||
) {
|
||||
(0, utils_1.safeLog)(`Locking issue ${hydrated.number}`);
|
||||
console.log(`Locking issue ${hydrated.number}`);
|
||||
await issue.lockIssue();
|
||||
}
|
||||
else {
|
||||
if (hydrated.locked) {
|
||||
(0, utils_1.safeLog)(`Issue ${hydrated.number} is already locked. Ignoring`);
|
||||
console.log(`Issue ${hydrated.number} is already locked. Ignoring`);
|
||||
}
|
||||
else if (hydrated.open) {
|
||||
(0, utils_1.safeLog)(`Issue ${hydrated.number} is open. Ignoring`);
|
||||
console.log(`Issue ${hydrated.number} is open. Ignoring`);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { GitHub, Issue } from '../api/api';
|
||||
import { daysAgoToHumanReadbleDate, safeLog } from '../common/utils';
|
||||
import { ActionBase } from '../common/ActionBase';
|
||||
import { GitHub, Issue } from '../api/api'
|
||||
import { daysAgoToHumanReadbleDate } from '../common/utils'
|
||||
import { ActionBase } from '../common/ActionBase'
|
||||
|
||||
export class Locker extends ActionBase {
|
||||
constructor(
|
||||
@@ -26,26 +26,26 @@ export class Locker extends ActionBase {
|
||||
}
|
||||
|
||||
async run() {
|
||||
const closedTimestamp = daysAgoToHumanReadbleDate(this.daysSinceClose);
|
||||
const updatedTimestamp = daysAgoToHumanReadbleDate(this.daysSinceUpdate);
|
||||
const closedTimestamp = daysAgoToHumanReadbleDate(this.daysSinceClose)
|
||||
const updatedTimestamp = daysAgoToHumanReadbleDate(this.daysSinceUpdate)
|
||||
|
||||
const query = this.buildQuery((this.daysSinceClose ? `closed:<${closedTimestamp} ` : "") + (this.daysSinceUpdate ? `updated:<${updatedTimestamp} ` : "") + "is:closed is:unlocked");
|
||||
|
||||
for await (const page of this.github.query({ q: query })) {
|
||||
await Promise.all(
|
||||
page.map(async (issue) => {
|
||||
const hydrated = await issue.getIssue();
|
||||
const hydrated = await issue.getIssue()
|
||||
|
||||
if (!hydrated.locked && hydrated.open === false && this.validateIssue(hydrated)
|
||||
// TODO: Verify closed and updated timestamps
|
||||
) {
|
||||
safeLog(`Locking issue ${hydrated.number}`);
|
||||
await issue.lockIssue();
|
||||
console.log(`Locking issue ${hydrated.number}`)
|
||||
await issue.lockIssue()
|
||||
} else {
|
||||
if (hydrated.locked) {
|
||||
safeLog(`Issue ${hydrated.number} is already locked. Ignoring`);
|
||||
console.log(`Issue ${hydrated.number} is already locked. Ignoring`)
|
||||
} else if (hydrated.open) {
|
||||
safeLog(`Issue ${hydrated.number} is open. Ignoring`);
|
||||
console.log(`Issue ${hydrated.number} is open. Ignoring`)
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -15,7 +15,7 @@ inputs:
|
||||
milestoneId:
|
||||
description: items with these milestones will be considered (id only, must match name)
|
||||
labels:
|
||||
description: items with these labels will be considered. May be "*".
|
||||
description: items with these labels will not be considered. May be "*".
|
||||
ignoreMilestoneNames:
|
||||
description: items with these milestones will not be considered (names only, must match IDs). May be "*".
|
||||
ignoreMilestoneIds:
|
||||
@@ -29,5 +29,5 @@ inputs:
|
||||
readonly:
|
||||
description: If true, changes are not applied.
|
||||
runs:
|
||||
using: 'node24'
|
||||
using: 'node12'
|
||||
main: 'index.js'
|
||||
|
||||
@@ -13,7 +13,7 @@ class LockerAction extends Action_1.Action {
|
||||
this.id = 'Locker';
|
||||
}
|
||||
async onTriggered(github) {
|
||||
await new Locker_1.Locker(github, +(0, utils_1.getRequiredInput)('daysSinceClose'), +(0, utils_1.getRequiredInput)('daysSinceUpdate'), (0, utils_1.getInput)('labels') || undefined, (0, utils_1.getInput)('milestoneName') || undefined, (0, utils_1.getInput)('milestoneId') || undefined, (0, utils_1.getInput)('ignoreLabels') || undefined, (0, utils_1.getInput)('ignoreMilestoneNames') || undefined, (0, utils_1.getInput)('ignoreMilestoneIds') || undefined, +((0, utils_1.getInput)('minimumVotes') || 0), +((0, utils_1.getInput)('maximumVotes') || 9999999)).run();
|
||||
await new Locker_1.Locker(github, +utils_1.getRequiredInput('daysSinceClose'), +utils_1.getRequiredInput('daysSinceUpdate'), utils_1.getInput('labels') || undefined, utils_1.getInput('milestoneName') || undefined, utils_1.getInput('milestoneId') || undefined, utils_1.getInput('ignoreLabels') || undefined, utils_1.getInput('ignoreMilestoneNames') || undefined, utils_1.getInput('ignoreMilestoneIds') || undefined, +(utils_1.getInput('minimumVotes') || 0), +(utils_1.getInput('maximumVotes') || 9999999)).run();
|
||||
}
|
||||
}
|
||||
new LockerAction().run(); // eslint-disable-line
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { OctoKit } from '../api/octokit';
|
||||
import { getInput, getRequiredInput } from '../common/utils';
|
||||
import { Locker } from './Locker';
|
||||
import { Action } from '../common/Action';
|
||||
import { OctoKit } from '../api/octokit'
|
||||
import { getInput, getRequiredInput } from '../common/utils'
|
||||
import { Locker } from './Locker'
|
||||
import { Action } from '../common/Action'
|
||||
|
||||
class LockerAction extends Action {
|
||||
id = 'Locker';
|
||||
id = 'Locker'
|
||||
|
||||
async onTriggered(github: OctoKit) {
|
||||
await new Locker(
|
||||
@@ -24,8 +24,8 @@ class LockerAction extends Action {
|
||||
getInput('ignoreMilestoneIds') || undefined,
|
||||
+(getInput('minimumVotes') || 0),
|
||||
+(getInput('maximumVotes') || 9999999)
|
||||
).run();
|
||||
).run()
|
||||
}
|
||||
}
|
||||
|
||||
new LockerAction().run(); // eslint-disable-line
|
||||
new LockerAction().run() // eslint-disable-line
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Reopener = void 0;
|
||||
const utils_1 = require("../common/utils");
|
||||
const ActionBase_1 = require("../common/ActionBase");
|
||||
class Reopener extends ActionBase_1.ActionBase {
|
||||
constructor(github, alsoApplyToOpenIssues, addLabels, removeLabels, reopenComment, setMilestoneId, labels, milestoneName, milestoneId, ignoreLabels, ignoreMilestoneNames, ignoreMilestoneIds, minimumVotes, maximumVotes) {
|
||||
@@ -20,7 +19,7 @@ class Reopener extends ActionBase_1.ActionBase {
|
||||
async run() {
|
||||
const addLabelsSet = this.addLabels ? this.addLabels.split(',') : [];
|
||||
const removeLabelsSet = this.removeLabels ? this.removeLabels.split(',') : [];
|
||||
(0, utils_1.safeLog)(`alsoApplyToOpenIssues: ${this.alsoApplyToOpenIssues}`);
|
||||
console.log(`alsoApplyToOpenIssues: ${this.alsoApplyToOpenIssues}`);
|
||||
const query = this.buildQuery((this.alsoApplyToOpenIssues ? "" : "is:closed ") + "is:unlocked");
|
||||
for await (const page of this.github.query({ q: query })) {
|
||||
await Promise.all(page.map(async (issue) => {
|
||||
@@ -29,17 +28,17 @@ class Reopener extends ActionBase_1.ActionBase {
|
||||
// TODO: Verify closed and updated timestamps
|
||||
) {
|
||||
if (hydrated.open === false) {
|
||||
(0, utils_1.safeLog)(`Reopening issue ${hydrated.number}`);
|
||||
console.log(`Reopening issue ${hydrated.number}`);
|
||||
await issue.reopenIssue();
|
||||
}
|
||||
if (this.setMilestoneId != undefined) {
|
||||
(0, utils_1.safeLog)(`Setting milestone of issue ${hydrated.number} to id ${+this.setMilestoneId}`);
|
||||
console.log(`Setting milestone of issue ${hydrated.number} to id ${+this.setMilestoneId}`);
|
||||
await issue.setMilestone(+this.setMilestoneId);
|
||||
}
|
||||
if (removeLabelsSet.length > 0) {
|
||||
for (const removeLabel of removeLabelsSet) {
|
||||
if (removeLabel && removeLabel.length > 0) {
|
||||
(0, utils_1.safeLog)(`Removing label on issue ${hydrated.number}: ${removeLabel}`);
|
||||
console.log(`Removing label on issue ${hydrated.number}: ${removeLabel}`);
|
||||
await issue.removeLabel(removeLabel);
|
||||
}
|
||||
}
|
||||
@@ -47,22 +46,22 @@ class Reopener extends ActionBase_1.ActionBase {
|
||||
if (addLabelsSet.length > 0) {
|
||||
for (const addLabel of addLabelsSet) {
|
||||
if (addLabel && addLabel.length > 0) {
|
||||
(0, utils_1.safeLog)(`Adding label on issue ${hydrated.number}: ${addLabel}`);
|
||||
console.log(`Adding label on issue ${hydrated.number}: ${addLabel}`);
|
||||
await issue.addLabel(addLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.reopenComment) {
|
||||
(0, utils_1.safeLog)(`Posting comment to issue ${hydrated.number}.`);
|
||||
console.log(`Posting comment to issue ${hydrated.number}.`);
|
||||
await issue.postComment(this.reopenComment);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (hydrated.locked) {
|
||||
(0, utils_1.safeLog)(`Issue ${hydrated.number} is locked. Ignoring`);
|
||||
console.log(`Issue ${hydrated.number} is locked. Ignoring`);
|
||||
}
|
||||
else if (!this.alsoApplyToOpenIssues && hydrated.open) {
|
||||
(0, utils_1.safeLog)(`Issue ${hydrated.number} is open. Ignoring`);
|
||||
console.log(`Issue ${hydrated.number} is open. Ignoring`);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { GitHub, Issue } from '../api/api';
|
||||
import { daysAgoToHumanReadbleDate, safeLog } from '../common/utils';
|
||||
import { ActionBase } from '../common/ActionBase';
|
||||
import { GitHub, Issue } from '../api/api'
|
||||
import { ActionBase } from '../common/ActionBase'
|
||||
|
||||
export class Reopener extends ActionBase {
|
||||
constructor(
|
||||
@@ -32,50 +31,50 @@ export class Reopener extends ActionBase {
|
||||
const addLabelsSet = this.addLabels ? this.addLabels.split(',') : [];
|
||||
const removeLabelsSet = this.removeLabels ? this.removeLabels.split(',') : [];
|
||||
|
||||
safeLog(`alsoApplyToOpenIssues: ${this.alsoApplyToOpenIssues}`);
|
||||
console.log(`alsoApplyToOpenIssues: ${this.alsoApplyToOpenIssues}`);
|
||||
|
||||
const query = this.buildQuery((this.alsoApplyToOpenIssues ? "": "is:closed ") + "is:unlocked");
|
||||
|
||||
for await (const page of this.github.query({ q: query })) {
|
||||
await Promise.all(
|
||||
page.map(async (issue) => {
|
||||
const hydrated = await issue.getIssue();
|
||||
const hydrated = await issue.getIssue()
|
||||
if (!hydrated.locked && (this.alsoApplyToOpenIssues || hydrated.open === false) && this.validateIssue(hydrated)
|
||||
// TODO: Verify closed and updated timestamps
|
||||
) {
|
||||
if (hydrated.open === false) {
|
||||
safeLog(`Reopening issue ${hydrated.number}`);
|
||||
await issue.reopenIssue();
|
||||
console.log(`Reopening issue ${hydrated.number}`)
|
||||
await issue.reopenIssue()
|
||||
}
|
||||
if (this.setMilestoneId != undefined) {
|
||||
safeLog(`Setting milestone of issue ${hydrated.number} to id ${+this.setMilestoneId}`);
|
||||
await issue.setMilestone(+this.setMilestoneId);
|
||||
console.log(`Setting milestone of issue ${hydrated.number} to id ${+this.setMilestoneId}`)
|
||||
await issue.setMilestone(+this.setMilestoneId)
|
||||
}
|
||||
if (removeLabelsSet.length > 0) {
|
||||
for (const removeLabel of removeLabelsSet) {
|
||||
if (removeLabel && removeLabel.length > 0) {
|
||||
safeLog(`Removing label on issue ${hydrated.number}: ${removeLabel}`);
|
||||
await issue.removeLabel(removeLabel);
|
||||
console.log(`Removing label on issue ${hydrated.number}: ${removeLabel}`)
|
||||
await issue.removeLabel(removeLabel)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (addLabelsSet.length > 0) {
|
||||
for (const addLabel of addLabelsSet) {
|
||||
if (addLabel && addLabel.length > 0) {
|
||||
safeLog(`Adding label on issue ${hydrated.number}: ${addLabel}`);
|
||||
await issue.addLabel(addLabel);
|
||||
console.log(`Adding label on issue ${hydrated.number}: ${addLabel}`)
|
||||
await issue.addLabel(addLabel)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.reopenComment) {
|
||||
safeLog(`Posting comment to issue ${hydrated.number}.`);
|
||||
await issue.postComment(this.reopenComment);
|
||||
console.log(`Posting comment to issue ${hydrated.number}.`)
|
||||
await issue.postComment(this.reopenComment)
|
||||
}
|
||||
} else {
|
||||
if (hydrated.locked) {
|
||||
safeLog(`Issue ${hydrated.number} is locked. Ignoring`);
|
||||
console.log(`Issue ${hydrated.number} is locked. Ignoring`)
|
||||
} else if (!this.alsoApplyToOpenIssues && hydrated.open) {
|
||||
safeLog(`Issue ${hydrated.number} is open. Ignoring`);
|
||||
console.log(`Issue ${hydrated.number} is open. Ignoring`)
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -19,7 +19,7 @@ inputs:
|
||||
milestoneId:
|
||||
description: items with these milestones will be considered (id only, must match name)
|
||||
labels:
|
||||
description: items with these labels will be considered. May be "*".
|
||||
description: items with these labels will not be considered. May be "*".
|
||||
ignoreMilestoneNames:
|
||||
description: items with these milestones will not be considered (names only, must match IDs). May be "*".
|
||||
ignoreMilestoneIds:
|
||||
@@ -33,5 +33,5 @@ inputs:
|
||||
readonly:
|
||||
description: If true, changes are not applied.
|
||||
runs:
|
||||
using: 'node24'
|
||||
using: 'node12'
|
||||
main: 'index.js'
|
||||
|
||||
@@ -10,11 +10,11 @@ const Action_1 = require("../common/Action");
|
||||
class ReopenerAction extends Action_1.Action {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.id = 'Reopener';
|
||||
this.id = 'Locker';
|
||||
}
|
||||
async onTriggered(github) {
|
||||
const alsoApplyToOpenIssues = (0, utils_1.getInput)('alsoApplyToOpenIssues');
|
||||
await new Reopener_1.Reopener(github, alsoApplyToOpenIssues != undefined && alsoApplyToOpenIssues.toLowerCase() == 'true', (0, utils_1.getInput)('addLabels') || undefined, (0, utils_1.getInput)('removeLabels') || undefined, (0, utils_1.getInput)('reopenComment') || '', (0, utils_1.getInput)('setMilestoneId') || undefined, (0, utils_1.getInput)('labels') || undefined, (0, utils_1.getInput)('milestoneName') || undefined, (0, utils_1.getInput)('milestoneId') || undefined, (0, utils_1.getInput)('ignoreLabels') || undefined, (0, utils_1.getInput)('ignoreMilestoneNames') || undefined, (0, utils_1.getInput)('ignoreMilestoneIds') || undefined, +((0, utils_1.getInput)('minimumVotes') || 0), +((0, utils_1.getInput)('maximumVotes') || 9999999)).run();
|
||||
const alsoApplyToOpenIssues = utils_1.getInput('alsoApplyToOpenIssues');
|
||||
await new Reopener_1.Reopener(github, alsoApplyToOpenIssues != undefined && alsoApplyToOpenIssues.toLowerCase() == 'true', utils_1.getInput('addLabels') || undefined, utils_1.getInput('removeLabels') || undefined, utils_1.getInput('reopenComment') || '', utils_1.getInput('setMilestoneId') || undefined, utils_1.getInput('labels') || undefined, utils_1.getInput('milestoneName') || undefined, utils_1.getInput('milestoneId') || undefined, utils_1.getInput('ignoreLabels') || undefined, utils_1.getInput('ignoreMilestoneNames') || undefined, utils_1.getInput('ignoreMilestoneIds') || undefined, +(utils_1.getInput('minimumVotes') || 0), +(utils_1.getInput('maximumVotes') || 9999999)).run();
|
||||
}
|
||||
}
|
||||
new ReopenerAction().run(); // eslint-disable-line
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { OctoKit } from '../api/octokit';
|
||||
import { getInput, getRequiredInput } from '../common/utils';
|
||||
import { Reopener } from './Reopener';
|
||||
import { Action } from '../common/Action';
|
||||
import { OctoKit } from '../api/octokit'
|
||||
import { getInput, getRequiredInput } from '../common/utils'
|
||||
import { Reopener } from './Reopener'
|
||||
import { Action } from '../common/Action'
|
||||
|
||||
class ReopenerAction extends Action {
|
||||
id = 'Reopener';
|
||||
id = 'Locker'
|
||||
|
||||
async onTriggered(github: OctoKit) {
|
||||
const alsoApplyToOpenIssues: string | undefined = getInput('alsoApplyToOpenIssues');
|
||||
@@ -28,8 +28,8 @@ class ReopenerAction extends Action {
|
||||
getInput('ignoreMilestoneIds') || undefined,
|
||||
+(getInput('minimumVotes') || 0),
|
||||
+(getInput('maximumVotes') || 9999999)
|
||||
).run();
|
||||
).run()
|
||||
}
|
||||
}
|
||||
|
||||
new ReopenerAction().run(); // eslint-disable-line
|
||||
new ReopenerAction().run() // eslint-disable-line
|
||||
|
||||
@@ -1,106 +1,106 @@
|
||||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.StaleCloser = void 0;
|
||||
const ActionBase_1 = require("../common/ActionBase");
|
||||
const utils_1 = require("../common/utils");
|
||||
class StaleCloser extends ActionBase_1.ActionBase {
|
||||
constructor(github, closeDays, labels, closeComment, pingDays, pingComment, additionalTeam, addLabels, removeLabels, setMilestoneId, milestoneName, milestoneId, ignoreLabels, ignoreMilestoneNames, ignoreMilestoneIds, minimumVotes, maximumVotes, involves) {
|
||||
super(labels, milestoneName, milestoneId, ignoreLabels, ignoreMilestoneNames, ignoreMilestoneIds, minimumVotes, maximumVotes, involves);
|
||||
this.github = github;
|
||||
this.closeDays = closeDays;
|
||||
this.closeComment = closeComment;
|
||||
this.pingDays = pingDays;
|
||||
this.pingComment = pingComment;
|
||||
this.additionalTeam = additionalTeam;
|
||||
this.addLabels = addLabels;
|
||||
this.removeLabels = removeLabels;
|
||||
this.setMilestoneId = setMilestoneId;
|
||||
}
|
||||
async run() {
|
||||
const updatedTimestamp = this.closeDays ? (0, utils_1.daysAgoToHumanReadbleDate)(this.closeDays) : undefined;
|
||||
const pingTimestamp = this.pingDays ? (0, utils_1.daysAgoToTimestamp)(this.pingDays) : undefined;
|
||||
const query = this.buildQuery((updatedTimestamp ? `updated:<${updatedTimestamp} ` : "") + "is:open is:unlocked");
|
||||
const addLabelsSet = this.addLabels ? this.addLabels.split(',') : [];
|
||||
const removeLabelsSet = this.removeLabels ? this.removeLabels.split(',') : [];
|
||||
for await (const page of this.github.query({ q: query })) {
|
||||
for (const issue of page) {
|
||||
const hydrated = await issue.getIssue();
|
||||
const lastCommentIterator = await issue.getComments(true).next();
|
||||
if (lastCommentIterator.done) {
|
||||
throw Error('Unexpected comment data');
|
||||
}
|
||||
const lastComment = lastCommentIterator.value[0];
|
||||
if (hydrated.open && this.validateIssue(hydrated)
|
||||
// TODO: Verify updated timestamp
|
||||
) {
|
||||
if (!lastComment ||
|
||||
lastComment.author.isGitHubApp ||
|
||||
pingTimestamp == undefined ||
|
||||
// TODO: List the collaborators once per go rather than checking a single user each issue
|
||||
this.additionalTeam.includes(lastComment.author.name) ||
|
||||
await issue.hasWriteAccess(lastComment.author)) {
|
||||
if (pingTimestamp != undefined) {
|
||||
if (lastComment) {
|
||||
(0, utils_1.safeLog)(`Last comment on issue ${hydrated.number} by ${lastComment.author.name}. Closing.`);
|
||||
}
|
||||
else {
|
||||
(0, utils_1.safeLog)(`No comments on issue ${hydrated.number}. Closing.`);
|
||||
}
|
||||
}
|
||||
if (this.closeComment) {
|
||||
(0, utils_1.safeLog)(`Posting comment on issue ${hydrated.number}`);
|
||||
await issue.postComment(this.closeComment);
|
||||
}
|
||||
if (removeLabelsSet.length > 0) {
|
||||
for (const removeLabel of removeLabelsSet) {
|
||||
if (removeLabel && removeLabel.length > 0) {
|
||||
(0, utils_1.safeLog)(`Removing label on issue ${hydrated.number}: ${removeLabel}`);
|
||||
await issue.removeLabel(removeLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (addLabelsSet.length > 0) {
|
||||
for (const addLabel of addLabelsSet) {
|
||||
if (addLabel && addLabel.length > 0) {
|
||||
(0, utils_1.safeLog)(`Adding label on issue ${hydrated.number}: ${addLabel}`);
|
||||
await issue.addLabel(addLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
await issue.closeIssue("not_planned");
|
||||
if (this.setMilestoneId != undefined) {
|
||||
(0, utils_1.safeLog)(`Setting milestone of issue ${hydrated.number} to id ${+this.setMilestoneId}`);
|
||||
await issue.setMilestone(+this.setMilestoneId);
|
||||
}
|
||||
(0, utils_1.safeLog)(`Closing issue ${hydrated.number}.`);
|
||||
}
|
||||
else {
|
||||
// Ping
|
||||
if (hydrated.updatedAt < pingTimestamp && hydrated.assignee) {
|
||||
(0, utils_1.safeLog)(`Last comment on issue ${hydrated.number} by ${lastComment.author.name}. Pinging @${hydrated.assignee}`);
|
||||
if (this.pingComment) {
|
||||
await issue.postComment(this.pingComment
|
||||
.replace('${assignee}', hydrated.assignee)
|
||||
.replace('${author}', hydrated.author.name));
|
||||
}
|
||||
}
|
||||
else {
|
||||
(0, utils_1.safeLog)(`Last comment on issue ${hydrated.number} by ${lastComment.author.name}. Skipping.${hydrated.assignee ? ' cc @' + hydrated.assignee : ''}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!hydrated.open) {
|
||||
(0, utils_1.safeLog)(`Issue ${hydrated.number} is not open. Ignoring`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.StaleCloser = StaleCloser;
|
||||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.StaleCloser = void 0;
|
||||
const ActionBase_1 = require("../common/ActionBase");
|
||||
const utils_1 = require("../common/utils");
|
||||
class StaleCloser extends ActionBase_1.ActionBase {
|
||||
constructor(github, closeDays, labels, closeComment, pingDays, pingComment, additionalTeam, addLabels, removeLabels, setMilestoneId, milestoneName, milestoneId, ignoreLabels, ignoreMilestoneNames, ignoreMilestoneIds, minimumVotes, maximumVotes, involves) {
|
||||
super(labels, milestoneName, milestoneId, ignoreLabels, ignoreMilestoneNames, ignoreMilestoneIds, minimumVotes, maximumVotes, involves);
|
||||
this.github = github;
|
||||
this.closeDays = closeDays;
|
||||
this.closeComment = closeComment;
|
||||
this.pingDays = pingDays;
|
||||
this.pingComment = pingComment;
|
||||
this.additionalTeam = additionalTeam;
|
||||
this.addLabels = addLabels;
|
||||
this.removeLabels = removeLabels;
|
||||
this.setMilestoneId = setMilestoneId;
|
||||
}
|
||||
async run() {
|
||||
const updatedTimestamp = utils_1.daysAgoToHumanReadbleDate(this.closeDays);
|
||||
const pingTimestamp = this.pingDays ? utils_1.daysAgoToTimestamp(this.pingDays) : undefined;
|
||||
const query = this.buildQuery((this.closeDays ? `updated:<${updatedTimestamp} ` : "") + "is:open is:unlocked");
|
||||
const addLabelsSet = this.addLabels ? this.addLabels.split(',') : [];
|
||||
const removeLabelsSet = this.removeLabels ? this.removeLabels.split(',') : [];
|
||||
for await (const page of this.github.query({ q: query })) {
|
||||
for (const issue of page) {
|
||||
const hydrated = await issue.getIssue();
|
||||
const lastCommentIterator = await issue.getComments(true).next();
|
||||
if (lastCommentIterator.done) {
|
||||
throw Error('Unexpected comment data');
|
||||
}
|
||||
const lastComment = lastCommentIterator.value[0];
|
||||
if (hydrated.open && this.validateIssue(hydrated)
|
||||
// TODO: Verify updated timestamp
|
||||
) {
|
||||
if (!lastComment ||
|
||||
lastComment.author.isGitHubApp ||
|
||||
pingTimestamp == undefined ||
|
||||
// TODO: List the collaborators once per go rather than checking a single user each issue
|
||||
this.additionalTeam.includes(lastComment.author.name) ||
|
||||
await issue.hasWriteAccess(lastComment.author)) {
|
||||
if (pingTimestamp != undefined) {
|
||||
if (lastComment) {
|
||||
console.log(`Last comment on issue ${hydrated.number} by ${lastComment.author.name}. Closing.`);
|
||||
}
|
||||
else {
|
||||
console.log(`No comments on issue ${hydrated.number}. Closing.`);
|
||||
}
|
||||
}
|
||||
if (this.closeComment) {
|
||||
console.log(`Posting comment on issue ${hydrated.number}`);
|
||||
await issue.postComment(this.closeComment);
|
||||
}
|
||||
if (removeLabelsSet.length > 0) {
|
||||
for (const removeLabel of removeLabelsSet) {
|
||||
if (removeLabel && removeLabel.length > 0) {
|
||||
console.log(`Removing label on issue ${hydrated.number}: ${removeLabel}`);
|
||||
await issue.removeLabel(removeLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (addLabelsSet.length > 0) {
|
||||
for (const addLabel of addLabelsSet) {
|
||||
if (addLabel && addLabel.length > 0) {
|
||||
console.log(`Adding label on issue ${hydrated.number}: ${addLabel}`);
|
||||
await issue.addLabel(addLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
await issue.closeIssue();
|
||||
if (this.setMilestoneId != undefined) {
|
||||
console.log(`Setting milestone of issue ${hydrated.number} to id ${+this.setMilestoneId}`);
|
||||
await issue.setMilestone(+this.setMilestoneId);
|
||||
}
|
||||
console.log(`Closing issue ${hydrated.number}.`);
|
||||
}
|
||||
else {
|
||||
// Ping
|
||||
if (hydrated.updatedAt < pingTimestamp && hydrated.assignee) {
|
||||
console.log(`Last comment on issue ${hydrated.number} by ${lastComment.author.name}. Pinging @${hydrated.assignee}`);
|
||||
if (this.pingComment) {
|
||||
await issue.postComment(this.pingComment
|
||||
.replace('${assignee}', hydrated.assignee)
|
||||
.replace('${author}', hydrated.author.name));
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.log(`Last comment on issue ${hydrated.number} by ${lastComment.author.name}. Skipping.${hydrated.assignee ? ' cc @' + hydrated.assignee : ''}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!hydrated.open) {
|
||||
console.log(`Issue ${hydrated.number} is not open. Ignoring`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.StaleCloser = StaleCloser;
|
||||
//# sourceMappingURL=StaleCloser.js.map
|
||||
@@ -3,9 +3,9 @@
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { GitHub } from '../api/api';
|
||||
import { ActionBase } from '../common/ActionBase';
|
||||
import { daysAgoToHumanReadbleDate, daysAgoToTimestamp, safeLog } from '../common/utils';
|
||||
import { GitHub } from '../api/api'
|
||||
import { ActionBase } from '../common/ActionBase'
|
||||
import { daysAgoToHumanReadbleDate, daysAgoToTimestamp } from '../common/utils'
|
||||
|
||||
export class StaleCloser extends ActionBase {
|
||||
constructor(
|
||||
@@ -33,22 +33,22 @@ export class StaleCloser extends ActionBase {
|
||||
}
|
||||
|
||||
async run() {
|
||||
const updatedTimestamp = this.closeDays ? daysAgoToHumanReadbleDate(this.closeDays) : undefined;
|
||||
const updatedTimestamp = daysAgoToHumanReadbleDate(this.closeDays)
|
||||
const pingTimestamp = this.pingDays ? daysAgoToTimestamp(this.pingDays) : undefined;
|
||||
|
||||
const query = this.buildQuery((updatedTimestamp ? `updated:<${updatedTimestamp} ` : "") + "is:open is:unlocked");
|
||||
const query = this.buildQuery((this.closeDays ? `updated:<${updatedTimestamp} ` : "") + "is:open is:unlocked");
|
||||
|
||||
const addLabelsSet = this.addLabels ? this.addLabels.split(',') : [];
|
||||
const removeLabelsSet = this.removeLabels ? this.removeLabels.split(',') : [];
|
||||
|
||||
for await (const page of this.github.query({ q: query })) {
|
||||
for (const issue of page) {
|
||||
const hydrated = await issue.getIssue();
|
||||
const lastCommentIterator = await issue.getComments(true).next();
|
||||
const hydrated = await issue.getIssue()
|
||||
const lastCommentIterator = await issue.getComments(true).next()
|
||||
if (lastCommentIterator.done) {
|
||||
throw Error('Unexpected comment data');
|
||||
throw Error('Unexpected comment data')
|
||||
}
|
||||
const lastComment = lastCommentIterator.value[0];
|
||||
const lastComment = lastCommentIterator.value[0]
|
||||
|
||||
if (hydrated.open && this.validateIssue(hydrated)
|
||||
// TODO: Verify updated timestamp
|
||||
@@ -63,63 +63,63 @@ export class StaleCloser extends ActionBase {
|
||||
) {
|
||||
if (pingTimestamp != undefined) {
|
||||
if (lastComment) {
|
||||
safeLog(
|
||||
console.log(
|
||||
`Last comment on issue ${hydrated.number} by ${lastComment.author.name}. Closing.`,
|
||||
);
|
||||
)
|
||||
} else {
|
||||
safeLog(`No comments on issue ${hydrated.number}. Closing.`);
|
||||
console.log(`No comments on issue ${hydrated.number}. Closing.`)
|
||||
}
|
||||
}
|
||||
if (this.closeComment) {
|
||||
safeLog(`Posting comment on issue ${hydrated.number}`);
|
||||
await issue.postComment(this.closeComment);
|
||||
console.log(`Posting comment on issue ${hydrated.number}`)
|
||||
await issue.postComment(this.closeComment)
|
||||
}
|
||||
if (removeLabelsSet.length > 0) {
|
||||
for (const removeLabel of removeLabelsSet) {
|
||||
if (removeLabel && removeLabel.length > 0) {
|
||||
safeLog(`Removing label on issue ${hydrated.number}: ${removeLabel}`);
|
||||
await issue.removeLabel(removeLabel);
|
||||
console.log(`Removing label on issue ${hydrated.number}: ${removeLabel}`)
|
||||
await issue.removeLabel(removeLabel)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (addLabelsSet.length > 0) {
|
||||
for (const addLabel of addLabelsSet) {
|
||||
if (addLabel && addLabel.length > 0) {
|
||||
safeLog(`Adding label on issue ${hydrated.number}: ${addLabel}`);
|
||||
await issue.addLabel(addLabel);
|
||||
console.log(`Adding label on issue ${hydrated.number}: ${addLabel}`)
|
||||
await issue.addLabel(addLabel)
|
||||
}
|
||||
}
|
||||
}
|
||||
await issue.closeIssue("not_planned");
|
||||
await issue.closeIssue()
|
||||
if (this.setMilestoneId != undefined) {
|
||||
safeLog(`Setting milestone of issue ${hydrated.number} to id ${+this.setMilestoneId}`);
|
||||
await issue.setMilestone(+this.setMilestoneId);
|
||||
console.log(`Setting milestone of issue ${hydrated.number} to id ${+this.setMilestoneId}`)
|
||||
await issue.setMilestone(+this.setMilestoneId)
|
||||
}
|
||||
safeLog(`Closing issue ${hydrated.number}.`);
|
||||
console.log(`Closing issue ${hydrated.number}.`)
|
||||
} else {
|
||||
// Ping
|
||||
// Ping
|
||||
if (hydrated.updatedAt < pingTimestamp && hydrated.assignee) {
|
||||
safeLog(
|
||||
console.log(
|
||||
`Last comment on issue ${hydrated.number} by ${lastComment.author.name}. Pinging @${hydrated.assignee}`,
|
||||
);
|
||||
)
|
||||
if (this.pingComment) {
|
||||
await issue.postComment(
|
||||
this.pingComment
|
||||
.replace('${assignee}', hydrated.assignee)
|
||||
.replace('${author}', hydrated.author.name),
|
||||
);
|
||||
)
|
||||
}
|
||||
} else {
|
||||
safeLog(
|
||||
console.log(
|
||||
`Last comment on issue ${hydrated.number} by ${lastComment.author.name}. Skipping.${
|
||||
hydrated.assignee ? ' cc @' + hydrated.assignee : ''
|
||||
}`,
|
||||
);
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!hydrated.open) {
|
||||
safeLog(`Issue ${hydrated.number} is not open. Ignoring`);
|
||||
console.log(`Issue ${hydrated.number} is not open. Ignoring`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ inputs:
|
||||
milestoneId:
|
||||
description: items with these milestones will be considered (id only, must match name)
|
||||
labels:
|
||||
description: items with these labels will be considered. May be "*".
|
||||
description: items with these labels will not be considered. May be "*".
|
||||
required: true
|
||||
ignoreMilestoneNames:
|
||||
description: items with these milestones will not be considered (names only, must match IDs). May be "*".
|
||||
@@ -43,5 +43,5 @@ inputs:
|
||||
readonly:
|
||||
description: If true, changes are not applied.
|
||||
runs:
|
||||
using: 'node24'
|
||||
using: 'node12'
|
||||
main: 'index.js'
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const utils_1 = require("../common/utils");
|
||||
const StaleCloser_1 = require("./StaleCloser");
|
||||
const Action_1 = require("../common/Action");
|
||||
class StaleCloserAction extends Action_1.Action {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.id = 'StaleCloser';
|
||||
}
|
||||
async onTriggered(github) {
|
||||
var _a;
|
||||
await new StaleCloser_1.StaleCloser(github, +(0, utils_1.getRequiredInput)('closeDays'), (0, utils_1.getRequiredInput)('labels'), (0, utils_1.getInput)('closeComment') || '', +((0, utils_1.getInput)('pingDays') || 0), (0, utils_1.getInput)('pingComment') || '', ((_a = (0, utils_1.getInput)('additionalTeam')) !== null && _a !== void 0 ? _a : '').split(','), (0, utils_1.getInput)('addLabels') || undefined, (0, utils_1.getInput)('removeLabels') || undefined, (0, utils_1.getInput)('setMilestoneId') || undefined, (0, utils_1.getInput)('milestoneName') || undefined, (0, utils_1.getInput)('milestoneId') || undefined, (0, utils_1.getInput)('ignoreLabels') || undefined, (0, utils_1.getInput)('ignoreMilestoneNames') || undefined, (0, utils_1.getInput)('ignoreMilestoneIds') || undefined, +((0, utils_1.getInput)('minimumVotes') || 0), +((0, utils_1.getInput)('maximumVotes') || 9999999), (0, utils_1.getInput)('involves') || undefined).run();
|
||||
}
|
||||
}
|
||||
new StaleCloserAction().run(); // eslint-disable-line
|
||||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const utils_1 = require("../common/utils");
|
||||
const StaleCloser_1 = require("./StaleCloser");
|
||||
const Action_1 = require("../common/Action");
|
||||
class StaleCloserAction extends Action_1.Action {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.id = 'StaleCloser';
|
||||
}
|
||||
async onTriggered(github) {
|
||||
var _a;
|
||||
await new StaleCloser_1.StaleCloser(github, +utils_1.getRequiredInput('closeDays'), utils_1.getRequiredInput('labels'), utils_1.getInput('closeComment') || '', +(utils_1.getInput('pingDays') || 0), utils_1.getInput('pingComment') || '', ((_a = utils_1.getInput('additionalTeam')) !== null && _a !== void 0 ? _a : '').split(','), utils_1.getInput('addLabels') || undefined, utils_1.getInput('removeLabels') || undefined, utils_1.getInput('setMilestoneId') || undefined, utils_1.getInput('milestoneName') || undefined, utils_1.getInput('milestoneId') || undefined, utils_1.getInput('ignoreLabels') || undefined, utils_1.getInput('ignoreMilestoneNames') || undefined, utils_1.getInput('ignoreMilestoneIds') || undefined, +(utils_1.getInput('minimumVotes') || 0), +(utils_1.getInput('maximumVotes') || 9999999), utils_1.getInput('involves') || undefined).run();
|
||||
}
|
||||
}
|
||||
new StaleCloserAction().run(); // eslint-disable-line
|
||||
//# sourceMappingURL=index.js.map
|
||||
@@ -9,7 +9,7 @@ import { StaleCloser } from './StaleCloser'
|
||||
import { Action } from '../common/Action'
|
||||
|
||||
class StaleCloserAction extends Action {
|
||||
id = 'StaleCloser';
|
||||
id = 'StaleCloser'
|
||||
|
||||
async onTriggered(github: OctoKit) {
|
||||
await new StaleCloser(
|
||||
@@ -31,8 +31,8 @@ class StaleCloserAction extends Action {
|
||||
+(getInput('minimumVotes') || 0),
|
||||
+(getInput('maximumVotes') || 9999999),
|
||||
getInput('involves') || undefined
|
||||
).run();
|
||||
).run()
|
||||
}
|
||||
}
|
||||
|
||||
new StaleCloserAction().run(); // eslint-disable-line
|
||||
new StaleCloserAction().run() // eslint-disable-line
|
||||
|
||||
+56
-79
@@ -4,53 +4,43 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export interface GitHub {
|
||||
repoOwner: string;
|
||||
repoName: string;
|
||||
query(query: Query): AsyncIterableIterator<GitHubIssue[]>
|
||||
|
||||
query(query: Query): AsyncIterableIterator<GitHubIssue[]>;
|
||||
hasWriteAccess(user: User): Promise<boolean>
|
||||
|
||||
hasWriteAccess(user: User): Promise<boolean>;
|
||||
repoHasLabel(label: string): Promise<boolean>
|
||||
createLabel(label: string, color: string, description: string): Promise<void>
|
||||
deleteLabel(label: string): Promise<void>
|
||||
|
||||
repoHasLabel(label: string): Promise<boolean>;
|
||||
createLabel(label: string, color: string, description: string): Promise<void>;
|
||||
deleteLabel(label: string): Promise<void>;
|
||||
readConfig(path: string): Promise<any>
|
||||
|
||||
readConfig(path: string): Promise<any>;
|
||||
dispatch(title: string): Promise<void>
|
||||
|
||||
dispatch(title: string): Promise<void>;
|
||||
createIssue(owner: string, repo: string, title: string, body: string): Promise<void>
|
||||
|
||||
createIssue(owner: string, repo: string, title: string, body: string): Promise<void>;
|
||||
|
||||
releaseContainsCommit(release: string, commit: string): Promise<'yes' | 'no' | 'unknown'>;
|
||||
|
||||
/**
|
||||
* Returns what we think the current milestone for the repo is based on the due on date.
|
||||
* @returns The milestone id if one is found, else undefined
|
||||
*/
|
||||
getCurrentRepoMilestone(): Promise<number | undefined>;
|
||||
releaseContainsCommit(release: string, commit: string): Promise<'yes' | 'no' | 'unknown'>
|
||||
}
|
||||
|
||||
export interface GitHubIssue extends GitHub {
|
||||
getIssue(): Promise<Issue>;
|
||||
getIssue(): Promise<Issue>
|
||||
|
||||
postComment(body: string): Promise<void>;
|
||||
deleteComment(id: number): Promise<void>;
|
||||
getComments(last?: boolean): AsyncIterableIterator<Comment[]>;
|
||||
postComment(body: string): Promise<void>
|
||||
deleteComment(id: number): Promise<void>
|
||||
getComments(last?: boolean): AsyncIterableIterator<Comment[]>
|
||||
|
||||
closeIssue(reason: 'completed' | 'not_planned'): Promise<void>;
|
||||
lockIssue(): Promise<void>;
|
||||
unlockIssue(): Promise<void>;
|
||||
reopenIssue(): Promise<void>;
|
||||
closeIssue(): Promise<void>
|
||||
lockIssue(): Promise<void>
|
||||
reopenIssue(): Promise<void>
|
||||
|
||||
setMilestone(milestoneId: number): Promise<void>;
|
||||
setMilestone(milestoneId: number): Promise<void>
|
||||
|
||||
addLabel(label: string): Promise<void>;
|
||||
removeLabel(label: string): Promise<void>;
|
||||
addLabel(label: string): Promise<void>
|
||||
removeLabel(label: string): Promise<void>
|
||||
|
||||
addAssignee(assignee: string): Promise<void>;
|
||||
removeAssignee(assignee: string): Promise<void>;
|
||||
addAssignee(assignee: string): Promise<void>
|
||||
removeAssignee(assignee: string): Promise<void>
|
||||
|
||||
getClosingInfo(): Promise<{ hash: string | undefined; timestamp: number } | undefined>;
|
||||
getClosingInfo(): Promise<{ hash: string | undefined; timestamp: number } | undefined>
|
||||
}
|
||||
|
||||
type SortVar =
|
||||
@@ -64,60 +54,47 @@ type SortVar =
|
||||
| 'reactions-tada'
|
||||
| 'interactions'
|
||||
| 'created'
|
||||
| 'updated';
|
||||
type SortOrder = 'asc' | 'desc';
|
||||
| 'updated'
|
||||
type SortOrder = 'asc' | 'desc'
|
||||
export type Reactions = {
|
||||
'+1': number;
|
||||
'-1': number;
|
||||
laugh: number;
|
||||
hooray: number;
|
||||
confused: number;
|
||||
heart: number;
|
||||
rocket: number;
|
||||
eyes: number;
|
||||
};
|
||||
'+1': number
|
||||
'-1': number
|
||||
laugh: number
|
||||
hooray: number
|
||||
confused: number
|
||||
heart: number
|
||||
rocket: number
|
||||
eyes: number
|
||||
}
|
||||
|
||||
export interface User {
|
||||
name: string;
|
||||
isGitHubApp?: boolean;
|
||||
name: string
|
||||
isGitHubApp?: boolean
|
||||
}
|
||||
export interface Comment {
|
||||
author: User;
|
||||
body: string;
|
||||
id: number;
|
||||
timestamp: number;
|
||||
author: User
|
||||
body: string
|
||||
id: number
|
||||
timestamp: number
|
||||
}
|
||||
export interface Issue {
|
||||
author: User;
|
||||
body: string;
|
||||
title: string;
|
||||
labels: string[];
|
||||
open: boolean;
|
||||
locked: boolean;
|
||||
number: number;
|
||||
isPr: boolean;
|
||||
numComments: number;
|
||||
reactions: Reactions;
|
||||
milestone: Milestone | null;
|
||||
assignee?: string;
|
||||
assignees: string[];
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
closedAt?: number;
|
||||
}
|
||||
export interface Milestone {
|
||||
milestoneId: number;
|
||||
title: string;
|
||||
description: string;
|
||||
numClosedIssues: number;
|
||||
numOpenIssues: number;
|
||||
dueOn: Date | null;
|
||||
createdAt: Date | null;
|
||||
closedAt: Date | null;
|
||||
state: 'open' | 'closed';
|
||||
author: User
|
||||
body: string
|
||||
title: string
|
||||
labels: string[]
|
||||
open: boolean
|
||||
locked: boolean
|
||||
number: number
|
||||
numComments: number
|
||||
reactions: Reactions
|
||||
milestoneId: number | null
|
||||
assignee?: string
|
||||
createdAt: number
|
||||
updatedAt: number
|
||||
closedAt?: number
|
||||
}
|
||||
export interface Query {
|
||||
q: string;
|
||||
sort?: SortVar;
|
||||
order?: SortOrder;
|
||||
q: string
|
||||
sort?: SortVar
|
||||
order?: SortOrder
|
||||
}
|
||||
|
||||
+93
-172
@@ -5,17 +5,12 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.OctoKitIssue = exports.OctoKit = exports.getNumRequests = void 0;
|
||||
const core_1 = require("@actions/core");
|
||||
const github_1 = require("@actions/github");
|
||||
const child_process_1 = require("child_process");
|
||||
const utils_1 = require("../common/utils");
|
||||
let numRequests = 0;
|
||||
const getNumRequests = () => numRequests;
|
||||
exports.getNumRequests = getNumRequests;
|
||||
exports.getNumRequests = () => numRequests;
|
||||
class OctoKit {
|
||||
get octokit() {
|
||||
numRequests++;
|
||||
return this._octokit;
|
||||
}
|
||||
constructor(token, params, options = { readonly: false }) {
|
||||
this.token = token;
|
||||
this.params = params;
|
||||
@@ -23,93 +18,73 @@ class OctoKit {
|
||||
// when in readonly mode, record labels just-created so at to not throw unneccesary errors
|
||||
this.mockLabels = new Set();
|
||||
this.writeAccessCache = {};
|
||||
this._octokit = (0, github_1.getOctokit)(token);
|
||||
this.repoName = params.repo;
|
||||
this.repoOwner = params.owner;
|
||||
this._octokit = new github_1.GitHub(token);
|
||||
}
|
||||
getIssueByNumber(number) {
|
||||
return new OctoKitIssue(this.token, this.params, { number: number });
|
||||
get octokit() {
|
||||
numRequests++;
|
||||
return this._octokit;
|
||||
}
|
||||
// TODO: just iterate over the issues in a page here instead of making caller do it
|
||||
async *query(query) {
|
||||
const q = query.q + ` repo:${this.params.owner}/${this.params.repo}`;
|
||||
const options = {
|
||||
console.log(`Querying for ${q}:`);
|
||||
const options = this.octokit.search.issuesAndPullRequests.endpoint.merge({
|
||||
...query,
|
||||
q,
|
||||
per_page: 100,
|
||||
headers: { Accept: 'application/vnd.github.squirrel-girl-preview+json' },
|
||||
};
|
||||
});
|
||||
let pageNum = 0;
|
||||
const timeout = async () => {
|
||||
if (pageNum < 2) {
|
||||
/* pass */
|
||||
}
|
||||
else if (pageNum < 4) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 10000));
|
||||
await new Promise((resolve) => setTimeout(resolve, 3000));
|
||||
}
|
||||
else {
|
||||
await new Promise((resolve) => setTimeout(resolve, 30000));
|
||||
}
|
||||
};
|
||||
for await (const pageResponse of this.octokit.paginate.iterator(this.octokit.rest.search.issuesAndPullRequests, options)) {
|
||||
for await (const pageResponse of this.octokit.paginate.iterator(options)) {
|
||||
await timeout();
|
||||
numRequests++;
|
||||
const page = pageResponse.data;
|
||||
(0, utils_1.safeLog)(`Page ${++pageNum}: ${page.map(({ number }) => number).join(' ')}`);
|
||||
console.log(`Page ${++pageNum}: ${page.map(({ number }) => number).join(' ')}`);
|
||||
yield page.map((issue) => new OctoKitIssue(this.token, this.params, this.octokitIssueToIssue(issue), this.options));
|
||||
}
|
||||
}
|
||||
async createIssue(owner, repo, title, body) {
|
||||
(0, utils_1.safeLog)(`Creating issue \`${title}\` on ${owner}/${repo}`);
|
||||
core_1.debug(`Creating issue \`${title}\` on ${owner}/${repo}`);
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.create({ owner, repo, title, body });
|
||||
await this.octokit.issues.create({ owner, repo, title, body });
|
||||
}
|
||||
octokitIssueToIssue(issue) {
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
return {
|
||||
author: { name: (_b = (_a = issue.user) === null || _a === void 0 ? void 0 : _a.login) !== null && _b !== void 0 ? _b : 'unkown', isGitHubApp: ((_c = issue.user) === null || _c === void 0 ? void 0 : _c.type) === 'Bot' },
|
||||
body: (_d = issue.body) !== null && _d !== void 0 ? _d : '',
|
||||
author: { name: issue.user.login, isGitHubApp: issue.user.type === 'Bot' },
|
||||
body: issue.body,
|
||||
number: issue.number,
|
||||
title: issue.title,
|
||||
isPr: !!((_e = issue.pull_request) === null || _e === void 0 ? void 0 : _e.html_url),
|
||||
labels: issue.labels.map((label) => { var _a; return (typeof label === 'string' ? label : (_a = label.name) !== null && _a !== void 0 ? _a : ''); }),
|
||||
labels: issue.labels.map((label) => label.name),
|
||||
open: issue.state === 'open',
|
||||
locked: issue.locked,
|
||||
numComments: issue.comments,
|
||||
reactions: issue.reactions,
|
||||
assignee: (_g = (_f = issue.assignee) === null || _f === void 0 ? void 0 : _f.login) !== null && _g !== void 0 ? _g : (_j = (_h = issue.assignees) === null || _h === void 0 ? void 0 : _h[0]) === null || _j === void 0 ? void 0 : _j.login,
|
||||
assignees: (_l = (_k = issue.assignees) === null || _k === void 0 ? void 0 : _k.map((assignee) => assignee.login)) !== null && _l !== void 0 ? _l : [],
|
||||
milestone: issue.milestone ? this.octokitMilestoneToMilestone(issue.milestone) : null,
|
||||
assignee: (_b = (_a = issue.assignee) === null || _a === void 0 ? void 0 : _a.login) !== null && _b !== void 0 ? _b : (_d = (_c = issue.assignees) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.login,
|
||||
milestoneId: (_f = (_e = issue.milestone) === null || _e === void 0 ? void 0 : _e.number) !== null && _f !== void 0 ? _f : null,
|
||||
createdAt: +new Date(issue.created_at),
|
||||
updatedAt: +new Date(issue.updated_at),
|
||||
closedAt: issue.closed_at ? +new Date(issue.closed_at) : undefined,
|
||||
};
|
||||
}
|
||||
octokitMilestoneToMilestone(milestone) {
|
||||
var _a;
|
||||
if ((milestone === null || milestone === void 0 ? void 0 : milestone.number) === undefined) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
title: milestone.title,
|
||||
milestoneId: milestone.number,
|
||||
// Remove the time portions of the dates as they're not important
|
||||
createdAt: milestone.created_at !== null ? new Date(milestone.created_at.split('T')[0]) : null,
|
||||
dueOn: milestone.due_on !== null ? new Date(milestone.due_on.split('T')[0]) : null,
|
||||
closedAt: milestone.closed_at !== null ? new Date(milestone.closed_at.split('T')[0]) : null,
|
||||
description: (_a = milestone.description) !== null && _a !== void 0 ? _a : '',
|
||||
numClosedIssues: milestone.closed_issues,
|
||||
numOpenIssues: milestone.open_issues,
|
||||
state: milestone.state === 'open' ? 'open' : 'closed',
|
||||
};
|
||||
}
|
||||
async hasWriteAccess(user) {
|
||||
if (user.name in this.writeAccessCache) {
|
||||
(0, utils_1.safeLog)('Got permissions from cache for ' + user);
|
||||
core_1.debug('Got permissions from cache for ' + user);
|
||||
return this.writeAccessCache[user.name];
|
||||
}
|
||||
(0, utils_1.safeLog)('Fetching permissions for ' + user.name);
|
||||
const permissions = (await this.octokit.rest.repos.getCollaboratorPermissionLevel({
|
||||
core_1.debug('Fetching permissions for ' + user);
|
||||
const permissions = (await this.octokit.repos.getCollaboratorPermissionLevel({
|
||||
...this.params,
|
||||
username: user.name,
|
||||
})).data.permission;
|
||||
@@ -117,44 +92,42 @@ class OctoKit {
|
||||
}
|
||||
async repoHasLabel(name) {
|
||||
try {
|
||||
await this.octokit.rest.issues.getLabel({ ...this.params, name });
|
||||
await this.octokit.issues.getLabel({ ...this.params, name });
|
||||
return true;
|
||||
}
|
||||
catch (err) {
|
||||
const statusErorr = err;
|
||||
if (statusErorr.status === 404) {
|
||||
if (err.status === 404) {
|
||||
return this.options.readonly && this.mockLabels.has(name);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
async createLabel(name, color, description) {
|
||||
(0, utils_1.safeLog)('Creating label ' + name);
|
||||
core_1.debug('Creating label ' + name);
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.createLabel({ ...this.params, color, description, name });
|
||||
await this.octokit.issues.createLabel({ ...this.params, color, description, name });
|
||||
else
|
||||
this.mockLabels.add(name);
|
||||
}
|
||||
async deleteLabel(name) {
|
||||
(0, utils_1.safeLog)('Deleting label ' + name);
|
||||
core_1.debug('Deleting label ' + name);
|
||||
try {
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.deleteLabel({ ...this.params, name });
|
||||
await this.octokit.issues.deleteLabel({ ...this.params, name });
|
||||
}
|
||||
catch (err) {
|
||||
const statusErorr = err;
|
||||
if (statusErorr.status === 404) {
|
||||
if (err.status === 404) {
|
||||
return;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
async readConfig(path) {
|
||||
(0, utils_1.safeLog)('Reading config at ' + path);
|
||||
core_1.debug('Reading config at ' + path);
|
||||
const repoPath = `.github/${path}.json`;
|
||||
try {
|
||||
const data = (await this.octokit.rest.repos.getContent({ ...this.params, path: repoPath })).data;
|
||||
if ('type' in data && data.type === 'file' && 'content' in data) {
|
||||
const data = (await this.octokit.repos.getContents({ ...this.params, path: repoPath })).data;
|
||||
if ('type' in data && data.type === 'file') {
|
||||
if (data.encoding === 'base64' && data.content) {
|
||||
return JSON.parse(Buffer.from(data.content, 'base64').toString('utf-8'));
|
||||
}
|
||||
@@ -167,10 +140,7 @@ class OctoKit {
|
||||
}
|
||||
}
|
||||
async releaseContainsCommit(release, commit) {
|
||||
const isHash = (s) => /^[a-fA-F0-9]*$/.test(s);
|
||||
if (!isHash(release) || !isHash(commit))
|
||||
return 'unknown';
|
||||
return new Promise((resolve, reject) => (0, child_process_1.exec)(`git -C ./repo merge-base --is-ancestor ${commit} ${release}`, (err) => {
|
||||
return new Promise((resolve, reject) => child_process_1.exec(`git -C ./repo merge-base --is-ancestor ${commit} ${release}`, (err) => {
|
||||
if (!err || err.code === 1) {
|
||||
resolve(!err ? 'yes' : 'no');
|
||||
}
|
||||
@@ -187,31 +157,10 @@ class OctoKit {
|
||||
}
|
||||
}));
|
||||
}
|
||||
async getCurrentRepoMilestone() {
|
||||
(0, utils_1.safeLog)(`Getting repo milestone for ${this.params.owner}/${this.params.repo}`);
|
||||
// Fetch all milestones open for this repo
|
||||
const allMilestones = (await this.octokit.rest.issues.listMilestones({
|
||||
owner: this.params.owner,
|
||||
repo: this.params.repo,
|
||||
state: 'open',
|
||||
sort: 'due_on',
|
||||
direction: 'asc',
|
||||
})).data;
|
||||
const currentDate = new Date();
|
||||
const possibleMilestones = allMilestones
|
||||
.filter((milestone) => new Date(milestone.due_on === null ? currentDate : milestone.due_on) > currentDate &&
|
||||
currentDate > new Date(milestone.created_at) &&
|
||||
!milestone.title.includes('Recovery'))
|
||||
.sort((a, b) => { var _a, _b; return +new Date((_a = a.due_on) !== null && _a !== void 0 ? _a : currentDate) - +new Date((_b = b.due_on) !== null && _b !== void 0 ? _b : currentDate); });
|
||||
if (possibleMilestones.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
return possibleMilestones[0].number;
|
||||
}
|
||||
async dispatch(title) {
|
||||
(0, utils_1.safeLog)('Dispatching ' + title);
|
||||
core_1.debug('Dispatching ' + title);
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.repos.createDispatchEvent({ ...this.params, event_type: title });
|
||||
await this.octokit.repos.createDispatchEvent({ ...this.params, event_type: title });
|
||||
}
|
||||
}
|
||||
exports.OctoKit = OctoKit;
|
||||
@@ -220,12 +169,12 @@ class OctoKitIssue extends OctoKit {
|
||||
super(token, params, options);
|
||||
this.params = params;
|
||||
this.issueData = issueData;
|
||||
(0, utils_1.safeLog)('running bot on issue', issueData.number);
|
||||
console.log('running bot on issue', issueData.number);
|
||||
}
|
||||
async addAssignee(assignee) {
|
||||
(0, utils_1.safeLog)('Adding assignee ' + assignee + ' to ' + this.issueData.number);
|
||||
core_1.debug('Adding assignee ' + assignee + ' to ' + this.issueData.number);
|
||||
if (!this.options.readonly) {
|
||||
await this.octokit.rest.issues.addAssignees({
|
||||
await this.octokit.issues.addAssignees({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
assignees: [assignee],
|
||||
@@ -233,64 +182,45 @@ class OctoKitIssue extends OctoKit {
|
||||
}
|
||||
}
|
||||
async removeAssignee(assignee) {
|
||||
(0, utils_1.safeLog)('Removing assignee ' + assignee + ' to ' + this.issueData.number);
|
||||
core_1.debug('Removing assignee ' + assignee + ' to ' + this.issueData.number);
|
||||
if (!this.options.readonly) {
|
||||
await this.octokit.rest.issues.removeAssignees({
|
||||
await this.octokit.issues.removeAssignees({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
assignees: [assignee],
|
||||
});
|
||||
}
|
||||
}
|
||||
async closeIssue(reason) {
|
||||
(0, utils_1.safeLog)('Closing issue ' + this.issueData.number);
|
||||
if (!this.options.readonly) {
|
||||
const issue = await this.octokit.rest.issues.get({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
});
|
||||
// Don't close already closed issues even if it means changing the state
|
||||
if (issue.data.state === 'closed') {
|
||||
return;
|
||||
}
|
||||
await this.octokit.rest.issues
|
||||
.update({
|
||||
async closeIssue() {
|
||||
core_1.debug('Closing issue ' + this.issueData.number);
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.issues.update({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
state: 'closed',
|
||||
state_reason: reason,
|
||||
})
|
||||
.catch((e) => {
|
||||
(0, utils_1.safeLog)('error closing issue:', e);
|
||||
});
|
||||
}
|
||||
}
|
||||
async reopenIssue() {
|
||||
(0, utils_1.safeLog)('Reopening issue ' + this.issueData.number);
|
||||
core_1.debug('Reopening issue ' + this.issueData.number);
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.update({
|
||||
await this.octokit.issues.update({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
state: 'open',
|
||||
});
|
||||
}
|
||||
async lockIssue() {
|
||||
(0, utils_1.safeLog)('Locking issue ' + this.issueData.number);
|
||||
core_1.debug('Locking issue ' + this.issueData.number);
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.lock({ ...this.params, issue_number: this.issueData.number });
|
||||
}
|
||||
async unlockIssue() {
|
||||
(0, utils_1.safeLog)('Unlocking issue ' + this.issueData.number);
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.unlock({ ...this.params, issue_number: this.issueData.number });
|
||||
await this.octokit.issues.lock({ ...this.params, issue_number: this.issueData.number });
|
||||
}
|
||||
async getIssue() {
|
||||
if (isIssue(this.issueData)) {
|
||||
(0, utils_1.safeLog)('Got issue data from query result ' + this.issueData.number);
|
||||
core_1.debug('Got issue data from query result ' + this.issueData.number);
|
||||
return this.issueData;
|
||||
}
|
||||
(0, utils_1.safeLog)('Fetching issue ' + this.issueData.number);
|
||||
const issue = (await this.octokit.rest.issues.get({
|
||||
console.log('Fetching issue ' + this.issueData.number);
|
||||
const issue = (await this.octokit.issues.get({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
mediaType: { previews: ['squirrel-girl'] },
|
||||
@@ -298,83 +228,77 @@ class OctoKitIssue extends OctoKit {
|
||||
return (this.issueData = this.octokitIssueToIssue(issue));
|
||||
}
|
||||
async postComment(body) {
|
||||
(0, utils_1.safeLog)(`Posting comment on ${this.issueData.number}`);
|
||||
core_1.debug(`Posting comment ${body} on ${this.issueData.number}`);
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.createComment({
|
||||
await this.octokit.issues.createComment({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
body,
|
||||
});
|
||||
}
|
||||
async deleteComment(id) {
|
||||
(0, utils_1.safeLog)(`Deleting comment ${id} on ${this.issueData.number}`);
|
||||
core_1.debug(`Deleting comment ${id} on ${this.issueData.number}`);
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.deleteComment({
|
||||
await this.octokit.issues.deleteComment({
|
||||
owner: this.params.owner,
|
||||
repo: this.params.repo,
|
||||
comment_id: id,
|
||||
});
|
||||
}
|
||||
async setMilestone(milestoneId) {
|
||||
(0, utils_1.safeLog)(`Setting milestone for ${this.issueData.number} to ${milestoneId}`);
|
||||
core_1.debug(`Setting milestone for ${this.issueData.number} to ${milestoneId}`);
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.update({
|
||||
await this.octokit.issues.update({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
milestone: milestoneId,
|
||||
});
|
||||
}
|
||||
async *getComments(last) {
|
||||
(0, utils_1.safeLog)('Fetching comments for ' + this.issueData.number);
|
||||
const response = this.octokit.paginate.iterator(this.octokit.rest.issues.listComments, {
|
||||
core_1.debug('Fetching comments for ' + this.issueData.number);
|
||||
const response = this.octokit.paginate.iterator(this.octokit.issues.listComments.endpoint.merge({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
per_page: 100,
|
||||
...(last ? { per_page: 1, page: (await this.getIssue()).numComments } : {}),
|
||||
});
|
||||
}));
|
||||
for await (const page of response) {
|
||||
numRequests++;
|
||||
yield page.data.map((comment) => {
|
||||
var _a, _b, _c, _d;
|
||||
return ({
|
||||
author: { name: (_b = (_a = comment.user) === null || _a === void 0 ? void 0 : _a.login) !== null && _b !== void 0 ? _b : '', isGitHubApp: ((_c = comment.user) === null || _c === void 0 ? void 0 : _c.type) === 'Bot' },
|
||||
body: (_d = comment.body) !== null && _d !== void 0 ? _d : '',
|
||||
id: comment.id,
|
||||
timestamp: +new Date(comment.created_at),
|
||||
});
|
||||
});
|
||||
yield page.data.map((comment) => ({
|
||||
author: { name: comment.user.login, isGitHubApp: comment.user.type === 'Bot' },
|
||||
body: comment.body,
|
||||
id: comment.id,
|
||||
timestamp: +new Date(comment.created_at),
|
||||
}));
|
||||
}
|
||||
}
|
||||
async addLabel(name) {
|
||||
(0, utils_1.safeLog)(`Adding label ${name} to ${this.issueData.number}`);
|
||||
core_1.debug(`Adding label ${name} to ${this.issueData.number}`);
|
||||
if (!(await this.repoHasLabel(name))) {
|
||||
throw Error(`Action could not execute becuase label ${name} is not defined.`);
|
||||
}
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.addLabels({
|
||||
await this.octokit.issues.addLabels({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
labels: [name],
|
||||
});
|
||||
}
|
||||
async getAssigner(assignee) {
|
||||
var _a, _b;
|
||||
const options = {
|
||||
const options = this.octokit.issues.listEventsForTimeline.endpoint.merge({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
};
|
||||
});
|
||||
let assigner;
|
||||
for await (const event of this.octokit.paginate.iterator(this.octokit.rest.issues.listEventsForTimeline, options)) {
|
||||
for await (const event of this.octokit.paginate.iterator(options)) {
|
||||
numRequests++;
|
||||
const timelineEvents = event.data;
|
||||
for (const timelineEvent of timelineEvents) {
|
||||
if (timelineEvent.event === 'assigned' && ((_a = timelineEvent.assignee) === null || _a === void 0 ? void 0 : _a.login) === assignee) {
|
||||
assigner = (_b = timelineEvent.actor) === null || _b === void 0 ? void 0 : _b.login;
|
||||
if (timelineEvent.event === 'assigned' &&
|
||||
timelineEvent.assignee.login === assignee) {
|
||||
assigner = timelineEvent.actor.login;
|
||||
}
|
||||
}
|
||||
if (assigner) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!assigner) {
|
||||
throw Error('Expected to find ' + assignee + ' in issue timeline but did not.');
|
||||
@@ -382,26 +306,25 @@ class OctoKitIssue extends OctoKit {
|
||||
return assigner;
|
||||
}
|
||||
async removeLabel(name) {
|
||||
(0, utils_1.safeLog)(`Removing label ${name} from ${this.issueData.number}`);
|
||||
core_1.debug(`Removing label ${name} from ${this.issueData.number}`);
|
||||
try {
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.removeLabel({
|
||||
await this.octokit.issues.removeLabel({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
name,
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
const statusErorr = err;
|
||||
if (statusErorr.status === 404) {
|
||||
(0, utils_1.safeLog)(`Label ${name} not found on issue`);
|
||||
if (err.status === 404) {
|
||||
console.log(`Label ${name} not found on issue`);
|
||||
return;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
async getClosingInfo(alreadyChecked = []) {
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h;
|
||||
var _a, _b, _c, _d, _e, _f, _g;
|
||||
if (alreadyChecked.includes(this.issueData.number)) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -409,21 +332,22 @@ class OctoKitIssue extends OctoKit {
|
||||
if ((await this.getIssue()).open) {
|
||||
return;
|
||||
}
|
||||
const closingHashComment = /(?:\\|\/)closedWith (?:https:\/\/github\.com\/microsoft\/vscode\/commit\/)?([a-fA-F0-9]{7,40})/;
|
||||
const options = {
|
||||
const closingHashComment = /(?:\\|\/)closedWith (\S*)/;
|
||||
const options = this.octokit.issues.listEventsForTimeline.endpoint.merge({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
};
|
||||
});
|
||||
let closingCommit;
|
||||
const crossReferencing = [];
|
||||
for await (const event of this.octokit.paginate.iterator(this.octokit.rest.issues.listEventsForTimeline, options)) {
|
||||
for await (const event of this.octokit.paginate.iterator(options)) {
|
||||
numRequests++;
|
||||
const timelineEvents = event.data;
|
||||
for (const timelineEvent of timelineEvents) {
|
||||
if ((timelineEvent.event === 'closed' || timelineEvent.event === 'merged') &&
|
||||
timelineEvent.created_at &&
|
||||
timelineEvent.commit_id &&
|
||||
((_a = timelineEvent.commit_url) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes(`/${this.params.owner}/${this.params.repo}/`.toLowerCase()))) {
|
||||
timelineEvent.commit_url
|
||||
.toLowerCase()
|
||||
.includes(`/${this.params.owner}/${this.params.repo}/`.toLowerCase())) {
|
||||
closingCommit = {
|
||||
hash: timelineEvent.commit_id,
|
||||
timestamp: +new Date(timelineEvent.created_at),
|
||||
@@ -432,18 +356,15 @@ class OctoKitIssue extends OctoKit {
|
||||
if (timelineEvent.event === 'reopened') {
|
||||
closingCommit = undefined;
|
||||
}
|
||||
if (timelineEvent.created_at &&
|
||||
timelineEvent.event === 'commented' &&
|
||||
!((_b = timelineEvent.body) === null || _b === void 0 ? void 0 : _b.includes('UNABLE_TO_LOCATE_COMMIT_MESSAGE')) &&
|
||||
if (timelineEvent.event === 'commented' &&
|
||||
!((_a = timelineEvent.body) === null || _a === void 0 ? void 0 : _a.includes('UNABLE_TO_LOCATE_COMMIT_MESSAGE')) &&
|
||||
closingHashComment.test(timelineEvent.body)) {
|
||||
closingCommit = {
|
||||
hash: closingHashComment.exec(timelineEvent.body)[1],
|
||||
timestamp: +new Date(timelineEvent.created_at),
|
||||
};
|
||||
}
|
||||
if (timelineEvent.event === 'cross-referenced' &&
|
||||
((_d = (_c = timelineEvent.source) === null || _c === void 0 ? void 0 : _c.issue) === null || _d === void 0 ? void 0 : _d.number) &&
|
||||
((_g = (_f = (_e = timelineEvent.source) === null || _e === void 0 ? void 0 : _e.issue) === null || _f === void 0 ? void 0 : _f.pull_request) === null || _g === void 0 ? void 0 : _g.url.includes(`/${this.params.owner}/${this.params.repo}/`.toLowerCase()))) {
|
||||
if (timelineEvent.event === 'cross-referenced' && ((_c = (_b = timelineEvent.source) === null || _b === void 0 ? void 0 : _b.issue) === null || _c === void 0 ? void 0 : _c.number) && ((_f = (_e = (_d = timelineEvent.source) === null || _d === void 0 ? void 0 : _d.issue) === null || _e === void 0 ? void 0 : _e.pull_request) === null || _f === void 0 ? void 0 : _f.url.includes(`/${this.params.owner}/${this.params.repo}/`.toLowerCase()))) {
|
||||
crossReferencing.push(timelineEvent.source.issue.number);
|
||||
}
|
||||
}
|
||||
@@ -454,16 +375,16 @@ class OctoKitIssue extends OctoKit {
|
||||
for (const id of crossReferencing.reverse()) {
|
||||
const closed = await new OctoKitIssue(this.token, this.params, {
|
||||
number: id,
|
||||
}).getClosingInfo(alreadyChecked);
|
||||
}, this.options).getClosingInfo(alreadyChecked);
|
||||
if (closed) {
|
||||
if (Math.abs(closed.timestamp - ((_h = (await this.getIssue()).closedAt) !== null && _h !== void 0 ? _h : 0)) < 5000) {
|
||||
if (Math.abs(closed.timestamp - ((_g = (await this.getIssue()).closedAt) !== null && _g !== void 0 ? _g : 0)) < 5000) {
|
||||
closingCommit = closed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(0, utils_1.safeLog)(`Got ${JSON.stringify(closingCommit)} as closing commit of ${this.issueData.number}`);
|
||||
console.log(`Got ${JSON.stringify(closingCommit)} as closing commit of ${this.issueData.number}`);
|
||||
return closingCommit;
|
||||
}
|
||||
}
|
||||
|
||||
+170
-259
@@ -3,242 +3,181 @@
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { getOctokit } from '@actions/github';
|
||||
import type { RequestError } from '@octokit/request-error';
|
||||
import { exec } from 'child_process';
|
||||
import { IssueGetResponse, IssuesGetResponseMilestone } from '../common/OctokitTypings';
|
||||
import { safeLog } from '../common/utils';
|
||||
import { Comment, GitHub, GitHubIssue, Issue, Milestone, Query, User } from './api';
|
||||
import { debug } from '@actions/core'
|
||||
import { GitHub as GitHubAPI } from '@actions/github'
|
||||
import { Octokit } from '@octokit/rest'
|
||||
import { exec } from 'child_process'
|
||||
import { Comment, GitHub, GitHubIssue, Issue, Query, User } from './api'
|
||||
|
||||
let numRequests = 0;
|
||||
export const getNumRequests = () => numRequests;
|
||||
let numRequests = 0
|
||||
export const getNumRequests = () => numRequests
|
||||
|
||||
export class OctoKit implements GitHub {
|
||||
private _octokit: ReturnType<typeof getOctokit>;
|
||||
protected get octokit(): ReturnType<typeof getOctokit> {
|
||||
numRequests++;
|
||||
return this._octokit;
|
||||
private _octokit: GitHubAPI
|
||||
protected get octokit(): GitHubAPI {
|
||||
numRequests++
|
||||
return this._octokit
|
||||
}
|
||||
|
||||
// when in readonly mode, record labels just-created so at to not throw unneccesary errors
|
||||
protected mockLabels: Set<string> = new Set();
|
||||
|
||||
public readonly repoName: string;
|
||||
public readonly repoOwner: string;
|
||||
protected mockLabels: Set<string> = new Set()
|
||||
|
||||
constructor(
|
||||
protected token: string,
|
||||
protected params: { repo: string; owner: string },
|
||||
protected options: { readonly: boolean } = { readonly: false },
|
||||
) {
|
||||
this._octokit = getOctokit(token);
|
||||
this.repoName = params.repo;
|
||||
this.repoOwner = params.owner;
|
||||
}
|
||||
|
||||
getIssueByNumber(number: number) {
|
||||
return new OctoKitIssue(this.token, this.params, { number: number });
|
||||
this._octokit = new GitHubAPI(token)
|
||||
}
|
||||
|
||||
// TODO: just iterate over the issues in a page here instead of making caller do it
|
||||
async *query(query: Query): AsyncIterableIterator<GitHubIssue[]> {
|
||||
const q = query.q + ` repo:${this.params.owner}/${this.params.repo}`;
|
||||
const q = query.q + ` repo:${this.params.owner}/${this.params.repo}`
|
||||
console.log(`Querying for ${q}:`)
|
||||
|
||||
const options = {
|
||||
const options = this.octokit.search.issuesAndPullRequests.endpoint.merge({
|
||||
...query,
|
||||
q,
|
||||
per_page: 100,
|
||||
headers: { Accept: 'application/vnd.github.squirrel-girl-preview+json' },
|
||||
};
|
||||
})
|
||||
|
||||
let pageNum = 0;
|
||||
let pageNum = 0
|
||||
|
||||
const timeout = async () => {
|
||||
if (pageNum < 2) {
|
||||
/* pass */
|
||||
} else if (pageNum < 4) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 10000));
|
||||
await new Promise((resolve) => setTimeout(resolve, 3000))
|
||||
} else {
|
||||
await new Promise((resolve) => setTimeout(resolve, 30000));
|
||||
await new Promise((resolve) => setTimeout(resolve, 30000))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
for await (const pageResponse of this.octokit.paginate.iterator(
|
||||
this.octokit.rest.search.issuesAndPullRequests,
|
||||
options,
|
||||
)) {
|
||||
await timeout();
|
||||
numRequests++;
|
||||
const page = pageResponse.data;
|
||||
safeLog(`Page ${++pageNum}: ${page.map(({ number }) => number).join(' ')}`);
|
||||
for await (const pageResponse of this.octokit.paginate.iterator(options)) {
|
||||
await timeout()
|
||||
numRequests++
|
||||
const page: Array<Octokit.SearchIssuesAndPullRequestsResponseItemsItem> = pageResponse.data
|
||||
console.log(`Page ${++pageNum}: ${page.map(({ number }) => number).join(' ')}`)
|
||||
yield page.map(
|
||||
(issue) =>
|
||||
new OctoKitIssue(this.token, this.params, this.octokitIssueToIssue(issue), this.options),
|
||||
);
|
||||
(issue) => new OctoKitIssue(this.token, this.params, this.octokitIssueToIssue(issue), this.options),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
async createIssue(owner: string, repo: string, title: string, body: string): Promise<void> {
|
||||
safeLog(`Creating issue \`${title}\` on ${owner}/${repo}`);
|
||||
if (!this.options.readonly) await this.octokit.rest.issues.create({ owner, repo, title, body });
|
||||
debug(`Creating issue \`${title}\` on ${owner}/${repo}`)
|
||||
if (!this.options.readonly) await this.octokit.issues.create({ owner, repo, title, body })
|
||||
}
|
||||
|
||||
protected octokitIssueToIssue(issue: IssueGetResponse): Issue {
|
||||
protected octokitIssueToIssue(
|
||||
issue: Octokit.IssuesGetResponse | Octokit.SearchIssuesAndPullRequestsResponseItemsItem,
|
||||
): Issue {
|
||||
return {
|
||||
author: { name: issue.user?.login ?? 'unkown', isGitHubApp: issue.user?.type === 'Bot' },
|
||||
body: issue.body ?? '',
|
||||
author: { name: issue.user.login, isGitHubApp: issue.user.type === 'Bot' },
|
||||
body: issue.body,
|
||||
number: issue.number,
|
||||
title: issue.title,
|
||||
isPr: !!issue.pull_request?.html_url,
|
||||
labels: issue.labels.map((label) => (typeof label === 'string' ? label : label.name ?? '')),
|
||||
labels: (issue.labels as Octokit.IssuesGetLabelResponse[]).map((label) => label.name),
|
||||
open: issue.state === 'open',
|
||||
locked: (issue as any).locked,
|
||||
numComments: issue.comments,
|
||||
reactions: (issue as any).reactions,
|
||||
assignee: issue.assignee?.login ?? (issue as IssueGetResponse).assignees?.[0]?.login,
|
||||
assignees: (issue as IssueGetResponse).assignees?.map((assignee) => assignee.login) ?? [],
|
||||
milestone: issue.milestone ? this.octokitMilestoneToMilestone(issue.milestone) : null,
|
||||
assignee: issue.assignee?.login ?? (issue as any).assignees?.[0]?.login,
|
||||
milestoneId: issue.milestone?.number ?? null,
|
||||
createdAt: +new Date(issue.created_at),
|
||||
updatedAt: +new Date(issue.updated_at),
|
||||
closedAt: issue.closed_at ? +new Date(issue.closed_at as unknown as string) : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
protected octokitMilestoneToMilestone(milestone: IssuesGetResponseMilestone): Milestone | null {
|
||||
if (milestone?.number === undefined) {
|
||||
return null;
|
||||
closedAt: issue.closed_at ? +new Date((issue.closed_at as unknown) as string) : undefined,
|
||||
}
|
||||
return {
|
||||
title: milestone.title,
|
||||
milestoneId: milestone.number,
|
||||
// Remove the time portions of the dates as they're not important
|
||||
createdAt: milestone.created_at !== null ? new Date(milestone.created_at.split('T')[0]) : null,
|
||||
dueOn: milestone.due_on !== null ? new Date(milestone.due_on.split('T')[0]) : null,
|
||||
closedAt: milestone.closed_at !== null ? new Date(milestone.closed_at.split('T')[0]) : null,
|
||||
description: milestone.description ?? '',
|
||||
numClosedIssues: milestone.closed_issues,
|
||||
numOpenIssues: milestone.open_issues,
|
||||
state: milestone.state === 'open' ? 'open' : 'closed',
|
||||
};
|
||||
}
|
||||
|
||||
private writeAccessCache: Record<string, boolean> = {};
|
||||
private writeAccessCache: Record<string, boolean> = {}
|
||||
async hasWriteAccess(user: User): Promise<boolean> {
|
||||
if (user.name in this.writeAccessCache) {
|
||||
safeLog('Got permissions from cache for ' + user);
|
||||
return this.writeAccessCache[user.name];
|
||||
debug('Got permissions from cache for ' + user)
|
||||
return this.writeAccessCache[user.name]
|
||||
}
|
||||
safeLog('Fetching permissions for ' + user.name);
|
||||
debug('Fetching permissions for ' + user)
|
||||
const permissions = (
|
||||
await this.octokit.rest.repos.getCollaboratorPermissionLevel({
|
||||
await this.octokit.repos.getCollaboratorPermissionLevel({
|
||||
...this.params,
|
||||
username: user.name,
|
||||
})
|
||||
).data.permission;
|
||||
return (this.writeAccessCache[user.name] = permissions === 'admin' || permissions === 'write');
|
||||
).data.permission
|
||||
return (this.writeAccessCache[user.name] = permissions === 'admin' || permissions === 'write')
|
||||
}
|
||||
|
||||
async repoHasLabel(name: string): Promise<boolean> {
|
||||
try {
|
||||
await this.octokit.rest.issues.getLabel({ ...this.params, name });
|
||||
return true;
|
||||
await this.octokit.issues.getLabel({ ...this.params, name })
|
||||
return true
|
||||
} catch (err) {
|
||||
const statusErorr = err as RequestError;
|
||||
if (statusErorr.status === 404) {
|
||||
return this.options.readonly && this.mockLabels.has(name);
|
||||
if (err.status === 404) {
|
||||
return this.options.readonly && this.mockLabels.has(name)
|
||||
}
|
||||
throw err;
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
async createLabel(name: string, color: string, description: string): Promise<void> {
|
||||
safeLog('Creating label ' + name);
|
||||
debug('Creating label ' + name)
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.createLabel({ ...this.params, color, description, name });
|
||||
else this.mockLabels.add(name);
|
||||
await this.octokit.issues.createLabel({ ...this.params, color, description, name })
|
||||
else this.mockLabels.add(name)
|
||||
}
|
||||
|
||||
async deleteLabel(name: string): Promise<void> {
|
||||
safeLog('Deleting label ' + name);
|
||||
debug('Deleting label ' + name)
|
||||
try {
|
||||
if (!this.options.readonly) await this.octokit.rest.issues.deleteLabel({ ...this.params, name });
|
||||
if (!this.options.readonly) await this.octokit.issues.deleteLabel({ ...this.params, name })
|
||||
} catch (err) {
|
||||
const statusErorr = err as RequestError;
|
||||
if (statusErorr.status === 404) {
|
||||
return;
|
||||
if (err.status === 404) {
|
||||
return
|
||||
}
|
||||
throw err;
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
async readConfig(path: string): Promise<any> {
|
||||
safeLog('Reading config at ' + path);
|
||||
const repoPath = `.github/${path}.json`;
|
||||
debug('Reading config at ' + path)
|
||||
const repoPath = `.github/${path}.json`
|
||||
try {
|
||||
const data = (await this.octokit.rest.repos.getContent({ ...this.params, path: repoPath })).data;
|
||||
if ('type' in data && data.type === 'file' && 'content' in data) {
|
||||
const data = (await this.octokit.repos.getContents({ ...this.params, path: repoPath })).data
|
||||
|
||||
if ('type' in data && data.type === 'file') {
|
||||
if (data.encoding === 'base64' && data.content) {
|
||||
return JSON.parse(Buffer.from(data.content, 'base64').toString('utf-8'));
|
||||
return JSON.parse(Buffer.from(data.content, 'base64').toString('utf-8'))
|
||||
}
|
||||
throw Error(`Could not read contents "${data.content}" in encoding "${data.encoding}"`);
|
||||
throw Error(`Could not read contents "${data.content}" in encoding "${data.encoding}"`)
|
||||
}
|
||||
throw Error('Found directory at config path when expecting file' + JSON.stringify(data));
|
||||
throw Error('Found directory at config path when expecting file' + JSON.stringify(data))
|
||||
} catch (e) {
|
||||
throw Error('Error with config file at ' + repoPath + ': ' + JSON.stringify(e));
|
||||
throw Error('Error with config file at ' + repoPath + ': ' + JSON.stringify(e))
|
||||
}
|
||||
}
|
||||
|
||||
async releaseContainsCommit(release: string, commit: string): Promise<'yes' | 'no' | 'unknown'> {
|
||||
const isHash = (s: string) => /^[a-fA-F0-9]*$/.test(s);
|
||||
if (!isHash(release) || !isHash(commit)) return 'unknown';
|
||||
return new Promise((resolve, reject) =>
|
||||
exec(`git -C ./repo merge-base --is-ancestor ${commit} ${release}`, (err) => {
|
||||
if (!err || err.code === 1) {
|
||||
resolve(!err ? 'yes' : 'no');
|
||||
resolve(!err ? 'yes' : 'no')
|
||||
} else if (err.message.includes(`Not a valid commit name ${release}`)) {
|
||||
// release branch is forked. Probably in endgame. Not released.
|
||||
resolve('no');
|
||||
resolve('no')
|
||||
} else if (err.message.includes(`Not a valid commit name ${commit}`)) {
|
||||
// commit is probably in a different repo.
|
||||
resolve('unknown');
|
||||
resolve('unknown')
|
||||
} else {
|
||||
reject(err);
|
||||
reject(err)
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async getCurrentRepoMilestone(): Promise<number | undefined> {
|
||||
safeLog(`Getting repo milestone for ${this.params.owner}/${this.params.repo}`);
|
||||
// Fetch all milestones open for this repo
|
||||
const allMilestones = (
|
||||
await this.octokit.rest.issues.listMilestones({
|
||||
owner: this.params.owner,
|
||||
repo: this.params.repo,
|
||||
state: 'open',
|
||||
sort: 'due_on',
|
||||
direction: 'asc',
|
||||
})
|
||||
).data;
|
||||
const currentDate = new Date();
|
||||
const possibleMilestones = allMilestones
|
||||
.filter(
|
||||
(milestone) =>
|
||||
new Date(milestone.due_on === null ? currentDate : milestone.due_on) > currentDate &&
|
||||
currentDate > new Date(milestone.created_at) &&
|
||||
!milestone.title.includes('Recovery'),
|
||||
)
|
||||
.sort((a, b) => +new Date(a.due_on ?? currentDate) - +new Date(b.due_on ?? currentDate));
|
||||
if (possibleMilestones.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
return possibleMilestones[0].number;
|
||||
)
|
||||
}
|
||||
|
||||
async dispatch(title: string): Promise<void> {
|
||||
safeLog('Dispatching ' + title);
|
||||
debug('Dispatching ' + title)
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.repos.createDispatchEvent({ ...this.params, event_type: title });
|
||||
await this.octokit.repos.createDispatchEvent({ ...this.params, event_type: title })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,206 +188,184 @@ export class OctoKitIssue extends OctoKit implements GitHubIssue {
|
||||
private issueData: { number: number } | Issue,
|
||||
options: { readonly: boolean } = { readonly: false },
|
||||
) {
|
||||
super(token, params, options);
|
||||
safeLog('running bot on issue', issueData.number);
|
||||
super(token, params, options)
|
||||
console.log('running bot on issue', issueData.number)
|
||||
}
|
||||
|
||||
async addAssignee(assignee: string): Promise<void> {
|
||||
safeLog('Adding assignee ' + assignee + ' to ' + this.issueData.number);
|
||||
debug('Adding assignee ' + assignee + ' to ' + this.issueData.number)
|
||||
if (!this.options.readonly) {
|
||||
await this.octokit.rest.issues.addAssignees({
|
||||
await this.octokit.issues.addAssignees({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
assignees: [assignee],
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async removeAssignee(assignee: string): Promise<void> {
|
||||
safeLog('Removing assignee ' + assignee + ' to ' + this.issueData.number);
|
||||
debug('Removing assignee ' + assignee + ' to ' + this.issueData.number)
|
||||
if (!this.options.readonly) {
|
||||
await this.octokit.rest.issues.removeAssignees({
|
||||
await this.octokit.issues.removeAssignees({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
assignees: [assignee],
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async closeIssue(reason: 'completed' | 'not_planned'): Promise<void> {
|
||||
safeLog('Closing issue ' + this.issueData.number);
|
||||
if (!this.options.readonly) {
|
||||
const issue = await this.octokit.rest.issues.get({
|
||||
async closeIssue(): Promise<void> {
|
||||
debug('Closing issue ' + this.issueData.number)
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.issues.update({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
});
|
||||
// Don't close already closed issues even if it means changing the state
|
||||
if (issue.data.state === 'closed') {
|
||||
return;
|
||||
}
|
||||
await this.octokit.rest.issues
|
||||
.update({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
state: 'closed',
|
||||
state_reason: reason,
|
||||
})
|
||||
.catch((e) => {
|
||||
safeLog('error closing issue:', e);
|
||||
});
|
||||
}
|
||||
state: 'closed',
|
||||
})
|
||||
}
|
||||
|
||||
async reopenIssue(): Promise<void> {
|
||||
safeLog('Reopening issue ' + this.issueData.number);
|
||||
debug('Reopening issue ' + this.issueData.number)
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.update({
|
||||
await this.octokit.issues.update({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
state: 'open',
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
async lockIssue(): Promise<void> {
|
||||
safeLog('Locking issue ' + this.issueData.number);
|
||||
debug('Locking issue ' + this.issueData.number)
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.lock({ ...this.params, issue_number: this.issueData.number });
|
||||
}
|
||||
|
||||
async unlockIssue(): Promise<void> {
|
||||
safeLog('Unlocking issue ' + this.issueData.number);
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.unlock({ ...this.params, issue_number: this.issueData.number });
|
||||
await this.octokit.issues.lock({ ...this.params, issue_number: this.issueData.number })
|
||||
}
|
||||
|
||||
async getIssue(): Promise<Issue> {
|
||||
if (isIssue(this.issueData)) {
|
||||
safeLog('Got issue data from query result ' + this.issueData.number);
|
||||
return this.issueData;
|
||||
debug('Got issue data from query result ' + this.issueData.number)
|
||||
return this.issueData
|
||||
}
|
||||
|
||||
safeLog('Fetching issue ' + this.issueData.number);
|
||||
console.log('Fetching issue ' + this.issueData.number)
|
||||
const issue = (
|
||||
await this.octokit.rest.issues.get({
|
||||
await this.octokit.issues.get({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
mediaType: { previews: ['squirrel-girl'] },
|
||||
})
|
||||
).data;
|
||||
return (this.issueData = this.octokitIssueToIssue(issue));
|
||||
).data
|
||||
return (this.issueData = this.octokitIssueToIssue(issue))
|
||||
}
|
||||
|
||||
async postComment(body: string): Promise<void> {
|
||||
safeLog(`Posting comment on ${this.issueData.number}`);
|
||||
debug(`Posting comment ${body} on ${this.issueData.number}`)
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.createComment({
|
||||
await this.octokit.issues.createComment({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
body,
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
async deleteComment(id: number): Promise<void> {
|
||||
safeLog(`Deleting comment ${id} on ${this.issueData.number}`);
|
||||
debug(`Deleting comment ${id} on ${this.issueData.number}`)
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.deleteComment({
|
||||
await this.octokit.issues.deleteComment({
|
||||
owner: this.params.owner,
|
||||
repo: this.params.repo,
|
||||
comment_id: id,
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
async setMilestone(milestoneId: number) {
|
||||
safeLog(`Setting milestone for ${this.issueData.number} to ${milestoneId}`);
|
||||
debug(`Setting milestone for ${this.issueData.number} to ${milestoneId}`)
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.update({
|
||||
await this.octokit.issues.update({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
milestone: milestoneId,
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
async *getComments(last?: boolean): AsyncIterableIterator<Comment[]> {
|
||||
safeLog('Fetching comments for ' + this.issueData.number);
|
||||
debug('Fetching comments for ' + this.issueData.number)
|
||||
|
||||
const response = this.octokit.paginate.iterator(this.octokit.rest.issues.listComments, {
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
per_page: 100,
|
||||
...(last ? { per_page: 1, page: (await this.getIssue()).numComments } : {}),
|
||||
});
|
||||
const response = this.octokit.paginate.iterator(
|
||||
this.octokit.issues.listComments.endpoint.merge({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
per_page: 100,
|
||||
...(last ? { per_page: 1, page: (await this.getIssue()).numComments } : {}),
|
||||
}),
|
||||
)
|
||||
|
||||
for await (const page of response) {
|
||||
numRequests++;
|
||||
yield page.data.map((comment) => ({
|
||||
author: { name: comment.user?.login ?? '', isGitHubApp: comment.user?.type === 'Bot' },
|
||||
body: comment.body ?? '',
|
||||
numRequests++
|
||||
yield (page.data as Octokit.IssuesListCommentsResponseItem[]).map((comment) => ({
|
||||
author: { name: comment.user.login, isGitHubApp: comment.user.type === 'Bot' },
|
||||
body: comment.body,
|
||||
id: comment.id,
|
||||
timestamp: +new Date(comment.created_at),
|
||||
}));
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
async addLabel(name: string): Promise<void> {
|
||||
safeLog(`Adding label ${name} to ${this.issueData.number}`);
|
||||
debug(`Adding label ${name} to ${this.issueData.number}`)
|
||||
if (!(await this.repoHasLabel(name))) {
|
||||
throw Error(`Action could not execute becuase label ${name} is not defined.`);
|
||||
throw Error(`Action could not execute becuase label ${name} is not defined.`)
|
||||
}
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.addLabels({
|
||||
await this.octokit.issues.addLabels({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
labels: [name],
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
async getAssigner(assignee: string): Promise<string> {
|
||||
const options = {
|
||||
const options = this.octokit.issues.listEventsForTimeline.endpoint.merge({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
};
|
||||
})
|
||||
|
||||
let assigner: string | undefined;
|
||||
let assigner: string | undefined
|
||||
|
||||
for await (const event of this.octokit.paginate.iterator(
|
||||
this.octokit.rest.issues.listEventsForTimeline,
|
||||
options,
|
||||
)) {
|
||||
numRequests++;
|
||||
const timelineEvents = event.data;
|
||||
for await (const event of this.octokit.paginate.iterator(options)) {
|
||||
numRequests++
|
||||
const timelineEvents = event.data as Octokit.IssuesListEventsForTimelineResponseItem[]
|
||||
for (const timelineEvent of timelineEvents) {
|
||||
if (timelineEvent.event === 'assigned' && timelineEvent.assignee?.login === assignee) {
|
||||
assigner = timelineEvent.actor?.login;
|
||||
if (
|
||||
timelineEvent.event === 'assigned' &&
|
||||
(timelineEvent as any).assignee.login === assignee
|
||||
) {
|
||||
assigner = timelineEvent.actor.login
|
||||
}
|
||||
}
|
||||
if (assigner) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!assigner) {
|
||||
throw Error('Expected to find ' + assignee + ' in issue timeline but did not.');
|
||||
throw Error('Expected to find ' + assignee + ' in issue timeline but did not.')
|
||||
}
|
||||
|
||||
return assigner;
|
||||
return assigner
|
||||
}
|
||||
|
||||
async removeLabel(name: string): Promise<void> {
|
||||
safeLog(`Removing label ${name} from ${this.issueData.number}`);
|
||||
debug(`Removing label ${name} from ${this.issueData.number}`)
|
||||
try {
|
||||
if (!this.options.readonly)
|
||||
await this.octokit.rest.issues.removeLabel({
|
||||
await this.octokit.issues.removeLabel({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
name,
|
||||
});
|
||||
})
|
||||
} catch (err) {
|
||||
const statusErorr = err as RequestError;
|
||||
if (statusErorr.status === 404) {
|
||||
safeLog(`Label ${name} not found on issue`);
|
||||
return;
|
||||
if (err.status === 404) {
|
||||
console.log(`Label ${name} not found on issue`)
|
||||
return
|
||||
}
|
||||
throw err;
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,49 +373,43 @@ export class OctoKitIssue extends OctoKit implements GitHubIssue {
|
||||
alreadyChecked: number[] = [],
|
||||
): Promise<{ hash: string | undefined; timestamp: number } | undefined> {
|
||||
if (alreadyChecked.includes(this.issueData.number)) {
|
||||
return undefined;
|
||||
return undefined
|
||||
}
|
||||
alreadyChecked.push(this.issueData.number);
|
||||
alreadyChecked.push(this.issueData.number)
|
||||
|
||||
if ((await this.getIssue()).open) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
const closingHashComment =
|
||||
/(?:\\|\/)closedWith (?:https:\/\/github\.com\/microsoft\/vscode\/commit\/)?([a-fA-F0-9]{7,40})/;
|
||||
const closingHashComment = /(?:\\|\/)closedWith (\S*)/
|
||||
|
||||
const options = {
|
||||
const options = this.octokit.issues.listEventsForTimeline.endpoint.merge({
|
||||
...this.params,
|
||||
issue_number: this.issueData.number,
|
||||
};
|
||||
let closingCommit: { hash: string | undefined; timestamp: number } | undefined;
|
||||
const crossReferencing: number[] = [];
|
||||
for await (const event of this.octokit.paginate.iterator(
|
||||
this.octokit.rest.issues.listEventsForTimeline,
|
||||
options,
|
||||
)) {
|
||||
numRequests++;
|
||||
})
|
||||
let closingCommit: { hash: string | undefined; timestamp: number } | undefined
|
||||
const crossReferencing: number[] = []
|
||||
for await (const event of this.octokit.paginate.iterator(options)) {
|
||||
numRequests++
|
||||
|
||||
const timelineEvents = event.data;
|
||||
const timelineEvents = event.data as Octokit.IssuesListEventsForTimelineResponseItem[]
|
||||
for (const timelineEvent of timelineEvents) {
|
||||
if (
|
||||
(timelineEvent.event === 'closed' || timelineEvent.event === 'merged') &&
|
||||
timelineEvent.created_at &&
|
||||
timelineEvent.commit_id &&
|
||||
timelineEvent.commit_url
|
||||
?.toLowerCase()
|
||||
.toLowerCase()
|
||||
.includes(`/${this.params.owner}/${this.params.repo}/`.toLowerCase())
|
||||
) {
|
||||
closingCommit = {
|
||||
hash: timelineEvent.commit_id,
|
||||
timestamp: +new Date(timelineEvent.created_at),
|
||||
};
|
||||
}
|
||||
}
|
||||
if (timelineEvent.event === 'reopened') {
|
||||
closingCommit = undefined;
|
||||
closingCommit = undefined
|
||||
}
|
||||
if (
|
||||
timelineEvent.created_at &&
|
||||
timelineEvent.event === 'commented' &&
|
||||
!((timelineEvent as any).body as string)?.includes('UNABLE_TO_LOCATE_COMMIT_MESSAGE') &&
|
||||
closingHashComment.test((timelineEvent as any).body)
|
||||
@@ -506,7 +417,7 @@ export class OctoKitIssue extends OctoKit implements GitHubIssue {
|
||||
closingCommit = {
|
||||
hash: closingHashComment.exec((timelineEvent as any).body)![1],
|
||||
timestamp: +new Date(timelineEvent.created_at),
|
||||
};
|
||||
}
|
||||
}
|
||||
if (
|
||||
timelineEvent.event === 'cross-referenced' &&
|
||||
@@ -515,7 +426,7 @@ export class OctoKitIssue extends OctoKit implements GitHubIssue {
|
||||
`/${this.params.owner}/${this.params.repo}/`.toLowerCase(),
|
||||
)
|
||||
) {
|
||||
crossReferencing.push((timelineEvent as any).source.issue.number);
|
||||
crossReferencing.push((timelineEvent as any).source.issue.number)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -526,19 +437,19 @@ export class OctoKitIssue extends OctoKit implements GitHubIssue {
|
||||
for (const id of crossReferencing.reverse()) {
|
||||
const closed = await new OctoKitIssue(this.token, this.params, {
|
||||
number: id,
|
||||
}).getClosingInfo(alreadyChecked);
|
||||
}, this.options).getClosingInfo(alreadyChecked)
|
||||
|
||||
if (closed) {
|
||||
if (Math.abs(closed.timestamp - ((await this.getIssue()).closedAt ?? 0)) < 5000) {
|
||||
closingCommit = closed;
|
||||
break;
|
||||
closingCommit = closed
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
safeLog(`Got ${JSON.stringify(closingCommit)} as closing commit of ${this.issueData.number}`);
|
||||
return closingCommit;
|
||||
console.log(`Got ${JSON.stringify(closingCommit)} as closing commit of ${this.issueData.number}`)
|
||||
return closingCommit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -553,7 +464,7 @@ function isIssue(object: any): object is Issue {
|
||||
'number' in object &&
|
||||
'numComments' in object &&
|
||||
'reactions' in object &&
|
||||
'milestoneId' in object;
|
||||
'milestoneId' in object
|
||||
|
||||
return isIssue;
|
||||
return isIssue
|
||||
}
|
||||
|
||||
@@ -11,50 +11,51 @@ const utils_1 = require("./utils");
|
||||
const core_1 = require("@actions/core");
|
||||
class Action {
|
||||
constructor() {
|
||||
this.token = (0, utils_1.getRequiredInput)('token');
|
||||
this.username = (0, github_1.getOctokit)(this.token)
|
||||
.rest.users.getAuthenticated()
|
||||
.then((v) => { var _a; return (_a = v.data.name) !== null && _a !== void 0 ? _a : 'unknown'; }, () => 'unknown');
|
||||
this.token = utils_1.getRequiredInput('token');
|
||||
this.username = new github_1.GitHub(this.token).users.getAuthenticated().then((v) => v.data.name);
|
||||
}
|
||||
async run() {
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
||||
console.log('running ', this.id, 'with context', {
|
||||
...github_1.context,
|
||||
payload: {
|
||||
issue: (_b = (_a = github_1.context.payload) === null || _a === void 0 ? void 0 : _a.issue) === null || _b === void 0 ? void 0 : _b.number,
|
||||
label: (_d = (_c = github_1.context.payload) === null || _c === void 0 ? void 0 : _c.label) === null || _d === void 0 ? void 0 : _d.name,
|
||||
repository: (_f = (_e = github_1.context.payload) === null || _e === void 0 ? void 0 : _e.repository) === null || _f === void 0 ? void 0 : _f.html_url,
|
||||
sender: (_j = (_h = (_g = github_1.context.payload) === null || _g === void 0 ? void 0 : _g.sender) === null || _h === void 0 ? void 0 : _h.login) !== null && _j !== void 0 ? _j : (_l = (_k = github_1.context.payload) === null || _k === void 0 ? void 0 : _k.sender) === null || _l === void 0 ? void 0 : _l.type,
|
||||
},
|
||||
});
|
||||
if (utils_1.errorLoggingIssue) {
|
||||
const { repo, issue, owner } = utils_1.errorLoggingIssue;
|
||||
if (github_1.context.repo.repo === repo &&
|
||||
github_1.context.repo.owner === owner &&
|
||||
((_a = github_1.context.payload.issue) === null || _a === void 0 ? void 0 : _a.number) === issue) {
|
||||
return (0, utils_1.safeLog)('refusing to run on error logging issue to prevent cascading errors');
|
||||
((_m = github_1.context.payload.issue) === null || _m === void 0 ? void 0 : _m.number) === issue) {
|
||||
return console.log('refusing to run on error logging issue to prevent cascading errors');
|
||||
}
|
||||
}
|
||||
try {
|
||||
const token = (0, utils_1.getRequiredInput)('token');
|
||||
const readonly = !!(0, core_1.getInput)('readonly');
|
||||
const issue = (_b = github_1.context === null || github_1.context === void 0 ? void 0 : github_1.context.issue) === null || _b === void 0 ? void 0 : _b.number;
|
||||
const token = utils_1.getRequiredInput('token');
|
||||
const readonly = !!core_1.getInput('readonly');
|
||||
const issue = (_o = github_1.context === null || github_1.context === void 0 ? void 0 : github_1.context.issue) === null || _o === void 0 ? void 0 : _o.number;
|
||||
if (issue) {
|
||||
const octokit = new octokit_1.OctoKitIssue(token, github_1.context.repo, { number: issue }, { readonly });
|
||||
if (github_1.context.eventName === 'issue_comment') {
|
||||
await this.onCommented(octokit, (_c = github_1.context.payload.comment) === null || _c === void 0 ? void 0 : _c.body, github_1.context.actor);
|
||||
await this.onCommented(octokit, github_1.context.payload.comment.body, github_1.context.actor);
|
||||
}
|
||||
else if (github_1.context.eventName === 'issues' ||
|
||||
github_1.context.eventName === 'pull_request' ||
|
||||
github_1.context.eventName === 'pull_request_target') {
|
||||
else if (github_1.context.eventName === 'issues') {
|
||||
switch (github_1.context.payload.action) {
|
||||
case 'opened':
|
||||
case 'ready_for_review':
|
||||
await this.onOpened(octokit, github_1.context.payload);
|
||||
await this.onOpened(octokit);
|
||||
break;
|
||||
case 'reopened':
|
||||
await this.onReopened(octokit);
|
||||
break;
|
||||
case 'closed':
|
||||
await this.onClosed(octokit, github_1.context.payload);
|
||||
await this.onClosed(octokit);
|
||||
break;
|
||||
case 'labeled':
|
||||
await this.onLabeled(octokit, github_1.context.payload.label.name);
|
||||
break;
|
||||
case 'assigned':
|
||||
await this.onAssigned(octokit, github_1.context.payload.assignee.login);
|
||||
break;
|
||||
case 'unassigned':
|
||||
await this.onUnassigned(octokit, github_1.context.payload.assignee.login);
|
||||
break;
|
||||
@@ -69,32 +70,22 @@ class Action {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (github_1.context.eventName === 'create') {
|
||||
await this.onCreated(new octokit_1.OctoKit(token, github_1.context.repo, { readonly }), (_d = github_1.context === null || github_1.context === void 0 ? void 0 : github_1.context.payload) === null || _d === void 0 ? void 0 : _d.ref, (_f = (_e = github_1.context === null || github_1.context === void 0 ? void 0 : github_1.context.payload) === null || _e === void 0 ? void 0 : _e.sender) === null || _f === void 0 ? void 0 : _f.login);
|
||||
}
|
||||
else {
|
||||
await this.onTriggered(new octokit_1.OctoKit(token, github_1.context.repo, { readonly }));
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
const err = e;
|
||||
try {
|
||||
await this.error(err);
|
||||
}
|
||||
catch {
|
||||
(0, utils_1.safeLog)((err === null || err === void 0 ? void 0 : err.stack) || (err === null || err === void 0 ? void 0 : err.message) || String(e));
|
||||
}
|
||||
await this.error(e);
|
||||
}
|
||||
const usage = await (0, utils_1.getRateLimit)(this.token);
|
||||
const usage = await utils_1.getRateLimit(this.token);
|
||||
}
|
||||
async error(error) {
|
||||
var _a;
|
||||
const details = {
|
||||
message: `${error.message}\n${error.stack}`,
|
||||
id: this.id,
|
||||
user: await this.username,
|
||||
};
|
||||
if ((_a = github_1.context.issue) === null || _a === void 0 ? void 0 : _a.number)
|
||||
if (github_1.context.issue.number)
|
||||
details.issue = github_1.context.issue.number;
|
||||
const rendered = `
|
||||
Message: ${details.message}
|
||||
@@ -103,34 +94,28 @@ Actor: ${details.user}
|
||||
|
||||
ID: ${details.id}
|
||||
`;
|
||||
await (0, utils_1.logErrorToIssue)(rendered, true, this.token);
|
||||
(0, core_1.setFailed)(error.message);
|
||||
await utils_1.logErrorToIssue(rendered, true, this.token);
|
||||
core_1.setFailed(error.message);
|
||||
}
|
||||
async onTriggered(_octokit) {
|
||||
throw Error('not implemented');
|
||||
}
|
||||
async onCreated(_octokit, _ref, _creator) {
|
||||
throw Error('not implemented');
|
||||
}
|
||||
async onEdited(_issue) {
|
||||
throw Error('not implemented');
|
||||
}
|
||||
async onLabeled(_issue, _label) {
|
||||
throw Error('not implemented');
|
||||
}
|
||||
async onAssigned(_issue, _assignee) {
|
||||
async onUnassigned(_issue, _label) {
|
||||
throw Error('not implemented');
|
||||
}
|
||||
async onUnassigned(_issue, _assignee) {
|
||||
throw Error('not implemented');
|
||||
}
|
||||
async onOpened(_issue, _payload) {
|
||||
async onOpened(_issue) {
|
||||
throw Error('not implemented');
|
||||
}
|
||||
async onReopened(_issue) {
|
||||
throw Error('not implemented');
|
||||
}
|
||||
async onClosed(_issue, _payload) {
|
||||
async onClosed(_issue) {
|
||||
throw Error('not implemented');
|
||||
}
|
||||
async onMilestoned(_issue) {
|
||||
|
||||
@@ -3,102 +3,87 @@
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { OctoKit, OctoKitIssue, getNumRequests } from '../api/octokit';
|
||||
import { context, getOctokit } from '@actions/github';
|
||||
import { getRequiredInput, logErrorToIssue, getRateLimit, errorLoggingIssue, safeLog } from './utils';
|
||||
import { getInput, setFailed } from '@actions/core';
|
||||
import { WebhookPayload } from '@actions/github/lib/interfaces';
|
||||
import { OctoKit, OctoKitIssue, getNumRequests } from '../api/octokit'
|
||||
import { context, GitHub } from '@actions/github'
|
||||
import { getRequiredInput, logErrorToIssue, getRateLimit, errorLoggingIssue } from './utils'
|
||||
import { getInput, setFailed } from '@actions/core'
|
||||
|
||||
export abstract class Action {
|
||||
abstract id: string;
|
||||
abstract id: string
|
||||
|
||||
private username: Promise<string>;
|
||||
private token = getRequiredInput('token');
|
||||
private username: Promise<string>
|
||||
private token = getRequiredInput('token')
|
||||
|
||||
constructor() {
|
||||
this.username = getOctokit(this.token)
|
||||
.rest.users.getAuthenticated()
|
||||
.then(
|
||||
(v) => v.data.name ?? 'unknown',
|
||||
() => 'unknown',
|
||||
);
|
||||
this.username = new GitHub(this.token).users.getAuthenticated().then((v) => v.data.name)
|
||||
}
|
||||
|
||||
public async run() {
|
||||
console.log('running ', this.id, 'with context', {
|
||||
...context,
|
||||
payload: {
|
||||
issue: context.payload?.issue?.number,
|
||||
label: context.payload?.label?.name,
|
||||
repository: context.payload?.repository?.html_url,
|
||||
sender: context.payload?.sender?.login ?? context.payload?.sender?.type,
|
||||
},
|
||||
})
|
||||
|
||||
if (errorLoggingIssue) {
|
||||
const { repo, issue, owner } = errorLoggingIssue;
|
||||
const { repo, issue, owner } = errorLoggingIssue
|
||||
if (
|
||||
context.repo.repo === repo &&
|
||||
context.repo.owner === owner &&
|
||||
context.payload.issue?.number === issue
|
||||
) {
|
||||
return safeLog('refusing to run on error logging issue to prevent cascading errors');
|
||||
return console.log('refusing to run on error logging issue to prevent cascading errors')
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const token = getRequiredInput('token');
|
||||
const readonly = !!getInput('readonly');
|
||||
const token = getRequiredInput('token')
|
||||
const readonly = !!getInput('readonly')
|
||||
|
||||
const issue = context?.issue?.number;
|
||||
const issue = context?.issue?.number
|
||||
if (issue) {
|
||||
const octokit = new OctoKitIssue(token, context.repo, { number: issue }, { readonly });
|
||||
const octokit = new OctoKitIssue(token, context.repo, { number: issue }, { readonly })
|
||||
if (context.eventName === 'issue_comment') {
|
||||
await this.onCommented(octokit, context.payload.comment?.body, context.actor);
|
||||
} else if (
|
||||
context.eventName === 'issues' ||
|
||||
context.eventName === 'pull_request' ||
|
||||
context.eventName === 'pull_request_target'
|
||||
) {
|
||||
await this.onCommented(octokit, context.payload.comment.body, context.actor)
|
||||
} else if (context.eventName === 'issues') {
|
||||
switch (context.payload.action) {
|
||||
case 'opened':
|
||||
case 'ready_for_review':
|
||||
await this.onOpened(octokit, context.payload);
|
||||
break;
|
||||
await this.onOpened(octokit)
|
||||
break
|
||||
case 'reopened':
|
||||
await this.onReopened(octokit);
|
||||
break;
|
||||
await this.onReopened(octokit)
|
||||
break
|
||||
case 'closed':
|
||||
await this.onClosed(octokit, context.payload);
|
||||
break;
|
||||
await this.onClosed(octokit)
|
||||
break
|
||||
case 'labeled':
|
||||
await this.onLabeled(octokit, context.payload.label.name);
|
||||
break;
|
||||
case 'assigned':
|
||||
await this.onAssigned(octokit, context.payload.assignee.login);
|
||||
break;
|
||||
await this.onLabeled(octokit, context.payload.label.name)
|
||||
break
|
||||
case 'unassigned':
|
||||
await this.onUnassigned(octokit, context.payload.assignee.login);
|
||||
break;
|
||||
await this.onUnassigned(octokit, context.payload.assignee.login)
|
||||
break
|
||||
case 'edited':
|
||||
await this.onEdited(octokit);
|
||||
break;
|
||||
await this.onEdited(octokit)
|
||||
break
|
||||
case 'milestoned':
|
||||
await this.onMilestoned(octokit);
|
||||
break;
|
||||
await this.onMilestoned(octokit)
|
||||
break
|
||||
default:
|
||||
throw Error('Unexpected action: ' + context.payload.action);
|
||||
throw Error('Unexpected action: ' + context.payload.action)
|
||||
}
|
||||
}
|
||||
} else if (context.eventName === 'create') {
|
||||
await this.onCreated(
|
||||
new OctoKit(token, context.repo, { readonly }),
|
||||
context?.payload?.ref,
|
||||
context?.payload?.sender?.login,
|
||||
);
|
||||
} else {
|
||||
await this.onTriggered(new OctoKit(token, context.repo, { readonly }));
|
||||
await this.onTriggered(new OctoKit(token, context.repo, { readonly }))
|
||||
}
|
||||
} catch (e) {
|
||||
const err = e as Error;
|
||||
try {
|
||||
await this.error(err);
|
||||
} catch {
|
||||
safeLog(err?.stack || err?.message || String(e));
|
||||
}
|
||||
await this.error(e)
|
||||
}
|
||||
|
||||
const usage = await getRateLimit(this.token);
|
||||
const usage = await getRateLimit(this.token)
|
||||
}
|
||||
|
||||
private async error(error: Error) {
|
||||
@@ -106,9 +91,9 @@ export abstract class Action {
|
||||
message: `${error.message}\n${error.stack}`,
|
||||
id: this.id,
|
||||
user: await this.username,
|
||||
};
|
||||
}
|
||||
|
||||
if (context.issue?.number) details.issue = context.issue.number;
|
||||
if (context.issue.number) details.issue = context.issue.number
|
||||
|
||||
const rendered = `
|
||||
Message: ${details.message}
|
||||
@@ -116,43 +101,37 @@ Message: ${details.message}
|
||||
Actor: ${details.user}
|
||||
|
||||
ID: ${details.id}
|
||||
`;
|
||||
await logErrorToIssue(rendered, true, this.token);
|
||||
`
|
||||
await logErrorToIssue(rendered, true, this.token)
|
||||
|
||||
setFailed(error.message);
|
||||
setFailed(error.message)
|
||||
}
|
||||
|
||||
protected async onTriggered(_octokit: OctoKit): Promise<void> {
|
||||
throw Error('not implemented');
|
||||
}
|
||||
protected async onCreated(_octokit: OctoKit, _ref: string, _creator: string): Promise<void> {
|
||||
throw Error('not implemented');
|
||||
throw Error('not implemented')
|
||||
}
|
||||
protected async onEdited(_issue: OctoKitIssue): Promise<void> {
|
||||
throw Error('not implemented');
|
||||
throw Error('not implemented')
|
||||
}
|
||||
protected async onLabeled(_issue: OctoKitIssue, _label: string): Promise<void> {
|
||||
throw Error('not implemented');
|
||||
throw Error('not implemented')
|
||||
}
|
||||
protected async onAssigned(_issue: OctoKitIssue, _assignee: string): Promise<void> {
|
||||
throw Error('not implemented');
|
||||
protected async onUnassigned(_issue: OctoKitIssue, _label: string): Promise<void> {
|
||||
throw Error('not implemented')
|
||||
}
|
||||
protected async onUnassigned(_issue: OctoKitIssue, _assignee: string): Promise<void> {
|
||||
throw Error('not implemented');
|
||||
}
|
||||
protected async onOpened(_issue: OctoKitIssue, _payload: WebhookPayload): Promise<void> {
|
||||
throw Error('not implemented');
|
||||
protected async onOpened(_issue: OctoKitIssue): Promise<void> {
|
||||
throw Error('not implemented')
|
||||
}
|
||||
protected async onReopened(_issue: OctoKitIssue): Promise<void> {
|
||||
throw Error('not implemented');
|
||||
throw Error('not implemented')
|
||||
}
|
||||
protected async onClosed(_issue: OctoKitIssue, _payload: WebhookPayload): Promise<void> {
|
||||
throw Error('not implemented');
|
||||
protected async onClosed(_issue: OctoKitIssue): Promise<void> {
|
||||
throw Error('not implemented')
|
||||
}
|
||||
protected async onMilestoned(_issue: OctoKitIssue): Promise<void> {
|
||||
throw Error('not implemented');
|
||||
throw Error('not implemented')
|
||||
}
|
||||
protected async onCommented(_issue: OctoKitIssue, _comment: string, _actor: string): Promise<void> {
|
||||
throw Error('not implemented');
|
||||
throw Error('not implemented')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,183 +1,181 @@
|
||||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ActionBase = void 0;
|
||||
const utils_1 = require("./utils");
|
||||
class ActionBase {
|
||||
constructor(labels, milestoneName, milestoneId, ignoreLabels, ignoreMilestoneNames, ignoreMilestoneIds, minimumVotes, maximumVotes, involves) {
|
||||
this.labels = labels;
|
||||
this.milestoneName = milestoneName;
|
||||
this.milestoneId = milestoneId;
|
||||
this.ignoreLabels = ignoreLabels;
|
||||
this.ignoreMilestoneNames = ignoreMilestoneNames;
|
||||
this.ignoreMilestoneIds = ignoreMilestoneIds;
|
||||
this.minimumVotes = minimumVotes;
|
||||
this.maximumVotes = maximumVotes;
|
||||
this.involves = involves;
|
||||
this.labelsSet = [];
|
||||
this.ignoreLabelsSet = [];
|
||||
this.ignoreMilestoneNamesSet = [];
|
||||
this.ignoreMilestoneIdsSet = [];
|
||||
this.ignoreAllWithLabels = false;
|
||||
this.ignoreAllWithMilestones = false;
|
||||
this.involvesSet = [];
|
||||
}
|
||||
buildQuery(baseQuery) {
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
let query = baseQuery;
|
||||
(0, utils_1.safeLog)(`labels: ${this.labels}`);
|
||||
(0, utils_1.safeLog)(`milestoneName: ${this.milestoneName}`);
|
||||
(0, utils_1.safeLog)(`milestoneId: ${this.milestoneId}`);
|
||||
(0, utils_1.safeLog)(`ignoreLabels: ${this.ignoreLabels}`);
|
||||
(0, utils_1.safeLog)(`ignoreMilestoneNames: ${this.ignoreMilestoneNames}`);
|
||||
(0, utils_1.safeLog)(`ignoreMilestoneIds: ${this.ignoreMilestoneIds}`);
|
||||
(0, utils_1.safeLog)(`minimumVotes: ${this.minimumVotes}`);
|
||||
(0, utils_1.safeLog)(`maximumVotes: ${this.maximumVotes}`);
|
||||
(0, utils_1.safeLog)(`involves: ${this.involves}`);
|
||||
// Both milestone name and milestone Id must be provided and must match.
|
||||
// The name is used to construct the query, which does not accept ID.
|
||||
// The ID is used for comparisons with issue data, which does not include the name.
|
||||
// TODO: Figure out a way to convert either from milestone name to ID, or vice versa.
|
||||
// If label inclusion and exclusion are mixed, exclusion will take precedence.
|
||||
// For example, an issue with both labels A and B will not match if B is excluded, even if A is included.
|
||||
// If a milestoneName/milestoneId are set, ignoreMilenameName/ignoreMilestoneIds are ignored.
|
||||
// GitHub does not appear to support searching for all issues with milestones (not lacking a milestone). "-no:milestone" does not work.
|
||||
// GitHub does not appear to support searching for all issues with labels (not lacking a label). "-no:label" does not work.
|
||||
// All indicated labels must be present
|
||||
if (this.labels) {
|
||||
if (((_a = this.labels) === null || _a === void 0 ? void 0 : _a.length) > 2 && ((_b = this.labels) === null || _b === void 0 ? void 0 : _b.startsWith('"')) && ((_c = this.labels) === null || _c === void 0 ? void 0 : _c.endsWith('"'))) {
|
||||
this.labels = this.labels.substring(1, this.labels.length - 2);
|
||||
}
|
||||
this.labelsSet = (_d = this.labels) === null || _d === void 0 ? void 0 : _d.split(',');
|
||||
for (const str of this.labelsSet) {
|
||||
if (str != "") {
|
||||
query = query.concat(` label:"${str}"`);
|
||||
}
|
||||
}
|
||||
}
|
||||
// The "involves" qualifier to find issues that in some way involve a certain user.
|
||||
// It is a logical OR between the author, assignee, and mentions.
|
||||
if (this.involves) {
|
||||
this.involvesSet = (_e = this.involves) === null || _e === void 0 ? void 0 : _e.split(',');
|
||||
for (const str of this.involvesSet) {
|
||||
if (str != "") {
|
||||
query = query.concat(` involves:"${str}"`);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.ignoreLabels) {
|
||||
if (this.ignoreLabels == "*" && !this.labels) { // only if unlabeled
|
||||
query = query.concat(` no:label`);
|
||||
this.ignoreAllWithLabels = true;
|
||||
}
|
||||
else {
|
||||
this.ignoreLabelsSet = (_f = this.ignoreLabels) === null || _f === void 0 ? void 0 : _f.split(',');
|
||||
for (const str of this.ignoreLabelsSet) {
|
||||
if (str != "") {
|
||||
query = query.concat(` -label:"${str}"`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.milestoneName) {
|
||||
query = query.concat(` milestone:"${this.milestoneName}"`);
|
||||
}
|
||||
else if (this.ignoreMilestoneNames) {
|
||||
if (this.ignoreMilestoneNames == "*") {
|
||||
query = query.concat(` no:milestone`);
|
||||
this.ignoreAllWithMilestones = true;
|
||||
}
|
||||
else if (this.ignoreMilestoneIds) {
|
||||
this.ignoreMilestoneNamesSet = this.ignoreMilestoneNames.split(',');
|
||||
this.ignoreMilestoneIdsSet = this.ignoreMilestoneIds.split(',');
|
||||
for (const str of this.ignoreMilestoneNamesSet) {
|
||||
if (str != "") {
|
||||
query = query.concat(` -milestone:"${str}"`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return query;
|
||||
}
|
||||
// This is necessary because GitHub sometimes returns incorrect results,
|
||||
// and because issues may get modified while we are processing them.
|
||||
validateIssue(issue) {
|
||||
var _a, _b;
|
||||
if (this.ignoreAllWithLabels) {
|
||||
// Validate that the issue does not have labels
|
||||
if (issue.labels && issue.labels.length !== 0) {
|
||||
(0, utils_1.safeLog)(`Issue ${issue.number} skipped due to label found after querying for no:label.`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Make sure all labels we wanted are present.
|
||||
if ((!issue.labels || issue.labels.length == 0) && this.labelsSet.length > 0) {
|
||||
(0, utils_1.safeLog)(`Issue ${issue.number} skipped due to not having a required label set. No labels found.`);
|
||||
return false;
|
||||
}
|
||||
for (const str of this.labelsSet) {
|
||||
if (!issue.labels.includes(str)) {
|
||||
(0, utils_1.safeLog)(`Issue ${issue.number} skipped due to not having a required label set.`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Make sure no labels we wanted to ignore are present.
|
||||
if (issue.labels && issue.labels.length > 0) {
|
||||
for (const str of this.ignoreLabelsSet) {
|
||||
if (issue.labels.includes(str)) {
|
||||
(0, utils_1.safeLog)(`Issue ${issue.number} skipped due to having an ignore label set: ${str}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.ignoreAllWithMilestones) {
|
||||
// Validate that the issue does not have a milestone.
|
||||
if (issue.milestone) {
|
||||
(0, utils_1.safeLog)(`Issue ${issue.number} skipped due to milestone found after querying for no:milestone.`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Make sure milestone is present, if required.
|
||||
if (this.milestoneId != null && ((_a = issue.milestone) === null || _a === void 0 ? void 0 : _a.milestoneId) != +this.milestoneId) {
|
||||
(0, utils_1.safeLog)(`Issue ${issue.number} skipped due to not having required milsetone id ${this.milestoneId}. Had: ${(_b = issue.milestone) === null || _b === void 0 ? void 0 : _b.milestoneId}`);
|
||||
return false;
|
||||
}
|
||||
// Make sure a milestones we wanted to ignore is not present.
|
||||
if (issue.milestone && issue.milestone.milestoneId != null) {
|
||||
for (const str of this.ignoreMilestoneIdsSet) {
|
||||
if (issue.milestone.milestoneId == +str) {
|
||||
(0, utils_1.safeLog)(`Issue ${issue.number} skipped due to milestone ${issue.milestone.milestoneId} found in list of ignored milestone IDs.`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Verify the issue has a sufficient number of upvotes
|
||||
let upvotes = 0;
|
||||
if (issue.reactions) {
|
||||
upvotes = issue.reactions['+1'];
|
||||
}
|
||||
if (this.minimumVotes != undefined) {
|
||||
if (upvotes < this.minimumVotes) {
|
||||
(0, utils_1.safeLog)(`Issue ${issue.number} skipped due to not having at least ${this.minimumVotes} upvotes. Had: ${upvotes}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Verify the issue does not have too many upvotes
|
||||
if (this.maximumVotes != undefined) {
|
||||
if (upvotes > this.maximumVotes) {
|
||||
(0, utils_1.safeLog)(`Issue ${issue.number} skipped due to having more than ${this.maximumVotes} upvotes. Had: ${upvotes}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
exports.ActionBase = ActionBase;
|
||||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ActionBase = void 0;
|
||||
class ActionBase {
|
||||
constructor(labels, milestoneName, milestoneId, ignoreLabels, ignoreMilestoneNames, ignoreMilestoneIds, minimumVotes, maximumVotes, involves) {
|
||||
this.labels = labels;
|
||||
this.milestoneName = milestoneName;
|
||||
this.milestoneId = milestoneId;
|
||||
this.ignoreLabels = ignoreLabels;
|
||||
this.ignoreMilestoneNames = ignoreMilestoneNames;
|
||||
this.ignoreMilestoneIds = ignoreMilestoneIds;
|
||||
this.minimumVotes = minimumVotes;
|
||||
this.maximumVotes = maximumVotes;
|
||||
this.involves = involves;
|
||||
this.labelsSet = [];
|
||||
this.ignoreLabelsSet = [];
|
||||
this.ignoreMilestoneNamesSet = [];
|
||||
this.ignoreMilestoneIdsSet = [];
|
||||
this.ignoreAllWithLabels = false;
|
||||
this.ignoreAllWithMilestones = false;
|
||||
this.involvesSet = [];
|
||||
}
|
||||
buildQuery(baseQuery) {
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
let query = baseQuery;
|
||||
console.log(`labels: ${this.labels}`);
|
||||
console.log(`milestoneName: ${this.milestoneName}`);
|
||||
console.log(`milestoneId: ${this.milestoneId}`);
|
||||
console.log(`ignoreLabels: ${this.ignoreLabels}`);
|
||||
console.log(`ignoreMilestoneNames: ${this.ignoreMilestoneNames}`);
|
||||
console.log(`ignoreMilestoneIds: ${this.ignoreMilestoneIds}`);
|
||||
console.log(`minimumVotes: ${this.minimumVotes}`);
|
||||
console.log(`maximumVotes: ${this.maximumVotes}`);
|
||||
console.log(`involves: ${this.involves}`);
|
||||
// Both milestone name and milestone Id must be provided and must match.
|
||||
// The name is used to construct the query, which does not accept ID.
|
||||
// The ID is used for comparisons with issue data, which does not include the name.
|
||||
// TODO: Figure out a way to convert either from milestone name to ID, or vice versa.
|
||||
// If label inclusion and exclusion are mixed, exclusion will take precedence.
|
||||
// For example, an issue with both labels A and B will not match if B is excluded, even if A is included.
|
||||
// If a milestoneName/milestoneId are set, ignoreMilenameName/ignoreMilestoneIds are ignored.
|
||||
// GitHub does not appear to support searching for all issues with milestones (not lacking a milestone). "-no:milestone" does not work.
|
||||
// GitHub does not appear to support searching for all issues with labels (not lacking a label). "-no:label" does not work.
|
||||
// All indicated labels must be present
|
||||
if (this.labels) {
|
||||
if (((_a = this.labels) === null || _a === void 0 ? void 0 : _a.length) > 2 && ((_b = this.labels) === null || _b === void 0 ? void 0 : _b.startsWith('"')) && ((_c = this.labels) === null || _c === void 0 ? void 0 : _c.endsWith('"'))) {
|
||||
this.labels = this.labels.substring(1, this.labels.length - 2);
|
||||
}
|
||||
this.labelsSet = (_d = this.labels) === null || _d === void 0 ? void 0 : _d.split(',');
|
||||
for (const str of this.labelsSet) {
|
||||
if (str != "") {
|
||||
query = query.concat(` label:"${str}"`);
|
||||
}
|
||||
}
|
||||
}
|
||||
// The "involves" qualifier to find issues that in some way involve a certain user.
|
||||
// It is a logical OR between the author, assignee, and mentions.
|
||||
if (this.involves) {
|
||||
this.involvesSet = (_e = this.involves) === null || _e === void 0 ? void 0 : _e.split(',');
|
||||
for (const str of this.involvesSet) {
|
||||
if (str != "") {
|
||||
query = query.concat(` involves:"${str}"`);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.ignoreLabels) {
|
||||
if (this.ignoreLabels == "*" && !this.labels) { // only if unlabeled
|
||||
query = query.concat(` no:label`);
|
||||
this.ignoreAllWithLabels = true;
|
||||
}
|
||||
else {
|
||||
this.ignoreLabelsSet = (_f = this.ignoreLabels) === null || _f === void 0 ? void 0 : _f.split(',');
|
||||
for (const str of this.ignoreLabelsSet) {
|
||||
if (str != "") {
|
||||
query = query.concat(` -label:"${str}"`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.milestoneName) {
|
||||
query = query.concat(` milestone:"${this.milestoneName}"`);
|
||||
}
|
||||
else if (this.ignoreMilestoneNames) {
|
||||
if (this.ignoreMilestoneNames == "*") {
|
||||
query = query.concat(` no:milestone`);
|
||||
this.ignoreAllWithMilestones = true;
|
||||
}
|
||||
else if (this.ignoreMilestoneIds) {
|
||||
this.ignoreMilestoneNamesSet = this.ignoreMilestoneNames.split(',');
|
||||
this.ignoreMilestoneIdsSet = this.ignoreMilestoneIds.split(',');
|
||||
for (const str of this.ignoreMilestoneNamesSet) {
|
||||
if (str != "") {
|
||||
query = query.concat(` -milestone:"${str}"`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return query;
|
||||
}
|
||||
// This is necessary because GitHub sometimes returns incorrect results,
|
||||
// and because issues may get modified while we are processing them.
|
||||
validateIssue(issue) {
|
||||
if (this.ignoreAllWithLabels) {
|
||||
// Validate that the issue does not have labels
|
||||
if (issue.labels && issue.labels.length !== 0) {
|
||||
console.log(`Issue ${issue.number} skipped due to label found after querying for no:label.`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Make sure all labels we wanted are present.
|
||||
if ((!issue.labels || issue.labels.length == 0) && this.labelsSet.length > 0) {
|
||||
console.log(`Issue ${issue.number} skipped due to not having a required label set. No labels found.`);
|
||||
return false;
|
||||
}
|
||||
for (const str of this.labelsSet) {
|
||||
if (!issue.labels.includes(str)) {
|
||||
console.log(`Issue ${issue.number} skipped due to not having a required label set.`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Make sure no labels we wanted to ignore are present.
|
||||
if (issue.labels && issue.labels.length > 0) {
|
||||
for (const str of this.ignoreLabelsSet) {
|
||||
if (issue.labels.includes(str)) {
|
||||
console.log(`Issue ${issue.number} skipped due to having an ignore label set: ${str}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.ignoreAllWithMilestones) {
|
||||
// Validate that the issue does not have a milestone.
|
||||
if (issue.milestoneId != null) {
|
||||
console.log(`Issue ${issue.number} skipped due to milestone found after querying for no:milestone.`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Make sure milestone is present, if required.
|
||||
if (this.milestoneId != undefined && issue.milestoneId != +this.milestoneId) {
|
||||
console.log(`Issue ${issue.number} skipped due to not having required milsetone id ${this.milestoneId}. Had: ${issue.milestoneId}`);
|
||||
return false;
|
||||
}
|
||||
// Make sure a milestones we wanted to ignore is not present.
|
||||
if (issue.milestoneId != null) {
|
||||
for (const str of this.ignoreMilestoneIdsSet) {
|
||||
if (issue.milestoneId == +str) {
|
||||
console.log(`Issue ${issue.number} skipped due to milestone ${issue.milestoneId} found in list of ignored milestone IDs.`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Verify the issue has a sufficient number of upvotes
|
||||
let upvotes = 0;
|
||||
if (issue.reactions) {
|
||||
upvotes = issue.reactions['+1'];
|
||||
}
|
||||
if (this.minimumVotes != undefined) {
|
||||
if (upvotes < this.minimumVotes) {
|
||||
console.log(`Issue ${issue.number} skipped due to not having at least ${this.minimumVotes} upvotes. Had: ${upvotes}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Verify the issue does not have too many upvotes
|
||||
if (this.maximumVotes != undefined) {
|
||||
if (upvotes > this.maximumVotes) {
|
||||
console.log(`Issue ${issue.number} skipped due to having more than ${this.maximumVotes} upvotes. Had: ${upvotes}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
exports.ActionBase = ActionBase;
|
||||
//# sourceMappingURL=ActionBase.js.map
|
||||
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Issue } from '../api/api'
|
||||
import { safeLog } from './utils';
|
||||
|
||||
export class ActionBase {
|
||||
constructor(
|
||||
@@ -30,15 +29,15 @@ export class ActionBase {
|
||||
buildQuery(baseQuery: string): string {
|
||||
let query = baseQuery;
|
||||
|
||||
safeLog(`labels: ${this.labels}`);
|
||||
safeLog(`milestoneName: ${this.milestoneName}`);
|
||||
safeLog(`milestoneId: ${this.milestoneId}`);
|
||||
safeLog(`ignoreLabels: ${this.ignoreLabels}`);
|
||||
safeLog(`ignoreMilestoneNames: ${this.ignoreMilestoneNames}`);
|
||||
safeLog(`ignoreMilestoneIds: ${this.ignoreMilestoneIds}`);
|
||||
safeLog(`minimumVotes: ${this.minimumVotes}`);
|
||||
safeLog(`maximumVotes: ${this.maximumVotes}`);
|
||||
safeLog(`involves: ${this.involves}`);
|
||||
console.log(`labels: ${this.labels}`);
|
||||
console.log(`milestoneName: ${this.milestoneName}`);
|
||||
console.log(`milestoneId: ${this.milestoneId}`);
|
||||
console.log(`ignoreLabels: ${this.ignoreLabels}`);
|
||||
console.log(`ignoreMilestoneNames: ${this.ignoreMilestoneNames}`);
|
||||
console.log(`ignoreMilestoneIds: ${this.ignoreMilestoneIds}`);
|
||||
console.log(`minimumVotes: ${this.minimumVotes}`);
|
||||
console.log(`maximumVotes: ${this.maximumVotes}`);
|
||||
console.log(`involves: ${this.involves}`);
|
||||
|
||||
// Both milestone name and milestone Id must be provided and must match.
|
||||
// The name is used to construct the query, which does not accept ID.
|
||||
@@ -118,18 +117,18 @@ export class ActionBase {
|
||||
if (this.ignoreAllWithLabels) {
|
||||
// Validate that the issue does not have labels
|
||||
if (issue.labels && issue.labels.length !== 0) {
|
||||
safeLog(`Issue ${issue.number} skipped due to label found after querying for no:label.`);
|
||||
console.log(`Issue ${issue.number} skipped due to label found after querying for no:label.`);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Make sure all labels we wanted are present.
|
||||
if ((!issue.labels || issue.labels.length == 0) && this.labelsSet.length > 0) {
|
||||
safeLog(`Issue ${issue.number} skipped due to not having a required label set. No labels found.`);
|
||||
console.log(`Issue ${issue.number} skipped due to not having a required label set. No labels found.`);
|
||||
return false;
|
||||
}
|
||||
for (const str of this.labelsSet) {
|
||||
if (!issue.labels.includes(str)) {
|
||||
safeLog(`Issue ${issue.number} skipped due to not having a required label set.`);
|
||||
console.log(`Issue ${issue.number} skipped due to not having a required label set.`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -137,7 +136,7 @@ export class ActionBase {
|
||||
if (issue.labels && issue.labels.length > 0) {
|
||||
for (const str of this.ignoreLabelsSet) {
|
||||
if (issue.labels.includes(str)) {
|
||||
safeLog(`Issue ${issue.number} skipped due to having an ignore label set: ${str}`);
|
||||
console.log(`Issue ${issue.number} skipped due to having an ignore label set: ${str}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -145,21 +144,21 @@ export class ActionBase {
|
||||
}
|
||||
if (this.ignoreAllWithMilestones) {
|
||||
// Validate that the issue does not have a milestone.
|
||||
if (issue.milestone) {
|
||||
safeLog(`Issue ${issue.number} skipped due to milestone found after querying for no:milestone.`);
|
||||
if (issue.milestoneId != null) {
|
||||
console.log(`Issue ${issue.number} skipped due to milestone found after querying for no:milestone.`);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Make sure milestone is present, if required.
|
||||
if (this.milestoneId != null && issue.milestone?.milestoneId != +this.milestoneId) {
|
||||
safeLog(`Issue ${issue.number} skipped due to not having required milsetone id ${this.milestoneId}. Had: ${issue.milestone?.milestoneId}`);
|
||||
if (this.milestoneId != undefined && issue.milestoneId != +this.milestoneId) {
|
||||
console.log(`Issue ${issue.number} skipped due to not having required milsetone id ${this.milestoneId}. Had: ${issue.milestoneId}`);
|
||||
return false;
|
||||
}
|
||||
// Make sure a milestones we wanted to ignore is not present.
|
||||
if (issue.milestone && issue.milestone.milestoneId != null) {
|
||||
if (issue.milestoneId != null) {
|
||||
for (const str of this.ignoreMilestoneIdsSet) {
|
||||
if (issue.milestone.milestoneId == +str) {
|
||||
safeLog(`Issue ${issue.number} skipped due to milestone ${issue.milestone.milestoneId} found in list of ignored milestone IDs.`);
|
||||
if (issue.milestoneId == +str) {
|
||||
console.log(`Issue ${issue.number} skipped due to milestone ${issue.milestoneId} found in list of ignored milestone IDs.`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -172,14 +171,14 @@ export class ActionBase {
|
||||
}
|
||||
if (this.minimumVotes != undefined) {
|
||||
if (upvotes < this.minimumVotes) {
|
||||
safeLog(`Issue ${issue.number} skipped due to not having at least ${this.minimumVotes} upvotes. Had: ${upvotes}`);
|
||||
console.log(`Issue ${issue.number} skipped due to not having at least ${this.minimumVotes} upvotes. Had: ${upvotes}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Verify the issue does not have too many upvotes
|
||||
if (this.maximumVotes != undefined) {
|
||||
if (upvotes > this.maximumVotes) {
|
||||
safeLog(`Issue ${issue.number} skipped due to having more than ${this.maximumVotes} upvotes. Had: ${upvotes}`);
|
||||
console.log(`Issue ${issue.number} skipped due to having more than ${this.maximumVotes} upvotes. Had: ${upvotes}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=OctokitTypings.js.map
|
||||
@@ -1,16 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import type { RestEndpointMethodTypes } from '@octokit/rest';
|
||||
|
||||
// This file is just to re-export some octokit types as nicer names
|
||||
|
||||
export type ActionsListWorkflowRunsResponseWorkflowRunsItem =
|
||||
RestEndpointMethodTypes['actions']['listWorkflowRuns']['response']['data']['workflow_runs'][0];
|
||||
|
||||
export type IssueGetResponse = RestEndpointMethodTypes['issues']['get']['response']['data'];
|
||||
|
||||
export type IssuesGetResponseMilestone =
|
||||
RestEndpointMethodTypes['issues']['get']['response']['data']['milestone'];
|
||||
@@ -4,16 +4,14 @@
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.safeLog = exports.logErrorToIssue = exports.errorLoggingIssue = exports.getRateLimit = exports.daysAgoToHumanReadbleDate = exports.daysAgoToTimestamp = exports.loadLatestRelease = exports.normalizeIssue = exports.getRequiredInput = exports.getInput = void 0;
|
||||
exports.logErrorToIssue = exports.errorLoggingIssue = exports.getRateLimit = exports.daysAgoToHumanReadbleDate = exports.daysAgoToTimestamp = exports.loadLatestRelease = exports.normalizeIssue = exports.getRequiredInput = exports.getInput = void 0;
|
||||
const core = require("@actions/core");
|
||||
const github_1 = require("@actions/github");
|
||||
const axios_1 = require("axios");
|
||||
const octokit_1 = require("../api/octokit");
|
||||
const getInput = (name) => core.getInput(name) || undefined;
|
||||
exports.getInput = getInput;
|
||||
const getRequiredInput = (name) => core.getInput(name, { required: true });
|
||||
exports.getRequiredInput = getRequiredInput;
|
||||
const normalizeIssue = (issue) => {
|
||||
exports.getInput = (name) => core.getInput(name) || undefined;
|
||||
exports.getRequiredInput = (name) => core.getInput(name, { required: true });
|
||||
exports.normalizeIssue = (issue) => {
|
||||
let { body, title } = issue;
|
||||
body = body !== null && body !== void 0 ? body : '';
|
||||
title = title !== null && title !== void 0 ? title : '';
|
||||
@@ -45,36 +43,25 @@ const normalizeIssue = (issue) => {
|
||||
issueType: isBug ? 'bug' : isFeatureRequest ? 'feature_request' : 'unknown',
|
||||
};
|
||||
};
|
||||
exports.normalizeIssue = normalizeIssue;
|
||||
const loadLatestRelease = async (quality) => (await axios_1.default.get(`https://update.code.visualstudio.com/api/update/darwin/${quality}/latest`)).data;
|
||||
exports.loadLatestRelease = loadLatestRelease;
|
||||
const daysAgoToTimestamp = (days) => +new Date(Date.now() - days * 24 * 60 * 60 * 1000);
|
||||
exports.daysAgoToTimestamp = daysAgoToTimestamp;
|
||||
const daysAgoToHumanReadbleDate = (days) => new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString().replace(/\.\d{3}\w$/, '');
|
||||
exports.daysAgoToHumanReadbleDate = daysAgoToHumanReadbleDate;
|
||||
const getRateLimit = async (token) => {
|
||||
const usageData = (await (0, github_1.getOctokit)(token).rest.rateLimit.get()).data.resources;
|
||||
exports.loadLatestRelease = async (quality) => (await axios_1.default.get(`https://vscode-update.azurewebsites.net/api/update/darwin/${quality}/latest`)).data;
|
||||
exports.daysAgoToTimestamp = (days) => +new Date(Date.now() - days * 24 * 60 * 60 * 1000);
|
||||
exports.daysAgoToHumanReadbleDate = (days) => new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString().replace(/\.\d{3}\w$/, '');
|
||||
exports.getRateLimit = async (token) => {
|
||||
const usageData = (await new github_1.GitHub(token).rateLimit.get()).data.resources;
|
||||
const usage = {};
|
||||
['core', 'graphql', 'search'].forEach(async (category) => {
|
||||
var _a, _b, _c, _d;
|
||||
if (usageData[category]) {
|
||||
usage[category] = 1 - ((_b = (_a = usageData[category]) === null || _a === void 0 ? void 0 : _a.remaining) !== null && _b !== void 0 ? _b : 0) / ((_d = (_c = usageData[category]) === null || _c === void 0 ? void 0 : _c.limit) !== null && _d !== void 0 ? _d : 1);
|
||||
}
|
||||
usage[category] = 1 - usageData[category].remaining / usageData[category].limit;
|
||||
});
|
||||
return usage;
|
||||
};
|
||||
exports.getRateLimit = getRateLimit;
|
||||
exports.errorLoggingIssue = (() => {
|
||||
try {
|
||||
const repo = github_1.context.repo.owner.toLowerCase() + '/' + github_1.context.repo.repo.toLowerCase();
|
||||
if (repo === 'microsoft/vscode' || repo === 'microsoft/vscode-remote-release') {
|
||||
return { repo: 'vscode', owner: 'Microsoft', issue: 93814 };
|
||||
if (repo === 'microsoft/vscode-cpptools') {
|
||||
return { repo: 'vscode-cpptools', owner: 'Microsoft', issue: 6282 };
|
||||
}
|
||||
else if (/microsoft\//.test(repo)) {
|
||||
return { repo: 'vscode-internalbacklog', owner: 'Microsoft', issue: 974 };
|
||||
}
|
||||
else if ((0, exports.getInput)('errorLogIssueNumber')) {
|
||||
return { ...github_1.context.repo, issue: +(0, exports.getRequiredInput)('errorLogIssueNumber') };
|
||||
else if (exports.getInput('errorLogIssueNumber')) {
|
||||
return { ...github_1.context.repo, issue: +exports.getRequiredInput('errorLogIssueNumber') };
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
@@ -85,20 +72,19 @@ exports.errorLoggingIssue = (() => {
|
||||
return undefined;
|
||||
}
|
||||
})();
|
||||
const logErrorToIssue = async (message, ping, token) => {
|
||||
var _a;
|
||||
exports.logErrorToIssue = async (message, ping, token) => {
|
||||
// Attempt to wait out abuse detection timeout if present
|
||||
await new Promise((resolve) => setTimeout(resolve, 10000));
|
||||
const dest = exports.errorLoggingIssue;
|
||||
if (!dest)
|
||||
return console.log('no error logging repo defined. swallowing error.');
|
||||
return new octokit_1.OctoKitIssue(token, { owner: dest.owner, repo: dest.repo }, { number: dest.issue })
|
||||
return console.log('no error logging repo defined. swallowing error:', message);
|
||||
return new octokit_1.OctoKitIssue(token, { owner: dest.owner, repo: dest.repo }, { number: dest.issue }, { readonly: !!exports.getInput('readonly') })
|
||||
.postComment(`
|
||||
Workflow: ${github_1.context.workflow}
|
||||
|
||||
Error: ${message}
|
||||
|
||||
Issue: ${ping ? `${github_1.context.repo.owner}/${github_1.context.repo.repo}#` : ''}${(_a = github_1.context.issue) === null || _a === void 0 ? void 0 : _a.number}
|
||||
Issue: ${ping ? `${github_1.context.repo.owner}/${github_1.context.repo.repo}#` : ''}${github_1.context.issue.number}
|
||||
|
||||
Repo: ${github_1.context.repo.owner}/${github_1.context.repo.repo}
|
||||
|
||||
@@ -110,10 +96,4 @@ ${JSON.stringify(github_1.context, null, 2)
|
||||
-->
|
||||
`);
|
||||
};
|
||||
exports.logErrorToIssue = logErrorToIssue;
|
||||
const safeLog = (message, ...args) => {
|
||||
const clean = (val) => ('' + val).replace(/:|#/g, '');
|
||||
console.log(clean(message), ...args.map(clean));
|
||||
};
|
||||
exports.safeLog = safeLog;
|
||||
//# sourceMappingURL=utils.js.map
|
||||
@@ -3,24 +3,24 @@
|
||||
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as core from '@actions/core';
|
||||
import { context, getOctokit } from '@actions/github';
|
||||
import axios from 'axios';
|
||||
import { OctoKitIssue } from '../api/octokit';
|
||||
import * as core from '@actions/core'
|
||||
import { context, GitHub } from '@actions/github'
|
||||
import axios from 'axios'
|
||||
import { OctoKitIssue } from '../api/octokit'
|
||||
|
||||
export const getInput = (name: string) => core.getInput(name) || undefined;
|
||||
export const getRequiredInput = (name: string) => core.getInput(name, { required: true });
|
||||
export const getInput = (name: string) => core.getInput(name) || undefined
|
||||
export const getRequiredInput = (name: string) => core.getInput(name, { required: true })
|
||||
|
||||
export const normalizeIssue = (issue: {
|
||||
body: string;
|
||||
title: string;
|
||||
body: string
|
||||
title: string
|
||||
}): { body: string; title: string; issueType: 'bug' | 'feature_request' | 'unknown' } => {
|
||||
let { body, title } = issue;
|
||||
body = body ?? '';
|
||||
title = title ?? '';
|
||||
const isBug = body.includes('bug_report_template') || /Issue Type:.*Bug.*/.test(body);
|
||||
let { body, title } = issue
|
||||
body = body ?? ''
|
||||
title = title ?? ''
|
||||
const isBug = body.includes('bug_report_template') || /Issue Type:.*Bug.*/.test(body)
|
||||
const isFeatureRequest =
|
||||
body.includes('feature_request_template') || /Issue Type:.*Feature Request.*/.test(body);
|
||||
body.includes('feature_request_template') || /Issue Type:.*Feature Request.*/.test(body)
|
||||
|
||||
const cleanse = (str: string) => {
|
||||
let out = str
|
||||
@@ -34,83 +34,78 @@ export const normalizeIssue = (issue: {
|
||||
.replace(/does this issue occur when all extensions are disabled.*/gu, '')
|
||||
.replace(/!?\[[^\]]*\]\([^)]*\)/gu, '')
|
||||
.replace(/\s+/gu, ' ')
|
||||
.replace(/```[^`]*?```/gu, '');
|
||||
.replace(/```[^`]*?```/gu, '')
|
||||
|
||||
while (
|
||||
out.includes(`<details>`) &&
|
||||
out.includes('</details>') &&
|
||||
out.indexOf(`</details>`) > out.indexOf(`<details>`)
|
||||
) {
|
||||
out = out.slice(0, out.indexOf('<details>')) + out.slice(out.indexOf(`</details>`) + 10);
|
||||
out = out.slice(0, out.indexOf('<details>')) + out.slice(out.indexOf(`</details>`) + 10)
|
||||
}
|
||||
|
||||
return out;
|
||||
};
|
||||
return out
|
||||
}
|
||||
|
||||
return {
|
||||
body: cleanse(body),
|
||||
title: cleanse(title),
|
||||
issueType: isBug ? 'bug' : isFeatureRequest ? 'feature_request' : 'unknown',
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export interface Release {
|
||||
productVersion: string;
|
||||
timestamp: number;
|
||||
version: string;
|
||||
productVersion: string
|
||||
timestamp: number
|
||||
version: string
|
||||
}
|
||||
|
||||
export const loadLatestRelease = async (quality: 'stable' | 'insider'): Promise<Release | undefined> =>
|
||||
(await axios.get(`https://update.code.visualstudio.com/api/update/darwin/${quality}/latest`)).data;
|
||||
(await axios.get(`https://vscode-update.azurewebsites.net/api/update/darwin/${quality}/latest`)).data
|
||||
|
||||
export const daysAgoToTimestamp = (days: number): number =>
|
||||
+new Date(Date.now() - days * 24 * 60 * 60 * 1000);
|
||||
export const daysAgoToTimestamp = (days: number): number => +new Date(Date.now() - days * 24 * 60 * 60 * 1000)
|
||||
|
||||
export const daysAgoToHumanReadbleDate = (days: number) =>
|
||||
new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString().replace(/\.\d{3}\w$/, '');
|
||||
new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString().replace(/\.\d{3}\w$/, '')
|
||||
|
||||
export const getRateLimit = async (token: string) => {
|
||||
const usageData = (await getOctokit(token).rest.rateLimit.get()).data.resources;
|
||||
const usage = {} as { core: number; graphql: number; search: number };
|
||||
(['core', 'graphql', 'search'] as const).forEach(async (category) => {
|
||||
if (usageData[category]) {
|
||||
usage[category] = 1 - (usageData[category]?.remaining ?? 0) / (usageData[category]?.limit ?? 1);
|
||||
}
|
||||
});
|
||||
return usage;
|
||||
};
|
||||
const usageData = (await new GitHub(token).rateLimit.get()).data.resources
|
||||
const usage = {} as { core: number; graphql: number; search: number }
|
||||
;(['core', 'graphql', 'search'] as const).forEach(async (category) => {
|
||||
usage[category] = 1 - usageData[category].remaining / usageData[category].limit
|
||||
})
|
||||
return usage
|
||||
}
|
||||
|
||||
export const errorLoggingIssue = (() => {
|
||||
try {
|
||||
const repo = context.repo.owner.toLowerCase() + '/' + context.repo.repo.toLowerCase();
|
||||
if (repo === 'microsoft/vscode' || repo === 'microsoft/vscode-remote-release') {
|
||||
return { repo: 'vscode', owner: 'Microsoft', issue: 93814 };
|
||||
} else if (/microsoft\//.test(repo)) {
|
||||
return { repo: 'vscode-internalbacklog', owner: 'Microsoft', issue: 974 };
|
||||
const repo = context.repo.owner.toLowerCase() + '/' + context.repo.repo.toLowerCase()
|
||||
if (repo === 'microsoft/vscode-cpptools') {
|
||||
return { repo: 'vscode-cpptools', owner: 'Microsoft', issue: 6282 }
|
||||
} else if (getInput('errorLogIssueNumber')) {
|
||||
return { ...context.repo, issue: +getRequiredInput('errorLogIssueNumber') };
|
||||
return { ...context.repo, issue: +getRequiredInput('errorLogIssueNumber') }
|
||||
} else {
|
||||
return undefined;
|
||||
return undefined
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return undefined;
|
||||
console.error(e)
|
||||
return undefined
|
||||
}
|
||||
})();
|
||||
})()
|
||||
|
||||
export const logErrorToIssue = async (message: string, ping: boolean, token: string): Promise<void> => {
|
||||
// Attempt to wait out abuse detection timeout if present
|
||||
await new Promise((resolve) => setTimeout(resolve, 10000));
|
||||
const dest = errorLoggingIssue;
|
||||
if (!dest) return console.log('no error logging repo defined. swallowing error.');
|
||||
await new Promise((resolve) => setTimeout(resolve, 10000))
|
||||
const dest = errorLoggingIssue
|
||||
if (!dest) return console.log('no error logging repo defined. swallowing error:', message)
|
||||
|
||||
return new OctoKitIssue(token, { owner: dest.owner, repo: dest.repo }, { number: dest.issue })
|
||||
return new OctoKitIssue(token, { owner: dest.owner, repo: dest.repo }, { number: dest.issue }, { readonly: !!getInput('readonly') })
|
||||
.postComment(`
|
||||
Workflow: ${context.workflow}
|
||||
|
||||
Error: ${message}
|
||||
|
||||
Issue: ${ping ? `${context.repo.owner}/${context.repo.repo}#` : ''}${context.issue?.number}
|
||||
Issue: ${ping ? `${context.repo.owner}/${context.repo.repo}#` : ''}${context.issue.number}
|
||||
|
||||
Repo: ${context.repo.owner}/${context.repo.repo}
|
||||
|
||||
@@ -120,10 +115,5 @@ ${JSON.stringify(context, null, 2)
|
||||
.replace(/-->/gu, '--@>')
|
||||
.replace(/\/|\\/gu, 'slash-')}
|
||||
-->
|
||||
`);
|
||||
};
|
||||
|
||||
export const safeLog = (message: string, ...args: (string | number | string[])[]): void => {
|
||||
const clean = (val: any) => ('' + val).replace(/:|#/g, '');
|
||||
console.log(clean(message), ...args.map(clean));
|
||||
};
|
||||
`)
|
||||
}
|
||||
|
||||
Generated
+1221
-5909
File diff suppressed because it is too large
Load Diff
@@ -10,38 +10,12 @@
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"dependencies": {
|
||||
"@actions/core": "^2.0.3",
|
||||
"@actions/github": "^8.0.1",
|
||||
"@octokit/rest": "^21.1.1",
|
||||
"@slack/web-api": "^6.9.1",
|
||||
"applicationinsights": "^2.5.1",
|
||||
"axios": "^1.15.0",
|
||||
"uuid": "^8.3.2"
|
||||
"@actions/core": "^1.2.6",
|
||||
"@actions/github": "^2.1.1",
|
||||
"axios": "^0.21.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@azure/storage-blob": "^12.13.0",
|
||||
"@types/chai": "^4.3.3",
|
||||
"@types/mocha": "^9.1.1",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@types/yargs": "^17.0.11",
|
||||
"@typescript-eslint/eslint-plugin": "^5.33.0",
|
||||
"@typescript-eslint/parser": "^5.33.0",
|
||||
"chai": "^4.3.6",
|
||||
"eslint": "^8.21.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"husky": "^8.0.1",
|
||||
"mocha": "^10.0.0",
|
||||
"mongodb": "^4.17.0",
|
||||
"nock": "^13.2.9",
|
||||
"prettier": "2.7.1",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.7.4",
|
||||
"yargs": "^17.5.1"
|
||||
},
|
||||
"overrides": {
|
||||
"serialize-javascript": "^7.0.5",
|
||||
"flatted": "^3.4.2",
|
||||
"fast-xml-parser": "^5.5.7"
|
||||
"eslint": "^6.8.0",
|
||||
"typescript": "^3.8.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
"moduleResolution": "node",
|
||||
"removeComments": false,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"lib": [
|
||||
"es2020"
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
name: Bug - debugger
|
||||
on:
|
||||
schedule:
|
||||
- cron: 50 12 * * * # Run at 12:50 PM UTC (4:50 AM PST, 5:50 AM PDT)
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
readonly:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Add Comment
|
||||
uses: ./.github/actions/AddComment
|
||||
with:
|
||||
readonly: ${{ github.event.inputs.readonly }}
|
||||
labels: bug,debugger
|
||||
ignoreLabels: "investigate: costing,investigate,external,by design,question,more info needed,Language Service,internal"
|
||||
createdAfter: "2024-07-22"
|
||||
addComment: "Thank you for reporting this issue. We’ll let you know if we need more information to investigate it. Additionally, if you're working with GDB/LLDB, please note that the code is open source at https://github.com/microsoft/MIEngine/wiki/Contributing-Code . Your contributions are always welcome and appreciated."
|
||||
addLabels: help wanted
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
name: By Design closer - debugger
|
||||
on:
|
||||
schedule:
|
||||
- cron: 0 13 * * * # Run at 1:00 PM UTC (5:00 AM PST, 6:00 AM PDT)
|
||||
- cron: 10 11 * * * # Run at 11:10 AM UTC (3:10 AM PST, 4:10 AM PDT)
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
readonly:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Stale Closer
|
||||
@@ -26,7 +21,6 @@ jobs:
|
||||
with:
|
||||
readonly: ${{ github.event.inputs.readonly }}
|
||||
labels: by design,debugger
|
||||
ignoreLabels: Language Service,internal
|
||||
ignoreLabels: language service,internal
|
||||
closeDays: 0
|
||||
closeComment: "This issue has been closed because the described behavior was determined to be by design."
|
||||
|
||||
closeComment: "This issue has been closed automatically because it's labeled as 'by design'."
|
||||
|
||||
@@ -8,17 +8,12 @@ on:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Stale Closer
|
||||
@@ -28,7 +23,6 @@ jobs:
|
||||
labels: by design
|
||||
ignoreLabels: debugger,Feature Request,more info needed,internal
|
||||
closeDays: 60
|
||||
closeComment: "This issue has been closed because the described behavior was determined to be by design."
|
||||
closeComment: "This issue has been closed automatically because it's labeled as 'by design' and has not had recent activity."
|
||||
pingDays: 80
|
||||
pingComment: "Hey @${assignee}, this issue might need further attention.\n\n@${author}, you can help us out by closing this issue if it is no longer relevant."
|
||||
|
||||
|
||||
@@ -1,17 +1,55 @@
|
||||
name: CI (Linux)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
job:
|
||||
uses: ./.github/workflows/job-compile-and-test.yml
|
||||
with:
|
||||
runner-env: ubuntu-24.04
|
||||
platform: linux
|
||||
name: CI (Linux)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Use Node.js 14.16.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 14.16.x
|
||||
|
||||
- name: Install Dependencies
|
||||
run: yarn install
|
||||
working-directory: Extension
|
||||
|
||||
- name: Generate hashes for runtime dependency packages
|
||||
run: yarn run generatePackageHashes
|
||||
working-directory: Extension
|
||||
|
||||
- name: Compile Sources
|
||||
run: yarn run compile
|
||||
working-directory: Extension
|
||||
|
||||
- name: Validate Extension/package.json
|
||||
run: yarn run pr-check
|
||||
working-directory: Extension
|
||||
|
||||
- name: Run Linter
|
||||
run: yarn run lint
|
||||
working-directory: Extension
|
||||
|
||||
- name: Compile Test Sources
|
||||
run: yarn run pretest
|
||||
working-directory: Extension
|
||||
|
||||
- name: Run unit tests
|
||||
uses: GabrielBB/[email protected]
|
||||
with:
|
||||
run: yarn run unitTests
|
||||
working-directory: Extension
|
||||
|
||||
- name: Run languageServer integration tests
|
||||
uses: GabrielBB/[email protected]
|
||||
with:
|
||||
run: yarn run integrationTests
|
||||
working-directory: Extension
|
||||
|
||||
@@ -1,18 +1,55 @@
|
||||
name: CI (Mac)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
job:
|
||||
uses: ./.github/workflows/job-compile-and-test.yml
|
||||
with:
|
||||
runner-env: macos-15
|
||||
platform: mac
|
||||
yarn-args: --network-timeout 100000
|
||||
name: CI (Mac)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Use Node.js 14.16.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 14.16.x
|
||||
|
||||
- name: Install Dependencies
|
||||
run: yarn install --network-timeout 100000
|
||||
working-directory: Extension
|
||||
|
||||
- name: Generate hashes for runtime dependency packages
|
||||
run: yarn run generatePackageHashes
|
||||
working-directory: Extension
|
||||
|
||||
- name: Compile Sources
|
||||
run: yarn run compile
|
||||
working-directory: Extension
|
||||
|
||||
- name: Validate Extension/package.json
|
||||
run: yarn run pr-check
|
||||
working-directory: Extension
|
||||
|
||||
- name: Run Linter
|
||||
run: yarn run lint
|
||||
working-directory: Extension
|
||||
|
||||
- name: Compile Test Sources
|
||||
run: yarn run pretest
|
||||
working-directory: Extension
|
||||
|
||||
- name: Run unit tests
|
||||
uses: GabrielBB/[email protected]
|
||||
with:
|
||||
run: yarn run unitTests
|
||||
working-directory: Extension
|
||||
|
||||
- name: Run languageServer integration tests
|
||||
uses: GabrielBB/[email protected]
|
||||
with:
|
||||
run: yarn run integrationTests
|
||||
working-directory: Extension
|
||||
|
||||
@@ -1,17 +1,51 @@
|
||||
name: CI (Windows)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
job:
|
||||
uses: ./.github/workflows/job-compile-and-test.yml
|
||||
with:
|
||||
runner-env: windows-2025
|
||||
platform: windows
|
||||
name: CI (Windows)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Use Node.js 14.16.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 14.16.x
|
||||
|
||||
- name: Install Dependencies
|
||||
run: yarn install
|
||||
working-directory: Extension
|
||||
|
||||
- name: Generate hashes for runtime dependency packages
|
||||
run: yarn run generatePackageHashes
|
||||
working-directory: Extension
|
||||
|
||||
- name: Compile Sources
|
||||
run: yarn run compile
|
||||
working-directory: Extension
|
||||
|
||||
- name: Validate Extension/package.json
|
||||
run: yarn run pr-check
|
||||
working-directory: Extension
|
||||
|
||||
- name: Run Linter
|
||||
run: yarn run lint
|
||||
working-directory: Extension
|
||||
|
||||
- name: Compile Test Sources
|
||||
run: yarn run pretest
|
||||
working-directory: Extension
|
||||
|
||||
- name: Run unit tests
|
||||
run: yarn run unitTests
|
||||
working-directory: Extension
|
||||
|
||||
- name: Run languageServer integration tests
|
||||
run: yarn run integrationTests
|
||||
working-directory: Extension
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main", "insiders", "release", "vs" ]
|
||||
pull_request:
|
||||
branches: [ "main", "insiders", "release", "vs" ]
|
||||
schedule:
|
||||
- cron: '29 4 * * 3'
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze (${{ matrix.language }})
|
||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
||||
# - https://gh.io/supported-runners-and-hardware-resources
|
||||
# - https://gh.io/using-larger-runners (GitHub.com only)
|
||||
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
||||
permissions:
|
||||
# required for all workflows
|
||||
security-events: write
|
||||
|
||||
# required to fetch internal or private CodeQL packs
|
||||
packages: read
|
||||
|
||||
# only required for workflows in private repositories
|
||||
actions: read
|
||||
contents: read
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- language: javascript-typescript
|
||||
build-mode: none
|
||||
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
|
||||
# Use `c-cpp` to analyze code written in C, C++ or both
|
||||
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
||||
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
||||
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
|
||||
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
|
||||
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
|
||||
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: ${{ matrix.build-mode }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
# If the analyze step fails for one of the languages you are analyzing with
|
||||
# "We were unable to automatically build your code", modify the matrix above
|
||||
# to set the build mode to "manual" for that language. Then modify this step
|
||||
# to build your code.
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
- if: matrix.build-mode == 'manual'
|
||||
shell: bash
|
||||
run: |
|
||||
echo 'If you are using a "manual" build mode for one or more of the' \
|
||||
'languages you are analyzing, replace this with the commands to build' \
|
||||
'your code, for example:'
|
||||
echo ' make bootstrap'
|
||||
echo ' make release'
|
||||
exit 1
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
@@ -8,17 +8,12 @@ on:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Stale Closer
|
||||
@@ -28,7 +23,6 @@ jobs:
|
||||
labels: duplicate
|
||||
ignoreLabels: debugger,Feature Request,more info needed,by design,internal
|
||||
closeDays: 60
|
||||
closeComment: "This issue has been closed because it is a duplicate of another issue we are tracking."
|
||||
closeComment: "This issue has been closed automatically because it's labeled as a 'duplicate' and has not had recent activity."
|
||||
pingDays: 80
|
||||
pingComment: "Hey @${assignee}, this issue might need further attention.\n\n@${author}, you can help us out by closing this issue if it is no longer relevant."
|
||||
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
name: Enhancement Closer (no milestone)
|
||||
on:
|
||||
schedule:
|
||||
- cron: 40 12 * * * # Run at 12:40 PM UTC (4:40 AM PST, 5:40 AM PDT)
|
||||
- cron: 50 11 * * * # Run at 11:50 AM UTC (3:50 AM PST, 4:50 AM PDT)
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
readonly:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Stale Closer
|
||||
@@ -30,7 +25,6 @@ jobs:
|
||||
addLabels: more votes needed
|
||||
closeDays: 60
|
||||
maximumVotes: 2
|
||||
closeComment: "This feature request is being closed due to insufficient upvotes. Please leave a 👍-upvote or 👎-downvote reaction on the issue to help us prioritize it. When enough upvotes are received, this issue will be eligible for our backlog."
|
||||
closeComment: "This feature request is being closed due to insufficient upvotes. When enough upvotes are received, this issue will be eligible for our backlog."
|
||||
setMilestoneId: 30
|
||||
ignoreMilestoneNames: "*"
|
||||
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
name: Enhancement Closer (Triage)
|
||||
on:
|
||||
schedule:
|
||||
- cron: 30 12 * * * # Run at 12:30 PM UTC (4:30 AM PST, 5:30 AM PDT)
|
||||
- cron: 40 11 * * * # Run at 11:40 AM UTC (3:40 AM PST, 4:40 AM PDT)
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
readonly:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Stale Closer
|
||||
@@ -30,7 +25,6 @@ jobs:
|
||||
addLabels: more votes needed
|
||||
closeDays: 60
|
||||
maximumVotes: 2
|
||||
closeComment: "This feature request is being closed due to insufficient upvotes. Please leave a 👍-upvote or 👎-downvote reaction on the issue to help us prioritize it. When enough upvotes are received, this issue will be eligible for our backlog."
|
||||
closeComment: "This feature request is being closed due to insufficient upvotes. When enough upvotes are received, this issue will be eligible for our backlog."
|
||||
milestoneName: Triage
|
||||
milestoneId: 30
|
||||
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
name: Enhancement Reopener
|
||||
on:
|
||||
schedule:
|
||||
- cron: 0 11 * * * # Run at 11:00 AM UTC (3:00 AM PST, 4:00 AM PDT)
|
||||
- cron: 20 12 * * * # Run at 12:20 PM UTC (4:20 AM PST, 5:20 AM PDT)
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
readonly:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Run Reopener
|
||||
@@ -34,4 +29,3 @@ jobs:
|
||||
milestoneName: Triage
|
||||
setMilestoneId: 28
|
||||
removeLabels: more votes needed
|
||||
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
name: External closer - debugger
|
||||
on:
|
||||
schedule:
|
||||
- cron: 10 13 * * * # Run at 1:10 PM UTC (5:10 AM PST, 6:10 AM PDT)
|
||||
- cron: 10 11 * * * # Run at 11:10 AM UTC (3:10 AM PST, 4:10 AM PDT)
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
readonly:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Stale Closer
|
||||
@@ -26,7 +21,6 @@ jobs:
|
||||
with:
|
||||
readonly: ${{ github.event.inputs.readonly }}
|
||||
labels: external,debugger
|
||||
ignoreLabels: Language Service,internal
|
||||
ignoreLabels: language service,internal
|
||||
closeDays: 0
|
||||
closeComment: "This issue has been closed because it is external or not applicable to the extension."
|
||||
|
||||
closeComment: "This issue has been closed automatically because it's labeled as 'external'."
|
||||
|
||||
@@ -8,17 +8,12 @@ on:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Stale Closer
|
||||
@@ -30,7 +25,6 @@ jobs:
|
||||
addLabels: more votes needed
|
||||
closeDays: 60
|
||||
maximumVotes: 2
|
||||
closeComment: "This feature request is being closed due to insufficient upvotes. Please leave a 👍-upvote or 👎-downvote reaction on the issue to help us prioritize it. When enough upvotes are received, this issue will be eligible for our backlog."
|
||||
closeComment: "This feature request is being closed due to insufficient upvotes. When enough upvotes are received, this issue will be eligible for our backlog."
|
||||
setMilestoneId: 30
|
||||
ignoreMilestoneNames: "*"
|
||||
|
||||
|
||||
@@ -8,17 +8,12 @@ on:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Stale Closer
|
||||
@@ -30,7 +25,6 @@ jobs:
|
||||
addLabels: more votes needed
|
||||
closeDays: 60
|
||||
maximumVotes: 2
|
||||
closeComment: "This feature request is being closed due to insufficient upvotes. Please leave a 👍-upvote or 👎-downvote reaction on the issue to help us prioritize it. When enough upvotes are received, this issue will be eligible for our backlog."
|
||||
closeComment: "This feature request is being closed due to insufficient upvotes. When enough upvotes are received, this issue will be eligible for our backlog."
|
||||
milestoneName: Triage
|
||||
milestoneId: 30
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
name: Feature Request - debugger
|
||||
on:
|
||||
schedule:
|
||||
- cron: 20 13 * * * # Run at 1:20 PM UTC (5:20 AM PST, 6:20 AM PDT)
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
readonly:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Add Comment
|
||||
uses: ./.github/actions/AddComment
|
||||
with:
|
||||
readonly: ${{ github.event.inputs.readonly }}
|
||||
labels: Feature Request,debugger
|
||||
ignoreLabels: "investigate: costing,investigate,external,by design,question,more info needed,Language Service,internal"
|
||||
createdAfter: "2024-07-22"
|
||||
addComment: "Thank you for your feature request. While we may not be able to implement it immediately, we will monitor community reactions to see how it fits into our backlog. Additionally, if you're working with GDB/LLDB, please note that the code is open source at https://github.com/microsoft/MIEngine/wiki/Contributing-Code . Your contributions are always welcome and appreciated."
|
||||
addLabels: help wanted
|
||||
|
||||
@@ -8,17 +8,12 @@ on:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Run Reopener
|
||||
@@ -34,4 +29,3 @@ jobs:
|
||||
milestoneName: Triage
|
||||
setMilestoneId: 28
|
||||
removeLabels: more votes needed
|
||||
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
name: Investigate closer - debugger
|
||||
on:
|
||||
schedule:
|
||||
- cron: 30 13 * * * # Run at 1:30 PM UTC (5:30 AM PST, 6:30 AM PDT)
|
||||
- cron: 10 11 * * * # Run at 11:10 AM UTC (3:10 AM PST, 4:10 AM PDT)
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
readonly:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Stale Closer
|
||||
@@ -26,7 +21,6 @@ jobs:
|
||||
with:
|
||||
readonly: ${{ github.event.inputs.readonly }}
|
||||
labels: investigate,debugger
|
||||
ignoreLabels: Language Service,internal
|
||||
ignoreLabels: language service,internal
|
||||
closeDays: 180
|
||||
closeComment: "This issue has been closed as lower priority. We're sorry if this issue still impacts you but unfortunately we're not able to address this. We will accept a pull request from the community if it's applicable for this issue."
|
||||
|
||||
closeComment: "This issue has been closed automatically because it has not had recent activity."
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
name: Investigate Costing closer - debugger
|
||||
on:
|
||||
schedule:
|
||||
- cron: 40 13 * * * # Run at 1:40 PM UTC (5:40 AM PST, 6:40 AM PDT)
|
||||
- cron: 10 11 * * * # Run at 11:10 AM UTC (3:10 AM PST, 4:10 AM PDT)
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
readonly:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Stale Closer
|
||||
@@ -26,7 +21,6 @@ jobs:
|
||||
with:
|
||||
readonly: ${{ github.event.inputs.readonly }}
|
||||
labels: "investigate: costing,debugger"
|
||||
ignoreLabels: Language Service,internal
|
||||
ignoreLabels: language service,internal
|
||||
closeDays: 180
|
||||
closeComment: "This issue has been closed as lower priority. We're sorry if this issue still impacts you but unfortunately we're not able to address this. We will accept a pull request from the community if it's applicable for this issue."
|
||||
|
||||
closeComment: "This issue has been closed automatically because it has not had recent activity."
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
# Reuable workflow for compiling and testing extension.
|
||||
name: Compile and test extension
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
runner-env:
|
||||
required: true
|
||||
type: string
|
||||
platform:
|
||||
# Expects 'mac', 'linux', or 'windows'
|
||||
required: true
|
||||
type: string
|
||||
yarn-args:
|
||||
type: string
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ inputs.runner-env }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Use Node.js 24
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
|
||||
- name: Install Dependencies
|
||||
run: yarn install ${{ inputs.yarn-args }}
|
||||
working-directory: Extension
|
||||
|
||||
- name: Compile Sources
|
||||
run: yarn run compile
|
||||
working-directory: Extension
|
||||
|
||||
- name: Run Linter
|
||||
run: yarn run lint
|
||||
working-directory: Extension
|
||||
|
||||
- name: Run unit tests
|
||||
run: yarn test
|
||||
working-directory: Extension
|
||||
|
||||
# These tests don't require the binary.
|
||||
# On Linux, it is failing (before the tests actually run) with: Test run terminated with signal SIGSEGV.
|
||||
# But it works on Linux during the E2E test.
|
||||
- name: Run SingleRootProject tests
|
||||
if: ${{ inputs.platform != 'linux' }}
|
||||
run: yarn test --scenario=SingleRootProject --skipCheckBinaries
|
||||
working-directory: Extension
|
||||
|
||||
# NOTE : We can't run the test that require the native binary files
|
||||
# yet -- there will be an update soon that allows the tester to
|
||||
# acquire them on-the-fly
|
||||
# - name: Run languageServer integration tests
|
||||
# if: ${{ inputs.platform == 'windows' }}
|
||||
# run: yarn test --scenario=SingleRootProject
|
||||
# working-directory: Extension
|
||||
|
||||
# - name: Run E2E IntelliSense features tests
|
||||
# if: ${{ inputs.platform == 'windows' }}
|
||||
# run: yarn test --scenario=MultirootDeadlockTest
|
||||
# working-directory: Extension
|
||||
|
||||
# - name: Run E2E IntelliSense features tests
|
||||
# if: ${{ inputs.platform == 'windows' }}
|
||||
# run: yarn test --scenario=RunWithoutDebugging
|
||||
# working-directory: Extension
|
||||
|
||||
# NOTE: For mac/linux run the tests with xvfb-action for UI support.
|
||||
# Another way to start xvfb https://github.com/microsoft/vscode-test/blob/master/sample/azure-pipelines.yml
|
||||
|
||||
# - name: Run languageServer integration tests (xvfb)
|
||||
# if: ${{ inputs.platform == 'mac' || inputs.platform == 'linux' }}
|
||||
# uses: coactions/setup-xvfb@v1
|
||||
# with:
|
||||
# run: yarn test --scenario=SingleRootProject
|
||||
# working-directory: Extension
|
||||
|
||||
# - name: Run E2E IntelliSense features tests (xvfb)
|
||||
# if: ${{ inputs.platform == 'mac' || inputs.platform == 'linux' }}
|
||||
# uses: coactions/setup-xvfb@v1
|
||||
# with:
|
||||
# run: yarn test --scenario=MultirootDeadlockTest
|
||||
# working-directory: Extension
|
||||
|
||||
# - name: Run E2E IntelliSense features tests (xvfb)
|
||||
# if: ${{ inputs.platform == 'mac' || inputs.platform == 'linux' }}
|
||||
# uses: coactions/setup-xvfb@v1
|
||||
# with:
|
||||
# run: yarn test --scenario=RunWithoutDebugging
|
||||
# working-directory: Extension
|
||||
|
||||
@@ -8,17 +8,12 @@ on:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Run Locker
|
||||
@@ -28,4 +23,3 @@ jobs:
|
||||
daysSinceClose: 45
|
||||
daysSinceUpdate: 3
|
||||
ignoreLabels: more votes needed,debugger,internal
|
||||
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
name: More Info Needed Closer - debugger
|
||||
on:
|
||||
schedule:
|
||||
- cron: 50 13 * * * # Run at 1:50 PM UTC (5:50 AM PST, 6:50 AM PDT)
|
||||
- cron: 10 11 * * * # Run at 11:10 AM UTC (3:10 AM PST, 4:10 AM PDT)
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
readonly:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Stale Closer
|
||||
@@ -26,10 +21,9 @@ jobs:
|
||||
with:
|
||||
readonly: ${{ github.event.inputs.readonly }}
|
||||
labels: more info needed,debugger
|
||||
ignoreLabels: Language Service,internal
|
||||
ignoreLabels: language service,internal
|
||||
involves: wardengnaw,pieandcakes,calgagi
|
||||
closeDays: 14
|
||||
closeComment: "This issue has been closed because it needs more information and has not had recent activity."
|
||||
closeComment: "This issue has been closed automatically because it needs more information and has not had recent activity."
|
||||
pingDays: 7
|
||||
pingComment: "Hey @${assignee}, this issue might need further attention.\n\n@${author}, you can help us out by closing this issue if the problem no longer exists, or adding more information."
|
||||
|
||||
|
||||
@@ -8,17 +8,12 @@ on:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Stale Closer
|
||||
@@ -27,8 +22,7 @@ jobs:
|
||||
readonly: ${{ github.event.inputs.readonly }}
|
||||
labels: more info needed
|
||||
ignoreLabels: debugger,internal
|
||||
closeDays: 30
|
||||
closeComment: "This issue has been closed because it needs more information and has not had recent activity."
|
||||
pingDays: 14
|
||||
closeDays: 60
|
||||
closeComment: "This issue has been closed automatically because it needs more information and has not had recent activity."
|
||||
pingDays: 80
|
||||
pingComment: "Hey @${assignee}, this issue might need further attention.\n\n@${author}, you can help us out by closing this issue if the problem no longer exists, or adding more information."
|
||||
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
name: Question Closer - debugger
|
||||
on:
|
||||
schedule:
|
||||
- cron: 0 14 * * * # Run at 2:00 PM UTC (6:00 AM PST, 7:00 AM PDT)
|
||||
- cron: 20 11 * * * # Run at 11:20 AM UTC (3:20 AM PST, 4:20 AM PDT)
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
readonly:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Stale Closer
|
||||
@@ -26,10 +21,9 @@ jobs:
|
||||
with:
|
||||
readonly: ${{ github.event.inputs.readonly }}
|
||||
labels: question,debugger
|
||||
ignoreLabels: Language Service,internal
|
||||
ignoreLabels: language service,internal
|
||||
involves: wardengnaw,pieandcakes,calgagi
|
||||
closeDays: 14
|
||||
closeComment: "This issue has been closed because it is a question and has not had recent activity."
|
||||
closeComment: "This issue has been closed automatically because it's labeled as a 'question' and has not had recent activity."
|
||||
pingDays: 7
|
||||
pingComment: "Hey @${assignee}, this issue might need further attention.\n\n@${author}, you can help us out by closing this issue if the question has been answered."
|
||||
|
||||
|
||||
@@ -8,17 +8,12 @@ on:
|
||||
description: "readonly: Specify true or 1 to prevent changes from being commited to GitHub"
|
||||
default: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Actions
|
||||
run: cd ./.github/actions && npm install --production && cd ../..
|
||||
- name: Stale Closer
|
||||
@@ -28,7 +23,6 @@ jobs:
|
||||
labels: question
|
||||
ignoreLabels: debugger,internal
|
||||
closeDays: 60
|
||||
closeComment: "This issue has been closed because it is a question and has not had recent activity."
|
||||
closeComment: "This issue has been closed automatically because it's labeled as a 'question' and has not had recent activity."
|
||||
pingDays: 80
|
||||
pingComment: "Hey @${assignee}, this issue might need further attention.\n\n@${author}, you can help us out by closing this issue if the question has been answered."
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ browse*.db*
|
||||
# ignore exported localization xlf and LCL directories
|
||||
Build/loc/LCL
|
||||
vscode-extensions-localization-export
|
||||
OneLocBuild
|
||||
|
||||
# ignore imported localization xlf directory
|
||||
vscode-translations-import
|
||||
|
||||
-120
@@ -1,120 +0,0 @@
|
||||
name: $(date:yyyyMMdd)$(rev:.r)
|
||||
trigger:
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
- release
|
||||
- insiders
|
||||
|
||||
schedules:
|
||||
- cron: 30 5 * * 0
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
always: true
|
||||
|
||||
resources:
|
||||
repositories:
|
||||
- repository: MicroBuildTemplate
|
||||
type: git
|
||||
name: 1ESPipelineTemplates/MicroBuildTemplate
|
||||
ref: refs/tags/release
|
||||
|
||||
variables:
|
||||
- name: Codeql.Enabled
|
||||
value: true
|
||||
- name: Codeql.Language
|
||||
value: javascript
|
||||
|
||||
extends:
|
||||
template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate
|
||||
parameters:
|
||||
pool:
|
||||
name: AzurePipelines-EO
|
||||
image: 1ESPT-Windows2025
|
||||
os: windows
|
||||
sdl:
|
||||
sourceAnalysisPool:
|
||||
name: AzurePipelines-EO
|
||||
image: 1ESPT-Windows2025
|
||||
os: windows
|
||||
binskim:
|
||||
preReleaseVersion: '4.3.1'
|
||||
tsa:
|
||||
enabled: true
|
||||
config:
|
||||
tsaVersion: TsaV2
|
||||
codebase: NewOrUpdate
|
||||
codebaseName: vscode-cpptools
|
||||
tsaStamp: $(TsaProjectName)
|
||||
tsaEnvironment: PROD
|
||||
notificationAliases: $(TsaNotificationAlias)
|
||||
codebaseAdmins: $(TsaCodebaseAdmins)
|
||||
instanceUrl: $(TsaInstanceUrl)
|
||||
projectName: $(TsaProjectName)
|
||||
areaPath: $(TsaAreaPath)
|
||||
iterationPath: $(TsaIterationPath)
|
||||
alltools: true
|
||||
repositoryName: vscode-cpptools
|
||||
policheck:
|
||||
enabled: true
|
||||
featureFlags:
|
||||
autoBaseline: false
|
||||
settings:
|
||||
networkIsolationPolicy: Permissive,CFSClean,CFSClean2,CFSClean3
|
||||
|
||||
stages:
|
||||
- stage: build
|
||||
jobs:
|
||||
- job: Phase_1
|
||||
displayName: Build cpptools.vsix
|
||||
timeoutInMinutes: 60
|
||||
cancelTimeoutInMinutes: 1
|
||||
templateContext:
|
||||
outputs:
|
||||
- output: pipelineArtifact
|
||||
displayName: 'cpptools.vsix'
|
||||
condition: succeeded()
|
||||
targetPath: $(Build.ArtifactStagingDirectory)\Extension
|
||||
artifactName: cpptools.vsix
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
|
||||
- task: UseNode@1
|
||||
displayName: Use Node 22.x
|
||||
inputs:
|
||||
version: 22.x
|
||||
|
||||
- script: IF EXIST %SYSTEMDRIVE%\Users\%USERNAME%\.npmrc del %SYSTEMDRIVE%\Users\%USERNAME%\.npmrc
|
||||
displayName: Delete .npmrc if it exists
|
||||
|
||||
- script: mkdir $(Build.ArtifactStagingDirectory)\Extension
|
||||
displayName: Create Extension Staging Directory
|
||||
|
||||
- task: Bash@3
|
||||
displayName: Build files
|
||||
inputs:
|
||||
targetType: 'inline'
|
||||
script: |
|
||||
export SRC_DIR=$(echo $BUILD_SOURCESDIRECTORY | sed 's|\\|/|g')
|
||||
cd "$SRC_DIR/Extension"
|
||||
npm run vsix-prepublish
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "npm run vsix-prepublish failed, sleeping for 30s before retrying..."
|
||||
sleep 30
|
||||
exit 1
|
||||
fi
|
||||
retryCountOnTaskFailure: 3
|
||||
|
||||
- script: yarn install --frozen-lockfile
|
||||
displayName: Install dependencies with yarn
|
||||
workingDirectory: $(Build.SourcesDirectory)\Extension
|
||||
|
||||
- script: if not exist node_modules\@vscode\vsce-sign\bin\vsce-sign.exe (echo Missing vsce-sign.exe && exit 1)
|
||||
displayName: Verify vsce-sign binary exists
|
||||
workingDirectory: $(Build.SourcesDirectory)\Extension
|
||||
|
||||
- script: npx vsce package --yarn -o $(Build.ArtifactStagingDirectory)\Extension\cpptools.vsix
|
||||
displayName: Run VSCE to package vsix
|
||||
workingDirectory: $(Build.SourcesDirectory)\Extension
|
||||
@@ -1,6 +0,0 @@
|
||||
This folder contains the entitlements needed for the debugger to run on macOS.
|
||||
|
||||
We use the entitlements that the .net runtime uses. See https://github.com/dotnet/runtime/blob/57678512d214af368ff055f358c5106f1aa19ac4/eng/pipelines/common/entitlements.plist
|
||||
|
||||
Related Links:
|
||||
https://docs.microsoft.com/en-us/dotnet/core/install/macos-notarization-issues#default-entitlements
|
||||
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.debugger</key>
|
||||
<true/>
|
||||
<key>com.apple.security.get-task-allow</key>
|
||||
<true/>
|
||||
<key>com.apple.security.task_for_pid-allow</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,30 +0,0 @@
|
||||
---
|
||||
parameters:
|
||||
archs: ["x86_64", "arm64"]
|
||||
|
||||
jobs:
|
||||
- job:
|
||||
pool:
|
||||
name: VSEngSS-MicroBuild2022-1ES
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- ${{ each arch in parameters.archs }}:
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Downloading unsigned_lldb-mi_${{ arch }}'
|
||||
inputs:
|
||||
targetPath: '$(Pipeline.Workspace)/Artifacts'
|
||||
artifactName: 'unsigned_lldb-mi_${{ arch }}'
|
||||
|
||||
- task: MicroBuildSignMacFiles@1
|
||||
displayName: 'ESRP Sign'
|
||||
inputs:
|
||||
SigningTarget: '$(Pipeline.Workspace)\Artifacts\lldb-mi_${{ arch }}.zip'
|
||||
SigningCert: 8023
|
||||
|
||||
- task: PublishPipelineArtifact@1
|
||||
displayName: 'Publish signed LLDB-MI'
|
||||
inputs:
|
||||
targetPath: '$(Pipeline.Workspace)\Artifacts\lldb-mi_${{ arch }}.zip'
|
||||
artifactName: 'lldb-mi_${{ arch }}_zip'
|
||||
...
|
||||
@@ -1,160 +0,0 @@
|
||||
parameters:
|
||||
# Note: Make sure llvm_repo is the same as the one in Extension/cgmanifest.json
|
||||
# 'RepositoryUrl' for llvm-project.
|
||||
llvm_repo: https://github.com/llvm/llvm-project.git
|
||||
|
||||
# Note: Make sure llvm_commit is the same as the one in Extension/cgmanifest.json
|
||||
# 'CommitHash' for llvm-project.
|
||||
llvm_commit: 0d44201451f03ba907cdb268ddddfc3fa38a0ebd
|
||||
|
||||
llvm_build_type: Release
|
||||
|
||||
llvm_arch: x86_64
|
||||
|
||||
llvm_additional_parameters: "-DLLDB_USE_SYSTEM_DEBUGSERVER=ON -DLLDB_RELOCATABLE_PYTHON=1 -DLLDB_INCLUDE_TESTS=OFF -DLLDB_BUILD_FRAMEWORK=1"
|
||||
|
||||
# Note: Make sure lldb_mi_repo is the same as the one in Extension/cgmanifest.json
|
||||
# 'CommitHash' for lldb-mi.
|
||||
lldb_mi_repo: https://github.com/lldb-tools/lldb-mi.git
|
||||
|
||||
# Note: Make sure lldb_mi_commit is the same as the one in Extension/cgmanifest.json
|
||||
# 'CommitHash' for lldb-mi.
|
||||
lldb_mi_commit: 2388bd74133bc21eac59b2e2bf97f2a30770a315
|
||||
|
||||
lldb_mi_additional_parameters: "-DUSE_LLDB_FRAMEWORK=1"
|
||||
|
||||
jobs:
|
||||
- job: LLDB_MI_${{ parameters.llvm_arch }}
|
||||
timeoutInMinutes: 360
|
||||
pool:
|
||||
${{if eq(parameters['llvm_arch'], 'arm64')}}:
|
||||
name: cpptoolsMacM1pool
|
||||
${{ else }}:
|
||||
vmImage: macOS-latest
|
||||
steps:
|
||||
- task: CmdLine@2
|
||||
displayName: 'Install Dependencies'
|
||||
inputs:
|
||||
script: brew install cmake ninja swig
|
||||
continueOnError: true
|
||||
|
||||
- task: CmdLine@2
|
||||
displayName: 'Make sure buildspace does not exist'
|
||||
inputs:
|
||||
script: rm -rf $(Build.StagingDirectory)/buildspace
|
||||
condition: always()
|
||||
|
||||
- task: CmdLine@2
|
||||
displayName: 'Build LLVM Project'
|
||||
inputs:
|
||||
script: |
|
||||
log_and_exec_cmd() {
|
||||
echo "##[command] $1"
|
||||
$1
|
||||
}
|
||||
|
||||
log_and_exec_cmd "sudo rm -rf /Library/Developer/CommandLineTools"
|
||||
log_and_exec_cmd "sudo xcode-select --switch /Applications/XCode.app"
|
||||
|
||||
log_and_exec_cmd "cd $(Build.StagingDirectory)"
|
||||
log_and_exec_cmd "mkdir $(Build.StagingDirectory)/buildspace"
|
||||
|
||||
log_and_exec_cmd "git clone ${{ parameters.llvm_repo }} llvm-project"
|
||||
log_and_exec_cmd "cd llvm-project"
|
||||
log_and_exec_cmd "git checkout ${{ parameters.llvm_commit }}"
|
||||
|
||||
log_and_exec_cmd "./lldb/scripts/macos-setup-codesign.sh"
|
||||
|
||||
log_and_exec_cmd "cd .."
|
||||
log_and_exec_cmd "mkdir $(Build.StagingDirectory)/buildspace/llvm-inst"
|
||||
log_and_exec_cmd "mkdir $(Build.StagingDirectory)/buildspace/llvm-build"
|
||||
log_and_exec_cmd "cd $(Build.StagingDirectory)/buildspace/llvm-build"
|
||||
|
||||
log_and_exec_cmd "cmake -DLLVM_ENABLE_PROJECTS=clang;lldb -DCMAKE_BUILD_TYPE=${{ parameters.llvm_build_type }} -DCMAKE_INSTALL_PREFIX=$(Build.StagingDirectory)/buildspace/llvm-inst/ -DCMAKE_OSX_ARCHITECTURES=${{ parameters.llvm_arch }} ${{ parameters.llvm_additional_parameters }} -GNinja $(Build.StagingDirectory)/llvm-project/llvm"
|
||||
if [[ $? -ne 0 ]]
|
||||
then
|
||||
echo "##[error] cmake llvm failed"
|
||||
cat $(Build.SourcesDirectory)/buildspace/llvm-build/CMakeFiles/CMakeError.log
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_and_exec_cmd ninja
|
||||
if [[ $? -ne 0 ]]
|
||||
then
|
||||
echo "##[error] ninja failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
### Workaround for https://github.com/llvm/llvm-project/issues/108
|
||||
log_and_exec_cmd "ninja install"
|
||||
|
||||
# Remove conflicting LLDB.framework file.
|
||||
log_and_exec_cmd "rm -rf $(Build.StagingDirectory)/buildspace/llvm-inst/Library/Frameworks/LLDB.framework"
|
||||
|
||||
# Build lldb/sources/API first
|
||||
log_and_exec_cmd "cmake -P $(Build.StagingDirectory)/buildspace/llvm-build/tools/lldb/source/API/cmake_install.cmake"
|
||||
### End of Workaround
|
||||
|
||||
log_and_exec_cmd "ninja install"
|
||||
if [[ $? -ne 0 ]]
|
||||
then
|
||||
echo "##[error] ninja install failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "##[section] Build LLDB-MI"
|
||||
# Download lldb-mi and build it against our custom installation.
|
||||
log_and_exec_cmd "cd $(Build.StagingDirectory)/buildspace"
|
||||
log_and_exec_cmd "git clone ${{ parameters.lldb_mi_repo }} lldb-mi"
|
||||
log_and_exec_cmd "cd lldb-mi"
|
||||
log_and_exec_cmd "git checkout ${{ parameters.lldb_mi_commit }}"
|
||||
|
||||
# Create a separate build directory for building lldb-mi.
|
||||
log_and_exec_cmd "mkdir build"
|
||||
log_and_exec_cmd "cd build"
|
||||
log_and_exec_cmd "cmake -DCMAKE_PREFIX_PATH=$(Build.StagingDirectory)/buildspace/llvm-inst/ -DCMAKE_OSX_ARCHITECTURES=${{ parameters.llvm_arch }} ${{ parameters.lldb_mi_additional_parameters }} -GNinja .."
|
||||
log_and_exec_cmd "ninja"
|
||||
if [[ $? -ne 0 ]]
|
||||
then
|
||||
echo "##[error] ninja failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_and_exec_cmd "mkdir $(Build.StagingDirectory)/publish"
|
||||
log_and_exec_cmd "cd $(Build.StagingDirectory)/publish"
|
||||
|
||||
log_and_exec_cmd "mkdir -p ./debugAdapters/lldb-mi_${{ parameters.llvm_arch }}/bin"
|
||||
|
||||
log_and_exec_cmd "cp $(Build.StagingDirectory)/buildspace/lldb-mi/build/src/lldb-mi ./debugAdapters/lldb-mi_${{ parameters.llvm_arch }}/bin/."
|
||||
|
||||
# Set rpath for finding LLDB.Framework
|
||||
log_and_exec_cmd "install_name_tool -add_rpath @rpath/LLDB.framework/Versions/A/LLDB ./debugAdapters/lldb-mi_${{ parameters.llvm_arch }}/bin/lldb-mi"
|
||||
|
||||
# Set rpath for App Store XCode LLDB.Framework
|
||||
log_and_exec_cmd "install_name_tool -add_rpath /Applications/Xcode.app/Contents/SharedFrameworks/ ./debugAdapters/lldb-mi_${{ parameters.llvm_arch }}/bin/lldb-mi"
|
||||
|
||||
# Set rpath for XCode CLI LLDB.Framework
|
||||
log_and_exec_cmd "install_name_tool -add_rpath /Library/Developer/CommandLineTools/Library/PrivateFrameworks/ ./debugAdapters/lldb-mi_${{ parameters.llvm_arch }}/bin/lldb-mi"
|
||||
|
||||
# Set rpath next to the lldb-mi executable LLDB.Framework
|
||||
log_and_exec_cmd "install_name_tool -add_rpath @executable_path/. ./debugAdapters/lldb-mi_${{ parameters.llvm_arch }}/bin/lldb-mi"
|
||||
|
||||
# Add entitlements
|
||||
log_and_exec_cmd "codesign -s - -f --entitlements $(Build.SourcesDirectory)/Build/lldb-mi/debugger-entitlements.plist ./debugAdapters/lldb-mi_${{ parameters.llvm_arch }}/bin/lldb-mi"
|
||||
|
||||
# Grab NOTICE.TXT
|
||||
cp $(Build.SourcesDirectory)/Build/lldb-mi/NOTICE.TXT ./debugAdapters/lldb-mi_${{ parameters.llvm_arch }}/.
|
||||
|
||||
zip -r $(Build.StagingDirectory)/lldb-mi_${{ parameters.llvm_arch }}.zip ./debugAdapters
|
||||
|
||||
- task: PublishPipelineArtifact@1
|
||||
displayName: 'Publish LLDB-MI'
|
||||
inputs:
|
||||
targetPath: '$(Build.StagingDirectory)/lldb-mi_${{ parameters.llvm_arch }}.zip'
|
||||
artifactName: 'unsigned_lldb-mi_${{ parameters.llvm_arch }}'
|
||||
|
||||
- task: CmdLine@2
|
||||
displayName: 'Clean up'
|
||||
inputs:
|
||||
script: rm -rf $(Build.StagingDirectory)/buildspace
|
||||
condition: always()
|
||||
+127
-21
@@ -1,23 +1,129 @@
|
||||
parameters:
|
||||
- name: Build_Type
|
||||
displayName: Build Type
|
||||
type: string
|
||||
default: Release
|
||||
variables:
|
||||
llvm_repo: https://github.com/llvm/llvm-project.git
|
||||
llvm_branch: release/12.x
|
||||
llvm_build_type: Release
|
||||
llvm_arch: x86_64
|
||||
llvm_additional_parameters: "-DLLDB_RELOCATABLE_PYTHON=1 -DLLDB_INCLUDE_TESTS=OFF -DLLDB_BUILD_FRAMEWORK=1"
|
||||
# TODO: fix lldb_mi_repo and lldb_mi_branch (https://github.com/lldb-tools/lldb-mi/pull/37 and https://github.com/lldb-tools/lldb-mi/pull/39)
|
||||
lldb_mi_repo: https://github.com/WardenGnaw/lldb-mi # TODO: Change to lldb-tools
|
||||
lldb_mi_branch: dev/waan/testLLDB12x # TODO: Change to main
|
||||
lldb_mi_additional_parameters: "-DUSE_LLDB_FRAMEWORK=1"
|
||||
|
||||
stages:
|
||||
- stage: Build
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: lldb-mi.template.yml
|
||||
parameters:
|
||||
llvm_build_type: ${{ parameters.Build_Type }}
|
||||
llvm_arch: x86_64
|
||||
- template: lldb-mi.template.yml
|
||||
parameters:
|
||||
llvm_build_type: ${{ parameters.Build_Type }}
|
||||
llvm_arch: arm64
|
||||
jobs:
|
||||
- job: LLDB_MI
|
||||
timeoutInMinutes: 360
|
||||
pool:
|
||||
vmImage: 'macOS-latest'
|
||||
steps:
|
||||
- task: CmdLine@2
|
||||
displayName: 'Install Dependencies'
|
||||
inputs:
|
||||
script: brew install cmake ninja swig
|
||||
continueOnError: true
|
||||
|
||||
- stage: Signing
|
||||
dependsOn: ["Build"]
|
||||
jobs:
|
||||
- template: lldb-mi-sign.template.yml
|
||||
- task: CmdLine@2
|
||||
displayName: 'Build LLVM Project'
|
||||
inputs:
|
||||
script: |
|
||||
log_and_exec_cmd() {
|
||||
echo "##[command] $1"
|
||||
$1
|
||||
}
|
||||
|
||||
# Don't use XCode CLI since it will cause C++ headers to be missing.
|
||||
log_and_exec_cmd "sudo rm -rf /Library/Developer/CommandLineTools"
|
||||
log_and_exec_cmd "sudo xcode-select --switch /Applications/XCode.app"
|
||||
|
||||
log_and_exec_cmd "cd $(Build.StagingDirectory)"
|
||||
log_and_exec_cmd "mkdir $(Build.StagingDirectory)/buildspace"
|
||||
|
||||
log_and_exec_cmd "git clone $(llvm_repo) llvm-project"
|
||||
log_and_exec_cmd "cd llvm-project"
|
||||
log_and_exec_cmd "git checkout $(llvm_branch)"
|
||||
|
||||
log_and_exec_cmd "./lldb/scripts/macos-setup-codesign.sh"
|
||||
|
||||
log_and_exec_cmd "cd .."
|
||||
log_and_exec_cmd "mkdir $(Build.StagingDirectory)/buildspace/llvm-inst"
|
||||
log_and_exec_cmd "mkdir $(Build.StagingDirectory)/buildspace/llvm-build"
|
||||
log_and_exec_cmd "cd $(Build.StagingDirectory)/buildspace/llvm-build"
|
||||
|
||||
log_and_exec_cmd "cmake -DLLVM_ENABLE_PROJECTS=clang;lldb -DCMAKE_BUILD_TYPE=$(llvm_build_type) -DCMAKE_INSTALL_PREFIX=$(Build.StagingDirectory)/buildspace/llvm-inst/ -DCMAKE_OSX_ARCHITECTURES=$(llvm_arch) $(llvm_additional_parameters) -GNinja $(Build.StagingDirectory)/llvm-project/llvm"
|
||||
if [[ $? -ne 0 ]]
|
||||
then
|
||||
echo "##[error] cmake llvm failed"
|
||||
cat $(Build.SourcesDirectory)/buildspace/llvm-build/CMakeFiles/CMakeError.log
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_and_exec_cmd ninja
|
||||
if [[ $? -ne 0 ]]
|
||||
then
|
||||
echo "##[error] ninja failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
### Workaround for https://github.com/llvm/llvm-project/issues/108
|
||||
log_and_exec_cmd "ninja install"
|
||||
|
||||
# Remove conflicting LLDB.framework file.
|
||||
log_and_exec_cmd "rm -rf $(Build.StagingDirectory)/buildspace/llvm-inst/Library/Frameworks/LLDB.framework"
|
||||
|
||||
# Build lldb/sources/API first
|
||||
log_and_exec_cmd "cmake -P $(Build.StagingDirectory)/buildspace/llvm-build/tools/lldb/source/API/cmake_install.cmake"
|
||||
### End of Workaround
|
||||
|
||||
log_and_exec_cmd "ninja install"
|
||||
if [[ $? -ne 0 ]]
|
||||
then
|
||||
echo "##[error] ninja install failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "##[section] Build LLDB-MI"
|
||||
# Download lldb-mi and build it against our custom installation.
|
||||
log_and_exec_cmd "cd $(Build.StagingDirectory)/buildspace"
|
||||
log_and_exec_cmd "git clone $(lldb_mi_repo) lldb-mi"
|
||||
log_and_exec_cmd "cd lldb-mi"
|
||||
log_and_exec_cmd "git checkout $(lldb_mi_branch)"
|
||||
|
||||
# Create a separate build directory for building lldb-mi.
|
||||
log_and_exec_cmd "mkdir build"
|
||||
log_and_exec_cmd "cd build"
|
||||
log_and_exec_cmd "cmake -DCMAKE_PREFIX_PATH=$(Build.StagingDirectory)/buildspace/llvm-inst/ $(lldb_mi_additional_parameters) -GNinja .."
|
||||
log_and_exec_cmd "ninja"
|
||||
if [[ $? -ne 0 ]]
|
||||
then
|
||||
echo "##[error] ninja failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_and_exec_cmd "mkdir $(Build.StagingDirectory)/publish"
|
||||
log_and_exec_cmd "cd $(Build.StagingDirectory)/publish"
|
||||
|
||||
log_and_exec_cmd "mkdir -p ./debugAdapters/lldb-mi/bin"
|
||||
|
||||
log_and_exec_cmd "cp $(Build.StagingDirectory)/buildspace/lldb-mi/build/src/lldb-mi ./debugAdapters/lldb-mi/bin/."
|
||||
|
||||
# Set rpath for finding LLDB.Framework
|
||||
log_and_exec_cmd "install_name_tool -add_rpath @rpath/LLDB.framework/Versions/A/LLDB ./debugAdapters/lldb-mi/bin/lldb-mi"
|
||||
|
||||
# Set rpath for App Store XCode LLDB.Framework
|
||||
log_and_exec_cmd "install_name_tool -add_rpath /Applications/Xcode.app/Contents/SharedFrameworks/ ./debugAdapters/lldb-mi/bin/lldb-mi"
|
||||
|
||||
# Set rpath for XCode CLI LLDB.Framework
|
||||
log_and_exec_cmd "install_name_tool -add_rpath /Library/Developer/CommandLineTools/Library/PrivateFrameworks/ ./debugAdapters/lldb-mi/bin/lldb-mi"
|
||||
|
||||
# Set rpath next to the lldb-mi executable LLDB.Framework
|
||||
log_and_exec_cmd "install_name_tool -add_rpath @executable_path/. ./debugAdapters/lldb-mi/bin/lldb-mi"
|
||||
|
||||
# Grab NOTICE.TXT
|
||||
cp $(Build.SourcesDirectory)/Build/lldb-mi/NOTICE.TXT ./debugAdapters/lldb-mi/.
|
||||
|
||||
# Build can be found at https://dev.azure.com/ms/vscode-cpptools/_build?definitionId=313
|
||||
# Click on the build and select 'Artifacts'
|
||||
- task: PublishPipelineArtifact@1
|
||||
displayName: 'Publish LLDB-MI'
|
||||
inputs:
|
||||
targetPath: '$(Build.StagingDirectory)/publish'
|
||||
artifactName: 'lldb-mi'
|
||||
|
||||
@@ -2,14 +2,11 @@
|
||||
# Pipeline for VsCodeExtension-Localization build definition
|
||||
# Runs OneLocBuild task to localize xlf file
|
||||
# ==================================================================================
|
||||
|
||||
resources:
|
||||
repositories:
|
||||
- repository: self
|
||||
clean: true
|
||||
- repository: MicroBuildTemplate
|
||||
type: git
|
||||
name: 1ESPipelineTemplates/MicroBuildTemplate
|
||||
ref: refs/tags/release
|
||||
|
||||
trigger: none
|
||||
pr: none
|
||||
@@ -21,72 +18,38 @@ schedules:
|
||||
- main
|
||||
always: true
|
||||
|
||||
variables:
|
||||
TeamName: cpptools
|
||||
Codeql.Language: javascript
|
||||
pool:
|
||||
vmImage: 'windows-latest'
|
||||
|
||||
extends:
|
||||
template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate
|
||||
parameters:
|
||||
pool:
|
||||
name: AzurePipelines-EO
|
||||
image: 1ESPT-Windows2025
|
||||
os: windows
|
||||
sdl:
|
||||
sourceAnalysisPool:
|
||||
name: AzurePipelines-EO
|
||||
image: 1ESPT-Windows2025
|
||||
os: windows
|
||||
stages:
|
||||
- stage: stage
|
||||
jobs:
|
||||
- job: job
|
||||
templateContext:
|
||||
outputs:
|
||||
- output: pipelineArtifact
|
||||
targetPath: '$(Build.ArtifactStagingDirectory)'
|
||||
artifactName: 'drop'
|
||||
publishLocation: 'Container'
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: '22.x'
|
||||
displayName: 'Install Node.js'
|
||||
steps:
|
||||
- task: CmdLine@2
|
||||
inputs:
|
||||
script: 'cd Extension && yarn install'
|
||||
|
||||
- task: CmdLine@2
|
||||
inputs:
|
||||
script: 'cd Extension && yarn install'
|
||||
- task: CmdLine@2
|
||||
inputs:
|
||||
script: 'cd ./Extension && yarn run translations-export && cd ..'
|
||||
|
||||
- task: CmdLine@2
|
||||
inputs:
|
||||
script: 'cd ./Extension && yarn run translations-export && cd ..'
|
||||
- task: OneLocBuild@2
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
inputs:
|
||||
locProj: 'Build/loc/LocProject.json'
|
||||
outDir: '$(Build.ArtifactStagingDirectory)'
|
||||
isCreatePrSelected: false
|
||||
prSourceBranchPrefix: 'locfiles'
|
||||
packageSourceAuth: 'patAuth'
|
||||
patVariable: '$(OneLocBuildPat)'
|
||||
LclSource: lclFilesfromPackage
|
||||
LclPackageId: 'LCL-JUNO-PROD-VCPP'
|
||||
lsBuildXLocPackageVersion: '7.0.30510'
|
||||
|
||||
# Requires Azure client 2.x
|
||||
- task: AzureCLI@2
|
||||
displayName: 'Set OneLocBuildToken'
|
||||
enabled: true
|
||||
inputs:
|
||||
azureSubscription: '$(AzureSubscription)' # Azure DevOps service connection
|
||||
scriptType: 'pscore'
|
||||
scriptLocation: 'inlineScript'
|
||||
inlineScript: |
|
||||
$token = az account get-access-token --query accessToken --resource $(AzureGuid) -o tsv
|
||||
Write-Host "##vso[task.setvariable variable=AzDO.OneLocBuildToken;issecret=true]${token}"
|
||||
- task: CmdLine@2
|
||||
inputs:
|
||||
script: 'cd Extension && node ./translations_auto_pr.js microsoft vscode-cpptools csigs $(csigsPat) csigs [email protected] "$(Build.ArtifactStagingDirectory)/loc" vscode-extensions-localization-export/vscode-extensions && cd ..'
|
||||
|
||||
- task: OneLocBuild@2
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
inputs:
|
||||
locProj: 'Build/loc/LocProject.json'
|
||||
outDir: '$(Build.ArtifactStagingDirectory)'
|
||||
isCreatePrSelected: false
|
||||
prSourceBranchPrefix: 'locfiles'
|
||||
packageSourceAuth: 'patAuth'
|
||||
patVariable: '$(AzDO.OneLocBuildToken)'
|
||||
LclSource: lclFilesfromPackage
|
||||
LclPackageId: 'LCL-JUNO-PROD-VCPP'
|
||||
lsBuildXLocPackageVersion: '7.0.30510'
|
||||
|
||||
- task: CmdLine@2
|
||||
inputs:
|
||||
script: 'cd Extension && node ./translations_auto_pr.js microsoft vscode-cpptools csigs $(csigsPat) csigs [email protected] "$(Build.ArtifactStagingDirectory)/loc" vscode-extensions-localization-export/vscode-extensions && cd ..'
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
|
||||
ArtifactName: 'drop'
|
||||
publishLocation: 'Container'
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
name: $(date:yyyyMMdd)$(rev:.r)
|
||||
trigger: none
|
||||
pr: none
|
||||
|
||||
parameters:
|
||||
- name: verifyVersion
|
||||
displayName: Attest version in package.json is correct
|
||||
type: boolean
|
||||
default: false
|
||||
- name: verifyReadme
|
||||
displayName: Attest README.md is updated
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
resources:
|
||||
repositories:
|
||||
- repository: MicroBuildTemplate
|
||||
type: git
|
||||
name: 1ESPipelineTemplates/MicroBuildTemplate
|
||||
ref: refs/tags/release
|
||||
|
||||
extends:
|
||||
template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate
|
||||
parameters:
|
||||
pool:
|
||||
name: AzurePipelines-EO
|
||||
image: 1ESPT-Windows2025
|
||||
os: windows
|
||||
sdl:
|
||||
sourceAnalysisPool:
|
||||
name: AzurePipelines-EO
|
||||
image: 1ESPT-Windows2025
|
||||
os: windows
|
||||
settings:
|
||||
networkIsolationPolicy: Permissive,CFSClean,CFSClean2,CFSClean3
|
||||
|
||||
stages:
|
||||
- stage: package
|
||||
jobs:
|
||||
# Introduce pipeline compilation errors to block scheduling if the requisite parameters are not set
|
||||
- ${{ if not(eq(parameters.verifyVersion, true)) }}:
|
||||
- 'The version in package.json should be updated before scheduling the pipeline.'
|
||||
|
||||
- ${{ if not(eq(parameters.verifyReadme, true)) }}:
|
||||
- 'README.md should be updated before scheduling the pipeline.'
|
||||
|
||||
- template: /Build/package/jobs_package_vsix.yml@self
|
||||
parameters:
|
||||
vsixName: cpptools-extension-pack
|
||||
srcDir: ExtensionPack
|
||||
@@ -1,50 +0,0 @@
|
||||
name: $(date:yyyyMMdd)$(rev:.r)
|
||||
trigger: none
|
||||
pr: none
|
||||
|
||||
parameters:
|
||||
- name: verifyVersion
|
||||
displayName: Attest version in package.json is correct
|
||||
type: boolean
|
||||
default: false
|
||||
- name: verifyReadme
|
||||
displayName: Attest README.md is updated
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
resources:
|
||||
repositories:
|
||||
- repository: MicroBuildTemplate
|
||||
type: git
|
||||
name: 1ESPipelineTemplates/MicroBuildTemplate
|
||||
ref: refs/tags/release
|
||||
|
||||
extends:
|
||||
template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate
|
||||
parameters:
|
||||
pool:
|
||||
name: AzurePipelines-EO
|
||||
image: 1ESPT-Windows2025
|
||||
os: windows
|
||||
sdl:
|
||||
sourceAnalysisPool:
|
||||
name: AzurePipelines-EO
|
||||
image: 1ESPT-Windows2025
|
||||
os: windows
|
||||
settings:
|
||||
networkIsolationPolicy: Permissive,CFSClean,CFSClean2,CFSClean3
|
||||
|
||||
stages:
|
||||
- stage: package
|
||||
jobs:
|
||||
# Introduce pipeline compilation errors to block scheduling if the requisite parameters are not set
|
||||
- ${{ if not(eq(parameters.verifyVersion, true)) }}:
|
||||
- 'The version in package.json should be updated before scheduling the pipeline.'
|
||||
|
||||
- ${{ if not(eq(parameters.verifyReadme, true)) }}:
|
||||
- 'README.md should be updated before scheduling the pipeline.'
|
||||
|
||||
- template: /Build/package/jobs_package_vsix.yml@self
|
||||
parameters:
|
||||
vsixName: cpptools-themes
|
||||
srcDir: Themes
|
||||
@@ -1,95 +0,0 @@
|
||||
parameters:
|
||||
- name: vsixName
|
||||
type: string
|
||||
default: ''
|
||||
- name: srcDir
|
||||
type: string
|
||||
default: ''
|
||||
- name: signType
|
||||
type: string
|
||||
default: 'real'
|
||||
|
||||
jobs:
|
||||
- job: package
|
||||
displayName: Build ${{ parameters.vsixName }}.vsix
|
||||
timeoutInMinutes: 30
|
||||
cancelTimeoutInMinutes: 1
|
||||
templateContext:
|
||||
mb: # Enable the MicroBuild Signing toolset
|
||||
signing:
|
||||
enabled: true
|
||||
signType: ${{ parameters.signType }}
|
||||
zipSources: false
|
||||
${{ if eq(parameters.signType, 'real') }}:
|
||||
signWithProd: true
|
||||
featureFlags:
|
||||
autoBaseline: false
|
||||
outputs:
|
||||
- output: pipelineArtifact
|
||||
displayName: '${{ parameters.vsixName }}.vsix'
|
||||
targetPath: $(Build.ArtifactStagingDirectory)\vsix
|
||||
artifactName: vsix
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
|
||||
- task: UseNode@1
|
||||
displayName: Use Node 22.x
|
||||
inputs:
|
||||
version: 22.x
|
||||
|
||||
- script: IF EXIST %SYSTEMDRIVE%\Users\%USERNAME%\.npmrc del %SYSTEMDRIVE%\Users\%USERNAME%\.npmrc
|
||||
displayName: Delete .npmrc if it exists
|
||||
|
||||
- task: Bash@3
|
||||
displayName: Build files
|
||||
inputs:
|
||||
targetType: 'inline'
|
||||
script: |
|
||||
export SRC_DIR=$(echo $BUILD_SOURCESDIRECTORY | sed 's|\\|/|g')
|
||||
cd "$SRC_DIR/${{ parameters.srcDir }}"
|
||||
npm install
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "npm install failed, sleeping for 30s before retrying..."
|
||||
sleep 30
|
||||
exit 1
|
||||
fi
|
||||
retryCountOnTaskFailure: 3
|
||||
|
||||
- script: mkdir $(Build.ArtifactStagingDirectory)\vsix
|
||||
displayName: Create Staging Directory
|
||||
|
||||
- script: npm install --no-save --ignore-scripts=false --include=optional --force @vscode/[email protected]
|
||||
displayName: Install vsce
|
||||
workingDirectory: $(Build.SourcesDirectory)\${{ parameters.srcDir }}
|
||||
|
||||
- script: npm rebuild @vscode/vsce-sign --ignore-scripts=false
|
||||
displayName: Rebuild vsce-sign binary
|
||||
workingDirectory: $(Build.SourcesDirectory)\${{ parameters.srcDir }}
|
||||
|
||||
- script: if not exist node_modules\@vscode\vsce-sign\bin\vsce-sign.exe (echo Missing vsce-sign.exe && exit 1)
|
||||
displayName: Verify vsce-sign binary exists
|
||||
workingDirectory: $(Build.SourcesDirectory)\${{ parameters.srcDir }}
|
||||
|
||||
- script: npx vsce package -o $(Build.ArtifactStagingDirectory)\vsix\${{ parameters.vsixName }}.vsix
|
||||
displayName: Run VSCE to package vsix
|
||||
workingDirectory: $(Build.SourcesDirectory)\${{ parameters.srcDir }}
|
||||
|
||||
# sign the vsix
|
||||
- script: npx vsce generate-manifest -i $(Build.ArtifactStagingDirectory)\vsix\${{ parameters.vsixName }}.vsix -o $(Build.ArtifactStagingDirectory)\vsix\${{ parameters.vsixName }}.manifest
|
||||
displayName: generate manifest
|
||||
workingDirectory: $(Build.SourcesDirectory)\${{ parameters.srcDir }}
|
||||
- script: copy $(Build.ArtifactStagingDirectory)\vsix\${{ parameters.vsixName }}.manifest $(Build.ArtifactStagingDirectory)\vsix\${{ parameters.vsixName }}.signature.p7s
|
||||
displayName: prepare manifest for signing
|
||||
workingDirectory: $(Build.SourcesDirectory)\${{ parameters.srcDir }}
|
||||
- task: NuGetToolInstaller@1
|
||||
displayName: Install NuGet
|
||||
- task: NuGetAuthenticate@1
|
||||
displayName: Authenticate NuGet
|
||||
- script: nuget restore $(Build.SourcesDirectory)\Build\signing\SignVsix.proj -PackagesDirectory $(Build.SourcesDirectory)\Build\signing\packages -ConfigFile $(Build.SourcesDirectory)\Build\signing\NuGet.config
|
||||
displayName: Restore MicroBuild Core
|
||||
- task: MSBuild@1
|
||||
displayName: Sign the vsix
|
||||
inputs:
|
||||
solution: $(Build.SourcesDirectory)\Build\signing\SignVsix.proj
|
||||
msbuildArguments: /p:SignType=${{ parameters.signType }}
|
||||
@@ -1,43 +0,0 @@
|
||||
name: $(Date:yyyyMMdd)$(rev:.r)
|
||||
trigger: none
|
||||
pr: none
|
||||
|
||||
resources:
|
||||
repositories:
|
||||
- repository: MicroBuildTemplate
|
||||
type: git
|
||||
name: 1ESPipelineTemplates/MicroBuildTemplate
|
||||
ref: refs/tags/release
|
||||
pipelines:
|
||||
- pipeline: vsixBuild
|
||||
source: '\VC\VSCode\CpptoolsVSIX\Package cpptools-extension-pack'
|
||||
trigger: true
|
||||
|
||||
extends:
|
||||
template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate
|
||||
parameters:
|
||||
pool:
|
||||
name: AzurePipelines-EO
|
||||
image: 1ESPT-Windows2025
|
||||
os: windows
|
||||
sdl:
|
||||
sourceAnalysisPool:
|
||||
name: AzurePipelines-EO
|
||||
image: 1ESPT-Windows2025
|
||||
os: windows
|
||||
|
||||
stages:
|
||||
- stage: Validate
|
||||
jobs:
|
||||
- template: /Build/publish/jobs_manual_validation.yml@self
|
||||
parameters:
|
||||
notifyUsers: $(NotifyUsers)
|
||||
releaseBuildUrl: $(ReleaseBuildUrl)
|
||||
|
||||
- stage: Release
|
||||
dependsOn: Validate
|
||||
jobs:
|
||||
- template: /Build/publish/jobs_publish_vsix.yml@self
|
||||
parameters:
|
||||
vsixName: cpptools-extension-pack
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
name: $(Date:yyyyMMdd)$(rev:.r)
|
||||
trigger: none
|
||||
pr: none
|
||||
|
||||
resources:
|
||||
repositories:
|
||||
- repository: MicroBuildTemplate
|
||||
type: git
|
||||
name: 1ESPipelineTemplates/MicroBuildTemplate
|
||||
ref: refs/tags/release
|
||||
pipelines:
|
||||
- pipeline: vsixBuild
|
||||
source: '\VC\VSCode\CpptoolsVSIX\Package cpptools-themes'
|
||||
trigger: true
|
||||
|
||||
extends:
|
||||
template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate
|
||||
parameters:
|
||||
pool:
|
||||
name: AzurePipelines-EO
|
||||
image: 1ESPT-Windows2025
|
||||
os: windows
|
||||
sdl:
|
||||
sourceAnalysisPool:
|
||||
name: AzurePipelines-EO
|
||||
image: 1ESPT-Windows2025
|
||||
os: windows
|
||||
|
||||
stages:
|
||||
- stage: Validate
|
||||
jobs:
|
||||
- template: /Build/publish/jobs_manual_validation.yml@self
|
||||
parameters:
|
||||
notifyUsers: $(NotifyUsers)
|
||||
releaseBuildUrl: $(ReleaseBuildUrl)
|
||||
|
||||
- stage: Release
|
||||
dependsOn: Validate
|
||||
jobs:
|
||||
- template: /Build/publish/jobs_publish_vsix.yml@self
|
||||
parameters:
|
||||
vsixName: cpptools-themes
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
parameters:
|
||||
- name: notifyUsers
|
||||
type: string
|
||||
default: ''
|
||||
- name: releaseBuildUrl
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
jobs:
|
||||
- job: WaitForValidation
|
||||
displayName: Wait for VSIX validation
|
||||
pool: server
|
||||
steps:
|
||||
- task: ManualValidation@0
|
||||
displayName: "Manual Validation"
|
||||
inputs:
|
||||
notifyUsers: $(notifyUsers)
|
||||
instructions: |
|
||||
Download and test the vsix from the latest release build: $(releaseBuildUrl)
|
||||
@@ -1,46 +0,0 @@
|
||||
parameters:
|
||||
- name: vsixName
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
jobs:
|
||||
- job: Publish
|
||||
displayName: Publish to Marketplace
|
||||
templateContext:
|
||||
type: releaseJob
|
||||
isProduction: true
|
||||
inputs:
|
||||
- input: pipelineArtifact
|
||||
pipeline: vsixBuild
|
||||
artifactName: vsix
|
||||
targetPath: $(Build.StagingDirectory)\vsix
|
||||
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
displayName: Use Node 22.x
|
||||
inputs:
|
||||
versionSpec: 22.x
|
||||
|
||||
- task: AzureCLI@2
|
||||
displayName: Generate AAD_TOKEN
|
||||
inputs:
|
||||
azureSubscription: $(AzureSubscription)
|
||||
scriptType: ps
|
||||
scriptLocation: inlineScript
|
||||
inlineScript: |
|
||||
$aadToken = az account get-access-token --query accessToken --resource $(AzureGuid) -o tsv
|
||||
Write-Host "##vso[task.setvariable variable=AAD_TOKEN;issecret=true]$aadToken"
|
||||
|
||||
- script: npm install --no-save --ignore-scripts=false --include=optional --force @vscode/[email protected]
|
||||
displayName: Install vsce
|
||||
|
||||
- script: npm rebuild @vscode/vsce-sign --ignore-scripts=false
|
||||
displayName: Rebuild vsce-sign binary
|
||||
|
||||
- script: if not exist node_modules\@vscode\vsce-sign\bin\vsce-sign.exe (echo Missing vsce-sign.exe && exit 1)
|
||||
displayName: Verify vsce-sign binary exists
|
||||
|
||||
- script: npx vsce publish --skip-duplicate -i $(Build.StagingDirectory)\vsix\${{ parameters.vsixName }}.vsix --manifestPath $(Build.StagingDirectory)\vsix\${{ parameters.vsixName }}.manifest --signaturePath $(Build.StagingDirectory)\vsix\${{ parameters.vsixName }}.signature.p7s
|
||||
displayName: Publish to Marketplace
|
||||
env:
|
||||
VSCE_PAT: $(AAD_TOKEN)
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="Engineering" value="https://pkgs.dev.azure.com/devdiv/_packaging/MicroBuildToolset/nuget/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="SignFiles" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="packages\Microsoft.VisualStudioEng.MicroBuild.Core.0.4.1\build\Microsoft.VisualStudioEng.MicroBuild.Core.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<BaseOutputDirectory>$(BUILD_STAGINGDIRECTORY)/Extension</BaseOutputDirectory>
|
||||
<!-- These properties are required by MicroBuild, which only signs files that are under these paths -->
|
||||
<IntermediateOutputPath>$(BaseOutputDirectory)</IntermediateOutputPath>
|
||||
<OutDir>$(BaseOutputDirectory)</OutDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Because of Webpack bundling, these are the only shipping Javascript files.
|
||||
There are no third-party files to sign because they've all been bundled. -->
|
||||
<FilesToSign Include="$(OutDir)\dist\src\main.js;$(OutDir)\dist\ui\settings.js">
|
||||
<Authenticode>Microsoft400</Authenticode>
|
||||
</FilesToSign>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="packages\Microsoft.VisualStudioEng.MicroBuild.Core.0.4.1\build\Microsoft.VisualStudioEng.MicroBuild.Core.targets" />
|
||||
</Project>
|
||||
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="SignFiles" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="packages\Microsoft.VisualStudioEng.MicroBuild.Core.0.4.1\build\Microsoft.VisualStudioEng.MicroBuild.Core.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<BaseOutputDirectory>$(BUILD_STAGINGDIRECTORY)</BaseOutputDirectory>
|
||||
<!-- These properties are required by MicroBuild, which only signs files that are under these paths -->
|
||||
<IntermediateOutputPath>$(BaseOutputDirectory)</IntermediateOutputPath>
|
||||
<OutDir>$(BaseOutputDirectory)</OutDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FilesToSign Include="$(OutDir)\vsix\cpptools-*.signature.p7s">
|
||||
<Authenticode>VSCodePublisher</Authenticode>
|
||||
</FilesToSign>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="packages\Microsoft.VisualStudioEng.MicroBuild.Core.0.4.1\build\Microsoft.VisualStudioEng.MicroBuild.Core.targets" />
|
||||
</Project>
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.VisualStudioEng.MicroBuild.Core" version="0.4.1" developmentDependency="true" />
|
||||
</packages>
|
||||
@@ -1,8 +0,0 @@
|
||||
# Each line is a file pattern followed by one or more owners.
|
||||
|
||||
# These owners will be the default owners for everything in
|
||||
# the repo. Unless a later match takes precedence,
|
||||
# @microsoft/cpptools-maintainers will be requested for
|
||||
# review when someone opens a pull request.
|
||||
|
||||
* @microsoft/cpptools-maintainers
|
||||
+1
-2
@@ -6,5 +6,4 @@ Resources:
|
||||
|
||||
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
|
||||
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
|
||||
- Contact [[email protected]](mailto:[email protected]) with questions or concerns
|
||||
- Employees can reach out at [aka.ms/opensource/moderation-support](https://aka.ms/opensource/moderation-support)
|
||||
- Contact [[email protected]](mailto:[email protected]) with questions or concerns
|
||||
+1
-22
@@ -5,7 +5,7 @@
|
||||
* [Build and debug the extension](Documentation/Building%20the%20Extension.md).
|
||||
* File an [issue](https://github.com/Microsoft/vscode-cpptools/issues) and a [pull request](https://github.com/Microsoft/vscode-cpptools/pulls) with the change and we will review it.
|
||||
* If the change affects functionality, add a line describing the change to [**CHANGELOG.md**](Extension/CHANGELOG.md).
|
||||
* Try and add a test in [**test/extension.test.ts**](Extension/test/scenarios/SingleRootProject/tests/extension.test.ts).
|
||||
* Try and add a test in [**test/extension.test.ts**](Extension/test/unitTests/extension.test.ts).
|
||||
* Run tests via opening the [**Extension**](https://github.com/Microsoft/vscode-cpptools/tree/main/Extension) folder in Visual Studio Code, selecting the "Launch Tests" configuration in the Debug pane, and choosing "Start Debugging".
|
||||
|
||||
## About the Code
|
||||
@@ -33,24 +33,3 @@ const localize: nls.LocalizeFunc = nls.loadMessageBundle();
|
||||
const readmeMessage: string = localize("refer.read.me", "Please refer to {0} for troubleshooting information. Issues can be created at {1}", readmePath, "https://github.com/Microsoft/vscode-cpptools/issues");
|
||||
```
|
||||
* The first parameter to localize should be a unique key for that string, not used by any other call to localize() in the file unless representing the same string. The second parameter is the string to localize. Both of these parameters must be string literals. Tokens such as {0} and {1} are supported in the localizable string, with replacement values passed as additional parameters to localize().
|
||||
|
||||
## Contributor License Agreement
|
||||
|
||||
This project welcomes contributions and suggestions. Most contributions require you to
|
||||
agree to a Contributor License Agreement (CLA) declaring that you have the right to,
|
||||
and actually do, grant us the rights to use your contribution. For details, visit
|
||||
https://cla.microsoft.com.
|
||||
|
||||
When you submit a pull request, a CLA-bot will automatically determine whether you need
|
||||
to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the
|
||||
instructions provided by the bot. You will only need to do this once across all repositories using our CLA.
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
|
||||
or contact [[email protected]](mailto:[email protected]) with any additional questions or comments.
|
||||
|
||||
### Adding/Updating package.json dependencies
|
||||
|
||||
We maintain a public Azure Artifacts feed that we point the package manager to in .npmrc files. If you want to add a dependency or update a version in package.json, you may need to contact us so we can add it to our feed. Please ping our team in a PR or new issue if you experience this issue.
|
||||
|
||||
For local development, you can delete the .npmrc file and the matching `yarn.lock` file while you wait for us to update the feed. However, these changes will need to be reverted in your branch before we will accept a PR.
|
||||
@@ -21,4 +21,4 @@ This option will generate a tasks.json file for you, build your active source fi
|
||||
|
||||
### F5
|
||||
Another way to begin building and debugging your active file is to execute the command by pressing <kbd>F5</kbd>. This method will configure
|
||||
both a tasks.json and launch.json file for you, build your active source file, and then launch the debugger.
|
||||
both a tasks.json and launch.json file for you, build your active source file, and then launch the debugger.
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Fib
|
||||
|
||||
This code sample is to show debugging. Update `launch.json` and `tasks.json` in the `.vscode` folder to use your setup to build and debug.
|
||||
This code sample is to show debugging. Update `launch.json` and `tasks.json` in the `.vscode` folder to use your setup to build and debug.
|
||||
@@ -15,14 +15,14 @@ static int fib(int n){
|
||||
switch (n) {
|
||||
case 0: return 1;
|
||||
case 1: return 1;
|
||||
default: return (fib(n-2) + fib(n-1));
|
||||
}
|
||||
default: return (fib(n-2) + fib(n-1));
|
||||
}
|
||||
}
|
||||
|
||||
void * thread_proc(void* ctx)
|
||||
{
|
||||
int tid = g_tid++;
|
||||
|
||||
|
||||
char thread_name[16];
|
||||
sprintf(thread_name, "Thread %d", tid);
|
||||
#ifdef __APPLE__
|
||||
@@ -30,19 +30,19 @@ void * thread_proc(void* ctx)
|
||||
#else
|
||||
pthread_setname_np(pthread_self(), thread_name);
|
||||
#endif
|
||||
|
||||
|
||||
// Random delay, 0 - 0.5 sec
|
||||
timespec ts;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 500000000 + ((float)rand() / (float)RAND_MAX) * 500000000;
|
||||
nanosleep(&ts, NULL);
|
||||
|
||||
|
||||
volatile int i = 0;
|
||||
while (i <= 30) {
|
||||
std::cout << "Thread " << tid << ": fib(" << i << ") = " << fib(i) << std::endl;
|
||||
i++;
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
|
||||
std::cout << thread_name << " exited!" << std::endl;
|
||||
}
|
||||
@@ -10,14 +10,6 @@ Prerequisite steps:
|
||||
* From a command line, run the following commands from the **Extension** folder in the root of the repository:
|
||||
* `yarn install` will install the dependencies needed to build the extension.
|
||||
* **(optional)** `yarn global add vsce` will install `vsce` globally to create a VSIX package that you can install.
|
||||
* **(optional)** Set an environment variable `CPPTOOLS_DEV=1`.
|
||||
* This enables the local developer workflow when testing the debugger, copying dependencies from the **node_modules** folder. Testing the language server does not require this step.
|
||||
* Open the **Extension** folder in Visual Studio Code and press F5. This will launch a VS Code Extension Host window and activate the TypeScript debugger. You can set breakpoints on the extension source code and debug your scenario.
|
||||
* If, after pressing F5, you see the following error in the `[Extension Development Host]` window,
|
||||
> Unable to start the C/C++ language server. IntelliSense features will be disabled. Error: Missing binary at .../vscode-cpptools/Extension/bin/cpptools
|
||||
* Then, you can follow the instructions in this [comment in a discussion about building this extension locally](https://github.com/microsoft/vscode-cpptools/discussions/8745#discussioncomment-2091563).
|
||||
> get the <package.version.number> binaries from installing the extension and then copying the binaries
|
||||
1. To do this, install this extension from the Visual Studio Marketplace and find its location on your device. It might be in a directory like `\\wsl$\Ubuntu\home\hamir\.vscode-server\extensions\ms-vscode.cpptools-<package.version.number>`, for example.
|
||||
2. Next, go to the `bin/` directory of the aforementioned directory, and drag-and-drop, or copy-and-paste, `cpptools` and `cpptools-srv` from `...\extensions\ms-vscode.cpptools-<package.version.number>\bin\` to this repository's `Extension\bin\` directory on your local device, so that `.../vscode-cpptools/Extension/bin/cpptools` and `.../vscode-cpptools/Extension/bin/cpptools-srv` both exist in your workspace.
|
||||
3. The aforementioned warning should be gone, and Intellisense, which gives those squiggly red error lines, should now be present.
|
||||
4. The `insiders` branch has binaries compatible with the latest Pre-Release version of the extension, and the `release` branch has binaries compatible with the latest Release version, but the `main` branch may have TypeScript changes that are incompatible with the published binaries, in which case, you'll need to create a branch off the `insiders` or `release` branches.
|
||||
|
||||
* Feel free to use [the Discussions tab of this repository](https://github.com/microsoft/vscode-cpptools/discussions) if you have any further questions on building this extension locally.
|
||||
|
||||
@@ -240,7 +240,7 @@
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
|
||||
<!-- Attributes for elements that support filtering by view-->
|
||||
<xs:attributeGroup name="ViewConstraints">
|
||||
<xs:attribute name="IncludeView" type ="ViewIncludeType" use="optional" />
|
||||
@@ -335,9 +335,9 @@
|
||||
are evaluated in the context of the node.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
|
||||
|
||||
<xs:complexType name="ListItemsNodeType">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Expression that points to value of the linked list node. It can be left empty or have 'this' to refer to the linked list node itself. This expression is evaluated under the context of the linked list node and not the parent linked list type.</xs:documentation>
|
||||
@@ -402,7 +402,7 @@
|
||||
<xs:documentation>
|
||||
Indicates that the item should use the icon associated with general data.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="Method">
|
||||
<xs:annotation>
|
||||
@@ -864,16 +864,16 @@
|
||||
<xs:complexType name="MostDerivedObjectType">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
Specifies an expression which evaluates to the current object, casted to its most-derived type.
|
||||
|
||||
In most cases, the debugger is able to automatically determine an object's most-derived type, in which case use of the <MostDerivedType>
|
||||
Specifies an expression which evaluates to the current object, casted to its most-derived type.
|
||||
|
||||
In most cases, the debugger is able to automatically determine an object's most-derived type, in which case use of the <MostDerivedType>
|
||||
element is unecessary. Automatic determination of an object's most-derived type requires the object to be an instance of a C++ class, with a
|
||||
compiler-generated virtual function table. This is sufficient for most class-hierarchies; however, custom logic may occasionally be necessary
|
||||
when dealing with a class hierarchy that does not contain virtual functions, or when the virtual function table is manually constructed by the
|
||||
when dealing with a class hierarchy that does not contain virtual functions, or when the virtual function table is manually constructed by the
|
||||
application code.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
|
||||
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="StringType">
|
||||
<xs:attributeGroup ref="CommonAttributes" />
|
||||
@@ -935,12 +935,12 @@
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
Indicates that the given type is a smart pointer. The text inside this element specifies the expression to evaluate the underlying pointer.
|
||||
|
||||
|
||||
The <SmartPointer> element has the following effects:
|
||||
- If no alternative <DisplayString> element is provided (or all <DisplayString> elements have failed conditions), the underlying pointer will be the display string
|
||||
- If no alternative <StringView> element is provided (or all <StringView> elements have failed conditions), the underlying pointer will be the string view, if it has one.
|
||||
- If no alternative <Expand> element is provided, the expansion of the smart pointer will be the expansion of the underlying pointer.
|
||||
- The smart pointer class will also support overloaded operators as determined by the <Usage> attribute. You can opt out of this behavior by specifying
|
||||
- The smart pointer class will also support overloaded operators as determined by the <Usage> attribute. You can opt out of this behavior by specifying
|
||||
'DefaultExpansion="false"'
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
@@ -949,7 +949,7 @@
|
||||
<xs:attributeGroup ref="CommonAttributes_NoCondition" />
|
||||
<xs:attribute name="Usage" type="SmartPointerUsage" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Indicates which combinations of operators this smart pointer object supports.
|
||||
<xs:documentation>Indicates which combinations of operators this smart pointer object supports.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
@@ -1004,10 +1004,10 @@
|
||||
<xs:documentation>Specifies an optional priority to assign to this entry for type matching. Higher priority entries within a particular file or directory
|
||||
are checked first. <Type> entries that do not specify a priority receive default priority of "Medium" <AlternativeType> entries which do not specify a priority
|
||||
will inherit the priority of the enclosing <Type> element. The priority is only used to disambiguate type matching when all other means of disambiguation are unavailable.
|
||||
For example, entries with more specific template instantiations, module constraints, or view constraints will take priority regardless of any priority values specified.
|
||||
Similarly, regardless of priority, natvis files that are part of a loaded project will always take precedence over files in the user natvis directory,
|
||||
which will, in turn, take precedence over files in the system-wide natvis directory.
|
||||
|
||||
For example, entries with more specific template instantiations, module constraints, or view constraints will take priority regardless of any priority values specified.
|
||||
Similarly, regardless of priority, natvis files that are part of a loaded project will always take precedence over files in the user natvis directory,
|
||||
which will, in turn, take precedence over files in the system-wide natvis directory.
|
||||
|
||||
If two entries have the same priority and cannot otherwise be disambiguated, it is unspecified which one will get used.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
|
||||
@@ -1 +1 @@
|
||||
The documentation for c_cpp_properties.json has moved to https://code.visualstudio.com/docs/cpp/customize-cpp-settings.
|
||||
The documentation for c_cpp_properties.json has moved to https://code.visualstudio.com/docs/cpp/c-cpp-properties-schema-reference.
|
||||
@@ -0,0 +1,4 @@
|
||||
*.js
|
||||
test/**/index.ts
|
||||
test/**/runTest.ts
|
||||
tools/prepublish.js
|
||||
@@ -0,0 +1,154 @@
|
||||
module.exports = {
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "tsconfig.json",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint",
|
||||
"@typescript-eslint/tslint",
|
||||
"eslint-plugin-jsdoc",
|
||||
"@typescript-eslint/eslint-plugin-tslint",
|
||||
"eslint-plugin-import",
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/adjacent-overload-signatures": "error",
|
||||
"@typescript-eslint/array-type": "error",
|
||||
"camelcase": "off",
|
||||
"@typescript-eslint/naming-convention": [
|
||||
"error",
|
||||
{
|
||||
"selector": "typeLike",
|
||||
"format": ["PascalCase"]
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/indent": "error",
|
||||
"@typescript-eslint/member-delimiter-style": [
|
||||
"error",
|
||||
{
|
||||
"multiline": {
|
||||
"delimiter": "semi",
|
||||
"requireLast": true
|
||||
},
|
||||
"singleline": {
|
||||
"delimiter": "semi",
|
||||
"requireLast": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-misused-new": "error",
|
||||
"@typescript-eslint/no-namespace": "error",
|
||||
"@typescript-eslint/no-non-null-assertion": "error",
|
||||
"@typescript-eslint/no-extra-non-null-assertion": "error",
|
||||
"@typescript-eslint/no-this-alias": "error",
|
||||
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
||||
"@typescript-eslint/no-unnecessary-type-arguments": "error",
|
||||
"@typescript-eslint/no-var-requires": "error",
|
||||
"@typescript-eslint/prefer-function-type": "error",
|
||||
"@typescript-eslint/prefer-namespace-keyword": "error",
|
||||
"@typescript-eslint/semi": "error",
|
||||
"@typescript-eslint/triple-slash-reference": "error",
|
||||
"@typescript-eslint/type-annotation-spacing": "error",
|
||||
"@typescript-eslint/unified-signatures": "error",
|
||||
"arrow-body-style": "error",
|
||||
"comma-dangle": "error",
|
||||
"constructor-super": "error",
|
||||
"curly": "error",
|
||||
"eol-last": "error",
|
||||
"eqeqeq": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"import/no-default-export": "error",
|
||||
"import/no-unassigned-import": "error",
|
||||
"jsdoc/no-types": "error",
|
||||
"new-parens": "error",
|
||||
"no-bitwise": "error",
|
||||
"no-caller": "error",
|
||||
"no-cond-assign": "error",
|
||||
"no-debugger": "error",
|
||||
"no-duplicate-case": "error",
|
||||
"no-duplicate-imports": "error",
|
||||
"no-eval": "error",
|
||||
"no-fallthrough": "error",
|
||||
"no-invalid-this": "error",
|
||||
"no-irregular-whitespace": "error",
|
||||
"no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 1, "maxBOF": 0 }],
|
||||
"no-new-wrappers": "error",
|
||||
"no-redeclare": "error",
|
||||
"no-return-await": "error",
|
||||
"no-sequences": "error",
|
||||
"no-sparse-arrays": "error",
|
||||
"no-trailing-spaces": "error",
|
||||
"no-undef-init": "error",
|
||||
"no-unsafe-finally": "error",
|
||||
"no-unused-expressions": "error",
|
||||
"no-unused-labels": "error",
|
||||
"no-var": "error",
|
||||
"one-var": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"prefer-const": "error",
|
||||
"prefer-object-spread": "error",
|
||||
"space-in-parens": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"spaced-comment": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"use-isnan": "error",
|
||||
"valid-typeof": "error",
|
||||
"yoda": "error",
|
||||
"@typescript-eslint/tslint/config": [
|
||||
"error",
|
||||
{
|
||||
"rules": {
|
||||
"encoding": true,
|
||||
"file-header": [
|
||||
true,
|
||||
".*"
|
||||
],
|
||||
"import-spacing": true,
|
||||
"match-default-export-name": true,
|
||||
"no-boolean-literal-compare": true,
|
||||
"no-mergeable-namespace": true,
|
||||
"no-reference-import": true,
|
||||
"no-unnecessary-callback-wrapper": true,
|
||||
"number-literal-format": true,
|
||||
"one-line": [
|
||||
true,
|
||||
"check-catch",
|
||||
"check-finally",
|
||||
"check-else",
|
||||
"check-open-brace",
|
||||
"check-whitespace"
|
||||
],
|
||||
"prefer-method-signature": true,
|
||||
"prefer-while": true,
|
||||
"typedef": [
|
||||
true,
|
||||
"variable-declaration",
|
||||
"call-signature",
|
||||
"variable-declaration-ignore-function"
|
||||
],
|
||||
"whitespace": [
|
||||
true,
|
||||
"check-branch",
|
||||
"check-operator",
|
||||
"check-separator",
|
||||
"check-preblock",
|
||||
"check-type"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
# ignore dependency packages
|
||||
node_modules
|
||||
|
||||
# ignore compiled typescript
|
||||
# ignore compliled typescript
|
||||
out
|
||||
dist
|
||||
|
||||
@@ -10,7 +10,6 @@ server
|
||||
debugAdapters
|
||||
LLVM
|
||||
bin/cpptools*
|
||||
bin/libc.so
|
||||
bin/*.dll
|
||||
bin/.vs
|
||||
bin/LICENSE.txt
|
||||
@@ -26,6 +25,7 @@ install.lock
|
||||
|
||||
# ignore generated localization file
|
||||
**/nls.*.json
|
||||
**/*.nls.json
|
||||
**/*.nls.*.json
|
||||
|
||||
# ignore generate native header
|
||||
@@ -34,5 +34,3 @@ localized_string_ids.h
|
||||
# ignore generate files. It will be generated when building
|
||||
src/nativeStrings.ts
|
||||
|
||||
vscode*.d.ts
|
||||
.scripts/_*
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
registry=https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/
|
||||
always-auth=true
|
||||
# Disable postinstall scripts for supply chain security. Allowlist exceptions with npm trust: https://docs.npmjs.com/cli/v11/commands/npm-trust
|
||||
ignore-scripts=true
|
||||
@@ -1,67 +0,0 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
import { error } from 'node:console';
|
||||
import { resolve, sep } from 'node:path';
|
||||
import { filepath } from '../src/Utility/Filesystem/filepath';
|
||||
import { verbose } from '../src/Utility/Text/streams';
|
||||
import { $root, Git, brightGreen, cyan, getModifiedIgnoredFiles, rimraf } from './common';
|
||||
|
||||
// notes:
|
||||
// list all gitignore'd files that are modified: `git clean -Xd -n`
|
||||
// list all untracked and ignored files that are modified/created: `git clean -Xd -n`
|
||||
|
||||
export async function main() {
|
||||
await rimraf(resolve($root, 'dist'));
|
||||
}
|
||||
|
||||
export async function all() {
|
||||
await rimraf(...(await getModifiedIgnoredFiles()).filter((each): each is string => each !== undefined && !each.includes('node_modules')));
|
||||
}
|
||||
|
||||
export async function reset() {
|
||||
verbose(`Resetting all .gitignored files in extension`);
|
||||
await rimraf(...(await getModifiedIgnoredFiles()).filter((each): each is string => each !== undefined));
|
||||
}
|
||||
|
||||
async function details(files: string[]) {
|
||||
const results = await Promise.all(files.filter(each => each).map(async (each) => {
|
||||
const [, stats] = await filepath.stats(each);
|
||||
if (!stats) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
filename: stats.isDirectory() ? cyan(`${each}${sep}**`) : brightGreen(`${each}`),
|
||||
date: stats.mtime.toLocaleDateString().replace(/\b(\d)\//g, '0$1\/'),
|
||||
time: stats.mtime.toLocaleTimeString().replace(/^(\d)\:/g, '0$1:'),
|
||||
modified: stats.mtime
|
||||
};
|
||||
}));
|
||||
let all = results.filter((each): each is NonNullable<typeof each> => each !== null);
|
||||
all = all.sort((a, b) => a.modified.getTime() - b.modified.getTime());
|
||||
// print a formatted table so the date and time are aligned
|
||||
const max = all.reduce((max, each) => Math.max(max, each.filename.length), 0);
|
||||
all.forEach(each => console.log(` ${each.filename.padEnd(max)} [${each.date} ${each.time}]`));
|
||||
console.log('');
|
||||
}
|
||||
|
||||
export async function show(opt?: string) {
|
||||
switch (opt?.toLowerCase()) {
|
||||
case 'new':
|
||||
console.log(cyan('\n\nNew files:'));
|
||||
const r = await Git('ls-files', '--others', '--exclude-standard', '-z');
|
||||
return details(r.stdio.all().map(each => resolve(each.trim().replace(/\0/g, ''))));
|
||||
|
||||
case undefined:
|
||||
case '':
|
||||
case 'ignored':
|
||||
case 'untracked':
|
||||
console.log(cyan('\n\nUntracked+Ignored files:'));
|
||||
return details((await getModifiedIgnoredFiles()).filter((each): each is string => each !== undefined));
|
||||
|
||||
default:
|
||||
return error(`Unknown option '${opt}'`);
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
import { spawnSync } from 'child_process';
|
||||
import { verbose } from '../src/Utility/Text/streams';
|
||||
import { $args, $root, $scenario, assertAnyFile, brightGreen, gray, green, pwd } from './common';
|
||||
|
||||
import { resolve } from 'path';
|
||||
import { getTestInfo } from '../test/common/selectTests';
|
||||
import { install, options } from "./vscode";
|
||||
|
||||
export { install, reset } from './vscode';
|
||||
|
||||
export async function main() {
|
||||
let ti = await getTestInfo($scenario);
|
||||
if (!ti) {
|
||||
// try using the first arg as a scenario name or location
|
||||
ti = await getTestInfo($args[0], $args[0] ? resolve(pwd, $args[0]) : undefined);
|
||||
if (ti) {
|
||||
$args[0] = ti.workspace;
|
||||
}
|
||||
} else {
|
||||
// we found it
|
||||
$args.unshift(ti.workspace);
|
||||
}
|
||||
await assertAnyFile('dist/src/main.js', `The extension entry point '${$root}/dist/src/main.js is missing. You should run ${brightGreen("yarn compile")}\n\n`);
|
||||
|
||||
const { cli, args } = await install();
|
||||
|
||||
// example of installing an extension into code
|
||||
//verbose(`Installing release version of 'ms-vscode.cpptools'`);
|
||||
//spawnSync(cli, [...args, '--install-extension', 'ms-vscode.cpptools'], { encoding: 'utf-8', stdio: 'ignore' })
|
||||
verbose(green('Launch VSCode'));
|
||||
const ARGS = [...args, ...options.launchArgs.filter(each => !each.startsWith('--extensions-dir=') && !each.startsWith('--user-data-dir=')), `--extensionDevelopmentPath=${$root}`, ...$args ].map(each => (each.indexOf(' ') > -1) && (each.indexOf('"') === -1) ? `"${each}"` : each);
|
||||
const CLI = cli.indexOf(' ') > -1 && cli.indexOf('"') === -1 ? `"${cli}"` : cli;
|
||||
|
||||
verbose(gray(`${CLI}\n ${ [...ARGS ].join('\n ')}`));
|
||||
|
||||
spawnSync(CLI, ARGS, { encoding: 'utf-8', stdio: 'ignore', env: { ...process.env, DONT_PROMPT_WSL_INSTALL:"1" }, shell: true });
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user