test: workflow test #17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | |
| }); |