snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 2s
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 2s
This commit is contained in:
246
.github/actions/build-docker/action.yml
vendored
Normal file
246
.github/actions/build-docker/action.yml
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
name: 'Build Docker'
|
||||
description: 'Build Docker images for Rocket.Chat and related services'
|
||||
|
||||
inputs:
|
||||
CR_USER:
|
||||
required: true
|
||||
description: 'GitHub Container Registry username'
|
||||
CR_PAT:
|
||||
required: true
|
||||
description: 'GitHub Container Registry Personal Access Token'
|
||||
DOCKER_USER:
|
||||
required: false
|
||||
description: 'DockerHub username (required for FIPS builds to pull private base image)'
|
||||
DOCKER_PASS:
|
||||
required: false
|
||||
description: 'DockerHub password (required for FIPS builds to pull private base image)'
|
||||
deno-version:
|
||||
required: true
|
||||
description: 'Deno version'
|
||||
arch:
|
||||
required: false
|
||||
description: 'Architecture'
|
||||
default: 'arm64'
|
||||
service:
|
||||
required: false
|
||||
description: 'Container to build'
|
||||
publish-image:
|
||||
required: false
|
||||
description: 'Publish image'
|
||||
default: 'true'
|
||||
setup-docker:
|
||||
required: false
|
||||
description: 'Setup Docker'
|
||||
default: 'true'
|
||||
type:
|
||||
required: false
|
||||
description: 'production, coverage, or fips'
|
||||
default: 'coverage'
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
|
||||
steps:
|
||||
- name: Login to GitHub Container Registry
|
||||
if: inputs.publish-image == 'true' && github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
|
||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ inputs.CR_USER }}
|
||||
password: ${{ inputs.CR_PAT }}
|
||||
|
||||
- name: Login to DockerHub
|
||||
# FIPS base image (rocketchat/dhi-node) lives in a private DockerHub repo and requires auth to pull.
|
||||
if: inputs.type == 'fips' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.event_name == 'merge_group' || github.ref == 'refs/heads/develop')
|
||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
||||
with:
|
||||
username: ${{ inputs.DOCKER_USER }}
|
||||
password: ${{ inputs.DOCKER_PASS }}
|
||||
|
||||
- name: Restore meteor build
|
||||
if: inputs.service == 'rocketchat'
|
||||
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
|
||||
with:
|
||||
name: build-${{ inputs.type == 'fips' && ((github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production') || inputs.type }}
|
||||
path: /tmp/build
|
||||
|
||||
- name: Unpack meteor build
|
||||
if: inputs.service == 'rocketchat'
|
||||
shell: bash
|
||||
run: |
|
||||
cd /tmp/build
|
||||
tar xzf Rocket.Chat.tar.gz
|
||||
rm Rocket.Chat.tar.gz
|
||||
|
||||
- name: Set up Docker
|
||||
if: inputs.setup-docker == 'true'
|
||||
uses: docker/setup-docker-action@e43656e248c0bd0647d3f5c195d116aacf6fcaf4 # v4.7.0
|
||||
with:
|
||||
daemon-config: |
|
||||
{
|
||||
"debug": false,
|
||||
"features": {
|
||||
"containerd-snapshotter": true
|
||||
}
|
||||
}
|
||||
|
||||
# Microservice images build from a pruned, self-contained context (out/<service>)
|
||||
# produced by `turbo prune`, instead of a hand-maintained list of COPY lines.
|
||||
# The rocketchat (Meteor) image is a prebuilt bundle and is staged separately above.
|
||||
- name: Stage service build context
|
||||
if: inputs.service != 'rocketchat'
|
||||
shell: bash
|
||||
env:
|
||||
INPUT_SERVICE: ${{ inputs.service }}
|
||||
run: |
|
||||
set -o xtrace
|
||||
|
||||
# The Docker SERVICE arg (folder under ee/apps) lives in the compose build args;
|
||||
# the compose service name (INPUT_SERVICE) can differ (e.g. ddp-streamer-service).
|
||||
SERVICE_DIR=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "$INPUT_SERVICE" '.services[$s].build.args.SERVICE')
|
||||
PKG_NAME=$(node -p "require('./ee/apps/${SERVICE_DIR}/package.json').name")
|
||||
TURBO_VERSION=$(node -p "require('./package.json').devDependencies.turbo")
|
||||
|
||||
rm -rf "out/${SERVICE_DIR}"
|
||||
|
||||
# `turbo prune` derives the exact workspace dependency closure for the service — no
|
||||
# hand-maintained list. --use-gitignore=false also captures the gitignored build output
|
||||
# we need (dist/, generated definition/), at the cost of dragging in node_modules/.turbo,
|
||||
# which we strip below; `yarn workspaces focus --production` rebuilds node_modules in-image.
|
||||
npx -y "turbo@${TURBO_VERSION}" prune "$PKG_NAME" --skip-infer --use-gitignore=false --out-dir "out/${SERVICE_DIR}"
|
||||
|
||||
find "out/${SERVICE_DIR}" \( -name node_modules -o -name .turbo \) -type d -prune -exec rm -rf {} +
|
||||
|
||||
- name: Build Docker images
|
||||
shell: bash
|
||||
env:
|
||||
DENO_VERSION: ${{ inputs.deno-version }}
|
||||
INPUT_ARCH: ${{ inputs.arch }}
|
||||
INPUT_SERVICE: ${{ inputs.service }}
|
||||
INPUT_PUBLISH_IMAGE: ${{ inputs.publish-image }}
|
||||
INPUT_TYPE: ${{ inputs.type }}
|
||||
GITHUB_RUN_ID: ${{ github.run_id }}
|
||||
GITHUB_SERVER_URL: ${{ github.server_url }}
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
GITHUB_EVENT_NAME: ${{ github.event_name }}
|
||||
GITHUB_REF: ${{ github.ref }}
|
||||
run: |
|
||||
set -o xtrace
|
||||
compose_fips_override=''
|
||||
if [[ "$INPUT_TYPE" == 'fips' ]]; then
|
||||
compose_fips_override='-f docker-compose-ci.fips.yml'
|
||||
fi
|
||||
|
||||
# Removes unnecessary swc cores and sharp binaries to reduce image size
|
||||
swc_arch='x64'
|
||||
if [[ "$INPUT_SERVICE" == 'rocketchat' ]]; then
|
||||
if [[ "$INPUT_ARCH" == 'arm64' ]]; then
|
||||
swc_arch='arm64'
|
||||
fi
|
||||
|
||||
find /tmp/build/bundle/programs/server/npm/node_modules/@img -type d -name 'sharp-*' -not -name "*-linuxmusl-${swc_arch}" -exec rm -rf {} +
|
||||
|
||||
find /tmp/build/bundle/programs/server/npm/node_modules/@napi-rs -type d -name 'pinyin-linux-*' -not -name "*-linux-${swc_arch}-*" -exec rm -rf {} +
|
||||
|
||||
find /tmp/build/bundle/programs/server/npm/node_modules/@esbuild -type d -name 'linux-*' -not -name "*-${swc_arch}" -exec rm -rf {} +
|
||||
|
||||
find /tmp/build/bundle/programs/server/npm/node_modules/@rocket.chat/apps/node_modules/@esbuild -type d -name 'linux-*' -not -name "*-${swc_arch}" -exec rm -rf {} +
|
||||
fi
|
||||
|
||||
if [[ "$INPUT_PUBLISH_IMAGE" == 'true' ]]; then
|
||||
LOAD_OR_PUSH="--push"
|
||||
else
|
||||
LOAD_OR_PUSH="--load"
|
||||
fi
|
||||
|
||||
# Get image name from docker-compose-ci.yml since rocketchat image is different from service name (rocket.chat)
|
||||
IMAGE=$(docker compose -f docker-compose-ci.yml $compose_fips_override config --format json 2>/dev/null | jq -r --arg s "$INPUT_SERVICE" '.services[$s].image')
|
||||
|
||||
docker buildx bake \
|
||||
-f docker-compose-ci.yml $compose_fips_override \
|
||||
${LOAD_OR_PUSH} \
|
||||
--allow=fs.read=/tmp/build \
|
||||
--set "*.tags+=${IMAGE}-gha-run-${GITHUB_RUN_ID}" \
|
||||
--set "*.labels.org.opencontainers.image.description=Build run: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" \
|
||||
--set "*.labels.org.opencontainers.image.source=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}" \
|
||||
--set "*.platform=linux/${INPUT_ARCH}" \
|
||||
--set *.cache-from=type=gha \
|
||||
--set *.cache-to=type=gha,mode=max \
|
||||
--provenance=false \
|
||||
--sbom=false \
|
||||
--metadata-file "/tmp/meta.json" \
|
||||
"$INPUT_SERVICE"
|
||||
|
||||
echo "Contents of /tmp/meta.json:"
|
||||
cat /tmp/meta.json
|
||||
|
||||
if [[ "$INPUT_PUBLISH_IMAGE" == 'true' ]]; then
|
||||
SERVICE_SUFFIX=''
|
||||
if [[ "$INPUT_SERVICE" == 'rocketchat' && "$INPUT_TYPE" == 'coverage' ]] && [[ "$GITHUB_EVENT_NAME" == 'release' || "$GITHUB_REF" == 'refs/heads/develop' ]]; then
|
||||
SERVICE_SUFFIX='-cov'
|
||||
elif [[ "$INPUT_TYPE" == 'fips' ]]; then
|
||||
SERVICE_SUFFIX='-fips'
|
||||
fi
|
||||
|
||||
mkdir -p "/tmp/manifests/${INPUT_SERVICE}${SERVICE_SUFFIX}/${INPUT_ARCH}"
|
||||
|
||||
# Get digest and image info
|
||||
DIGEST=$(jq -r --arg service "$INPUT_SERVICE" '.[$service].["containerimage.digest"]' "/tmp/meta.json")
|
||||
IMAGE_NO_TAG=$(echo "$IMAGE" | sed 's/:.*$//')
|
||||
FULL_IMAGE="${IMAGE_NO_TAG}@${DIGEST}"
|
||||
|
||||
echo "Inspecting image: $FULL_IMAGE"
|
||||
|
||||
# Inspect the image and save complete manifest with sizes (using -v for verbose)
|
||||
docker manifest inspect -v "$FULL_IMAGE" > "/tmp/manifests/${INPUT_SERVICE}${SERVICE_SUFFIX}/${INPUT_ARCH}/manifest.json"
|
||||
|
||||
echo "Saved manifest to /tmp/manifests/${INPUT_SERVICE}${SERVICE_SUFFIX}/${INPUT_ARCH}/manifest.json"
|
||||
cat "/tmp/manifests/${INPUT_SERVICE}${SERVICE_SUFFIX}/${INPUT_ARCH}/manifest.json" | jq '.'
|
||||
fi
|
||||
|
||||
- name: Save Docker image as artifact
|
||||
if: inputs.publish-image == 'false' && inputs.arch == 'amd64'
|
||||
shell: bash
|
||||
env:
|
||||
SERVICE: ${{ inputs.service }}
|
||||
ARCH: ${{ inputs.arch }}
|
||||
TYPE: ${{ inputs.type }}
|
||||
run: |
|
||||
set -o xtrace
|
||||
compose_fips_override=''
|
||||
if [[ "$TYPE" == 'fips' ]]; then
|
||||
compose_fips_override='-f docker-compose-ci.fips.yml'
|
||||
fi
|
||||
|
||||
# Get image name from docker-compose-ci.yml
|
||||
IMAGE=$(docker compose -f docker-compose-ci.yml $compose_fips_override config --format json 2>/dev/null | jq -r --arg s "$SERVICE" '.services[$s].image')
|
||||
|
||||
# Create directory for image archives
|
||||
mkdir -p /tmp/docker-images
|
||||
|
||||
# Save the image to a tar file
|
||||
docker save "${IMAGE}" -o "/tmp/docker-images/${SERVICE}-${ARCH}-${TYPE}.tar"
|
||||
|
||||
echo "Saved image to /tmp/docker-images/${SERVICE}-${ARCH}-${TYPE}.tar"
|
||||
ls -lh /tmp/docker-images/
|
||||
|
||||
- name: Upload Docker image artifact
|
||||
if: inputs.publish-image == 'false' && inputs.arch == 'amd64'
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: docker-image-${{ inputs.service }}-${{ inputs.arch }}-${{ inputs.type }}
|
||||
path: /tmp/docker-images/${{ inputs.service }}-${{ inputs.arch }}-${{ inputs.type }}.tar
|
||||
retention-days: 1
|
||||
|
||||
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
if: inputs.publish-image == 'true'
|
||||
with:
|
||||
name: manifests-${{ inputs.service }}-${{ inputs.arch }}-${{ inputs.type }}
|
||||
path: /tmp/manifests
|
||||
retention-days: 5
|
||||
|
||||
- name: Clean up temporary files
|
||||
if: inputs.service == 'rocketchat'
|
||||
shell: bash
|
||||
run: |
|
||||
sudo rm -rf /tmp/build
|
||||
581
.github/actions/docker-image-size-tracker/action.yml
vendored
Normal file
581
.github/actions/docker-image-size-tracker/action.yml
vendored
Normal file
@@ -0,0 +1,581 @@
|
||||
name: 'Docker Image Size Tracker'
|
||||
description: 'Track and report Docker image sizes in Pull Requests'
|
||||
author: 'Rocket.Chat'
|
||||
|
||||
inputs:
|
||||
github-token:
|
||||
description: 'GitHub token for commenting on PRs'
|
||||
required: true
|
||||
ci-pat:
|
||||
description: 'GitHub token for committing to history branch'
|
||||
required: true
|
||||
registry:
|
||||
description: 'Container registry (e.g., ghcr.io)'
|
||||
required: false
|
||||
default: 'ghcr.io'
|
||||
repository:
|
||||
description: 'Repository name (e.g., rocketchat)'
|
||||
required: true
|
||||
tag:
|
||||
description: 'Image tag to measure'
|
||||
required: true
|
||||
baseline-tag:
|
||||
description: 'Baseline tag to compare against'
|
||||
required: false
|
||||
default: 'develop'
|
||||
platform:
|
||||
description: 'Platform architecture to compare (amd64 or arm64)'
|
||||
required: false
|
||||
default: 'amd64'
|
||||
size-thresholds:
|
||||
description: 'Optional JSON: per-image trigger thresholds. Only comment when an image increase exceeds its threshold. Example: {"rocketchat":{"mb":50,"percent":5},"omnichannel":{"mb":10,"percent":2}}'
|
||||
required: false
|
||||
default: ''
|
||||
fail-thresholds:
|
||||
description: 'Optional JSON: per-image fail thresholds. Task fails when an image increase exceeds its threshold (mb and/or percent). Example: {"rocketchat":{"mb":100,"percent":15}}'
|
||||
required: false
|
||||
default: ''
|
||||
|
||||
outputs:
|
||||
total-size:
|
||||
description: 'Total size in bytes'
|
||||
value: ${{ steps.measure.outputs.total-size }}
|
||||
size-diff:
|
||||
description: 'Size difference in bytes'
|
||||
value: ${{ steps.compare.outputs.size-diff }}
|
||||
size-diff-percent:
|
||||
description: 'Size difference percentage'
|
||||
value: ${{ steps.compare.outputs.size-diff-percent }}
|
||||
comment-triggered:
|
||||
description: 'Whether to post PR comment (only when size is bigger and thresholds met)'
|
||||
value: ${{ steps.compare.outputs.comment-triggered }}
|
||||
failed:
|
||||
description: 'True if image size exceeded fail-thresholds'
|
||||
value: ${{ steps.compare.outputs.failed }}
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Download manifests
|
||||
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
|
||||
with:
|
||||
pattern: manifests-*
|
||||
path: /tmp/manifests
|
||||
merge-multiple: true
|
||||
|
||||
- name: Measure image sizes from artifacts
|
||||
id: measure
|
||||
shell: bash
|
||||
env:
|
||||
PLATFORM: ${{ inputs.platform }}
|
||||
TAG: ${{ inputs.tag }}
|
||||
run: |
|
||||
echo "Reading image sizes from build artifacts for platform: $PLATFORM"
|
||||
|
||||
declare -A sizes
|
||||
declare -a services_list
|
||||
total=0
|
||||
|
||||
# Loop through service directories (same as publish workflow)
|
||||
shopt -s nullglob
|
||||
for service_dir in /tmp/manifests/*; do
|
||||
[[ -d "$service_dir" ]] || continue
|
||||
service="$(basename "$service_dir")"
|
||||
|
||||
echo "Processing service: $service"
|
||||
services_list+=("$service")
|
||||
|
||||
size=0
|
||||
# Read only the specified platform architecture
|
||||
manifest_file="$service_dir/$PLATFORM/manifest.json"
|
||||
if [[ -f "$manifest_file" ]]; then
|
||||
# docker manifest inspect -v puts the manifest under SchemaV2Manifest
|
||||
# (Docker schema2 images) or OCIManifest (OCI images, which buildx
|
||||
# produces by default). Coalesce so both formats are read.
|
||||
config_size=$(jq -r '(.SchemaV2Manifest // .OCIManifest).config.size // 0' "$manifest_file")
|
||||
layers_size=$(jq '[(.SchemaV2Manifest // .OCIManifest).layers[]?.size // 0] | add // 0' "$manifest_file")
|
||||
size=$((config_size + layers_size))
|
||||
|
||||
echo " → Found $manifest_file: $size bytes (config: $config_size, layers: $layers_size)"
|
||||
else
|
||||
echo " ⚠ Manifest not found for platform $PLATFORM: $manifest_file"
|
||||
fi
|
||||
|
||||
sizes[$service]=$size
|
||||
total=$((total + size))
|
||||
done
|
||||
|
||||
echo "Total size (all services, $PLATFORM only): $total bytes"
|
||||
echo "total-size=$total" >> $GITHUB_OUTPUT
|
||||
|
||||
# Save to JSON
|
||||
echo "{" > current-sizes.json
|
||||
echo " \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"," >> current-sizes.json
|
||||
echo " \"tag\": \"$TAG\"," >> current-sizes.json
|
||||
echo " \"total\": $total," >> current-sizes.json
|
||||
echo " \"services\": {" >> current-sizes.json
|
||||
|
||||
first=true
|
||||
for service in "${services_list[@]}"; do
|
||||
if [[ "$first" == "true" ]]; then
|
||||
first=false
|
||||
else
|
||||
echo "," >> current-sizes.json
|
||||
fi
|
||||
echo " \"$service\": ${sizes[$service]}" >> current-sizes.json
|
||||
done
|
||||
|
||||
echo " }" >> current-sizes.json
|
||||
echo "}" >> current-sizes.json
|
||||
|
||||
echo "Current sizes saved:"
|
||||
cat current-sizes.json
|
||||
|
||||
# Save services list for baseline measurement
|
||||
printf '%s\n' "${services_list[@]}" > /tmp/services-list.txt
|
||||
|
||||
- name: Measure baseline
|
||||
id: baseline
|
||||
shell: bash
|
||||
continue-on-error: true
|
||||
env:
|
||||
REGISTRY: ${{ inputs.registry }}
|
||||
ORG: ${{ inputs.repository }}
|
||||
TAG: ${{ inputs.baseline-tag }}
|
||||
PLATFORM: ${{ inputs.platform }}
|
||||
run: |
|
||||
echo "Measuring baseline: $REGISTRY/$ORG/*:$TAG (platform: $PLATFORM)"
|
||||
|
||||
declare -A sizes
|
||||
declare -a services_list
|
||||
total=0
|
||||
|
||||
# Read services list from current measurement
|
||||
while IFS= read -r service; do
|
||||
services_list+=("$service")
|
||||
|
||||
# Map service name to image name (handle rocketchat -> rocket.chat)
|
||||
if [[ "$service" == "rocketchat" ]] || [[ "$service" == "rocketchat-cov" ]]; then
|
||||
image_name="rocket.chat"
|
||||
[[ "$service" == "rocketchat-cov" ]] && image_name="rocket.chat-cov"
|
||||
else
|
||||
image_name="$service"
|
||||
fi
|
||||
|
||||
image="$REGISTRY/$ORG/$image_name:$TAG"
|
||||
echo " → Inspecting $image"
|
||||
|
||||
size=0
|
||||
if manifest=$(docker manifest inspect "$image" 2>/dev/null); then
|
||||
# Check if it's a manifest list (multi-arch)
|
||||
if echo "$manifest" | jq -e '.manifests' > /dev/null 2>&1; then
|
||||
# Manifest list - find the specified platform
|
||||
echo " → Multi-arch manifest detected, filtering for $PLATFORM"
|
||||
platform_digest=$(echo "$manifest" | jq -r --arg arch "$PLATFORM" '.manifests[] | select(.platform.architecture == $arch) | .digest' | head -1)
|
||||
|
||||
if [[ -n "$platform_digest" ]]; then
|
||||
echo " → Inspecting $PLATFORM platform: $platform_digest"
|
||||
if platform_manifest=$(docker manifest inspect "$REGISTRY/$ORG/$image_name@$platform_digest" 2>/dev/null); then
|
||||
config_size=$(echo "$platform_manifest" | jq -r '.config.size // 0')
|
||||
layers_size=$(echo "$platform_manifest" | jq '[.layers[]?.size // 0] | add // 0')
|
||||
size=$((config_size + layers_size))
|
||||
echo " → Size: $size bytes"
|
||||
fi
|
||||
else
|
||||
echo " ⚠ Platform $PLATFORM not found in manifest"
|
||||
fi
|
||||
else
|
||||
# Single arch manifest
|
||||
config_size=$(echo "$manifest" | jq -r '.config.size // 0')
|
||||
layers_size=$(echo "$manifest" | jq '[.layers[]?.size // 0] | add // 0')
|
||||
size=$((config_size + layers_size))
|
||||
fi
|
||||
fi
|
||||
|
||||
sizes[$service]=$size
|
||||
total=$((total + size))
|
||||
done < /tmp/services-list.txt
|
||||
|
||||
echo "baseline-total=$total" >> $GITHUB_OUTPUT
|
||||
|
||||
echo "{" > baseline-sizes.json
|
||||
echo " \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"," >> baseline-sizes.json
|
||||
echo " \"tag\": \"$TAG\"," >> baseline-sizes.json
|
||||
echo " \"total\": $total," >> baseline-sizes.json
|
||||
echo " \"services\": {" >> baseline-sizes.json
|
||||
|
||||
first=true
|
||||
for service in "${services_list[@]}"; do
|
||||
if [[ "$first" == "true" ]]; then
|
||||
first=false
|
||||
else
|
||||
echo "," >> baseline-sizes.json
|
||||
fi
|
||||
echo " \"$service\": ${sizes[$service]}" >> baseline-sizes.json
|
||||
done
|
||||
|
||||
echo " }" >> baseline-sizes.json
|
||||
echo "}" >> baseline-sizes.json
|
||||
|
||||
- name: Setup history storage
|
||||
id: history
|
||||
shell: bash
|
||||
run: |
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
# Create a separate worktree for history branch
|
||||
mkdir -p /tmp/history-worktree
|
||||
|
||||
# Try to fetch history branch
|
||||
if git ls-remote --heads origin image-size-history | grep -q image-size-history; then
|
||||
git fetch origin image-size-history
|
||||
git worktree add /tmp/history-worktree image-size-history
|
||||
else
|
||||
# Create orphan branch for history in worktree
|
||||
git worktree add --detach /tmp/history-worktree
|
||||
cd /tmp/history-worktree
|
||||
git checkout --orphan image-size-history
|
||||
git rm -rf . 2>/dev/null || true
|
||||
mkdir -p history
|
||||
echo "# Image Size History" > README.md
|
||||
echo "This branch stores historical image size data for tracking" >> README.md
|
||||
git add README.md
|
||||
git commit -m "Initialize image size history"
|
||||
git push origin image-size-history
|
||||
cd -
|
||||
fi
|
||||
|
||||
mkdir -p /tmp/history-worktree/history
|
||||
|
||||
- name: Load historical data
|
||||
shell: bash
|
||||
run: |
|
||||
# Load last 30 measurements and group by day (keep only last entry per day)
|
||||
echo "[]" > history-data.json
|
||||
if [[ -d /tmp/history-worktree/history ]]; then
|
||||
jq -s '.' /tmp/history-worktree/history/*.json 2>/dev/null | jq '
|
||||
sort_by(.timestamp) |
|
||||
group_by(.timestamp[0:10]) |
|
||||
map(.[-1]) |
|
||||
.[-30:]
|
||||
' > history-data.json || echo "[]" > history-data.json
|
||||
fi
|
||||
|
||||
count=$(jq 'length' history-data.json)
|
||||
echo "Loaded $count historical measurements (one per day)"
|
||||
|
||||
- name: Save current measurement to history
|
||||
if: github.ref == 'refs/heads/develop'
|
||||
shell: bash
|
||||
env:
|
||||
CI_PAT: ${{ inputs.ci-pat }}
|
||||
run: |
|
||||
timestamp=$(date -u +%Y%m%d-%H%M%S)
|
||||
commit_sha="${{ github.sha }}"
|
||||
|
||||
# Add commit info to current measurement
|
||||
jq --arg sha "$commit_sha" '. + {commit: $sha}' current-sizes.json > "/tmp/history-worktree/history/${timestamp}.json"
|
||||
|
||||
cd /tmp/history-worktree
|
||||
git add "history/${timestamp}.json"
|
||||
git commit -m "Add measurement for ${timestamp} (${commit_sha:0:7})"
|
||||
git config --global user.email "ci@rocket.chat"
|
||||
git config --global user.name "rocketchat-ci[bot]"
|
||||
git config --global url.https://$CI_PAT@github.com/.insteadOf https://github.com/
|
||||
git push origin image-size-history
|
||||
cd -
|
||||
|
||||
echo "Saved measurement to history"
|
||||
|
||||
- name: Compare and generate report
|
||||
id: compare
|
||||
shell: bash
|
||||
env:
|
||||
SIZE_THRESHOLDS: ${{ inputs.size-thresholds }}
|
||||
FAIL_THRESHOLDS: ${{ inputs.fail-thresholds }}
|
||||
TAG: ${{ inputs.tag }}
|
||||
BASELINE_TAG: ${{ inputs.baseline-tag }}
|
||||
run: |
|
||||
current_total=$(jq -r '.total' current-sizes.json)
|
||||
|
||||
if [[ ! -f baseline-sizes.json ]]; then
|
||||
echo "No baseline available"
|
||||
echo "size-diff=0" >> $GITHUB_OUTPUT
|
||||
echo "size-diff-percent=0" >> $GITHUB_OUTPUT
|
||||
echo "comment-triggered=false" >> $GITHUB_OUTPUT
|
||||
|
||||
cat > report.md << 'EOF'
|
||||
# 📦 Docker Image Size Report
|
||||
|
||||
**Status:** First measurement - no baseline for comparison
|
||||
|
||||
**Total Size:** $(numfmt --to=iec-i --suffix=B $current_total)
|
||||
EOF
|
||||
exit 0
|
||||
fi
|
||||
|
||||
baseline_total=$(jq -r '.total' baseline-sizes.json)
|
||||
diff=$((current_total - baseline_total))
|
||||
|
||||
if [[ $baseline_total -gt 0 ]]; then
|
||||
percent=$(awk "BEGIN {printf \"%.2f\", ($diff / $baseline_total) * 100}")
|
||||
else
|
||||
percent=0
|
||||
fi
|
||||
|
||||
echo "size-diff=$diff" >> $GITHUB_OUTPUT
|
||||
echo "size-diff-percent=$percent" >> $GITHUB_OUTPUT
|
||||
|
||||
# Only comment when size is bigger than baseline; optionally require per-image thresholds
|
||||
THRESHOLDS="$SIZE_THRESHOLDS"
|
||||
FAIL_THRESHOLDS="$FAIL_THRESHOLDS"
|
||||
comment_triggered=false
|
||||
fail_triggered=false
|
||||
if [[ $diff -gt 0 ]]; then
|
||||
if [[ -z "$THRESHOLDS" ]] || [[ "$THRESHOLDS" == "{}" ]]; then
|
||||
comment_triggered=true
|
||||
fi
|
||||
fi
|
||||
|
||||
color="gray"
|
||||
if (( $(awk "BEGIN {print ($percent > 0.01)}") )); then
|
||||
color="red"
|
||||
elif (( $(awk "BEGIN {print ($percent < -0.01)}") )); then
|
||||
color="green"
|
||||
fi
|
||||
|
||||
# Generate report
|
||||
if [[ $diff -gt 0 ]]; then
|
||||
emoji="📈"
|
||||
badge=""
|
||||
sign="+"
|
||||
elif [[ $diff -lt 0 ]]; then
|
||||
emoji="📉"
|
||||
badge=""
|
||||
sign="-"
|
||||
else
|
||||
emoji="➡️"
|
||||
badge=""
|
||||
sign=""
|
||||
fi
|
||||
|
||||
cat > report.md << EOF
|
||||
# 📦 Docker Image Size Report
|
||||
|
||||
## $emoji Changes $badge
|
||||
|
||||
| Service | Current | Baseline | Change | Percent |
|
||||
|---------|---------|----------|--------|---------|
|
||||
| **sum of all images** | **$(numfmt --to=iec-i --suffix=B $current_total)** | **$(numfmt --to=iec-i --suffix=B $baseline_total)** | **${sign}$(numfmt --to=iec-i --suffix=B ${diff#-})** | $badge |
|
||||
EOF
|
||||
|
||||
# Get services dynamically from current-sizes.json, sorted by size (largest first)
|
||||
for service in $(jq -r '.services | to_entries | sort_by(-.value) | .[].key' current-sizes.json); do
|
||||
current=$(jq -r ".services.\"$service\"" current-sizes.json)
|
||||
baseline=$(jq -r ".services.\"$service\" // 0" baseline-sizes.json)
|
||||
service_diff=$((current - baseline))
|
||||
|
||||
if [[ $baseline -gt 0 ]]; then
|
||||
service_percent=$(awk "BEGIN {printf \"%.2f\", ($service_diff / $baseline) * 100}")
|
||||
else
|
||||
service_percent=0
|
||||
fi
|
||||
|
||||
# Check per-image thresholds for comment trigger (only when size increased)
|
||||
if [[ $diff -gt 0 ]] && [[ -n "$THRESHOLDS" ]] && [[ "$THRESHOLDS" != "{}" ]]; then
|
||||
threshold_mb=$(echo "$THRESHOLDS" | jq -r ".\"$service\".mb // empty")
|
||||
threshold_pct=$(echo "$THRESHOLDS" | jq -r ".\"$service\".percent // empty")
|
||||
if [[ -n "$threshold_mb" ]] || [[ -n "$threshold_pct" ]]; then
|
||||
exceeded=false
|
||||
if [[ -n "$threshold_mb" ]] && [[ $service_diff -ge $(awk "BEGIN {printf \"%.0f\", $threshold_mb * 1048576}") ]]; then
|
||||
exceeded=true
|
||||
fi
|
||||
if [[ -n "$threshold_pct" ]] && [[ $service_percent != "0.00" ]] && (( $(awk "BEGIN {print ($service_percent >= $threshold_pct)}") )); then
|
||||
exceeded=true
|
||||
fi
|
||||
[[ "$exceeded" == "true" ]] && comment_triggered=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check per-image fail thresholds (task fails when exceeded)
|
||||
if [[ $diff -gt 0 ]] && [[ -n "$FAIL_THRESHOLDS" ]] && [[ "$FAIL_THRESHOLDS" != "{}" ]]; then
|
||||
fail_mb=$(echo "$FAIL_THRESHOLDS" | jq -r ".\"$service\".mb // empty")
|
||||
fail_pct=$(echo "$FAIL_THRESHOLDS" | jq -r ".\"$service\".percent // empty")
|
||||
if [[ -n "$fail_mb" ]] || [[ -n "$fail_pct" ]]; then
|
||||
exceeded=false
|
||||
if [[ -n "$fail_mb" ]] && [[ $service_diff -ge $(awk "BEGIN {printf \"%.0f\", $fail_mb * 1048576}") ]]; then
|
||||
exceeded=true
|
||||
fi
|
||||
if [[ -n "$fail_pct" ]] && [[ $service_percent != "0.00" ]] && (( $(awk "BEGIN {print ($service_percent >= $fail_pct)}") )); then
|
||||
exceeded=true
|
||||
fi
|
||||
[[ "$exceeded" == "true" ]] && fail_triggered=true
|
||||
fi
|
||||
fi
|
||||
|
||||
color="gray"
|
||||
if (( $(awk "BEGIN {print ($service_percent > 0.01)}") )); then
|
||||
color="red"
|
||||
elif (( $(awk "BEGIN {print ($service_percent < -0.01)}") )); then
|
||||
color="green"
|
||||
fi
|
||||
|
||||
if [[ $service_diff -gt 0 ]]; then
|
||||
badge=""
|
||||
sign="+"
|
||||
elif [[ $service_diff -lt 0 ]]; then
|
||||
badge=""
|
||||
sign="-"
|
||||
else
|
||||
badge=""
|
||||
sign=""
|
||||
fi
|
||||
|
||||
echo "| $service | $(numfmt --to=iec-i --suffix=B $current) | $(numfmt --to=iec-i --suffix=B $baseline) | ${sign}$(numfmt --to=iec-i --suffix=B ${service_diff#-}) | $badge |" >> report.md
|
||||
done
|
||||
|
||||
# Generate historical trend chart
|
||||
echo "" >> report.md
|
||||
echo "## 📊 Historical Trend" >> report.md
|
||||
echo "" >> report.md
|
||||
|
||||
# Load history and generate mermaid chart
|
||||
history_count=$(jq 'length' history-data.json)
|
||||
|
||||
if [[ $history_count -gt 0 ]]; then
|
||||
# Get all services from current build
|
||||
all_services=$(jq -r '.services | keys | .[]' current-sizes.json | sort)
|
||||
|
||||
# Generate Mermaid chart data
|
||||
x_labels=""
|
||||
declare -A service_data
|
||||
|
||||
# Initialize service data arrays
|
||||
for service in $all_services; do
|
||||
service_data[$service]=""
|
||||
done
|
||||
|
||||
# Process historical data
|
||||
while IFS= read -r line; do
|
||||
timestamp=$(echo "$line" | jq -r '.timestamp')
|
||||
date_label=$(date -d "$timestamp" +"%m/%d %H:%M")
|
||||
|
||||
if [[ -z "$x_labels" ]]; then
|
||||
x_labels="\"$date_label\""
|
||||
else
|
||||
x_labels="$x_labels, \"$date_label\""
|
||||
fi
|
||||
|
||||
# Add data point for each service
|
||||
for service in $all_services; do
|
||||
size=$(echo "$line" | jq -r ".services.\"$service\" // 0")
|
||||
size_gb=$(awk "BEGIN {printf \"%.2f\", $size / 1073741824}")
|
||||
|
||||
if [[ -z "${service_data[$service]}" ]]; then
|
||||
service_data[$service]="$size_gb"
|
||||
else
|
||||
service_data[$service]="${service_data[$service]}, $size_gb"
|
||||
fi
|
||||
done
|
||||
done < <(jq -c '.[]' history-data.json)
|
||||
|
||||
# Add current PR as last point
|
||||
current_date=$(date -u +"%m/%d %H:%M")
|
||||
x_labels="$x_labels, \"$current_date (PR)\""
|
||||
|
||||
for service in $all_services; do
|
||||
size=$(jq -r ".services.\"$service\" // 0" current-sizes.json)
|
||||
size_gb=$(awk "BEGIN {printf \"%.2f\", $size / 1073741824}")
|
||||
service_data[$service]="${service_data[$service]}, $size_gb"
|
||||
done
|
||||
|
||||
# Generate mermaid chart with multiple lines
|
||||
cat >> report.md << EOF
|
||||
\`\`\`mermaid
|
||||
---
|
||||
config:
|
||||
theme: "dark"
|
||||
xyChart:
|
||||
width: 900
|
||||
height: 400
|
||||
---
|
||||
xychart
|
||||
title "Image Size Evolution by Service (Last 30 Days + This PR)"
|
||||
x-axis [$x_labels]
|
||||
y-axis "Size (GB)" 0 --> 0.5
|
||||
EOF
|
||||
|
||||
# Add a line for each service
|
||||
for service in $all_services; do
|
||||
echo " line \"$service\" [${service_data[$service]}]" >> report.md
|
||||
done
|
||||
|
||||
cat >> report.md << 'EOF'
|
||||
```
|
||||
|
||||
EOF
|
||||
|
||||
# Add summary stats
|
||||
min_size=$(jq '[.[].total] | min' history-data.json)
|
||||
max_size=$(jq '[.[].total] | max' history-data.json)
|
||||
avg_size=$(jq '[.[].total] | add / length' history-data.json)
|
||||
|
||||
cat >> report.md << EOF
|
||||
**Statistics (last $history_count days):**
|
||||
- 📊 Average: $(numfmt --to=iec-i --suffix=B ${avg_size%.*})
|
||||
- ⬇️ Minimum: $(numfmt --to=iec-i --suffix=B $min_size)
|
||||
- ⬆️ Maximum: $(numfmt --to=iec-i --suffix=B $max_size)
|
||||
- 🎯 Current PR: $(numfmt --to=iec-i --suffix=B $current_total)
|
||||
|
||||
EOF
|
||||
|
||||
else
|
||||
cat >> report.md << 'EOF'
|
||||
*No historical data available yet. History tracking starts after merging to develop.*
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
cat >> report.md << EOF
|
||||
|
||||
<details>
|
||||
<summary>ℹ️ About this report</summary>
|
||||
|
||||
This report compares Docker image sizes from this build against the \`$BASELINE_TAG\` baseline.
|
||||
|
||||
- **Tag:** \`$TAG\`
|
||||
- **Baseline:** \`$BASELINE_TAG\`
|
||||
- **Timestamp:** $(date -u +"%Y-%m-%d %H:%M:%S UTC")
|
||||
- **Historical data points:** $history_count
|
||||
|
||||
</details>
|
||||
EOF
|
||||
|
||||
echo "comment-triggered=$comment_triggered" >> $GITHUB_OUTPUT
|
||||
echo "failed=$fail_triggered" >> $GITHUB_OUTPUT
|
||||
|
||||
if [[ "$fail_triggered" == "true" ]]; then
|
||||
echo "::error::Docker image size exceeded fail-thresholds (mb/percent). Check the report for details."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Add report to Job Summary
|
||||
if: always()
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ -f report.md ]]; then
|
||||
cat report.md >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
- name: Cleanup worktree
|
||||
if: always()
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ -d /tmp/history-worktree ]]; then
|
||||
git worktree remove /tmp/history-worktree --force 2>/dev/null || true
|
||||
fi
|
||||
|
||||
branding:
|
||||
icon: 'package'
|
||||
color: 'blue'
|
||||
218
.github/actions/meteor-build/action.yml
vendored
Normal file
218
.github/actions/meteor-build/action.yml
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
name: 'Meteor Build'
|
||||
description: 'Build Meteor bundle for production or coverage'
|
||||
|
||||
inputs:
|
||||
type:
|
||||
required: false
|
||||
description: 'production or coverage'
|
||||
default: 'production'
|
||||
reset-meteor:
|
||||
required: false
|
||||
description: 'Reset Meteor'
|
||||
node-version:
|
||||
required: true
|
||||
description: 'Node version'
|
||||
NPM_TOKEN:
|
||||
required: false
|
||||
description: 'NPM token'
|
||||
deno-version:
|
||||
required: true
|
||||
description: 'Deno version'
|
||||
source-hash:
|
||||
required: true
|
||||
description: 'RC cache id (e.g. packages-build-cache-key + meteor apps/meteor archive hash from CI)'
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
|
||||
steps:
|
||||
- name: Cache build
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
id: cache-build
|
||||
with:
|
||||
path: /tmp/Rocket.Chat.tar.gz
|
||||
key: ${{ runner.arch }}-${{ runner.os }}-${{ inputs.type }}-rc-build-${{ inputs.source-hash }}
|
||||
|
||||
- name: Set Swap Space
|
||||
uses: pierotofy/set-swap-space@49819abfb41bd9b44fb781159c033dba90353a7c # v1.0
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
with:
|
||||
swap-size-gb: 4
|
||||
|
||||
- name: Merge dependencies for build
|
||||
shell: bash
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
# Merge dependencies and devDependencies into a new 'dependencies' field
|
||||
cd apps/meteor
|
||||
cp package.json package.json.bak
|
||||
jq '.dependencies = (.dependencies + .devDependencies) | del(.devDependencies)' package.json > package.json.tmp && mv package.json.tmp package.json
|
||||
|
||||
- name: Setup NodeJS
|
||||
uses: ./.github/actions/setup-node
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
with:
|
||||
node-version: ${{ inputs.node-version }}
|
||||
deno-version: ${{ inputs.deno-version }}
|
||||
cache-modules: true
|
||||
install: true
|
||||
type: 'production'
|
||||
NPM_TOKEN: ${{ inputs.NPM_TOKEN }}
|
||||
|
||||
# - name: Free disk space
|
||||
# run: |
|
||||
# sudo apt clean
|
||||
# docker rmi $(docker image ls -aq)
|
||||
# df -h
|
||||
|
||||
- name: Cache vite
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
with:
|
||||
path: ./node_modules/.vite
|
||||
key: vite-local-cache-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('package.json') }}
|
||||
restore-keys: |
|
||||
vite-local-cache-${{ runner.arch }}-${{ runner.os }}-
|
||||
|
||||
- name: Cache meteor local
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
with:
|
||||
path: ./apps/meteor/.meteor/local
|
||||
key: meteor-local-cache-${{ runner.arch }}-${{ runner.os }}-${{ inputs.type }}-${{ hashFiles('apps/meteor/.meteor/versions') }}
|
||||
restore-keys: |
|
||||
meteor-local-cache-${{ runner.arch }}-${{ runner.os }}-${{ inputs.type }}-
|
||||
|
||||
- name: Cache meteor
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
with:
|
||||
path: ~/.meteor
|
||||
key: meteor-cache-${{ runner.arch }}-${{ runner.os }}-${{ inputs.type }}-${{ hashFiles('apps/meteor/.meteor/release') }}
|
||||
restore-keys: |
|
||||
meteor-cache-${{ runner.arch }}-${{ runner.os }}-${{ inputs.type }}-
|
||||
|
||||
- name: Install Meteor
|
||||
shell: bash
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
# Restore bin from cache
|
||||
set +e
|
||||
METEOR_SYMLINK_TARGET=$(readlink ~/.meteor/meteor)
|
||||
METEOR_TOOL_DIRECTORY=$(dirname "$METEOR_SYMLINK_TARGET")
|
||||
set -e
|
||||
LAUNCHER=$HOME/.meteor/$METEOR_TOOL_DIRECTORY/scripts/admin/launch-meteor
|
||||
if [ -e $LAUNCHER ]
|
||||
then
|
||||
echo "Cached Meteor bin found, restoring it"
|
||||
sudo cp "$LAUNCHER" "/usr/local/bin/meteor"
|
||||
else
|
||||
echo "No cached Meteor bin found."
|
||||
fi
|
||||
|
||||
# only install meteor if bin isn't found
|
||||
command -v meteor >/dev/null 2>&1 || curl https://install.meteor.com | sed s/--progress-bar/-sL/g | /bin/sh
|
||||
|
||||
- name: Versions
|
||||
shell: bash
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
npm --versions
|
||||
yarn -v
|
||||
node -v
|
||||
meteor --version
|
||||
meteor npm --versions
|
||||
meteor node -v
|
||||
git version
|
||||
|
||||
- uses: rharkor/caching-for-turbo@00a0515f175df9fd2e15c4560144ad5fdbebb0c7 # v2.3.13
|
||||
|
||||
- name: Reset Meteor
|
||||
shell: bash
|
||||
if: ${{ steps.cache-build.outputs.cache-hit != 'true' && inputs.reset-meteor == 'true' }}
|
||||
working-directory: ./apps/meteor
|
||||
run: meteor reset
|
||||
|
||||
- name: Restore packages build
|
||||
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
|
||||
with:
|
||||
name: packages-build
|
||||
path: /tmp
|
||||
|
||||
- name: Unpack packages build
|
||||
shell: bash
|
||||
run: |
|
||||
tar -xzf /tmp/RocketChat-packages-build.tar.gz -C .
|
||||
|
||||
- name: Build Rocket.Chat
|
||||
shell: bash
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
env:
|
||||
METEOR_PROFILE: 1000
|
||||
BABEL_ENV: ${{ inputs.type }}
|
||||
run: |
|
||||
# check if BABEL_ENV is set to coverage
|
||||
if [[ $BABEL_ENV == "coverage" ]]; then
|
||||
echo -e "rocketchat:coverage\n" >> ./apps/meteor/.meteor/packages
|
||||
# Inject swc-plugin-coverage-instrument into .swcrc for istanbul-compatible coverage
|
||||
node -e "
|
||||
const fs = require('fs');
|
||||
const swcrc = JSON.parse(fs.readFileSync('./apps/meteor/.swcrc', 'utf8'));
|
||||
swcrc.jsc.experimental = swcrc.jsc.experimental || {};
|
||||
swcrc.jsc.experimental.plugins = swcrc.jsc.experimental.plugins || [];
|
||||
swcrc.jsc.experimental.plugins.push(['swc-plugin-coverage-instrument', {}]);
|
||||
fs.writeFileSync('./apps/meteor/.swcrc', JSON.stringify(swcrc, null, 2) + '\n');
|
||||
"
|
||||
echo "Coverage enabled (SWC istanbul plugin injected)"
|
||||
fi
|
||||
|
||||
# Restore original package.json so meteor should not copy devDependencies
|
||||
mv apps/meteor/package.json.bak apps/meteor/package.json
|
||||
|
||||
yarn build:ci
|
||||
|
||||
declare -a meter_modules_to_remove=(
|
||||
"meteor/babel-compiler/node_modules/@meteorjs/swc-core/.swc/node_modules/@swc/core-darwin-arm64" # Removes 35M
|
||||
"meteor/babel-compiler/node_modules/@meteorjs/swc-core/.swc/node_modules/@swc/core-linux-x64-musl" # Removes 58M
|
||||
"meteor/babel-compiler/node_modules/@meteorjs/swc-core/.swc/node_modules/@swc/core-linux-arm64-musl" # Removes 44M
|
||||
"meteor/babel-compiler/node_modules/typescript" # Removes 31M
|
||||
# "meteor/babel-compiler/node_modules/@babel" # Removes 14M
|
||||
|
||||
"@rocket.chat/i18n/src" # Removes 16M
|
||||
"typescript" # Removes 19M
|
||||
# "@babel" # Removes 34M - Needed by Minimongo
|
||||
)
|
||||
|
||||
du -s /tmp/dist/bundle
|
||||
|
||||
for dir_path in "${meter_modules_to_remove[@]}"; do
|
||||
path=/tmp/dist/bundle/programs/server/npm/node_modules/${dir_path}
|
||||
|
||||
if [ -d "$path" ]; then
|
||||
rm -rf "$path"
|
||||
|
||||
echo "Removed directory: $path"
|
||||
else
|
||||
echo "Path is not a directory or does not exist: $path"
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove all .d.ts files from node_modules to reduce size
|
||||
# Removes 184M
|
||||
find /tmp/dist/bundle -type f -name "*.d.ts" -delete
|
||||
du -s /tmp/dist/bundle
|
||||
|
||||
- name: Prepare build
|
||||
shell: bash
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
cd /tmp/dist
|
||||
tar czf /tmp/Rocket.Chat.tar.gz bundle
|
||||
|
||||
- name: Store build
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: build-${{ inputs.type }}
|
||||
path: /tmp/Rocket.Chat.tar.gz
|
||||
overwrite: true
|
||||
include-hidden-files: true
|
||||
16
.github/actions/restore-packages/action.yml
vendored
Normal file
16
.github/actions/restore-packages/action.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
name: 'Restore Packages Build'
|
||||
description: 'Downloads and unpacks the packages build artifact'
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Restore packages build
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: packages-build
|
||||
path: /tmp
|
||||
|
||||
- name: Unpack packages build
|
||||
shell: bash
|
||||
run: |
|
||||
tar -xzf /tmp/RocketChat-packages-build.tar.gz -C .
|
||||
120
.github/actions/setup-node/action.yml
vendored
Normal file
120
.github/actions/setup-node/action.yml
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
name: 'Setup Node'
|
||||
description: 'Setup NodeJS'
|
||||
|
||||
inputs:
|
||||
node-version:
|
||||
required: false
|
||||
description: 'Node version. If not provided, read from package.json volta.node'
|
||||
cache-modules:
|
||||
required: false
|
||||
description: 'Cache node_modules'
|
||||
install:
|
||||
required: false
|
||||
description: 'Install dependencies'
|
||||
type:
|
||||
required: false
|
||||
description: 'development or production'
|
||||
default: 'development'
|
||||
deno-version:
|
||||
required: false
|
||||
description: 'Deno version. If not provided, read from .tool-versions'
|
||||
NPM_TOKEN:
|
||||
required: false
|
||||
description: 'NPM token'
|
||||
HARDENED_MODE:
|
||||
required: false
|
||||
description: 'Hardened mode'
|
||||
default: '0'
|
||||
|
||||
outputs:
|
||||
node-version:
|
||||
description: 'Node version'
|
||||
value: ${{ steps.node-version.outputs.node-version }}
|
||||
cache-deno-hit:
|
||||
description: 'Exact key hit for Deno cache'
|
||||
value: ${{ steps.cache-deno.outputs.cache-hit }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
|
||||
steps:
|
||||
- name: Resolve tool versions
|
||||
shell: bash
|
||||
run: |
|
||||
NODE_VERSION="${{ inputs.node-version }}"
|
||||
if [ -z "$NODE_VERSION" ]; then
|
||||
NODE_VERSION=$(node -p "require('./package.json').volta.node")
|
||||
fi
|
||||
echo "NODE_VERSION: ${NODE_VERSION}"
|
||||
echo "NODE_VERSION=${NODE_VERSION}" >> $GITHUB_ENV
|
||||
|
||||
DENO_VERSION="${{ inputs.deno-version }}"
|
||||
if [ -z "$DENO_VERSION" ]; then
|
||||
DENO_VERSION=$(awk '$1=="deno"{ print $2 }' .tool-versions)
|
||||
fi
|
||||
echo "DENO_VERSION: ${DENO_VERSION}"
|
||||
echo "DENO_VERSION=${DENO_VERSION}" >> $GITHUB_ENV
|
||||
|
||||
# Turbo local cache: use rharkor/caching-for-turbo in workflows — not stored here to avoid huge redundant keys.
|
||||
- name: Cache Deno (apps)
|
||||
if: inputs.cache-modules
|
||||
id: cache-deno
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
with:
|
||||
path: packages/apps/.deno-cache
|
||||
key: deno-${{ runner.os }}-${{ runner.arch }}-v${{ env.DENO_VERSION }}-${{ hashFiles('packages/apps/deno-runtime/deno.lock') }}
|
||||
restore-keys: |
|
||||
deno-${{ runner.os }}-${{ runner.arch }}-v${{ env.DENO_VERSION }}-
|
||||
|
||||
- name: Use Node.js ${{ env.NODE_VERSION }}
|
||||
id: node-version
|
||||
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: ${{ inputs.cache-modules && 'yarn' || '' }}
|
||||
|
||||
- name: Use Deno ${{ env.DENO_VERSION }}
|
||||
uses: denoland/setup-deno@667a34cdef165d8d2b2e98dde39547c9daac7282 # v2.0.4
|
||||
with:
|
||||
deno-version: ${{ env.DENO_VERSION }}
|
||||
|
||||
- name: Cache mongodb-memory-server binary
|
||||
if: inputs.cache-modules
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
with:
|
||||
path: ${{ runner.temp }}/mongodb-memory-server
|
||||
key: mongoms-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
|
||||
- name: Configure mongodb-memory-server cache
|
||||
shell: bash
|
||||
run: |
|
||||
CACHE_DIR="${{ runner.temp }}/mongodb-memory-server"
|
||||
echo "MONGOMS_DOWNLOAD_DIR=$CACHE_DIR" >> $GITHUB_ENV
|
||||
echo "MONGOMS_PREFER_GLOBAL_PATH=false" >> $GITHUB_ENV
|
||||
|
||||
- name: yarn login
|
||||
shell: bash
|
||||
if: inputs.NPM_TOKEN
|
||||
run: |
|
||||
echo "//registry.npmjs.org/:_authToken=${{ inputs.NPM_TOKEN }}" > ~/.npmrc
|
||||
|
||||
- name: yarn config
|
||||
if: inputs.install
|
||||
shell: bash
|
||||
run: |
|
||||
yarn config set supportedArchitectures --json '{"os": ["linux"], "cpu": ["arm64", "x64"], "libc": ["glibc", "musl"]}'
|
||||
|
||||
- name: yarn install
|
||||
if: inputs.install && inputs.type == 'development'
|
||||
shell: bash
|
||||
run: YARN_ENABLE_HARDENED_MODE=${{ inputs.HARDENED_MODE }} yarn
|
||||
|
||||
- name: yarn install production
|
||||
if: inputs.install && inputs.type == 'production'
|
||||
shell: bash
|
||||
run: YARN_ENABLE_HARDENED_MODE=${{ inputs.HARDENED_MODE }} yarn workspaces focus --all --production
|
||||
|
||||
- name: restore yarn config file
|
||||
if: inputs.install
|
||||
shell: bash
|
||||
run: git checkout -- .yarnrc.yml
|
||||
21
.github/actions/setup-playwright/action.yml
vendored
Normal file
21
.github/actions/setup-playwright/action.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
name: Setup Playwright
|
||||
description: 'Setup Playwright binaries and dependencies'
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
|
||||
steps:
|
||||
- name: Cache Playwright binaries
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
id: cache-playwright
|
||||
with:
|
||||
path: |
|
||||
~/.cache/ms-playwright
|
||||
# This is the version of Playwright that we are using, if you are willing to upgrade, you should update this.
|
||||
key: playwright-${{ runner.arch }}-${{ runner.os }}-1.52.0
|
||||
|
||||
- name: Install Playwright
|
||||
shell: bash
|
||||
if: steps.cache-playwright.outputs.cache-hit != 'true'
|
||||
working-directory: .
|
||||
run: npx playwright install --with-deps
|
||||
26
.github/actions/update-version-durability/action.yml
vendored
Normal file
26
.github/actions/update-version-durability/action.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
name: Update Version Durability
|
||||
description: Update Version Durability page on Document360
|
||||
|
||||
inputs:
|
||||
LTS_VERSIONS:
|
||||
required: true
|
||||
description: Comma separated list of LTS versions
|
||||
GH_TOKEN:
|
||||
required: true
|
||||
description: GitHub API Token
|
||||
D360_TOKEN:
|
||||
required: true
|
||||
description: Document360 API Token
|
||||
D360_ARTICLE_ID:
|
||||
required: true
|
||||
description: Document360 Article ID
|
||||
D360_USER_ID:
|
||||
required: true
|
||||
description: Document360 User ID used to fork and publish the article
|
||||
PUBLISH:
|
||||
required: true
|
||||
description: Publish Draft
|
||||
|
||||
runs:
|
||||
using: node20
|
||||
main: index.js
|
||||
228
.github/actions/update-version-durability/index.js
vendored
Normal file
228
.github/actions/update-version-durability/index.js
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
import 'colors';
|
||||
import axios from 'axios';
|
||||
import * as Diff from 'diff';
|
||||
import semver from 'semver';
|
||||
import crypto from 'crypto';
|
||||
import fs from 'fs/promises';
|
||||
import BeautyHtml from 'beauty-html';
|
||||
import { DOMParser } from '@xmldom/xmldom';
|
||||
import core from '@actions/core';
|
||||
import { Octokit } from '@octokit/rest';
|
||||
|
||||
const D360_TOKEN = core.getInput('D360_TOKEN');
|
||||
const D360_ARTICLE_ID = core.getInput('D360_ARTICLE_ID');
|
||||
const D360_USER_ID = core.getInput('D360_USER_ID');
|
||||
const PUBLISH = core.getInput('PUBLISH') === 'true';
|
||||
const LTS_VERSIONS = (core.getInput('LTS_VERSIONS') || '7.10').split(',').map((v) => v.trim());
|
||||
|
||||
const octokit = new Octokit({
|
||||
auth: core.getInput('GH_TOKEN'),
|
||||
});
|
||||
|
||||
|
||||
async function requestDocument360(method = 'get', api, data = {}) {
|
||||
return axios.request({
|
||||
method,
|
||||
maxBodyLength: Infinity,
|
||||
url: `https://apihub.us.document360.io/v1/${api}`,
|
||||
headers: {
|
||||
'accept': 'application/json',
|
||||
'api_token': D360_TOKEN,
|
||||
},
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
function md5(text) {
|
||||
return crypto.createHash('md5').update(text).digest("hex");
|
||||
}
|
||||
|
||||
async function generateTable({ owner, repo } = {}) {
|
||||
const response = await requestDocument360('get', `Articles/${D360_ARTICLE_ID}/en`);
|
||||
|
||||
// console.log(response.data.data);
|
||||
|
||||
// const releasesResult = JSON.parse(await fs.readFile('/tmp/releasesResult'));
|
||||
const releasesResult = await octokit.paginate(octokit.repos.listReleases.endpoint.merge({ owner, repo, per_page: 100 }));
|
||||
// await fs.writeFile('/tmp/releasesResult', JSON.stringify(releasesResult));
|
||||
|
||||
const releases = releasesResult
|
||||
.filter((release) => !release.tag_name.includes('-rc') && semver.gte(release.tag_name, '1.0.0'))
|
||||
.sort((a, b) => semver.compare(b.tag_name, a.tag_name));
|
||||
|
||||
const releasesMap = {};
|
||||
|
||||
for (const release of releases) {
|
||||
release.releaseDate = new Date(release.published_at);
|
||||
|
||||
releasesMap[release.tag_name] = release;
|
||||
}
|
||||
|
||||
let index = 0;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
const release = releases[index];
|
||||
|
||||
release.minor_tag = release.tag_name.replace(/\.\d+$/, '');
|
||||
release.minorRelease = releasesMap[`${release.minor_tag}.0`];
|
||||
|
||||
if (!releases[index + 1]) {
|
||||
break;
|
||||
}
|
||||
|
||||
const currentVersion = semver.parse(release.tag_name);
|
||||
const previousVersion = semver.parse(releases[index + 1].tag_name);
|
||||
|
||||
releases[index + 1].nextRelease = release;
|
||||
|
||||
// Remove duplicated due to patches
|
||||
if (currentVersion.major === previousVersion.major && currentVersion.minor === previousVersion.minor) {
|
||||
releases.splice(index + 1, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Mark LTS
|
||||
if (LTS_VERSIONS.includes(`${currentVersion.major}.${currentVersion.minor}`)) {
|
||||
release.lts = true;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
releases[0].last = true;
|
||||
|
||||
const releaseData = [];
|
||||
|
||||
for (const { tag_name, html_url, lts, last, nextRelease, minorRelease, minor_tag} of releases) {
|
||||
let supportDate;
|
||||
let supportDateStart;
|
||||
|
||||
let releasedAt = new Date(minorRelease.releaseDate);
|
||||
releasedAt.setDate(1);
|
||||
|
||||
let minorDate = new Date(minorRelease.releaseDate);
|
||||
minorDate.setDate(1);
|
||||
supportDateStart = minorDate;
|
||||
supportDate = new Date(minorDate);
|
||||
supportDate.setMonth(supportDate.getMonth() + (lts ? 12 : 6));
|
||||
|
||||
releaseData.push({
|
||||
release: {
|
||||
version: minor_tag,
|
||||
releasedAt,
|
||||
extendedSupport: {
|
||||
start: supportDateStart,
|
||||
end: supportDate,
|
||||
},
|
||||
lts: lts === true,
|
||||
},
|
||||
latestPatch: {
|
||||
version: tag_name,
|
||||
url: html_url,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function header({data, salt = ''}) {
|
||||
return [
|
||||
'<th colspan="1" data-vertical-align="middle" data-horizontal-align="left" rowspan="1" style="vertical-align:middle;text-align:left;">',
|
||||
`<p data-block-id="${md5(salt+data)}">${data}</p>`,
|
||||
'</th>',
|
||||
].join('');
|
||||
}
|
||||
|
||||
function line({data, salt = ''}) {
|
||||
return [
|
||||
'<td colspan="1" rowspan="1" data-vertical-align="middle" data-horizontal-align="left" style="vertical-align:middle;text-align:left;">',
|
||||
`<p data-block-id="${md5(salt+data)}">${data}</p>`,
|
||||
'</td>',
|
||||
].join('');
|
||||
}
|
||||
|
||||
const text = [
|
||||
'<tr>',
|
||||
header({data: 'Rocket.Chat Release'}),
|
||||
header({data: 'Released At'}),
|
||||
header({data: 'End of Life'}),
|
||||
'</tr>',
|
||||
];
|
||||
|
||||
releaseData.forEach(({release, latestPatch}) => {
|
||||
const releasedAt = release.releasedAt.toLocaleString('en', { month: 'short', year: "numeric" });
|
||||
const endOfLife = !release.extendedSupport
|
||||
? 'TBD'
|
||||
: release.extendedSupport.end.toLocaleString('en', { month: 'short', year: "numeric" });
|
||||
const link = `${release.version}${release.lts ? " LTS" : ""} (<a href="${latestPatch.url}" target="_blank" translate="no">${latestPatch.version}</a>)`;
|
||||
|
||||
text.push(
|
||||
'<tr>',
|
||||
line({data: link}),
|
||||
line({data: releasedAt, salt: release.version}),
|
||||
line({data: endOfLife, salt: release.version}),
|
||||
'</tr>',
|
||||
);
|
||||
});
|
||||
|
||||
const content = response.data.data.html_content.replace(/<tbody>.+(\n.+)*<\/tbody>/m, `<tbody>${text.join('').replace(/\t|\n/g, '')}</tbody>`)
|
||||
|
||||
// console.log(content);
|
||||
|
||||
const parser = new BeautyHtml({ parser: DOMParser });
|
||||
const diff = Diff.diffLines(parser.beautify(response.data.data.html_content), parser.beautify(content), { ignoreWhitespace: true, newlineIsToken: false });
|
||||
diff.forEach((item) => {
|
||||
let color = 'green';
|
||||
|
||||
if (item.removed) {
|
||||
color = 'red';
|
||||
}
|
||||
|
||||
if (item.removed || item.added) {
|
||||
item.value.split('\n').forEach((line) => {
|
||||
if (line === '') { return };
|
||||
console.log(`${item.removed ? '-' : '+'} ${line}`[color]);
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
if (diff.length === 1) {
|
||||
console.log('No changes found');
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.data.data.status === 3) {
|
||||
console.log('forking article', response.data.data.version_number);
|
||||
|
||||
const forkResponse = await requestDocument360('put', `Articles/${D360_ARTICLE_ID}/fork`, {
|
||||
lang_code: "en",
|
||||
user_id: D360_USER_ID,
|
||||
version_number: response.data.data.version_number,
|
||||
});
|
||||
|
||||
console.log(forkResponse.data);
|
||||
|
||||
if (!forkResponse.data.success) {
|
||||
throw new Error(`Failed to fork article: ${JSON.stringify(forkResponse.data.errors)}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Updating article');
|
||||
const updateResponse = await requestDocument360('put', `Articles/${D360_ARTICLE_ID}/en`, {
|
||||
content,
|
||||
});
|
||||
|
||||
console.log(updateResponse.data);
|
||||
|
||||
if (PUBLISH) {
|
||||
console.log('publishing article', updateResponse.data.data.version_number);
|
||||
|
||||
const forkResponse = await requestDocument360('post', `Articles/${D360_ARTICLE_ID}/en/publish`, {
|
||||
user_id: D360_USER_ID,
|
||||
version_number: updateResponse.data.data.version_number,
|
||||
publish_message: 'Update support versions table via GitHub Action',
|
||||
});
|
||||
|
||||
console.log(forkResponse.data);
|
||||
}
|
||||
}
|
||||
|
||||
generateTable({ owner: 'RocketChat', repo: 'Rocket.Chat' });
|
||||
717
.github/actions/update-version-durability/package-lock.json
generated
vendored
Normal file
717
.github/actions/update-version-durability/package-lock.json
generated
vendored
Normal file
@@ -0,0 +1,717 @@
|
||||
{
|
||||
"name": "scripts",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "scripts",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.1",
|
||||
"@octokit/rest": "^21.0.2",
|
||||
"@xmldom/xmldom": "^0.8.15",
|
||||
"axios": "^1.18.1",
|
||||
"beauty-html": "^1.3.1",
|
||||
"colors": "^1.4.0",
|
||||
"diff": "^5.1.0",
|
||||
"semver": "^7.5.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/core": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz",
|
||||
"integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/http-client": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/exec": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
|
||||
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/io": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/http-client": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.1.tgz",
|
||||
"integrity": "sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==",
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6",
|
||||
"undici": "^5.25.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/io": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
|
||||
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/auth-token": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.1.tgz",
|
||||
"integrity": "sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/core": {
|
||||
"version": "6.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.6.tgz",
|
||||
"integrity": "sha512-kIU8SLQkYWGp3pVKiYzA5OSaNF5EE03P/R8zEmmrG6XwOg5oBjXyQVVIauQ0dgau4zYhpZEhJrvIYt6oM+zZZA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^5.0.0",
|
||||
"@octokit/graphql": "^8.2.2",
|
||||
"@octokit/request": "^9.2.3",
|
||||
"@octokit/request-error": "^6.1.8",
|
||||
"@octokit/types": "^14.0.0",
|
||||
"before-after-hook": "^3.0.2",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/core/node_modules/@octokit/openapi-types": {
|
||||
"version": "25.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz",
|
||||
"integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/core/node_modules/@octokit/types": {
|
||||
"version": "14.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz",
|
||||
"integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^25.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/endpoint": {
|
||||
"version": "10.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.4.tgz",
|
||||
"integrity": "sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^14.0.0",
|
||||
"universal-user-agent": "^7.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": {
|
||||
"version": "25.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz",
|
||||
"integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/endpoint/node_modules/@octokit/types": {
|
||||
"version": "14.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz",
|
||||
"integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^25.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql": {
|
||||
"version": "8.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.2.tgz",
|
||||
"integrity": "sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/request": "^9.2.3",
|
||||
"@octokit/types": "^14.0.0",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": {
|
||||
"version": "25.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz",
|
||||
"integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/graphql/node_modules/@octokit/types": {
|
||||
"version": "14.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz",
|
||||
"integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^25.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/openapi-types": {
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest": {
|
||||
"version": "11.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.4.2.tgz",
|
||||
"integrity": "sha512-BXJ7XPCTDXFF+wxcg/zscfgw2O/iDPtNSkwwR1W1W5c4Mb3zav/M2XvxQ23nVmKj7jpweB4g8viMeCQdm7LMVA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^13.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-request-log": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz",
|
||||
"integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "13.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.5.0.tgz",
|
||||
"integrity": "sha512-9Pas60Iv9ejO3WlAX3maE1+38c5nqbJXV5GrncEfkndIpZrJ/WPMRd2xYDcPPEt5yzpxcjw9fWNoPhsSGzqKqw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^13.10.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": {
|
||||
"version": "24.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
|
||||
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": {
|
||||
"version": "13.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
|
||||
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^24.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request": {
|
||||
"version": "9.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.4.tgz",
|
||||
"integrity": "sha512-q8ybdytBmxa6KogWlNa818r0k1wlqzNC+yNkcQDECHvQo8Vmstrg18JwqJHdJdUiHD2sjlwBgSm9kHkOKe2iyA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/endpoint": "^10.1.4",
|
||||
"@octokit/request-error": "^6.1.8",
|
||||
"@octokit/types": "^14.0.0",
|
||||
"fast-content-type-parse": "^2.0.0",
|
||||
"universal-user-agent": "^7.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request-error": {
|
||||
"version": "6.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.8.tgz",
|
||||
"integrity": "sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^14.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": {
|
||||
"version": "25.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz",
|
||||
"integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/request-error/node_modules/@octokit/types": {
|
||||
"version": "14.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz",
|
||||
"integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^25.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request/node_modules/@octokit/openapi-types": {
|
||||
"version": "25.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz",
|
||||
"integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/request/node_modules/@octokit/types": {
|
||||
"version": "14.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz",
|
||||
"integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^25.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.1.1.tgz",
|
||||
"integrity": "sha512-sTQV7va0IUVZcntzy1q3QqPm/r8rWtDCqpRAmb8eXXnKkjoQEtFe3Nt5GTVsHft+R6jJoHeSiVLcgcvhtue/rg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/core": "^6.1.4",
|
||||
"@octokit/plugin-paginate-rest": "^11.4.2",
|
||||
"@octokit/plugin-request-log": "^5.3.1",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^13.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/types": {
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@xmldom/xmldom": {
|
||||
"version": "0.8.15",
|
||||
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.15.tgz",
|
||||
"integrity": "sha512-/5NV/vDALVFDXgLmfsy9TRCBlKwO2LNBFzpzvb9iIj+jR+eSc6DLYYvVOdivT/jm7MtU6TebYuRmzEOI7w40UA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.18.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz",
|
||||
"integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.16.0",
|
||||
"form-data": "^4.0.5",
|
||||
"https-proxy-agent": "^5.0.1",
|
||||
"proxy-from-env": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/beauty-html": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/beauty-html/-/beauty-html-1.3.1.tgz",
|
||||
"integrity": "sha512-c0iKWc527T2MQcYhIMMw9OHN8kcXSf/ijadWzURhZWi6e6cnBXxAQ5IlXbYd0YZJE9lFtXRB1fJVQrvJf5DmPQ=="
|
||||
},
|
||||
"node_modules/before-after-hook": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz",
|
||||
"integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A=="
|
||||
},
|
||||
"node_modules/call-bind-apply-helpers": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/colors": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
|
||||
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
|
||||
"engines": {
|
||||
"node": ">=0.1.90"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz",
|
||||
"integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==",
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-errors": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-object-atoms": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-set-tostringtag": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"get-intrinsic": "^1.2.6",
|
||||
"has-tostringtag": "^1.0.2",
|
||||
"hasown": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-content-type-parse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz",
|
||||
"integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
|
||||
"integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
|
||||
"integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"hasown": "^2.0.4",
|
||||
"mime-types": "^2.1.35"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"es-define-property": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"es-object-atoms": "^1.1.1",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-proto": "^1.0.1",
|
||||
"gopd": "^1.2.0",
|
||||
"has-symbols": "^1.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"math-intrinsics": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dunder-proto": "^1.0.1",
|
||||
"es-object-atoms": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/gopd": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-symbols": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-tostringtag": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-symbols": "^1.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
|
||||
"integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/https-proxy-agent": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/math-intrinsics": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
|
||||
"integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.6.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
|
||||
"integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/tunnel": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
||||
"engines": {
|
||||
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "6.28.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz",
|
||||
"integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.17"
|
||||
}
|
||||
},
|
||||
"node_modules/universal-user-agent": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz",
|
||||
"integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==",
|
||||
"license": "ISC"
|
||||
}
|
||||
}
|
||||
}
|
||||
24
.github/actions/update-version-durability/package.json
vendored
Normal file
24
.github/actions/update-version-durability/package.json
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "scripts",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"description": "",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.1",
|
||||
"@octokit/rest": "^21.0.2",
|
||||
"axios": "^1.18.1",
|
||||
"beauty-html": "^1.3.1",
|
||||
"colors": "^1.4.0",
|
||||
"diff": "^5.1.0",
|
||||
"semver": "^7.5.4",
|
||||
"@xmldom/xmldom": "^0.8.15"
|
||||
},
|
||||
"overrides": {
|
||||
"undici": "6.28.0"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user