@harness-engineering/core 0.17.0 → 0.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +64 -15
- package/dist/index.mjs +64 -15
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -5166,6 +5166,10 @@ interface GitHubAdapterOptions {
|
|
|
5166
5166
|
fetchFn?: typeof fetch;
|
|
5167
5167
|
/** Override API base URL (for GitHub Enterprise) */
|
|
5168
5168
|
apiBase?: string;
|
|
5169
|
+
/** Max retries on rate limit (default: 5) */
|
|
5170
|
+
maxRetries?: number;
|
|
5171
|
+
/** Base delay in ms for exponential backoff (default: 1000) */
|
|
5172
|
+
baseDelayMs?: number;
|
|
5169
5173
|
}
|
|
5170
5174
|
declare class GitHubIssuesSyncAdapter implements TrackerSyncAdapter {
|
|
5171
5175
|
private readonly token;
|
|
@@ -5174,8 +5178,14 @@ declare class GitHubIssuesSyncAdapter implements TrackerSyncAdapter {
|
|
|
5174
5178
|
private readonly apiBase;
|
|
5175
5179
|
private readonly owner;
|
|
5176
5180
|
private readonly repo;
|
|
5181
|
+
private readonly retryOpts;
|
|
5177
5182
|
constructor(options: GitHubAdapterOptions);
|
|
5178
5183
|
private headers;
|
|
5184
|
+
/**
|
|
5185
|
+
* Close an issue if the feature status maps to 'closed'.
|
|
5186
|
+
* GitHub Issues API doesn't accept state on POST — requires a follow-up PATCH.
|
|
5187
|
+
*/
|
|
5188
|
+
private closeIfDone;
|
|
5179
5189
|
createTicket(feature: RoadmapFeature, milestone: string): Promise<Result<ExternalTicket>>;
|
|
5180
5190
|
updateTicket(externalId: string, changes: Partial<RoadmapFeature>): Promise<Result<ExternalTicket>>;
|
|
5181
5191
|
fetchTicketState(externalId: string): Promise<Result<ExternalTicketState>>;
|
package/dist/index.d.ts
CHANGED
|
@@ -5166,6 +5166,10 @@ interface GitHubAdapterOptions {
|
|
|
5166
5166
|
fetchFn?: typeof fetch;
|
|
5167
5167
|
/** Override API base URL (for GitHub Enterprise) */
|
|
5168
5168
|
apiBase?: string;
|
|
5169
|
+
/** Max retries on rate limit (default: 5) */
|
|
5170
|
+
maxRetries?: number;
|
|
5171
|
+
/** Base delay in ms for exponential backoff (default: 1000) */
|
|
5172
|
+
baseDelayMs?: number;
|
|
5169
5173
|
}
|
|
5170
5174
|
declare class GitHubIssuesSyncAdapter implements TrackerSyncAdapter {
|
|
5171
5175
|
private readonly token;
|
|
@@ -5174,8 +5178,14 @@ declare class GitHubIssuesSyncAdapter implements TrackerSyncAdapter {
|
|
|
5174
5178
|
private readonly apiBase;
|
|
5175
5179
|
private readonly owner;
|
|
5176
5180
|
private readonly repo;
|
|
5181
|
+
private readonly retryOpts;
|
|
5177
5182
|
constructor(options: GitHubAdapterOptions);
|
|
5178
5183
|
private headers;
|
|
5184
|
+
/**
|
|
5185
|
+
* Close an issue if the feature status maps to 'closed'.
|
|
5186
|
+
* GitHub Issues API doesn't accept state on POST — requires a follow-up PATCH.
|
|
5187
|
+
*/
|
|
5188
|
+
private closeIfDone;
|
|
5179
5189
|
createTicket(feature: RoadmapFeature, milestone: string): Promise<Result<ExternalTicket>>;
|
|
5180
5190
|
updateTicket(externalId: string, changes: Partial<RoadmapFeature>): Promise<Result<ExternalTicket>>;
|
|
5181
5191
|
fetchTicketState(externalId: string): Promise<Result<ExternalTicketState>>;
|
package/dist/index.js
CHANGED
|
@@ -12574,6 +12574,29 @@ function labelsForStatus(status, config) {
|
|
|
12574
12574
|
}
|
|
12575
12575
|
return [...base];
|
|
12576
12576
|
}
|
|
12577
|
+
var RETRY_DEFAULTS = { maxRetries: 5, baseDelayMs: 1e3 };
|
|
12578
|
+
function sleep(ms) {
|
|
12579
|
+
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
12580
|
+
}
|
|
12581
|
+
async function fetchWithRetry(fetchFn, input, init, opts = RETRY_DEFAULTS) {
|
|
12582
|
+
let lastResponse;
|
|
12583
|
+
for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {
|
|
12584
|
+
const response = await fetchFn(input, init);
|
|
12585
|
+
if (response.status !== 403 && response.status !== 429) return response;
|
|
12586
|
+
lastResponse = response;
|
|
12587
|
+
if (attempt === opts.maxRetries) break;
|
|
12588
|
+
const retryAfter = response.headers.get("Retry-After");
|
|
12589
|
+
let delayMs;
|
|
12590
|
+
if (retryAfter) {
|
|
12591
|
+
const seconds = parseInt(retryAfter, 10);
|
|
12592
|
+
delayMs = isNaN(seconds) ? opts.baseDelayMs : seconds * 1e3;
|
|
12593
|
+
} else {
|
|
12594
|
+
delayMs = opts.baseDelayMs * Math.pow(2, attempt) + Math.random() * 500;
|
|
12595
|
+
}
|
|
12596
|
+
await sleep(delayMs);
|
|
12597
|
+
}
|
|
12598
|
+
return lastResponse;
|
|
12599
|
+
}
|
|
12577
12600
|
var GitHubIssuesSyncAdapter = class {
|
|
12578
12601
|
token;
|
|
12579
12602
|
config;
|
|
@@ -12581,11 +12604,16 @@ var GitHubIssuesSyncAdapter = class {
|
|
|
12581
12604
|
apiBase;
|
|
12582
12605
|
owner;
|
|
12583
12606
|
repo;
|
|
12607
|
+
retryOpts;
|
|
12584
12608
|
constructor(options) {
|
|
12585
12609
|
this.token = options.token;
|
|
12586
12610
|
this.config = options.config;
|
|
12587
12611
|
this.fetchFn = options.fetchFn ?? globalThis.fetch;
|
|
12588
12612
|
this.apiBase = options.apiBase ?? "https://api.github.com";
|
|
12613
|
+
this.retryOpts = {
|
|
12614
|
+
maxRetries: options.maxRetries ?? RETRY_DEFAULTS.maxRetries,
|
|
12615
|
+
baseDelayMs: options.baseDelayMs ?? RETRY_DEFAULTS.baseDelayMs
|
|
12616
|
+
};
|
|
12589
12617
|
const repoParts = (options.config.repo ?? "").split("/");
|
|
12590
12618
|
if (repoParts.length !== 2 || !repoParts[0] || !repoParts[1]) {
|
|
12591
12619
|
throw new Error(`Invalid repo format: "${options.config.repo}". Expected "owner/repo".`);
|
|
@@ -12601,6 +12629,20 @@ var GitHubIssuesSyncAdapter = class {
|
|
|
12601
12629
|
"X-GitHub-Api-Version": "2022-11-28"
|
|
12602
12630
|
};
|
|
12603
12631
|
}
|
|
12632
|
+
/**
|
|
12633
|
+
* Close an issue if the feature status maps to 'closed'.
|
|
12634
|
+
* GitHub Issues API doesn't accept state on POST — requires a follow-up PATCH.
|
|
12635
|
+
*/
|
|
12636
|
+
async closeIfDone(issueNumber, featureStatus) {
|
|
12637
|
+
const externalStatus = this.config.statusMap[featureStatus];
|
|
12638
|
+
if (externalStatus !== "closed") return;
|
|
12639
|
+
await fetchWithRetry(
|
|
12640
|
+
this.fetchFn,
|
|
12641
|
+
`${this.apiBase}/repos/${this.owner}/${this.repo}/issues/${issueNumber}`,
|
|
12642
|
+
{ method: "PATCH", headers: this.headers(), body: JSON.stringify({ state: "closed" }) },
|
|
12643
|
+
this.retryOpts
|
|
12644
|
+
);
|
|
12645
|
+
}
|
|
12604
12646
|
async createTicket(feature, milestone) {
|
|
12605
12647
|
try {
|
|
12606
12648
|
const labels = labelsForStatus(feature.status, this.config);
|
|
@@ -12610,17 +12652,15 @@ var GitHubIssuesSyncAdapter = class {
|
|
|
12610
12652
|
`**Milestone:** ${milestone}`,
|
|
12611
12653
|
feature.spec ? `**Spec:** ${feature.spec}` : ""
|
|
12612
12654
|
].filter(Boolean).join("\n");
|
|
12613
|
-
const response = await
|
|
12655
|
+
const response = await fetchWithRetry(
|
|
12656
|
+
this.fetchFn,
|
|
12614
12657
|
`${this.apiBase}/repos/${this.owner}/${this.repo}/issues`,
|
|
12615
12658
|
{
|
|
12616
12659
|
method: "POST",
|
|
12617
12660
|
headers: this.headers(),
|
|
12618
|
-
body: JSON.stringify({
|
|
12619
|
-
|
|
12620
|
-
|
|
12621
|
-
labels
|
|
12622
|
-
})
|
|
12623
|
-
}
|
|
12661
|
+
body: JSON.stringify({ title: feature.name, body, labels })
|
|
12662
|
+
},
|
|
12663
|
+
this.retryOpts
|
|
12624
12664
|
);
|
|
12625
12665
|
if (!response.ok) {
|
|
12626
12666
|
const text = await response.text();
|
|
@@ -12628,6 +12668,7 @@ var GitHubIssuesSyncAdapter = class {
|
|
|
12628
12668
|
}
|
|
12629
12669
|
const data = await response.json();
|
|
12630
12670
|
const externalId = buildExternalId(this.owner, this.repo, data.number);
|
|
12671
|
+
await this.closeIfDone(data.number, feature.status);
|
|
12631
12672
|
return (0, import_types21.Ok)({ externalId, url: data.html_url });
|
|
12632
12673
|
} catch (error) {
|
|
12633
12674
|
return (0, import_types21.Err)(error instanceof Error ? error : new Error(String(error)));
|
|
@@ -12648,13 +12689,15 @@ var GitHubIssuesSyncAdapter = class {
|
|
|
12648
12689
|
patch.state = externalStatus;
|
|
12649
12690
|
patch.labels = labelsForStatus(changes.status, this.config);
|
|
12650
12691
|
}
|
|
12651
|
-
const response = await
|
|
12692
|
+
const response = await fetchWithRetry(
|
|
12693
|
+
this.fetchFn,
|
|
12652
12694
|
`${this.apiBase}/repos/${parsed.owner}/${parsed.repo}/issues/${parsed.number}`,
|
|
12653
12695
|
{
|
|
12654
12696
|
method: "PATCH",
|
|
12655
12697
|
headers: this.headers(),
|
|
12656
12698
|
body: JSON.stringify(patch)
|
|
12657
|
-
}
|
|
12699
|
+
},
|
|
12700
|
+
this.retryOpts
|
|
12658
12701
|
);
|
|
12659
12702
|
if (!response.ok) {
|
|
12660
12703
|
const text = await response.text();
|
|
@@ -12670,12 +12713,14 @@ var GitHubIssuesSyncAdapter = class {
|
|
|
12670
12713
|
try {
|
|
12671
12714
|
const parsed = parseExternalId(externalId);
|
|
12672
12715
|
if (!parsed) return (0, import_types21.Err)(new Error(`Invalid externalId format: "${externalId}"`));
|
|
12673
|
-
const response = await
|
|
12716
|
+
const response = await fetchWithRetry(
|
|
12717
|
+
this.fetchFn,
|
|
12674
12718
|
`${this.apiBase}/repos/${parsed.owner}/${parsed.repo}/issues/${parsed.number}`,
|
|
12675
12719
|
{
|
|
12676
12720
|
method: "GET",
|
|
12677
12721
|
headers: this.headers()
|
|
12678
|
-
}
|
|
12722
|
+
},
|
|
12723
|
+
this.retryOpts
|
|
12679
12724
|
);
|
|
12680
12725
|
if (!response.ok) {
|
|
12681
12726
|
const text = await response.text();
|
|
@@ -12700,12 +12745,14 @@ var GitHubIssuesSyncAdapter = class {
|
|
|
12700
12745
|
let page = 1;
|
|
12701
12746
|
const perPage = 100;
|
|
12702
12747
|
while (true) {
|
|
12703
|
-
const response = await
|
|
12748
|
+
const response = await fetchWithRetry(
|
|
12749
|
+
this.fetchFn,
|
|
12704
12750
|
`${this.apiBase}/repos/${this.owner}/${this.repo}/issues?state=all&per_page=${perPage}&page=${page}${labelsParam}`,
|
|
12705
12751
|
{
|
|
12706
12752
|
method: "GET",
|
|
12707
12753
|
headers: this.headers()
|
|
12708
|
-
}
|
|
12754
|
+
},
|
|
12755
|
+
this.retryOpts
|
|
12709
12756
|
);
|
|
12710
12757
|
if (!response.ok) {
|
|
12711
12758
|
const text = await response.text();
|
|
@@ -12734,13 +12781,15 @@ var GitHubIssuesSyncAdapter = class {
|
|
|
12734
12781
|
const parsed = parseExternalId(externalId);
|
|
12735
12782
|
if (!parsed) return (0, import_types21.Err)(new Error(`Invalid externalId format: "${externalId}"`));
|
|
12736
12783
|
const login = assignee.startsWith("@") ? assignee.slice(1) : assignee;
|
|
12737
|
-
const response = await
|
|
12784
|
+
const response = await fetchWithRetry(
|
|
12785
|
+
this.fetchFn,
|
|
12738
12786
|
`${this.apiBase}/repos/${parsed.owner}/${parsed.repo}/issues/${parsed.number}/assignees`,
|
|
12739
12787
|
{
|
|
12740
12788
|
method: "POST",
|
|
12741
12789
|
headers: this.headers(),
|
|
12742
12790
|
body: JSON.stringify({ assignees: [login] })
|
|
12743
|
-
}
|
|
12791
|
+
},
|
|
12792
|
+
this.retryOpts
|
|
12744
12793
|
);
|
|
12745
12794
|
if (!response.ok) {
|
|
12746
12795
|
const text = await response.text();
|
package/dist/index.mjs
CHANGED
|
@@ -10465,6 +10465,29 @@ function labelsForStatus(status, config) {
|
|
|
10465
10465
|
}
|
|
10466
10466
|
return [...base];
|
|
10467
10467
|
}
|
|
10468
|
+
var RETRY_DEFAULTS = { maxRetries: 5, baseDelayMs: 1e3 };
|
|
10469
|
+
function sleep(ms) {
|
|
10470
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
10471
|
+
}
|
|
10472
|
+
async function fetchWithRetry(fetchFn, input, init, opts = RETRY_DEFAULTS) {
|
|
10473
|
+
let lastResponse;
|
|
10474
|
+
for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {
|
|
10475
|
+
const response = await fetchFn(input, init);
|
|
10476
|
+
if (response.status !== 403 && response.status !== 429) return response;
|
|
10477
|
+
lastResponse = response;
|
|
10478
|
+
if (attempt === opts.maxRetries) break;
|
|
10479
|
+
const retryAfter = response.headers.get("Retry-After");
|
|
10480
|
+
let delayMs;
|
|
10481
|
+
if (retryAfter) {
|
|
10482
|
+
const seconds = parseInt(retryAfter, 10);
|
|
10483
|
+
delayMs = isNaN(seconds) ? opts.baseDelayMs : seconds * 1e3;
|
|
10484
|
+
} else {
|
|
10485
|
+
delayMs = opts.baseDelayMs * Math.pow(2, attempt) + Math.random() * 500;
|
|
10486
|
+
}
|
|
10487
|
+
await sleep(delayMs);
|
|
10488
|
+
}
|
|
10489
|
+
return lastResponse;
|
|
10490
|
+
}
|
|
10468
10491
|
var GitHubIssuesSyncAdapter = class {
|
|
10469
10492
|
token;
|
|
10470
10493
|
config;
|
|
@@ -10472,11 +10495,16 @@ var GitHubIssuesSyncAdapter = class {
|
|
|
10472
10495
|
apiBase;
|
|
10473
10496
|
owner;
|
|
10474
10497
|
repo;
|
|
10498
|
+
retryOpts;
|
|
10475
10499
|
constructor(options) {
|
|
10476
10500
|
this.token = options.token;
|
|
10477
10501
|
this.config = options.config;
|
|
10478
10502
|
this.fetchFn = options.fetchFn ?? globalThis.fetch;
|
|
10479
10503
|
this.apiBase = options.apiBase ?? "https://api.github.com";
|
|
10504
|
+
this.retryOpts = {
|
|
10505
|
+
maxRetries: options.maxRetries ?? RETRY_DEFAULTS.maxRetries,
|
|
10506
|
+
baseDelayMs: options.baseDelayMs ?? RETRY_DEFAULTS.baseDelayMs
|
|
10507
|
+
};
|
|
10480
10508
|
const repoParts = (options.config.repo ?? "").split("/");
|
|
10481
10509
|
if (repoParts.length !== 2 || !repoParts[0] || !repoParts[1]) {
|
|
10482
10510
|
throw new Error(`Invalid repo format: "${options.config.repo}". Expected "owner/repo".`);
|
|
@@ -10492,6 +10520,20 @@ var GitHubIssuesSyncAdapter = class {
|
|
|
10492
10520
|
"X-GitHub-Api-Version": "2022-11-28"
|
|
10493
10521
|
};
|
|
10494
10522
|
}
|
|
10523
|
+
/**
|
|
10524
|
+
* Close an issue if the feature status maps to 'closed'.
|
|
10525
|
+
* GitHub Issues API doesn't accept state on POST — requires a follow-up PATCH.
|
|
10526
|
+
*/
|
|
10527
|
+
async closeIfDone(issueNumber, featureStatus) {
|
|
10528
|
+
const externalStatus = this.config.statusMap[featureStatus];
|
|
10529
|
+
if (externalStatus !== "closed") return;
|
|
10530
|
+
await fetchWithRetry(
|
|
10531
|
+
this.fetchFn,
|
|
10532
|
+
`${this.apiBase}/repos/${this.owner}/${this.repo}/issues/${issueNumber}`,
|
|
10533
|
+
{ method: "PATCH", headers: this.headers(), body: JSON.stringify({ state: "closed" }) },
|
|
10534
|
+
this.retryOpts
|
|
10535
|
+
);
|
|
10536
|
+
}
|
|
10495
10537
|
async createTicket(feature, milestone) {
|
|
10496
10538
|
try {
|
|
10497
10539
|
const labels = labelsForStatus(feature.status, this.config);
|
|
@@ -10501,17 +10543,15 @@ var GitHubIssuesSyncAdapter = class {
|
|
|
10501
10543
|
`**Milestone:** ${milestone}`,
|
|
10502
10544
|
feature.spec ? `**Spec:** ${feature.spec}` : ""
|
|
10503
10545
|
].filter(Boolean).join("\n");
|
|
10504
|
-
const response = await
|
|
10546
|
+
const response = await fetchWithRetry(
|
|
10547
|
+
this.fetchFn,
|
|
10505
10548
|
`${this.apiBase}/repos/${this.owner}/${this.repo}/issues`,
|
|
10506
10549
|
{
|
|
10507
10550
|
method: "POST",
|
|
10508
10551
|
headers: this.headers(),
|
|
10509
|
-
body: JSON.stringify({
|
|
10510
|
-
|
|
10511
|
-
|
|
10512
|
-
labels
|
|
10513
|
-
})
|
|
10514
|
-
}
|
|
10552
|
+
body: JSON.stringify({ title: feature.name, body, labels })
|
|
10553
|
+
},
|
|
10554
|
+
this.retryOpts
|
|
10515
10555
|
);
|
|
10516
10556
|
if (!response.ok) {
|
|
10517
10557
|
const text = await response.text();
|
|
@@ -10519,6 +10559,7 @@ var GitHubIssuesSyncAdapter = class {
|
|
|
10519
10559
|
}
|
|
10520
10560
|
const data = await response.json();
|
|
10521
10561
|
const externalId = buildExternalId(this.owner, this.repo, data.number);
|
|
10562
|
+
await this.closeIfDone(data.number, feature.status);
|
|
10522
10563
|
return Ok4({ externalId, url: data.html_url });
|
|
10523
10564
|
} catch (error) {
|
|
10524
10565
|
return Err3(error instanceof Error ? error : new Error(String(error)));
|
|
@@ -10539,13 +10580,15 @@ var GitHubIssuesSyncAdapter = class {
|
|
|
10539
10580
|
patch.state = externalStatus;
|
|
10540
10581
|
patch.labels = labelsForStatus(changes.status, this.config);
|
|
10541
10582
|
}
|
|
10542
|
-
const response = await
|
|
10583
|
+
const response = await fetchWithRetry(
|
|
10584
|
+
this.fetchFn,
|
|
10543
10585
|
`${this.apiBase}/repos/${parsed.owner}/${parsed.repo}/issues/${parsed.number}`,
|
|
10544
10586
|
{
|
|
10545
10587
|
method: "PATCH",
|
|
10546
10588
|
headers: this.headers(),
|
|
10547
10589
|
body: JSON.stringify(patch)
|
|
10548
|
-
}
|
|
10590
|
+
},
|
|
10591
|
+
this.retryOpts
|
|
10549
10592
|
);
|
|
10550
10593
|
if (!response.ok) {
|
|
10551
10594
|
const text = await response.text();
|
|
@@ -10561,12 +10604,14 @@ var GitHubIssuesSyncAdapter = class {
|
|
|
10561
10604
|
try {
|
|
10562
10605
|
const parsed = parseExternalId(externalId);
|
|
10563
10606
|
if (!parsed) return Err3(new Error(`Invalid externalId format: "${externalId}"`));
|
|
10564
|
-
const response = await
|
|
10607
|
+
const response = await fetchWithRetry(
|
|
10608
|
+
this.fetchFn,
|
|
10565
10609
|
`${this.apiBase}/repos/${parsed.owner}/${parsed.repo}/issues/${parsed.number}`,
|
|
10566
10610
|
{
|
|
10567
10611
|
method: "GET",
|
|
10568
10612
|
headers: this.headers()
|
|
10569
|
-
}
|
|
10613
|
+
},
|
|
10614
|
+
this.retryOpts
|
|
10570
10615
|
);
|
|
10571
10616
|
if (!response.ok) {
|
|
10572
10617
|
const text = await response.text();
|
|
@@ -10591,12 +10636,14 @@ var GitHubIssuesSyncAdapter = class {
|
|
|
10591
10636
|
let page = 1;
|
|
10592
10637
|
const perPage = 100;
|
|
10593
10638
|
while (true) {
|
|
10594
|
-
const response = await
|
|
10639
|
+
const response = await fetchWithRetry(
|
|
10640
|
+
this.fetchFn,
|
|
10595
10641
|
`${this.apiBase}/repos/${this.owner}/${this.repo}/issues?state=all&per_page=${perPage}&page=${page}${labelsParam}`,
|
|
10596
10642
|
{
|
|
10597
10643
|
method: "GET",
|
|
10598
10644
|
headers: this.headers()
|
|
10599
|
-
}
|
|
10645
|
+
},
|
|
10646
|
+
this.retryOpts
|
|
10600
10647
|
);
|
|
10601
10648
|
if (!response.ok) {
|
|
10602
10649
|
const text = await response.text();
|
|
@@ -10625,13 +10672,15 @@ var GitHubIssuesSyncAdapter = class {
|
|
|
10625
10672
|
const parsed = parseExternalId(externalId);
|
|
10626
10673
|
if (!parsed) return Err3(new Error(`Invalid externalId format: "${externalId}"`));
|
|
10627
10674
|
const login = assignee.startsWith("@") ? assignee.slice(1) : assignee;
|
|
10628
|
-
const response = await
|
|
10675
|
+
const response = await fetchWithRetry(
|
|
10676
|
+
this.fetchFn,
|
|
10629
10677
|
`${this.apiBase}/repos/${parsed.owner}/${parsed.repo}/issues/${parsed.number}/assignees`,
|
|
10630
10678
|
{
|
|
10631
10679
|
method: "POST",
|
|
10632
10680
|
headers: this.headers(),
|
|
10633
10681
|
body: JSON.stringify({ assignees: [login] })
|
|
10634
|
-
}
|
|
10682
|
+
},
|
|
10683
|
+
this.retryOpts
|
|
10635
10684
|
);
|
|
10636
10685
|
if (!response.ok) {
|
|
10637
10686
|
const text = await response.text();
|