chore: add github stuff

This commit is contained in:
MengXi
2025-11-08 22:29:35 -08:00
parent 0e267414e3
commit adb4f9a70e
15 changed files with 976 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
# Changesets
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
+20
View File
@@ -0,0 +1,20 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
"changelog": [
"@changesets/changelog-github",
{
"repo": "mengxi-ream/read-frog"
}
],
"commit": false,
"fixed": [],
"linked": [],
"access": "restricted",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": [],
"privatePackages": {
"version": true,
"tag": true
}
}
+3
View File
@@ -0,0 +1,3 @@
# These are supported funding model platforms
github: mengxi-ream
+85
View File
@@ -0,0 +1,85 @@
name: Report a bug
description: Create a report to help us improve Read Frog
labels: [bug]
title: '[BUG] '
assignees: []
body:
- type: checkboxes
id: preflight
attributes:
label: Before you report
description: |
Please confirm the following before submitting. For questions and quick help, join our Discord community.
Discord: https://discord.gg/ej45e3PezJ
options:
- label: I have searched existing issues to avoid duplicates
required: true
- label: I have tried with the latest available version (or can reproduce on latest)
required: false
- type: markdown
attributes:
value: |
This template is used for reporting an issue with Read Frog.
Feature requests should be opened via the [Feature Request Form](https://github.com/mengxi-ream/read-frog/issues/new?assignees=&labels=enhancement&projects=&template=feature_request.yml&title=)
- type: textarea
id: expected
attributes:
label: Current vs. Expected behavior
description: |
A clear and concise description of what happened (e.g., screenshots, logs, errors) and what you expected to happen.
Skipping this / failure to provide complete information may result in the issue being closed.
placeholder: 'Following the steps from the previous section, I expected A to happen, but I observed B instead.'
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: To Reproduce
description: |
A step-by-step description of how to reproduce the issue. Screenshots can be provided in the issue body as well.
placeholder: |
Ex:
1. Open a news article page
2. Click the Read Frog icon to open the popup
3. Enable Immersive Translation
4. Observe translation not appearing on the page
validations:
required: true
- type: dropdown
id: areas
attributes:
label: Which area(s) are affected? (Select all that apply)
multiple: true
options:
- Browser Extension
- Website
- Other
validations:
required: true
- type: input
id: extension_version
attributes:
label: Extension version (if applicable)
description: Provide the current version of the browser extension
placeholder: 1.x.x
- type: textarea
id: environment
attributes:
label: Provide environment information
description: Please collect the following information and paste the results.
render: bash
placeholder: |
- OS: [e.g. macOS 14.5]
- Browser: [e.g. Chrome 126, Edge 125]
- Extension channel/version: [e.g. Chrome Web Store 1.2.3]
- Website: [e.g. https://readfrog.app, date/time observed]
validations:
required: true
- type: textarea
id: additional
attributes:
label: Additional context
description: |
Any extra information that might help us investigate. For example, is it only reproducible online, or locally too? Is the issue only happening in a specific website or browser?
+8
View File
@@ -0,0 +1,8 @@
blank_issues_enabled: true
contact_links:
- name: Read Frog Discord
url: https://discord.gg/ej45e3PezJ
about: Quick questions or support are often answered faster in Discord.
- name: Official Website
url: https://readfrog.app
about: Learn more about Read Frog and access docs and resources.
@@ -0,0 +1,54 @@
name: Feature request
description: Suggest an idea for Read Frog
title: '[FEATURE] '
labels: [enhancement]
assignees: []
body:
- type: checkboxes
id: preflight
attributes:
label: Before you begin
description: |
Please confirm the following before submitting. For questions and quick help, join our Discord community.
Discord: https://discord.gg/ej45e3PezJ
options:
- label: I have searched existing issues to avoid duplicates
required: true
- label: I am willing to contribute a PR for this feature
required: false
- type: markdown
attributes:
value: |
This template is used for suggesting a feature for Read Frog.
Bug reports should be opened via the [Bug Report Form](https://github.com/mengxi-ream/read-frog/issues/new?assignees=&labels=bug&projects=&template=bug_report.yml&title=)
- type: textarea
id: problem
attributes:
label: Is your feature request related to a problem? Please describe.
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
validations:
required: true
- type: textarea
id: solution
attributes:
label: Describe the solution you'd like
description: A clear and concise description of what you want to happen.
validations:
required: true
- type: dropdown
id: areas
attributes:
label: Which area(s) would this feature affect? (Select all that apply)
multiple: true
options:
- Browser Extension
- Website
- Other
validations:
required: true
- type: textarea
id: context
attributes:
label: Additional context
description: Add any other context or screenshots about the feature request here.
+52
View File
@@ -0,0 +1,52 @@
## Type of Changes
<!--- Please select one type below -->
- [ ] ✨ New feature (feat)
- [ ] 🐛 Bug fix (fix)
- [ ] 📝 Documentation change (docs)
- [ ] 💄 UI/style change (style)
- [ ] ♻️ Code refactoring (refactor)
- [ ] ⚡ Performance improvement (perf)
- [ ] ✅ Test related (test)
- [ ] 🔧 Build or dependencies update (build)
- [ ] 🔄 CI/CD related (ci)
- [ ] 🌐 Internationalization (i18n)
- [ ] 🧠 AI model related (ai)
- [ ] 🔄 Revert a previous commit (revert)
- [ ] 📦 Other changes that do not modify src or test files (chore)
## Description
<!--- Please describe the changes in the PR and the problem it solves -->
## Related Issue
<!--- If this PR closes an issue, please link the issue below -->
Closes #
## How Has This Been Tested?
<!--- Please describe how you tested your changes -->
- [ ] Added unit tests
- [ ] Verified through manual testing
## Screenshots
<!--- If applicable, add screenshots to help explain your changes -->
## Checklist
<!--- Go over all the following points before requesting a review -->
- [ ] I have tested these changes locally
- [ ] I have updated the documentation accordingly if necessary
- [ ] My code follows the code style of this project
- [ ] My changes do not break existing functionality
- [ ] If my code was generated by AI, I have proofread and improved it as necessary.
## Additional Information
<!--- Any other information that reviewers should know -->
+45
View File
@@ -0,0 +1,45 @@
changelog:
exclude:
labels:
- ignore-for-release
- dependencies
- automated
- bot
- github-actions
authors:
- dependabot[bot]
- github-actions[bot]
- github-actions
- action-bot
categories:
- title: 🚨 Breaking Changes
labels:
- breaking-change
- title: ✨ New Features
labels:
- feat
- title: 🐛 Bug Fixes
labels:
- fix
- title: 🤖 AI
labels:
- ai
- title: 🎨 UI Styles
labels:
- style
- title: 🚀 Performance
labels:
- perf
- title: 📚 Documentation
labels:
- docs
- title: 🔧 Maintenance
labels:
- chore
- refactor
- ci
- build
- i18n
- title: Other Changes
labels: ['*']
@@ -0,0 +1,176 @@
name: PR - Major Version Warning
on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- '.changeset/*.md'
permissions:
contents: read
pull-requests: write
issues: write
jobs:
check-major:
name: Check Breaking Changes
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get changed changeset files
id: changed-files
uses: tj-actions/changed-files@v47
with:
files: '.changeset/*.md'
files_ignore: .changeset/README.md
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Check for major changes
id: check-major
if: steps.changed-files.outputs.any_changed == 'true'
run: |
echo "Checking changeset files for major changes..."
major_files=""
major_packages=""
for file in ${{ steps.changed-files.outputs.all_changed_files }}; do
echo "Checking file: $file"
# Extract front matter and check for major (more robust parsing)
if sed -n '/^---$/,/^---$/p' "$file" | grep -q ": major"; then
echo "Found major change in: $file"
major_files="$major_files$file "
# Extract package names with major changes (more precise)
packages=$(sed -n '/^---$/,/^---$/p' "$file" | grep ": major" | sed 's/^"\([^"]*\)": major$/\1/' | tr '\n' ' ')
major_packages="$major_packages$packages"
fi
done
if [ -n "$major_files" ]; then
echo "has_major=true" >> $GITHUB_OUTPUT
echo "major_files=$major_files" >> $GITHUB_OUTPUT
echo "major_packages=$major_packages" >> $GITHUB_OUTPUT
else
echo "has_major=false" >> $GITHUB_OUTPUT
fi
- name: Comment on PR with major version warning
if: steps.check-major.outputs.has_major == 'true' && github.event.pull_request.head.repo.full_name == github.repository
uses: actions/github-script@v7
with:
script: |
const majorFiles = ${{ toJSON(steps.check-major.outputs.major_files) }}.trim();
const majorPackages = ${{ toJSON(steps.check-major.outputs.major_packages) }}.trim();
// Check if we already have a major version warning comment
const comments = await github.rest.issues.listComments({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
});
const botComment = comments.data.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('⚠️ Major Version Change Detected')
);
const comment = `## ⚠️ Major Version Change Detected
This PR contains **MAJOR** version changes, which means **breaking changes**!
### 📦 Affected Packages
${majorPackages.split(' ').filter(p => p).map(pkg => `- \`${pkg}\``).join('\n')}
### 📁 Related Changeset Files
${majorFiles.split(' ').filter(f => f).map(file => `- \`${file}\``).join('\n')}
### 🔢 Version Impact
Major version changes will:
- Increment the major version number by 1 (e.g., 1.2.3 → 2.0.0)
- Reset minor and patch versions to 0
- Indicate **breaking changes** that may cause existing user code to fail
### ❓ Please Confirm
Please carefully confirm the following:
1. **Does this really contain breaking changes?**
- API removal or modification
- Default behavior changes
- Major dependency updates
2. **Should you use \`minor\` or \`patch\` instead?**
- \`minor\`: New features but backward compatible
- \`patch\`: Bug fixes, backward compatible
3. **Are you ready to release a major version?**
- Updated documentation explaining breaking changes
- Provided migration guide
- Notified users of upcoming major update
### 🛠️ How to Modify
If you need to downgrade the version type:
1. Edit the changeset file, change \`major\` to \`minor\` or \`patch\`
2. Commit the changes
### 📚 References
- [Semantic Versioning](https://semver.org/)
- [Changesets Documentation](https://github.com/changesets/changesets)
---
*This warning is generated by automated checks to prevent accidental breaking version releases.*`;
if (botComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: comment
});
} else {
// Create new comment
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
}
- name: Fail workflow for major changes (fork repos only)
if: steps.check-major.outputs.has_major == 'true' && github.event.pull_request.head.repo.full_name != github.repository
run: |
echo "::error::⚠️ Major version changes detected in fork repository!"
echo "::error::"
echo "::error::❓ Are you sure this PR contains BREAKING CHANGES?"
echo "::error:: Major versions (1.2.3 → 2.0.0) are only for:"
echo "::error:: • API removals or incompatible changes"
echo "::error:: • Behavior changes that break existing code"
echo "::error:: • Major dependency updates with breaking changes"
echo "::error::"
echo "::error::🚫 Fork repositories cannot submit major version changes due to their breaking nature."
echo "::error:: Major changes require repository maintainer approval and coordination."
echo "::error::"
echo "::error::📝 Please either:"
echo "::error:: 1. Change 'major' to 'minor' or 'patch' in your changeset files"
echo "::error:: 2. Contact repository maintainers to handle this major change"
echo "::error:: 3. Open an issue to discuss the breaking changes first"
echo "::error::"
echo "::error::For more info about semantic versioning: https://semver.org/"
exit 1
+54
View File
@@ -0,0 +1,54 @@
name: PR - Claude Review
on:
pull_request:
types: [opened, synchronize]
# Optional: Only run on specific file changes
# paths:
# - "src/**/*.ts"
# - "src/**/*.tsx"
# - "src/**/*.js"
# - "src/**/*.jsx"
jobs:
code-review:
if: github.event.pull_request.head.repo.full_name == github.repository
# Optional: Filter by PR author
# if: |
# github.event.pull_request.user.login == 'external-contributor' ||
# github.event.pull_request.user.login == 'new-developer' ||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Run Claude Code Review
id: claude-review
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
prompt: |
Please review this pull request and provide feedback on:
- Code quality and best practices
- Potential bugs or issues
- Performance considerations
- Security concerns
- Test coverage
Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback.
Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR.
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://docs.anthropic.com/en/docs/claude-code/sdk#command-line for available options
claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'
+49
View File
@@ -0,0 +1,49 @@
name: Bot - Claude Assistant
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]
jobs:
claude-assistant:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# This is an optional setting that allows Claude to read CI results on PRs
additional_permissions: |
actions: read
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
# prompt: 'Update the pull request description to include a summary of changes.'
# Optional: Add claude_args to customize behavior and configuration
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://docs.anthropic.com/en/docs/claude-code/sdk#command-line for available options
# claude_args: '--model claude-opus-4-1-20250805 --allowed-tools Bash(gh pr:*)'
+102
View File
@@ -0,0 +1,102 @@
name: PR - Lint & Label
on:
pull_request_target:
types:
- opened
- edited
- synchronize
jobs:
lint-and-label:
name: Validate & Auto-label
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
contents: read
steps:
- name: Validate PR title
uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: |
feat
fix
docs
style
refactor
perf
test
build
ci
chore
revert
i18n
ai
- name: Auto Label PR
uses: actions/github-script@v7
with:
script: |
const title = context.payload.pull_request.title;
const prNumber = context.payload.pull_request.number;
// Mapping from commit type to label
const typeToLabel = {
'feat': 'feat',
'fix': 'fix',
'docs': 'docs',
'style': 'style',
'refactor': 'refactor',
'perf': 'perf',
'test': 'test',
'build': 'build',
'ci': 'ci',
'chore': 'chore',
'revert': 'revert',
'i18n': 'i18n',
'ai': 'ai'
};
// Extract type from PR title (format: "type: description" or "type(scope): description")
const match = title.match(/^(\w+)(?:\([^)]*\))?(!)?:\s/);
if (match) {
const commitType = match[1];
const hasBreakingMark = match[2] === '!';
const label = typeToLabel[commitType];
// Check for breaking change indicator
const isBreaking = hasBreakingMark || title.toLowerCase().includes('breaking change');
if (label) {
console.log(`Adding label "${label}" to PR #${prNumber} based on type "${commitType}"`);
const labelsToAdd = [label];
// Add breaking-change label if it's a breaking change
if (isBreaking) {
labelsToAdd.push('breaking-change');
console.log(`Also adding "breaking-change" label due to breaking change indicator`);
}
try {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
labels: labelsToAdd
});
console.log(`Successfully added labels: ${labelsToAdd.join(', ')}`);
} catch (error) {
console.error(`Failed to add labels: ${error.message}`);
}
} else {
console.log(`No label mapping found for commit type "${commitType}"`);
}
} else {
console.log(`PR title "${title}" doesn't match conventional commit format`);
}
+54
View File
@@ -0,0 +1,54 @@
name: PR - Test & Build
on:
pull_request:
branches:
- main
jobs:
test-and-build:
name: Test & Build
runs-on: ubuntu-latest
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
steps:
- name: Checkout Repo
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '24'
cache: pnpm
- name: Install Dependencies
run: pnpm install --frozen-lockfile
shell: bash
- name: Check for eruda imports
run: |
if grep -r "import.*eruda" src/ --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" | grep -v ":.*[[:space:]]*//.*import.*eruda"; then
echo "❌ Found uncommented eruda imports in the codebase!"
echo "Please comment out or remove eruda imports before merging."
exit 1
else
echo "✅ No uncommented eruda imports found."
fi
shell: bash
- name: ESLint
run: pnpm lint
- name: Type check
run: pnpm type-check
- name: Build
run: pnpm build
- name: Run tests
run: pnpm test -- --exclude="**/free-api.test.ts"
+227
View File
@@ -0,0 +1,227 @@
name: Deploy - Release & Publish
on:
push:
branches:
- main
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
release:
name: Release Packages
runs-on: ubuntu-latest
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
SKIP_ENV_VALIDATION: true
SKIP_PRE_PUSH: true
steps:
- name: Checkout Repo
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '24'
cache: pnpm
- name: Install Dependencies
run: pnpm install
shell: bash
- name: Create Release Pull Request or Tag
id: changesets
uses: changesets/action@v1
with:
commit: 'chore(release): version packages'
title: 'chore(release): version packages'
publish: pnpm run release
createGithubReleases: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SKIP_FREE_API: true
- name: Send Discord Notification
if: steps.changesets.outputs.published == 'true'
run: |
echo "Sending Discord notification for published packages..."
# Get published packages from changesets output
PUBLISHED_PACKAGES='${{ steps.changesets.outputs.publishedPackages }}'
if [ -z "$PUBLISHED_PACKAGES" ] || [ "$PUBLISHED_PACKAGES" = "[]" ]; then
echo "No packages were published"
exit 0
fi
echo "Published packages: $PUBLISHED_PACKAGES"
# Process each published package individually
echo "$PUBLISHED_PACKAGES" | jq -c '.[]' | while read -r package_info; do
if [ -n "$package_info" ]; then
PACKAGE_NAME=$(echo "$package_info" | jq -r '.name')
PACKAGE_VERSION=$(echo "$package_info" | jq -r '.version')
echo "Processing package: $PACKAGE_NAME@$PACKAGE_VERSION"
# Generate tag name based on changesets convention
PACKAGE_TAG="$PACKAGE_NAME@$PACKAGE_VERSION"
PACKAGE_URL="https://github.com/${{ github.repository }}/releases/tag/$PACKAGE_TAG"
# Get release info and notes for this specific package tag
RELEASE_NOTES_RAW=""
SPECIFIC_RELEASE_URL=""
# Try to get release data for this specific tag
RELEASE_DATA=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
"https://api.github.com/repos/${{ github.repository }}/releases/tags/$PACKAGE_TAG" 2>/dev/null || echo '{}')
# If specific release doesn't exist, try to get the latest release
if [ "$(echo "$RELEASE_DATA" | jq -r '.id // "null"')" = "null" ]; then
echo "No specific release found for $PACKAGE_TAG, trying latest release..."
LATEST_TAG=$(git describe --abbrev=0 --tags 2>/dev/null || echo "")
if [ -z "$LATEST_TAG" ]; then
# Fallback to getting latest release from GitHub API
LATEST_TAG=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
"https://api.github.com/repos/${{ github.repository }}/releases/latest" \
| jq -r '.tag_name // ""')
fi
if [ -n "$LATEST_TAG" ] && [ "$LATEST_TAG" != "null" ]; then
RELEASE_DATA=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
"https://api.github.com/repos/${{ github.repository }}/releases/tags/$LATEST_TAG")
SPECIFIC_RELEASE_URL=$(echo "$RELEASE_DATA" | jq -r '.html_url // ""')
fi
else
SPECIFIC_RELEASE_URL=$(echo "$RELEASE_DATA" | jq -r '.html_url // ""')
fi
# Use package URL if no specific release URL found
if [ -z "$SPECIFIC_RELEASE_URL" ]; then
SPECIFIC_RELEASE_URL="$PACKAGE_URL"
fi
# Extract release notes and clean them up
RELEASE_NOTES_RAW=$(echo "$RELEASE_DATA" | jq -r '.body // "No release notes available"')
# Remove HTML comments and format headers
if [ -n "$RELEASE_NOTES_RAW" ] && [ "$RELEASE_NOTES_RAW" != "No release notes available" ]; then
RELEASE_NOTES_RAW=$(echo "$RELEASE_NOTES_RAW" | sed 's/<!--[^>]*-->//g')
RELEASE_NOTES_RAW=$(echo "$RELEASE_NOTES_RAW" | \
sed 's/^## \(.*\)$/**\1**/g' | \
sed 's/^### \(.*\)$/▸ **\1**/g' | \
sed 's/^#### \(.*\)$/ • **\1**/g' | \
sed 's/^##### \(.*\)$/ ◦ **\1**/g')
# Remove leading/trailing whitespace
RELEASE_NOTES_RAW=$(echo "$RELEASE_NOTES_RAW" | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//')
# Limit to Discord embed limit (leaving room for other content)
if [ ${#RELEASE_NOTES_RAW} -gt 800 ]; then
RELEASE_NOTES_RAW=$(echo "$RELEASE_NOTES_RAW" | head -c 800)
RELEASE_NOTES_RAW="${RELEASE_NOTES_RAW}..."
fi
fi
# Get package emoji
case "$PACKAGE_NAME" in
*"extension"*) EMOJI="🐸" ;;
*"website"*) EMOJI="🌐" ;;
*"cli"*) EMOJI="⚡" ;;
*"api"*) EMOJI="🔌" ;;
*"core"*) EMOJI="⚙️" ;;
*"sdk"*) EMOJI="🛠️" ;;
*) EMOJI="📦" ;;
esac
# Extract display name (e.g., @read-frog/extension -> Extension)
PACKAGE_DISPLAY_NAME=$(echo "$PACKAGE_NAME" | sed 's/.*\///g' | sed 's/\b\w/\U&/g')
TITLE="$EMOJI $PACKAGE_DISPLAY_NAME Release!"
DESCRIPTION="**$PACKAGE_DISPLAY_NAME** version \`$PACKAGE_VERSION\` has been released!"
# Build fields using jq
if [ -n "$RELEASE_NOTES_RAW" ] && [ "$RELEASE_NOTES_RAW" != "No release notes available" ]; then
FIELDS_JSON=$(jq -n \
--arg tag "$PACKAGE_TAG" \
--arg release_notes "$RELEASE_NOTES_RAW" \
'[
{
"name": "🏷️ Tag",
"value": ("`" + $tag + "`"),
"inline": true
},
{
"name": "📝 Release Notes",
"value": $release_notes,
"inline": false
}
]')
else
FIELDS_JSON=$(jq -n \
--arg tag "$PACKAGE_TAG" \
'[
{
"name": "🏷️ Tag",
"value": ("`" + $tag + "`"),
"inline": true
}
]')
fi
# Create individual embed for this package
TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%S.000Z)
EMBED_JSON=$(jq -n \
--arg title "$TITLE" \
--arg description "$DESCRIPTION" \
--arg url "$SPECIFIC_RELEASE_URL" \
--argjson fields "$FIELDS_JSON" \
--arg timestamp "$TIMESTAMP" \
'{
title: $title,
description: $description,
url: $url,
color: 48253,
fields: $fields,
footer: {
text: "GitHub Actions",
icon_url: "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"
},
timestamp: $timestamp
}')
# Create Discord payload for this individual package
DISCORD_PAYLOAD=$(echo "$EMBED_JSON" | jq '{embeds: [.]}')
echo "Discord payload for $PACKAGE_NAME:"
echo "$DISCORD_PAYLOAD"
# Validate JSON before sending
if ! echo "$DISCORD_PAYLOAD" | jq empty 2>/dev/null; then
echo "Error: Generated invalid JSON payload for $PACKAGE_NAME"
continue
fi
# Send individual notification to Discord
echo "Sending Discord notification for $PACKAGE_NAME@$PACKAGE_VERSION..."
RESPONSE=$(curl -s -w "%{http_code}" -H "Content-Type: application/json" \
-X POST \
-d "$DISCORD_PAYLOAD" \
${{ secrets.DISCORD_WEBHOOK_URL }})
HTTP_CODE=$(echo "$RESPONSE" | tail -c 4)
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
echo "✅ Successfully sent Discord notification for $PACKAGE_NAME (HTTP $HTTP_CODE)"
else
echo "❌ Failed to send Discord notification for $PACKAGE_NAME (HTTP $HTTP_CODE)"
echo "Response: $RESPONSE"
fi
# Add a small delay between notifications to avoid rate limiting
sleep 1
fi
done
+39
View File
@@ -0,0 +1,39 @@
name: Maintenance - Stale Issues & PRs
on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
jobs:
stale:
name: Mark Stale Items
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
# ---- Issue settings ----
days-before-issue-stale: 60
days-before-issue-close: 365
stale-issue-message: |
This issue has been inactive for 60 days and is now marked as stale.
It will be automatically closed in 360 days if no further activity occurs.
close-issue-message: |
Since it has been a long time without updates, the issue has been automatically closed.
If you need to continue, please reopen or create a new issue.
# ---- PR settings ----
days-before-pr-stale: 14
days-before-pr-close: 30
stale-pr-message: |
This PR has been inactive for 14 days and is now marked as stale.
It will be automatically closed in 30 days if no further activity occurs.
close-pr-message: |
Since it has been a long time without updates, the PR has been automatically closed.
If you need to continue, please reopen or create a new PR.
exempt-pr-labels: |
pinned
WIP