Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
06a3a62
Implement
sf-tyler-jeong Apr 1, 2026
dc367f4
chore: migrate npm publish to OIDC trusted publishing
sf-tyler-jeong Apr 2, 2026
bc43850
fix warnings
sf-tyler-jeong Apr 2, 2026
eeae3ce
ci: add test step to release workflow before npm publish
sf-tyler-jeong Apr 2, 2026
79eb576
ci: add workflow for manual Node 24 build and test verification
sf-tyler-jeong Apr 2, 2026
0fd80e7
ci: update build-and-test workflow to Node 24 with latest actions
sf-tyler-jeong Apr 2, 2026
123b89a
fix: replace deprecated import assert with import with in rollup config
sf-tyler-jeong Apr 2, 2026
cd7aa3f
ci: handle unhandled rejection in test step for Node 24 compatibility
sf-tyler-jeong Apr 2, 2026
7edf6bb
test: mock global fetch in jest setup for Node 24 native fetch compat…
sf-tyler-jeong Apr 2, 2026
dd163ea
ci: change coverage workflow to manual trigger and update actions
sf-tyler-jeong Apr 2, 2026
23c388e
ci: add lint step and align test options with build-and-test workflow
sf-tyler-jeong Apr 2, 2026
f6bfeb4
fix: prevent shell injection in package-publish npm_tag input
sf-tyler-jeong Apr 2, 2026
13b9bf8
fix: resolve shell injection and env context warnings in package-publish
sf-tyler-jeong Apr 2, 2026
641124c
chore: fix missing comma and use single quotes in jest config
sf-tyler-jeong Apr 2, 2026
c860537
ci: switch coverage to manual trigger with original config as comments
sf-tyler-jeong Apr 2, 2026
21ee9f4
ci: add JUnit reporter, failed test retry script, and reorder release…
sf-tyler-jeong Apr 6, 2026
7ee3365
fix: use env vars instead of expression interpolation in release work…
sf-tyler-jeong Apr 7, 2026
bfdf72b
fix: correct python package check and add contents write permission i…
sf-tyler-jeong Apr 7, 2026
dbf4b11
fix: rebuild dist after merge and enable file attribute in jest-junit
sf-tyler-jeong Apr 16, 2026
1c5a2b7
ci: automate CHANGELOG.md updates and finalize release date
sf-tyler-jeong Apr 28, 2026
0641a48
ci: remove skip-template check from prepare-changelog
sf-tyler-jeong Apr 28, 2026
90de97a
ci: harden release workflows after code review
sf-tyler-jeong Apr 28, 2026
8734311
ci: add CHANGELOG_DRAFT.md freshness check to release workflow
sf-tyler-jeong Apr 28, 2026
25cd4d9
ci: detect template-only CHANGELOG_DRAFT.md as a release blocker
sf-tyler-jeong Apr 28, 2026
b752694
ci: validate release branch and wait for checks before merge
sf-tyler-jeong Apr 28, 2026
e3ad381
ci: sleep before gh pr checks --watch to avoid race
sf-tyler-jeong Apr 28, 2026
4859cfb
ci: migrate package-publish to OIDC trusted publishing
sf-tyler-jeong Apr 28, 2026
f42aa34
ci: unify permissions.contents to write across publish workflows
sf-tyler-jeong Apr 28, 2026
a1299d3
ci: fix Node version and repository URL for npm OIDC publish
sf-tyler-jeong Apr 28, 2026
5c54bd4
docs(ci): note npm Trusted Publisher swap for manual publish workflow
sf-tyler-jeong Apr 28, 2026
7658017
docs: remove obsolete RELEASE_GUIDE.md from public repo
sf-tyler-jeong Apr 28, 2026
63f0480
ci: enforce dispatch ref matches version input in package-publish
sf-tyler-jeong Apr 28, 2026
9525cdd
ci: use yarn install --immutable in package-publish
sf-tyler-jeong Apr 28, 2026
8c3d75f
ci: prevent prerelease publish to latest and orphan tag_suffix
sf-tyler-jeong Apr 28, 2026
6b93459
ci: tighten input validation to forbid prerelease in version and npm_…
sf-tyler-jeong Apr 28, 2026
a4b9d66
ci: align npm_tag/tag_suffix regex with semver prerelease identifier set
sf-tyler-jeong Apr 28, 2026
852cb3e
ci: enforce dot-separated semver prerelease form for npm_tag/tag_suffix
sf-tyler-jeong Apr 28, 2026
52f39e2
ci: tighten semver validation, empty-draft, and junit parser
sf-tyler-jeong Apr 28, 2026
4c50a76
ci: reject npm_tag starting with digit or v/V
sf-tyler-jeong Apr 28, 2026
01abdad
build: read package.json via createRequire for Node 18.0+ compat
sf-tyler-jeong Apr 28, 2026
90ca78b
docs: add v3.17.12 changelog entry for MessageInput zero-width space fix
sf-tyler-jeong May 13, 2026
ecce64d
Merge branch 'main' into feature/CLNP-8355
sf-tyler-jeong May 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
push:
branches:
- main
- release/**
concurrency:
group: build-and-test-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true
Expand All @@ -17,12 +18,12 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: '16.19.1'
node-version: '24'
cache: 'yarn'

- name: Install dependencies
Expand All @@ -43,4 +44,12 @@ jobs:
if: ${{ success() }}
timeout-minutes: 15
run: |
yarn test --forceExit --runInBand
yarn test --forceExit --runInBand || {
if [ -f "./test-results/junit-report.xml" ]; then
echo "Tests failed. Retrying failed tests..."
node scripts/failed-test-retry.js
else
echo "Tests failed and no JUnit report found."
exit 1
fi
}
23 changes: 15 additions & 8 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
name: Coverage Report

# Manual trigger only. To restore PR comment trigger, replace workflow_dispatch with:
# on:
# issue_comment:
# types: [created, edited]
# And add this condition to the job:
# if: github.event.issue.pull_request && contains(github.event.comment.body, './coverage')

on:
issue_comment:
types: [created, edited]
workflow_dispatch:

jobs:
coverage:
runs-on: ubuntu-latest
if: github.event.issue.pull_request && contains(github.event.comment.body, './coverage')
steps:
- uses: actions/checkout@v3
- uses: ArtiomTr/jest-coverage-report-action@v2
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: ArtiomTr/jest-coverage-report-action@v2
103 changes: 89 additions & 14 deletions .github/workflows/package-publish.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# Manual publish workflow (typically for beta/RC releases).
#
# IMPORTANT: npm OIDC trusted publishing allows only one publisher
# configuration per package. The default is set to release-workflow.yml.
# Before dispatching this workflow:
# 1. Open the package on npmjs.com → Settings → "Trusted publisher"
# 2. Change the workflow filename to "package-publish.yml"
# 3. Run this workflow
# 4. Restore the workflow filename to "release-workflow.yml"
name: Package build and publish

on:
Expand All @@ -19,19 +28,86 @@ on:
jobs:
publish:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write
env:
SKIP_REST: '' # Set to 'true' when npm_tag is provided
VERSION: ${{ github.event.inputs.version }}
NPM_TAG: ${{ github.event.inputs.npm_tag }}
TAG_SUFFIX: ${{ github.event.inputs.tag_suffix }}
BRANCH_NAME: ${{ github.ref_name }}
steps:
- uses: actions/checkout@v4
- name: Validate dispatch inputs
run: |
# VERSION must be stable X.Y.Z. Prerelease versions are built up via
# npm_tag (+ optional tag_suffix), e.g., 3.18.0 + beta + 0 => 3.18.0-beta-0.
if ! printf '%s' "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
echo "Invalid version: '$VERSION' (expected stable X.Y.Z; use npm_tag for prerelease)"
exit 1
fi
if [ -n "$NPM_TAG" ]; then
if ! printf '%s' "$NPM_TAG" | grep -qE '^[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*$'; then
echo "Invalid npm_tag: '$NPM_TAG'"
exit 1
fi
if [ "$NPM_TAG" = "latest" ]; then
echo "npm_tag 'latest' is not allowed; leave npm_tag empty for a stable publish."
exit 1
fi
fi
if [ -n "$TAG_SUFFIX" ]; then
if ! printf '%s' "$TAG_SUFFIX" | grep -qE '^[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*$'; then
echo "Invalid tag_suffix: '$TAG_SUFFIX'"
exit 1
fi
if [ -z "$NPM_TAG" ]; then
echo "tag_suffix requires npm_tag. Provide npm_tag (e.g., beta) or remove tag_suffix."
exit 1
fi
fi
# npm rejects dist-tags that can be parsed as a semver version or range
# (e.g. 1.0, v1.4, 1.x, 1.2.x, 1.2.3-beta). The simplest way to cover
# all of these is to forbid leading digits and a leading v/V.
if [ -n "$NPM_TAG" ] && printf '%s' "$NPM_TAG" | grep -qE '^([0-9]|[vV])'; then
echo "npm_tag '$NPM_TAG' starts with a digit or v/V; npm rejects such dist-tags (interpreted as a semver version/range)."
exit 1
fi
# Validate the constructed npm version against semver 2.0 (catches things like
# beta.01 → 3.18.0-beta.01, which is rejected by the spec for leading zeros)
candidate_version="$VERSION"
if [ -n "$NPM_TAG" ]; then
if [ -z "$TAG_SUFFIX" ]; then
candidate_version="$VERSION-$NPM_TAG"
else
candidate_version="$VERSION-$NPM_TAG-$TAG_SUFFIX"
fi
fi
semver_re='^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-(0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*)?$'
if ! printf '%s' "$candidate_version" | grep -qE "$semver_re"; then
echo "Constructed npm version '$candidate_version' is not valid semver 2.0."
exit 1
fi
- name: Validate dispatch ref matches release branch
run: |
expected="release/v$VERSION"
if [ "$BRANCH_NAME" != "$expected" ]; then
echo "Dispatched from '$BRANCH_NAME' but version input is $VERSION."
echo "Re-dispatch this workflow with the correct ref ($expected) selected in the GitHub Actions UI."
exit 1
fi
- uses: actions/checkout@v6
with:
token: ${{ secrets.SDK_GH_BOT1_TOKEN }}
fetch-depth: 0
- uses: actions/setup-node@v4
- uses: actions/setup-node@v6
with:
node-version: 18.x
node-version: '24'
cache: 'yarn'
- name: Check if the release branch exists
run: |
set -x
branch_name="release/v${{ github.event.inputs.version }}"
branch_name="release/v$VERSION"
if ! git ls-remote --exit-code --heads origin "$branch_name" > /dev/null; then
echo "Branch $branch_name does not exist. Make sure to create the branch and create a Jira ticket with pr-comment-bot."
exit 1
Expand All @@ -42,10 +118,10 @@ jobs:
- name: Update version in package.json if npm_tag is provided
if: ${{ github.event.inputs.npm_tag }}
run: |
if [ -z "${{ github.event.inputs.tag_suffix }}" ]; then
npm_version="${{ github.event.inputs.version }}-${{ github.event.inputs.npm_tag }}"
if [ -z "$TAG_SUFFIX" ]; then
npm_version="$VERSION-$NPM_TAG"
else
npm_version="${{ github.event.inputs.version }}-${{ github.event.inputs.npm_tag }}-${{ github.event.inputs.tag_suffix }}"
npm_version="$VERSION-$NPM_TAG-$TAG_SUFFIX"
fi
jq --arg npm_version "$npm_version" '.version = $npm_version' package.json > package.json.tmp && mv package.json.tmp package.json
- name: Set environments
Expand All @@ -54,16 +130,15 @@ jobs:
git config --global user.email "sha.sdk_deployment@sendbird.com"
- name: Install and Build
run: |
yarn install
yarn install --immutable
yarn build
- name: Publish to npm
run: |
cd ./dist
echo "//registry.npmjs.org/:_authToken=${{ secrets.npm_token }}" > .npmrc
if [ -z "${{ github.event.inputs.npm_tag }}" ]; then
npm publish --access=public
if [ -z "$NPM_TAG" ]; then
npm publish --access=public --provenance
else
Comment thread
sf-tyler-jeong marked this conversation as resolved.
Comment thread
sf-tyler-jeong marked this conversation as resolved.
npm publish --tag ${{ github.event.inputs.npm_tag }} --access=public
npm publish --tag "$NPM_TAG" --access=public --provenance
echo "npm_tag is provided; Skipping the rest of the steps."
echo "SKIP_REST=true" >> $GITHUB_ENV
fi
Expand Down Expand Up @@ -99,5 +174,5 @@ jobs:
- name: Tag new target and push to origin
if: env.SKIP_REST != 'true'
run: |
git tag v${{ github.event.inputs.version }}
git push origin v${{ github.event.inputs.version }}
git tag "v$VERSION"
git push origin "v$VERSION"
2 changes: 1 addition & 1 deletion .github/workflows/pr-comment-bot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
if : ${{ github.event.issue.pull_request}}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- uses: sendbird/release-automation-action@latest
with:
gh_token: ${{ secrets.SDK_GH_BOT1_TOKEN }}
Expand Down
71 changes: 71 additions & 0 deletions .github/workflows/prepare-changelog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Prepare CHANGELOG

on:
push:
branches:
- 'release/v*'
paths:
- 'CHANGELOG_DRAFT.md'
- 'package.json'

concurrency:
group: prepare-changelog-${{ github.ref_name }}
cancel-in-progress: false

jobs:
prepare:
runs-on: ubuntu-latest
permissions:
contents: write

env:
BRANCH_NAME: ${{ github.ref_name }}
BOT_EMAIL: 'sha.sdk_deployment@sendbird.com'
BOT_NAME: 'sendbird-sdk-deployment'

steps:
- name: Checkout
uses: actions/checkout@v6
with:
token: ${{ secrets.SDK_GH_BOT1_TOKEN }}
fetch-depth: 2
ref: ${{ github.ref_name }}

- name: Skip if last commit was made by the release bot
id: skip-bot
run: |
last_author=$(git log -1 --pretty=%ae)
if [ "$last_author" = "$BOT_EMAIL" ]; then
echo "Last commit author is the release bot ($BOT_EMAIL); skipping."
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi

- name: Setup Node.js
if: steps.skip-bot.outputs.skip != 'true'
uses: actions/setup-node@v6
with:
node-version: '24'

- name: Update CHANGELOG.md
if: steps.skip-bot.outputs.skip != 'true'
run: |
VERSION="${BRANCH_NAME#release/v}"
DATE=$(date -u '+%b %d %Y' | tr '[:lower:]' '[:upper:]')
export VERSION DATE
node scripts/update-changelog.js

- name: Commit and push CHANGELOG.md
if: steps.skip-bot.outputs.skip != 'true'
run: |
if git diff --quiet CHANGELOG.md; then
echo "CHANGELOG.md unchanged; nothing to commit."
exit 0
fi
VERSION="${BRANCH_NAME#release/v}"
git config user.email "$BOT_EMAIL"
git config user.name "$BOT_NAME"
git add CHANGELOG.md
git commit -m "chore: prepare CHANGELOG.md for v${VERSION}"
git push origin "$BRANCH_NAME"
Loading