Skip to content

test: workflow test #17

test: workflow test

test: workflow test #17

name: Preview Package Publishing
on:
pull_request:
branches: [feat/v3]
paths:
- 'packages/**'
types: [opened, synchronize, reopened]
jobs:
check-changes:
runs-on: ubuntu-latest
outputs:
packages-changed: ${{ steps.changes.outputs.packages }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: dorny/paths-filter@v2
id: changes
with:
filters: |
packages:
- 'packages/**'
publish-preview:
needs: check-changes
if: needs.check-changes.outputs.packages-changed == 'true'
runs-on: ubuntu-latest
outputs:
published: ${{ steps.publish.outputs.published }}
version: ${{ steps.version.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: Build workspace dependencies
run: |
echo "🔨 Building all packages in dependency order..."
# Use yarn workspaces to build in proper order, but continue if some fail
yarn workspaces foreach --verbose --topological-dev run build || echo "⚠️ Some builds failed, but continuing..."
- name: Update internal package references
run: |
echo "🔄 Updating internal package references to preview versions..."
# Update all package.json files to reference the preview versions of internal packages
for package_dir in packages/*/; do
if [ ! -f "${package_dir}package.json" ]; then
continue
fi
package_file="${package_dir}package.json"
# Update dependencies that reference other packages in this monorepo
node -e "
const fs = require('fs');
const path = require('path');
const pkg = JSON.parse(fs.readFileSync('$package_file', 'utf8'));
const previewVersion = '${{ steps.version.outputs.version }}';
// Update dependencies
['dependencies', 'devDependencies', 'peerDependencies'].forEach(depType => {
if (pkg[depType]) {
Object.keys(pkg[depType]).forEach(dep => {
// If this dependency starts with @gluestack-ui-nightly, update it to preview version
if (dep.startsWith('@gluestack-ui-nightly/')) {
console.log(\`Updating \${dep} to \${previewVersion} in \${depType}\`);
pkg[depType][dep] = previewVersion;
}
});
}
});
fs.writeFileSync('$package_file', JSON.stringify(pkg, null, 2) + '\n');
"
done
- name: Generate preview version
id: version
run: |
PR_NUMBER=${{ github.event.pull_request.number }}
SHORT_SHA=$(git rev-parse --short HEAD)
PREVIEW_VERSION="0.0.0-pr-${PR_NUMBER}-${SHORT_SHA}"
echo "version=${PREVIEW_VERSION}" >> $GITHUB_OUTPUT
echo "🏷️ Generated preview version: ${PREVIEW_VERSION}"
- name: Update package versions
run: |
# Update only root-level package.json files in packages/ directory (not node_modules)
for package_dir in packages/*/; do
if [ ! -f "${package_dir}package.json" ]; then
continue
fi
# Skip if it's a node_modules directory
if [[ "$package_dir" == *"/node_modules/"* ]]; then
continue
fi
package_file="${package_dir}package.json"
# Create backup
cp "$package_file" "$package_file.bak"
# Update version using Node.js
node -e "
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('$package_file', 'utf8'));
pkg.version = '${{ steps.version.outputs.version }}';
fs.writeFileSync('$package_file', JSON.stringify(pkg, null, 2) + '\n');
"
echo "✅ Updated version in $package_file to ${{ steps.version.outputs.version }}"
done
- name: Setup NPM authentication
run: |
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
- name: Publish preview packages
id: publish
run: |
# Create a temporary file to track published packages
PUBLISHED_PACKAGES_FILE=$(mktemp)
SUCCESS=false
# Get packages in dependency order
echo "📋 Determining package publish order..."
PACKAGE_DIRS=$(find packages -maxdepth 1 -type d -name "*" | grep -v "^packages$" | sort)
for package_dir in $PACKAGE_DIRS; do
if [ ! -f "${package_dir}/package.json" ]; then
continue
fi
# Skip if it's a node_modules directory
if [[ "$package_dir" == *"/node_modules/"* ]]; then
continue
fi
PACKAGE_JSON=$(cat "${package_dir}/package.json")
PACKAGE_NAME=$(echo "$PACKAGE_JSON" | node -e "
try {
const pkg = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8'));
console.log(pkg.name || '');
} catch(e) { console.log(''); }
")
IS_PRIVATE=$(echo "$PACKAGE_JSON" | node -e "
try {
const pkg = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8'));
console.log(pkg.private === true ? 'true' : 'false');
} catch(e) { console.log('false'); }
")
if [ -z "$PACKAGE_NAME" ]; then
echo "⏭️ Skipping package with no name in $package_dir"
continue
fi
if [ "$IS_PRIVATE" = "true" ]; then
echo "⏭️ Skipping private package: $PACKAGE_NAME"
continue
fi
echo "📦 Publishing $PACKAGE_NAME from $package_dir..."
cd "$package_dir"
# Always run build for each package individually before publishing
if npm run --list 2>/dev/null | grep -q "\bbuild\b"; then
echo "🔨 Building $PACKAGE_NAME..."
if ! npm run build; then
echo "❌ Build failed for $PACKAGE_NAME, skipping publish"
cd - > /dev/null
continue
fi
fi
# Publish with preview tag
if npm publish --tag preview --access public; then
echo "✅ Successfully published $PACKAGE_NAME@${{ steps.version.outputs.version }}"
echo "$PACKAGE_NAME@${{ steps.version.outputs.version }}" >> "$PUBLISHED_PACKAGES_FILE"
SUCCESS=true
else
echo "⚠️ Failed to publish $PACKAGE_NAME, but continuing with other packages"
fi
cd - > /dev/null
done
if [ "$SUCCESS" = true ]; then
# Read all published packages into a single variable
PUBLISHED_PACKAGES=$(cat "$PUBLISHED_PACKAGES_FILE" | tr '\n' ' ' | sed 's/ $//')
echo "published=true" >> $GITHUB_OUTPUT
echo "packages=$PUBLISHED_PACKAGES" >> $GITHUB_OUTPUT
echo "📋 Published packages: $PUBLISHED_PACKAGES"
else
echo "published=false" >> $GITHUB_OUTPUT
echo "❌ No packages were published successfully"
fi
# Cleanup
rm -f "$PUBLISHED_PACKAGES_FILE"
- name: Restore package.json files
if: always()
run: |
# Restore original package.json files
for package_dir in packages/*/; do
if [ ! -f "${package_dir}package.json.bak" ]; then
continue
fi
backup_file="${package_dir}package.json.bak"
original_file="${package_dir}package.json"
mv "$backup_file" "$original_file"
echo "✅ Restored $original_file"
done
- name: Comment on PR
if: steps.publish.outputs.published == 'true'
uses: actions/github-script@v7
with:
script: |
const packages = `${{ steps.publish.outputs.packages }}`.trim();
if (!packages) {
console.log('No packages published, skipping comment');
return;
}
const comment = `## 🚀 Preview packages published!
**Version:** \`${{ steps.version.outputs.version }}\`
**Published packages:**
${packages.split(' ').map(pkg => `- \`${pkg}\``).join('\n')}
**Install commands:**
\`\`\`bash
# Install specific package
npm install <package-name>@${{ steps.version.outputs.version }}
# Or with yarn
yarn add <package-name>@${{ steps.version.outputs.version }}
\`\`\`
> 💡 These are preview packages for testing only.`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
trigger-vercel-preview:
needs: [check-changes, publish-preview]
if: needs.publish-preview.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: Debug outputs
run: |
echo "🔍 Debugging job outputs:"
echo "Published: ${{ needs.publish-preview.outputs.published }}"
echo "Version: ${{ needs.publish-preview.outputs.version }}"
echo "Packages: ${{ needs.publish-preview.outputs.packages }}"
- name: Trigger Vercel Preview Deployments
id: deploy
run: |
# Parse project IDs from secrets
PROJECT_IDS='${{ secrets.VERCEL_PROJECT_IDS }}'
DEPLOYED_PROJECTS=""
DEPLOYMENT_URLS=""
PACKAGE_VERSION="${{ needs.publish-preview.outputs.version }}"
echo "📦 Using package version: $PACKAGE_VERSION"
if [ -z "$PACKAGE_VERSION" ]; then
echo "❌ Package version is empty, cannot proceed with deployment"
exit 1
fi
echo "$PROJECT_IDS" | jq -r 'to_entries[] | "\(.key):\(.value)"' | while IFS=':' read -r PROJECT_NAME PROJECT_ID; do
echo "🚀 Deploying $PROJECT_NAME (ID: $PROJECT_ID)..."
# Create deployment using Vercel API with Git source for code changes
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\",
\"gitSource\": {
\"type\": \"github\",
\"ref\": \"${{ github.head_ref }}\",
\"sha\": \"${{ github.sha }}\",
\"repoId\": ${{ github.event.repository.id }}
},
\"meta\": {
\"githubCommitSha\": \"${{ github.sha }}\",
\"githubCommitAuthorName\": \"${{ github.actor }}\",
\"githubCommitMessage\": \"${{ github.event.pull_request.title }}\",
\"githubPR\": \"${{ github.event.pull_request.number }}\",
\"triggeredBy\": \"github-actions\",
\"packageVersion\": \"$PACKAGE_VERSION\"
}
}")
# 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 deployment for $PROJECT_NAME"
echo "📍 Preview 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"
if [ -n "$ERROR_MESSAGE" ]; then
echo "Error: $ERROR_MESSAGE"
fi
echo "Response: $RESPONSE"
fi
done
# Save results for next step
echo "deployed_projects=$DEPLOYED_PROJECTS" >> $GITHUB_OUTPUT
echo -e "deployment_urls=$DEPLOYMENT_URLS" >> $GITHUB_OUTPUT
- name: Update PR with Vercel deployment info
uses: actions/github-script@v7
with:
script: |
const deploymentUrls = `${{ steps.deploy.outputs.deployment_urls }}`.trim();
const deployedProjects = `${{ steps.deploy.outputs.deployed_projects }}`.trim();
const packageVersion = `${{ needs.publish-preview.outputs.version }}`;
if (!deployedProjects) {
const errorComment = `## ⚠️ Vercel deployment failed
**Package Version:** \`${packageVersion}\`
No projects were deployed successfully. Please check the [workflow logs](${context.payload.repository.html_url}/actions/runs/${context.runId}) for details.
**Possible issues:**
- Git not connected to Vercel projects
- Incorrect project IDs in VERCEL_PROJECT_IDS
- Vercel token permissions
`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: errorComment
});
return;
}
const successComment = `## 🚀 Vercel preview deployments successful!
**Package Version:** \`${packageVersion}\`
**Deployed Projects:**${deploymentUrls}
⏱️ Deployments are building. Check your [Vercel dashboard](https://vercel.com/dashboard) for detailed status.
`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: successComment
});