Skip to content

Merge pull request #3197 from Maltronic/patch-1 #139

Merge pull request #3197 from Maltronic/patch-1

Merge pull request #3197 from Maltronic/patch-1 #139

name: Production Package Publishing
on:
push:
branches: [main]
paths-ignore:
- '**/package-lock.json'
- '**/yarn.lock'
jobs:
check-automation:
runs-on: ubuntu-latest
outputs:
should-skip: ${{ steps.check-automation.outputs.should-skip }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check if triggered by automation
id: check-automation
run: |
# Skip if actor is github-actions or dependabot
if [[ "${{ github.actor }}" == "github-actions[bot]" ]] || [[ "${{ github.actor }}" == "dependabot[bot]" ]] || [[ "${{ github.actor }}" == "github-actions" ]]; then
echo "should-skip=true" >> $GITHUB_OUTPUT
echo "🚫 Skipping workflow: triggered by automated actor (${{ github.actor }})"
exit 0
fi
# Get the latest commit message and author
COMMIT_MESSAGE=$(git log -1 --pretty=%B)
COMMIT_AUTHOR=$(git log -1 --pretty=%an)
echo "Commit message: $COMMIT_MESSAGE"
echo "Commit author: $COMMIT_AUTHOR"
# Skip if commit message contains [skip ci] or [ci skip]
if echo "$COMMIT_MESSAGE" | grep -q "\[skip ci\]"; then
echo "should-skip=true" >> $GITHUB_OUTPUT
echo "🚫 Skipping workflow: [skip ci] found in commit message"
exit 0
fi
if echo "$COMMIT_MESSAGE" | grep -q "\[ci skip\]"; then
echo "should-skip=true" >> $GITHUB_OUTPUT
echo "🚫 Skipping workflow: [ci skip] found in commit message"
exit 0
fi
# Skip if commit author is automated
if [[ "$COMMIT_AUTHOR" == *"github-actions"* ]] || [[ "$COMMIT_AUTHOR" == *"GitHub Action"* ]] || [[ "$COMMIT_AUTHOR" == *"dependabot"* ]]; then
echo "should-skip=true" >> $GITHUB_OUTPUT
echo "🚫 Skipping workflow: commit by automated author ($COMMIT_AUTHOR)"
exit 0
fi
# Skip if commit message starts with automated version update pattern
if echo "$COMMIT_MESSAGE" | grep -q "^chore: update package versions to"; then
echo "should-skip=true" >> $GITHUB_OUTPUT
echo "🚫 Skipping workflow: automated version update commit"
exit 0
fi
echo "should-skip=false" >> $GITHUB_OUTPUT
echo "✅ Proceeding with workflow"
check-changesets:
needs: check-automation
if: needs.check-automation.outputs.should-skip != 'true'
runs-on: ubuntu-latest
outputs:
has-changesets: ${{ steps.check-changesets.outputs.has-changesets }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for changesets
id: check-changesets
run: |
if [ -d ".changeset" ] && [ "$(ls -A .changeset/*.md 2>/dev/null | wc -l)" -gt 0 ]; then
echo "has-changesets=true" >> $GITHUB_OUTPUT
else
echo "has-changesets=false" >> $GITHUB_OUTPUT
fi
publish-production:
needs: [check-automation, check-changesets]
if: needs.check-automation.outputs.should-skip != 'true' && needs.check-changesets.outputs.has-changesets == 'true'
runs-on: ubuntu-latest
outputs:
published: ${{ steps.publish.outputs.published }}
version: ${{ steps.publish.outputs.version }}
packages: ${{ steps.publish.outputs.packages }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'yarn'
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Setup NPM authentication
run: |
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
- name: Version packages with changesets
id: version
run: |
set -e # Exit on any error
set -o pipefail # Exit on pipeline errors
# Check if there are changesets to consume
if [ -d ".changeset" ] && [ "$(ls -A .changeset/*.md 2>/dev/null | wc -l)" -gt 0 ]; then
echo "📝 Consuming changesets..."
yarn changeset:version
# Check if any package.json was modified
if git diff --quiet; then
echo "No version changes needed"
echo "version_changed=false" >> $GITHUB_OUTPUT
else
echo "Version changes detected"
echo "version_changed=true" >> $GITHUB_OUTPUT
# Get the new version from the packages that were actually modified by changesets
MODIFIED_PACKAGES=$(git diff --name-only HEAD~1 | grep "packages/.*/package.json" || true)
if [ -z "$MODIFIED_PACKAGES" ]; then
echo "No modified package.json files found, falling back to first non-private package"
NEW_VERSION=$(node -e "
const fs = require('fs');
const packages = fs.readdirSync('packages');
for (const pkg of packages) {
try {
const pkgJson = JSON.parse(fs.readFileSync(\`packages/\${pkg}/package.json\`, 'utf8'));
if (!pkgJson.private) {
console.log(pkgJson.version);
break;
}
} catch (e) {}
}
")
else
echo "📋 Getting version from modified packages: $MODIFIED_PACKAGES"
# Get version from the first modified package
FIRST_MODIFIED=$(echo "$MODIFIED_PACKAGES" | head -n1)
NEW_VERSION=$(node -e "
try {
const pkg = JSON.parse(require('fs').readFileSync('$FIRST_MODIFIED', 'utf8'));
console.log(pkg.version || '');
} catch(e) { console.log(''); }
")
fi
echo "📋 Using version: $NEW_VERSION"
echo "version=${NEW_VERSION}" >> $GITHUB_OUTPUT
fi
else
echo "No changesets found, skipping versioning"
echo "version_changed=false" >> $GITHUB_OUTPUT
fi
- name: Get packages to publish
id: packages-to-publish
if: steps.version.outputs.version_changed == 'true'
run: |
set -e # Exit on any error
set -o pipefail # Exit on pipeline errors
echo "🔍 Identifying packages that need to be published..."
# Get list of modified package.json files (these are the ones that were versioned by changesets)
MODIFIED_PACKAGES=$(git diff --name-only HEAD~1 | grep "packages/.*/package.json" || true)
if [ -z "$MODIFIED_PACKAGES" ]; then
echo "❌ CRITICAL: No modified package.json files found"
echo "::error::No packages were modified by changesets"
echo "packages_to_publish=" >> $GITHUB_OUTPUT
exit 1
fi
echo " Modified packages:"
echo "$MODIFIED_PACKAGES"
# Extract package directories and names
PACKAGE_DIRS=""
PACKAGE_NAMES=""
while IFS= read -r pkg_file; do
if [ -n "$pkg_file" ]; then
PACKAGE_DIR=$(dirname "$pkg_file")
PACKAGE_NAME=$(node -e "
try {
const pkg = JSON.parse(require('fs').readFileSync('$pkg_file', 'utf8'));
console.log(pkg.name || '');
} catch(e) { console.log(''); }
")
if [ -n "$PACKAGE_NAME" ]; then
PACKAGE_DIRS="$PACKAGE_DIRS $PACKAGE_DIR"
PACKAGE_NAMES="$PACKAGE_NAMES $PACKAGE_NAME"
echo "✅ Will publish: $PACKAGE_NAME from $PACKAGE_DIR"
fi
fi
done <<< "$MODIFIED_PACKAGES"
echo "packages_to_publish=$PACKAGE_NAMES" >> $GITHUB_OUTPUT
echo "package_dirs=$PACKAGE_DIRS" >> $GITHUB_OUTPUT
- name: Publish packages
id: publish
if: steps.version.outputs.version_changed == 'true'
run: |
set -e # Exit on any error
set -o pipefail # Exit on pipeline errors
echo "🚀 Publishing packages..."
PUBLISHED_PACKAGES=""
PACKAGE_DIRS="${{ steps.packages-to-publish.outputs.package_dirs }}"
PACKAGE_NAMES="${{ steps.packages-to-publish.outputs.packages_to_publish }}"
echo "📦 Packages to publish: $PACKAGE_NAMES"
echo "📁 Package directories: $PACKAGE_DIRS"
# Function to check if version exists on npm
check_npm_version() {
local package_name=$1
local version=$2
if npm view "$package_name@$version" version >/dev/null 2>&1; then
echo "true"
else
echo "false"
fi
}
# Function to get latest version from npm
get_npm_latest_version() {
local package_name=$1
local latest_version=$(npm view "$package_name" version 2>/dev/null || echo "0.0.0")
echo "$latest_version"
}
# Function to increment version
increment_version() {
local version=$1
local increment_type=${2:-patch}
node -e "
const semver = require('semver');
const version = '$version';
const incrementType = '$increment_type';
console.log(semver.inc(version, incrementType));
" 2>/dev/null || node -e "
const version = '$version';
const parts = version.split('.');
parts[2] = (parseInt(parts[2]) + 1).toString();
console.log(parts.join('.'));
"
}
# Publish only the packages that were versioned by changesets
for package_dir in $PACKAGE_DIRS; do
if [ ! -d "$package_dir" ]; then
echo "⚠️ Package directory not found: $package_dir"
continue
fi
PACKAGE_JSON=$(cat "$package_dir/package.json")
PACKAGE_NAME=$(echo "$PACKAGE_JSON" | node -e "console.log(JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8')).name)")
IS_PRIVATE=$(echo "$PACKAGE_JSON" | node -e "console.log(JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8')).private || false)")
if [ "$IS_PRIVATE" = "true" ]; then
echo "⏭️ Skipping private package: $PACKAGE_NAME"
continue
fi
echo "📦 Processing $PACKAGE_NAME from $package_dir..."
cd "$package_dir"
# Get current package version
CURRENT_VERSION=$(node -e "console.log(JSON.parse(require('fs').readFileSync('package.json', 'utf8')).version)")
echo "📋 Current version: $CURRENT_VERSION"
# Check if version already exists on npm
VERSION_EXISTS=$(check_npm_version "$PACKAGE_NAME" "$CURRENT_VERSION")
if [ "$VERSION_EXISTS" = "true" ]; then
echo "⚠️ Version $CURRENT_VERSION already exists on npm for $PACKAGE_NAME"
echo "🔄 Checking latest version on npm..."
NPM_LATEST=$(get_npm_latest_version "$PACKAGE_NAME")
echo "📦 Latest version on npm: $NPM_LATEST"
if [ "$CURRENT_VERSION" = "$NPM_LATEST" ]; then
echo "📈 Incrementing patch version..."
NEW_VERSION=$(increment_version "$CURRENT_VERSION" "patch")
else
echo "📈 Using next version after npm latest..."
NEW_VERSION=$(increment_version "$NPM_LATEST" "patch")
fi
echo "🔄 Updating package version to $NEW_VERSION..."
# Update package.json version
node -e "
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
pkg.version = '$NEW_VERSION';
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
"
CURRENT_VERSION=$NEW_VERSION
echo "✅ Updated to version: $CURRENT_VERSION"
fi
# Install utils dependency if this is core package
if [[ "$PACKAGE_NAME" == *"core"* ]]; then
echo "🎯 Installing utils package for core package..."
echo "📦 Attempting to install latest utils package: @gluestack-ui/utils"
# First try to install the latest public version
if npm install @gluestack-ui/utils --no-save --registry https://registry.npmjs.org/ 2>&1; then
echo "✅ Utils package installed successfully"
# Show which version was installed
INSTALLED_VERSION=$(node -e "try { console.log(require('./node_modules/@gluestack-ui/utils/package.json').version) } catch(e) { console.log('unknown') }")
echo "📦 Installed utils version: $INSTALLED_VERSION"
else
echo "⚠️ Failed to install utils package, but continuing..."
echo "🔍 Available versions:"
npm view @gluestack-ui/utils versions --json 2>/dev/null || echo "Could not fetch available versions"
fi
# Verify utils package is available in node_modules
if [ -d "./node_modules/@gluestack-ui/utils" ]; then
echo "✅ Utils package verified in node_modules"
else
echo "⚠️ Utils package not found in node_modules, build may fail"
fi
fi
# Build if build script exists
if yarn run --list 2>/dev/null | grep -q "build"; then
echo "🔨 Building $PACKAGE_NAME..."
yarn build
fi
# Publish to latest tag
echo "🚀 Publishing $PACKAGE_NAME@$CURRENT_VERSION..."
if npm publish --access public; then
echo "✅ Successfully published $PACKAGE_NAME@$CURRENT_VERSION"
PUBLISHED_PACKAGES="$PUBLISHED_PACKAGES $PACKAGE_NAME@$CURRENT_VERSION"
else
PUBLISH_ERROR=$?
echo "❌ Failed to publish $PACKAGE_NAME@$CURRENT_VERSION (exit code: $PUBLISH_ERROR)"
if [ $PUBLISH_ERROR -eq 1 ]; then
echo "🔄 Version conflict detected. Incrementing version and retrying..."
NEW_VERSION=$(increment_version "$CURRENT_VERSION" "patch")
node -e "
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
pkg.version = '$NEW_VERSION';
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
"
CURRENT_VERSION=$NEW_VERSION
echo "🔄 Retrying publish with version $CURRENT_VERSION..."
if npm publish --access public; then
echo "✅ Successfully published $PACKAGE_NAME@$CURRENT_VERSION"
PUBLISHED_PACKAGES="$PUBLISHED_PACKAGES $PACKAGE_NAME@$CURRENT_VERSION"
else
echo "❌ CRITICAL: Failed to publish $PACKAGE_NAME@$CURRENT_VERSION after retry"
echo "::error::npm publish failed for $PACKAGE_NAME after retry"
exit 1
fi
else
echo "❌ CRITICAL: Unexpected publish error for $PACKAGE_NAME"
echo "::error::Unexpected npm publish error for $PACKAGE_NAME"
exit 1
fi
fi
cd - > /dev/null
done
echo "published=true" >> $GITHUB_OUTPUT
echo "packages=$PUBLISHED_PACKAGES" >> $GITHUB_OUTPUT
# Update the version output to reflect the actual published version
# Extract the version from the first published package
if [ -n "$PUBLISHED_PACKAGES" ]; then
ACTUAL_VERSION=$(echo "$PUBLISHED_PACKAGES" | tr ' ' '\n' | grep '@' | sed 's/.*@//' | head -n1)
echo "📋 Setting actual published version: $ACTUAL_VERSION"
echo "version=$ACTUAL_VERSION" >> $GITHUB_OUTPUT
else
echo "⚠️ No published packages found, keeping original version"
fi
- name: Update package versions in consuming projects
if: steps.publish.outputs.published == 'true'
run: |
echo "🔄 Updating package versions in consuming projects..."
PUBLISHED_VERSION="${{ steps.version.outputs.version }}"
PUBLISHED_PACKAGES="${{ steps.publish.outputs.packages }}"
# Extract package names from published packages
PACKAGE_NAMES=$(echo "$PUBLISHED_PACKAGES" | sed 's/@[^ ]*//g')
echo "📦 Published packages: $PACKAGE_NAMES"
echo "📋 Published version: $PUBLISHED_VERSION"
# Update package.json files in apps/ and other consuming directories
find . -name "package.json" -not -path "*/node_modules/*" -not -path "./packages/*" | while read -r pkg_file; do
echo "📝 Checking $pkg_file..."
# Check if this package.json uses any of our published packages
HAS_DEPENDENCIES=false
for pkg_name in $PACKAGE_NAMES; do
if grep -q "\"$pkg_name\"" "$pkg_file"; then
HAS_DEPENDENCIES=true
break
fi
done
if [ "$HAS_DEPENDENCIES" = "true" ]; then
echo "📝 Updating dependencies in $pkg_file..."
# Update dependencies to use the new version
node -e "
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('$pkg_file', 'utf8'));
const newVersion = '$PUBLISHED_VERSION';
const packageNames = '$PACKAGE_NAMES'.split(' ');
let changed = false;
['dependencies', 'devDependencies', 'peerDependencies'].forEach(depType => {
if (pkg[depType]) {
packageNames.forEach(pkgName => {
if (pkg[depType][pkgName]) {
console.log(\`Updating \${pkgName} from \${pkg[depType][pkgName]} to \${newVersion} in \${depType}\`);
pkg[depType][pkgName] = newVersion;
changed = true;
}
});
}
});
if (changed) {
fs.writeFileSync('$pkg_file', JSON.stringify(pkg, null, 2) + '\n');
console.log('✅ Updated $pkg_file');
} else {
console.log('ℹ️ No updates needed in $pkg_file');
}
"
fi
done
- name: Create PR for version updates
if: steps.publish.outputs.published == 'true'
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GH_TOKEN }} # Use PAT instead of default token
script: |
const { execSync } = require('child_process');
// Check if there are any changes to commit
try {
const status = execSync('git status --porcelain', { encoding: 'utf8' });
if (!status.trim()) {
console.log('No changes to commit, skipping PR creation');
return;
}
} catch (e) {
console.log('Error checking git status:', e.message);
return;
}
// Create a new branch for the PR
const branchName = `update-package-versions-${Date.now()}`;
const commitMessage = `chore: update package versions to ${{ steps.version.outputs.version }} [skip ci]`;
try {
// Configure git
execSync('git config --local user.email "[email protected]"');
execSync('git config --local user.name "GitHub Action"');
// Create new branch
execSync(`git checkout -b ${branchName}`);
// Add and commit changes
execSync('git add .');
execSync(`git commit -m "${commitMessage}"`);
// Push the branch
execSync(`git push origin ${branchName}`);
// Create PR
const pr = await github.rest.pulls.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `chore: update package versions to ${{ steps.version.outputs.version }}`,
body: `## 📦 Package Version Updates
This PR updates package versions in consuming projects to use the newly published packages.
**Published packages:**
${{ steps.publish.outputs.packages }}
**New version:** \`${{ steps.version.outputs.version }}\`
> ⚠️ **Do not auto-merge this PR** - Review the changes before merging.
> This PR was created automatically by the GitHub Actions workflow.
`,
head: branchName,
base: 'main',
draft: false
});
console.log(`✅ Created PR #${pr.data.number}: ${pr.data.html_url}`);
} catch (error) {
console.error('Error creating PR:', error.message);
}
- name: Create GitHub Release
if: steps.publish.outputs.published == 'true'
uses: actions/github-script@v7
with:
script: |
const { execSync } = require('child_process');
// Get latest tag
let latestTag;
try {
latestTag = execSync('git describe --tags --abbrev=0', { encoding: 'utf8' }).trim();
} catch (e) {
latestTag = '';
}
// Generate changelog
let changelog = '## Changes\n\n';
if (latestTag) {
try {
const commits = execSync(`git log ${latestTag}..HEAD --oneline --no-merges`, { encoding: 'utf8' })
.trim()
.split('\n')
.filter(line => line.length > 0)
.map(line => `- ${line}`)
.join('\n');
changelog += commits || 'No significant changes';
} catch (e) {
changelog += 'Unable to generate changelog';
}
} else {
changelog += 'Initial release';
}
// Check if release already exists and create or update accordingly
const tagName = `v${{ steps.version.outputs.version }}`;
const releaseBody = changelog + '\n\n**Published packages:**\n${{ steps.publish.outputs.packages }}';
try {
// Try to get existing release
const existingRelease = await github.rest.repos.getReleaseByTag({
owner: context.repo.owner,
repo: context.repo.repo,
tag: tagName
});
console.log(`Release ${tagName} already exists, updating it...`);
// Update existing release
await github.rest.repos.updateRelease({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: existingRelease.data.id,
name: tagName,
body: releaseBody,
draft: false,
prerelease: false
});
console.log(`✅ Updated existing release ${tagName}`);
} catch (error) {
if (error.status === 404) {
// Release doesn't exist, create it
console.log(`Creating new release ${tagName}...`);
await github.rest.repos.createRelease({
owner: context.repo.owner,
repo: context.repo.repo,
tag_name: tagName,
name: tagName,
body: releaseBody,
draft: false,
prerelease: false
});
console.log(`✅ Created new release ${tagName}`);
} else {
// Re-throw other errors
throw error;
}
}
trigger-vercel-production:
needs: [check-automation, check-changesets, publish-production]
if: needs.check-automation.outputs.should-skip != 'true' && needs.publish-production.outputs.published == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Trigger Vercel Production Deployments
id: deploy
run: |
# Parse project IDs from secrets
PROJECT_IDS='${{ secrets.VERCEL_PROJECT_IDS }}'
DEPLOYED_PROJECTS=""
DEPLOYMENT_URLS=""
echo "$PROJECT_IDS" | jq -r 'to_entries[] | "\(.key):\(.value)"' | while IFS=':' read -r PROJECT_NAME PROJECT_ID; do
echo "🚀 Deploying $PROJECT_NAME to production (ID: $PROJECT_ID)..."
# Create production deployment using Vercel API
RESPONSE=$(curl -s -X POST "https://api.vercel.com/v13/deployments" \
-H "Authorization: Bearer ${{ secrets.VERCEL_TOKEN }}" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"$PROJECT_NAME\",
\"project\": \"$PROJECT_ID\",
\"target\": \"production\",
\"gitSource\": {
\"type\": \"github\",
\"ref\": \"main\",
\"sha\": \"${{ github.sha }}\",
\"repoId\": ${{ github.event.repository.id }}
},
\"meta\": {
\"githubCommitSha\": \"${{ github.sha }}\",
\"githubCommitAuthorName\": \"${{ github.actor }}\",
\"packageVersion\": \"${{ needs.publish-production.outputs.version }}\",
\"deploymentType\": \"production\",
\"triggeredBy\": \"github-actions\"
}
}")
# Extract deployment URL and ID
DEPLOYMENT_URL=$(echo "$RESPONSE" | jq -r '.url // empty')
DEPLOYMENT_ID=$(echo "$RESPONSE" | jq -r '.id // empty')
ERROR_MESSAGE=$(echo "$RESPONSE" | jq -r '.error.message // empty')
if [ -n "$DEPLOYMENT_URL" ] && [ -n "$DEPLOYMENT_ID" ]; then
echo "✅ Successfully triggered production deployment for $PROJECT_NAME"
echo "📍 Production URL: https://$DEPLOYMENT_URL"
DEPLOYED_PROJECTS="$DEPLOYED_PROJECTS $PROJECT_NAME"
DEPLOYMENT_URLS="$DEPLOYMENT_URLS\\n- **$PROJECT_NAME**: https://$DEPLOYMENT_URL"
else
echo "❌ Failed to deploy $PROJECT_NAME to production"
if [ -n "$ERROR_MESSAGE" ]; then
echo "Error: $ERROR_MESSAGE"
fi
echo "Response: $RESPONSE"
fi
done
# Save results for GitHub release
echo "deployed_projects=$DEPLOYED_PROJECTS" >> $GITHUB_OUTPUT
echo -e "deployment_urls=$DEPLOYMENT_URLS" >> $GITHUB_OUTPUT
- name: Update GitHub Release with Deployment Info
if: steps.deploy.outputs.deployed_projects != ''
uses: actions/github-script@v7
with:
script: |
const deploymentUrls = `${{ steps.deploy.outputs.deployment_urls }}`;
const tagName = `v${{ needs.publish-production.outputs.version }}`;
// Get the release
let release;
try {
release = await github.rest.repos.getReleaseByTag({
owner: context.repo.owner,
repo: context.repo.repo,
tag: tagName
});
} catch (error) {
console.log('Release not found, skipping deployment URL update');
return;
}
// Update release body with deployment URLs
const updatedBody = release.data.body +
'\n\n## 🚀 Deployment URLs\n' +
deploymentUrls;
await github.rest.repos.updateRelease({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: release.data.id,
body: updatedBody
});