mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-19 22:09:37 +00:00
Compare commits
2 Commits
v1.43.10
...
feat/relea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3dc094844 | ||
|
|
4400f7d1f5 |
32
.github/workflows/release-pr-label-tagger.yaml
vendored
Normal file
32
.github/workflows/release-pr-label-tagger.yaml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: Release PR Label Tagger
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_tag:
|
||||
description: 'Release tag to process (e.g. core/v1.40.0)'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
label-prs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Setup frontend
|
||||
uses: ./.github/actions/setup-frontend
|
||||
|
||||
- name: Tag PRs with release label
|
||||
run: pnpm exec tsx scripts/release-pr-label-tagger.ts
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
INPUT_RELEASE_TAG: ${{ inputs.release_tag }}
|
||||
@@ -116,6 +116,8 @@
|
||||
"zod-validation-error": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@actions/core": "^1.10.1",
|
||||
"@actions/github": "^6.0.0",
|
||||
"@eslint/js": "catalog:",
|
||||
"@intlify/eslint-plugin-vue-i18n": "catalog:",
|
||||
"@lobehub/i18n-cli": "catalog:",
|
||||
|
||||
188
pnpm-lock.yaml
generated
188
pnpm-lock.yaml
generated
@@ -513,6 +513,12 @@ importers:
|
||||
specifier: 'catalog:'
|
||||
version: 3.3.0(zod@3.24.1)
|
||||
devDependencies:
|
||||
'@actions/core':
|
||||
specifier: ^1.10.1
|
||||
version: 1.11.1
|
||||
'@actions/github':
|
||||
specifier: ^6.0.0
|
||||
version: 6.0.1
|
||||
'@eslint/js':
|
||||
specifier: 'catalog:'
|
||||
version: 9.39.1
|
||||
@@ -846,6 +852,21 @@ packages:
|
||||
'@acemir/cssom@0.9.30':
|
||||
resolution: {integrity: sha512-9CnlMCI0LmCIq0olalQqdWrJHPzm0/tw3gzOA9zJSgvFX7Xau3D24mAGa4BtwxwY69nsuJW6kQqqCzf/mEcQgg==}
|
||||
|
||||
'@actions/core@1.11.1':
|
||||
resolution: {integrity: sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==}
|
||||
|
||||
'@actions/exec@1.1.1':
|
||||
resolution: {integrity: sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==}
|
||||
|
||||
'@actions/github@6.0.1':
|
||||
resolution: {integrity: sha512-xbZVcaqD4XnQAe35qSQqskb3SqIAfRyLBrHMd/8TuL7hJSz2QtbDwnNM8zWx4zO5l2fnGtseNE3MbEvD7BxVMw==}
|
||||
|
||||
'@actions/http-client@2.2.3':
|
||||
resolution: {integrity: sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==}
|
||||
|
||||
'@actions/io@1.1.3':
|
||||
resolution: {integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==}
|
||||
|
||||
'@adobe/css-tools@4.4.4':
|
||||
resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==}
|
||||
|
||||
@@ -1899,6 +1920,10 @@ packages:
|
||||
'@exodus/crypto':
|
||||
optional: true
|
||||
|
||||
'@fastify/busboy@2.1.1':
|
||||
resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
'@firebase/analytics-compat@0.2.18':
|
||||
resolution: {integrity: sha512-Hw9mzsSMZaQu6wrTbi3kYYwGw9nBqOHr47pVLxfr5v8CalsdrG5gfs9XUlPOZjHRVISp3oQrh1j7d3E+ulHPjQ==}
|
||||
peerDependencies:
|
||||
@@ -2516,6 +2541,54 @@ packages:
|
||||
'@nx/workspace@22.2.6':
|
||||
resolution: {integrity: sha512-DQnyxoFcf0oDrYIlwAHU4JOxDTA9AKODF3L3JUjNyKqMBSj9Z9o9FEf32wZZCzi0Akf4LDZxyPxU7wz+o1u/WA==}
|
||||
|
||||
'@octokit/auth-token@4.0.0':
|
||||
resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
'@octokit/core@5.2.2':
|
||||
resolution: {integrity: sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
'@octokit/endpoint@9.0.6':
|
||||
resolution: {integrity: sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
'@octokit/graphql@7.1.1':
|
||||
resolution: {integrity: sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
'@octokit/openapi-types@20.0.0':
|
||||
resolution: {integrity: sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==}
|
||||
|
||||
'@octokit/openapi-types@24.2.0':
|
||||
resolution: {integrity: sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==}
|
||||
|
||||
'@octokit/plugin-paginate-rest@9.2.2':
|
||||
resolution: {integrity: sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==}
|
||||
engines: {node: '>= 18'}
|
||||
peerDependencies:
|
||||
'@octokit/core': '5'
|
||||
|
||||
'@octokit/plugin-rest-endpoint-methods@10.4.1':
|
||||
resolution: {integrity: sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==}
|
||||
engines: {node: '>= 18'}
|
||||
peerDependencies:
|
||||
'@octokit/core': '5'
|
||||
|
||||
'@octokit/request-error@5.1.1':
|
||||
resolution: {integrity: sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
'@octokit/request@8.4.1':
|
||||
resolution: {integrity: sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
'@octokit/types@12.6.0':
|
||||
resolution: {integrity: sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==}
|
||||
|
||||
'@octokit/types@13.10.0':
|
||||
resolution: {integrity: sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==}
|
||||
|
||||
'@one-ini/wasm@0.1.1':
|
||||
resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==}
|
||||
|
||||
@@ -4415,6 +4488,9 @@ packages:
|
||||
resolution: {integrity: sha512-k9xFKplee6KIio3IDbwj+uaCLpqzOwakOgmqzPezM0sFJlFKcg30vk2wOiAJtkTSfx0SSQDSe8q+mWA/fSH5Zg==}
|
||||
hasBin: true
|
||||
|
||||
before-after-hook@2.2.3:
|
||||
resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==}
|
||||
|
||||
bidi-js@1.0.3:
|
||||
resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==}
|
||||
|
||||
@@ -4867,6 +4943,9 @@ packages:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
deprecation@2.3.1:
|
||||
resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==}
|
||||
|
||||
dequal@2.0.3:
|
||||
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -7849,6 +7928,10 @@ packages:
|
||||
engines: {node: '>=18.0.0'}
|
||||
hasBin: true
|
||||
|
||||
tunnel@0.0.6:
|
||||
resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==}
|
||||
engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'}
|
||||
|
||||
tw-animate-css@1.3.8:
|
||||
resolution: {integrity: sha512-Qrk3PZ7l7wUcGYhwZloqfkWCmaXZAoqjkdbIDvzfGshwGtexa/DAs9koXxIkrpEasyevandomzCBAV1Yyop5rw==}
|
||||
|
||||
@@ -7927,6 +8010,10 @@ packages:
|
||||
undici-types@7.16.0:
|
||||
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
|
||||
|
||||
undici@5.29.0:
|
||||
resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==}
|
||||
engines: {node: '>=14.0'}
|
||||
|
||||
unescape-js@1.1.4:
|
||||
resolution: {integrity: sha512-42SD8NOQEhdYntEiUQdYq/1V/YHwr1HLwlHuTJB5InVVdOSbgI6xu8jK5q65yIzuFCfczzyDF/7hbGzVbyCw0g==}
|
||||
|
||||
@@ -7961,6 +8048,9 @@ packages:
|
||||
unist-util-visit@5.0.0:
|
||||
resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
|
||||
|
||||
universal-user-agent@6.0.1:
|
||||
resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==}
|
||||
|
||||
universalify@2.0.1:
|
||||
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
@@ -8540,6 +8630,32 @@ snapshots:
|
||||
|
||||
'@acemir/cssom@0.9.30': {}
|
||||
|
||||
'@actions/core@1.11.1':
|
||||
dependencies:
|
||||
'@actions/exec': 1.1.1
|
||||
'@actions/http-client': 2.2.3
|
||||
|
||||
'@actions/exec@1.1.1':
|
||||
dependencies:
|
||||
'@actions/io': 1.1.3
|
||||
|
||||
'@actions/github@6.0.1':
|
||||
dependencies:
|
||||
'@actions/http-client': 2.2.3
|
||||
'@octokit/core': 5.2.2
|
||||
'@octokit/plugin-paginate-rest': 9.2.2(@octokit/core@5.2.2)
|
||||
'@octokit/plugin-rest-endpoint-methods': 10.4.1(@octokit/core@5.2.2)
|
||||
'@octokit/request': 8.4.1
|
||||
'@octokit/request-error': 5.1.1
|
||||
undici: 5.29.0
|
||||
|
||||
'@actions/http-client@2.2.3':
|
||||
dependencies:
|
||||
tunnel: 0.0.6
|
||||
undici: 5.29.0
|
||||
|
||||
'@actions/io@1.1.3': {}
|
||||
|
||||
'@adobe/css-tools@4.4.4': {}
|
||||
|
||||
'@alcalzone/ansi-tokenize@0.2.0':
|
||||
@@ -9643,6 +9759,8 @@ snapshots:
|
||||
|
||||
'@exodus/bytes@1.7.0': {}
|
||||
|
||||
'@fastify/busboy@2.1.1': {}
|
||||
|
||||
'@firebase/analytics-compat@0.2.18(@firebase/app-compat@0.2.53)(@firebase/app@0.11.4)':
|
||||
dependencies:
|
||||
'@firebase/analytics': 0.10.12(@firebase/app@0.11.4)
|
||||
@@ -10658,6 +10776,64 @@ snapshots:
|
||||
- '@swc/core'
|
||||
- debug
|
||||
|
||||
'@octokit/auth-token@4.0.0': {}
|
||||
|
||||
'@octokit/core@5.2.2':
|
||||
dependencies:
|
||||
'@octokit/auth-token': 4.0.0
|
||||
'@octokit/graphql': 7.1.1
|
||||
'@octokit/request': 8.4.1
|
||||
'@octokit/request-error': 5.1.1
|
||||
'@octokit/types': 13.10.0
|
||||
before-after-hook: 2.2.3
|
||||
universal-user-agent: 6.0.1
|
||||
|
||||
'@octokit/endpoint@9.0.6':
|
||||
dependencies:
|
||||
'@octokit/types': 13.10.0
|
||||
universal-user-agent: 6.0.1
|
||||
|
||||
'@octokit/graphql@7.1.1':
|
||||
dependencies:
|
||||
'@octokit/request': 8.4.1
|
||||
'@octokit/types': 13.10.0
|
||||
universal-user-agent: 6.0.1
|
||||
|
||||
'@octokit/openapi-types@20.0.0': {}
|
||||
|
||||
'@octokit/openapi-types@24.2.0': {}
|
||||
|
||||
'@octokit/plugin-paginate-rest@9.2.2(@octokit/core@5.2.2)':
|
||||
dependencies:
|
||||
'@octokit/core': 5.2.2
|
||||
'@octokit/types': 12.6.0
|
||||
|
||||
'@octokit/plugin-rest-endpoint-methods@10.4.1(@octokit/core@5.2.2)':
|
||||
dependencies:
|
||||
'@octokit/core': 5.2.2
|
||||
'@octokit/types': 12.6.0
|
||||
|
||||
'@octokit/request-error@5.1.1':
|
||||
dependencies:
|
||||
'@octokit/types': 13.10.0
|
||||
deprecation: 2.3.1
|
||||
once: 1.4.0
|
||||
|
||||
'@octokit/request@8.4.1':
|
||||
dependencies:
|
||||
'@octokit/endpoint': 9.0.6
|
||||
'@octokit/request-error': 5.1.1
|
||||
'@octokit/types': 13.10.0
|
||||
universal-user-agent: 6.0.1
|
||||
|
||||
'@octokit/types@12.6.0':
|
||||
dependencies:
|
||||
'@octokit/openapi-types': 20.0.0
|
||||
|
||||
'@octokit/types@13.10.0':
|
||||
dependencies:
|
||||
'@octokit/openapi-types': 24.2.0
|
||||
|
||||
'@one-ini/wasm@0.1.1': {}
|
||||
|
||||
'@oxc-project/runtime@0.112.0': {}
|
||||
@@ -12615,6 +12791,8 @@ snapshots:
|
||||
|
||||
baseline-browser-mapping@2.9.7: {}
|
||||
|
||||
before-after-hook@2.2.3: {}
|
||||
|
||||
bidi-js@1.0.3:
|
||||
dependencies:
|
||||
require-from-string: 2.0.2
|
||||
@@ -13075,6 +13253,8 @@ snapshots:
|
||||
|
||||
delayed-stream@1.0.0: {}
|
||||
|
||||
deprecation@2.3.1: {}
|
||||
|
||||
dequal@2.0.3: {}
|
||||
|
||||
detect-libc@2.1.2: {}
|
||||
@@ -16769,6 +16949,8 @@ snapshots:
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
tunnel@0.0.6: {}
|
||||
|
||||
tw-animate-css@1.3.8: {}
|
||||
|
||||
type-check@0.4.0:
|
||||
@@ -16858,6 +17040,10 @@ snapshots:
|
||||
|
||||
undici-types@7.16.0: {}
|
||||
|
||||
undici@5.29.0:
|
||||
dependencies:
|
||||
'@fastify/busboy': 2.1.1
|
||||
|
||||
unescape-js@1.1.4:
|
||||
dependencies:
|
||||
string.fromcodepoint: 0.2.1
|
||||
@@ -16902,6 +17088,8 @@ snapshots:
|
||||
unist-util-is: 6.0.0
|
||||
unist-util-visit-parents: 6.0.1
|
||||
|
||||
universal-user-agent@6.0.1: {}
|
||||
|
||||
universalify@2.0.1: {}
|
||||
|
||||
unplugin-icons@22.5.0(@vue/compiler-sfc@3.5.25):
|
||||
|
||||
263
scripts/release-pr-label-tagger.ts
Normal file
263
scripts/release-pr-label-tagger.ts
Normal file
@@ -0,0 +1,263 @@
|
||||
import * as core from '@actions/core'
|
||||
import { context, getOctokit } from '@actions/github'
|
||||
|
||||
type OctokitInstance = ReturnType<typeof getOctokit>
|
||||
|
||||
type ReleaseLabel = 'released:core' | 'released:cloud'
|
||||
|
||||
const LABEL_COLORS: Record<ReleaseLabel, string> = {
|
||||
'released:core': '0075ca',
|
||||
'released:cloud': 'e4e669'
|
||||
}
|
||||
|
||||
function getLabelForBranch(branchName: string | null): ReleaseLabel | null {
|
||||
if (branchName?.startsWith('core/')) return 'released:core'
|
||||
if (branchName?.startsWith('cloud/')) return 'released:cloud'
|
||||
return null
|
||||
}
|
||||
|
||||
function getLabelForTag(tag: string): ReleaseLabel | null {
|
||||
if (tag.startsWith('core/')) return 'released:core'
|
||||
if (tag.startsWith('cloud/')) return 'released:cloud'
|
||||
return null
|
||||
}
|
||||
|
||||
function isHttpError(err: unknown): err is { status: number } {
|
||||
return typeof err === 'object' && err !== null && 'status' in err
|
||||
}
|
||||
|
||||
async function ensureLabelExists(
|
||||
octokit: OctokitInstance,
|
||||
label: ReleaseLabel
|
||||
): Promise<void> {
|
||||
try {
|
||||
await octokit.rest.issues.getLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
name: label
|
||||
})
|
||||
core.info(`Label '${label}' already exists`)
|
||||
} catch (err: unknown) {
|
||||
if (isHttpError(err) && err.status === 404) {
|
||||
await octokit.rest.issues.createLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
name: label,
|
||||
color: LABEL_COLORS[label]
|
||||
})
|
||||
core.info(`Created label '${label}'`)
|
||||
} else {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function findPreviousReleaseTag(
|
||||
octokit: OctokitInstance,
|
||||
branchPrefix: string,
|
||||
currentTag: string
|
||||
): Promise<string | null> {
|
||||
const releases = await octokit.paginate(octokit.rest.repos.listReleases, {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
per_page: 100
|
||||
})
|
||||
|
||||
const samePrefix = releases.filter(
|
||||
(r) => r.tag_name !== currentTag && r.tag_name.startsWith(branchPrefix)
|
||||
)
|
||||
|
||||
if (samePrefix.length === 0) return null
|
||||
|
||||
const currentRelease = releases.find((r) => r.tag_name === currentTag)
|
||||
const currentDate = currentRelease?.published_at
|
||||
? new Date(currentRelease.published_at)
|
||||
: new Date()
|
||||
|
||||
const previous = samePrefix
|
||||
.filter((r) => r.published_at && new Date(r.published_at) < currentDate)
|
||||
.sort(
|
||||
(a, b) =>
|
||||
new Date(b.published_at ?? 0).getTime() -
|
||||
new Date(a.published_at ?? 0).getTime()
|
||||
)
|
||||
|
||||
return previous[0]?.tag_name ?? null
|
||||
}
|
||||
|
||||
async function getCommitsInRange(
|
||||
octokit: OctokitInstance,
|
||||
releaseTag: string,
|
||||
previousTag: string | null
|
||||
): Promise<Array<{ sha: string }>> {
|
||||
if (previousTag) {
|
||||
const comparison = await octokit.rest.repos.compareCommitsWithBasehead({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
basehead: `${previousTag}...${releaseTag}`
|
||||
})
|
||||
const { commits } = comparison.data
|
||||
core.info(
|
||||
`Found ${commits.length} commits between ${previousTag} and ${releaseTag}`
|
||||
)
|
||||
return commits
|
||||
}
|
||||
|
||||
const { data: tagCommit } = await octokit.rest.repos.getCommit({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
ref: releaseTag
|
||||
})
|
||||
core.info(
|
||||
`No previous release; processing single HEAD commit ${tagCommit.sha}`
|
||||
)
|
||||
return [tagCommit]
|
||||
}
|
||||
|
||||
async function collectMergedPRNumbers(
|
||||
octokit: OctokitInstance,
|
||||
commits: Array<{ sha: string }>
|
||||
): Promise<Set<number>> {
|
||||
const prNumbers = new Set<number>()
|
||||
for (const commit of commits) {
|
||||
const { data: prs } =
|
||||
await octokit.rest.repos.listPullRequestsAssociatedWithCommit({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
commit_sha: commit.sha
|
||||
})
|
||||
for (const pr of prs) {
|
||||
if (pr.merged_at) prNumbers.add(pr.number)
|
||||
}
|
||||
}
|
||||
return prNumbers
|
||||
}
|
||||
|
||||
async function labelPRs(
|
||||
octokit: OctokitInstance,
|
||||
prNumbers: Set<number>,
|
||||
label: ReleaseLabel
|
||||
): Promise<{ labeled: string[]; skipped: string[] }> {
|
||||
const labeled: string[] = []
|
||||
const skipped: string[] = []
|
||||
|
||||
for (const prNumber of prNumbers) {
|
||||
const { data: pr } = await octokit.rest.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber
|
||||
})
|
||||
|
||||
if (pr.labels.some((l) => l.name === label)) {
|
||||
skipped.push(`#${prNumber}`)
|
||||
continue
|
||||
}
|
||||
|
||||
await octokit.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: prNumber,
|
||||
labels: [label]
|
||||
})
|
||||
|
||||
labeled.push(`#${prNumber} ${pr.title}`)
|
||||
core.info(`Labeled PR #${prNumber}: ${pr.title}`)
|
||||
}
|
||||
|
||||
return { labeled, skipped }
|
||||
}
|
||||
|
||||
async function writeSummary(
|
||||
releaseTag: string,
|
||||
label: ReleaseLabel,
|
||||
previousTag: string | null,
|
||||
labeled: string[],
|
||||
skipped: string[]
|
||||
): Promise<void> {
|
||||
const summaryLines = [
|
||||
`## Release PR Label Tagger`,
|
||||
``,
|
||||
`**Release tag:** \`${releaseTag}\``,
|
||||
`**Label applied:** \`${label}\``,
|
||||
`**Previous release:** ${previousTag ? `\`${previousTag}\`` : '_none_'}`,
|
||||
``
|
||||
]
|
||||
|
||||
if (labeled.length > 0) {
|
||||
summaryLines.push(`### Labeled PRs (${labeled.length})`)
|
||||
summaryLines.push(...labeled.map((entry) => `- ${entry}`))
|
||||
summaryLines.push(``)
|
||||
}
|
||||
|
||||
if (skipped.length > 0) {
|
||||
summaryLines.push(`### Skipped (already labeled): ${skipped.join(', ')}`)
|
||||
summaryLines.push(``)
|
||||
}
|
||||
|
||||
if (labeled.length === 0 && skipped.length === 0) {
|
||||
summaryLines.push(`_No PRs found to label._`)
|
||||
}
|
||||
|
||||
await core.summary.addRaw(summaryLines.join('\n')).write()
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const token = process.env.GITHUB_TOKEN
|
||||
if (!token) throw new Error('GITHUB_TOKEN is required')
|
||||
|
||||
const octokit = getOctokit(token)
|
||||
const isManual = context.eventName === 'workflow_dispatch'
|
||||
|
||||
const releaseTag: string = isManual
|
||||
? (process.env.INPUT_RELEASE_TAG ?? context.payload.inputs?.release_tag)
|
||||
: context.payload.release?.tag_name
|
||||
|
||||
if (!releaseTag) throw new Error('Could not determine release tag')
|
||||
|
||||
const branch: string | null = isManual
|
||||
? null
|
||||
: (context.payload.release?.target_commitish ?? null)
|
||||
|
||||
core.info(`Processing release tag: ${releaseTag}`)
|
||||
core.info(
|
||||
`Target branch: ${branch ?? '(manual trigger, will be derived from tag)'}`
|
||||
)
|
||||
|
||||
const label = getLabelForBranch(branch) ?? getLabelForTag(releaseTag)
|
||||
if (!label) {
|
||||
core.notice(
|
||||
`Skipping: branch '${branch}' / tag '${releaseTag}' does not match core/ or cloud/ pattern`
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
core.info(`Will apply label: ${label}`)
|
||||
|
||||
const branchPrefix = label === 'released:core' ? 'core/' : 'cloud/'
|
||||
|
||||
await ensureLabelExists(octokit, label)
|
||||
|
||||
const previousTag = await findPreviousReleaseTag(
|
||||
octokit,
|
||||
branchPrefix,
|
||||
releaseTag
|
||||
)
|
||||
core.info(
|
||||
previousTag
|
||||
? `Previous release tag: ${previousTag}`
|
||||
: 'No previous release found; will use all commits reachable from this tag'
|
||||
)
|
||||
|
||||
const commits = await getCommitsInRange(octokit, releaseTag, previousTag)
|
||||
const prNumbers = await collectMergedPRNumbers(octokit, commits)
|
||||
core.info(`Found ${prNumbers.size} merged PRs associated with these commits`)
|
||||
|
||||
const { labeled, skipped } = await labelPRs(octokit, prNumbers, label)
|
||||
|
||||
await writeSummary(releaseTag, label, previousTag, labeled, skipped)
|
||||
}
|
||||
|
||||
main().catch((err: unknown) => {
|
||||
core.setFailed(err instanceof Error ? err.message : String(err))
|
||||
process.exit(1)
|
||||
})
|
||||
Reference in New Issue
Block a user