-
Notifications
You must be signed in to change notification settings - Fork 4
feat: implement preview packages with GitHub Actions and version conflict handling #57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
7dd31a4
7e1669c
5e28b9d
76d4d6f
f10f546
61a4676
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,182 @@ | ||||||||||||||||||||
name: 📦 Preview Packages | ||||||||||||||||||||
|
||||||||||||||||||||
# Run on pushes to branches (excluding master and next) after tests pass | ||||||||||||||||||||
on: | ||||||||||||||||||||
workflow_run: | ||||||||||||||||||||
workflows: ["🧪 Test code"] | ||||||||||||||||||||
types: | ||||||||||||||||||||
- completed | ||||||||||||||||||||
branches: | ||||||||||||||||||||
- "**" | ||||||||||||||||||||
- "!master" | ||||||||||||||||||||
- "!next" | ||||||||||||||||||||
|
||||||||||||||||||||
env: | ||||||||||||||||||||
HUSKY: 0 | ||||||||||||||||||||
|
||||||||||||||||||||
jobs: | ||||||||||||||||||||
preview-package: | ||||||||||||||||||||
# Only run if tests passed and commit contains [img:tag-name] pattern | ||||||||||||||||||||
if: github.event.workflow_run.conclusion == 'success' | ||||||||||||||||||||
runs-on: ubuntu-latest | ||||||||||||||||||||
permissions: | ||||||||||||||||||||
contents: read | ||||||||||||||||||||
id-token: write | ||||||||||||||||||||
pull-requests: write | ||||||||||||||||||||
issues: write | ||||||||||||||||||||
steps: | ||||||||||||||||||||
# Checkout repository | ||||||||||||||||||||
- name: 📥 Checkout code | ||||||||||||||||||||
uses: actions/checkout@v4 | ||||||||||||||||||||
with: | ||||||||||||||||||||
ref: ${{ github.event.workflow_run.head_branch }} | ||||||||||||||||||||
fetch-depth: 2 | ||||||||||||||||||||
|
||||||||||||||||||||
# Check if commit contains preview package pattern | ||||||||||||||||||||
- name: 🔍 Check for preview package pattern | ||||||||||||||||||||
id: check-pattern | ||||||||||||||||||||
run: | | ||||||||||||||||||||
COMMIT_MSG=$(git log -1 --pretty=%B) | ||||||||||||||||||||
echo "Commit message: $COMMIT_MSG" | ||||||||||||||||||||
|
||||||||||||||||||||
if [[ "$COMMIT_MSG" =~ \[img:([^\]]+)\] ]]; then | ||||||||||||||||||||
TAG_NAME="${BASH_REMATCH[1]}" | ||||||||||||||||||||
echo "Preview package detected with tag: $TAG_NAME" | ||||||||||||||||||||
echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT | ||||||||||||||||||||
echo "should_publish=true" >> $GITHUB_OUTPUT | ||||||||||||||||||||
else | ||||||||||||||||||||
echo "No preview package pattern found" | ||||||||||||||||||||
echo "should_publish=false" >> $GITHUB_OUTPUT | ||||||||||||||||||||
fi | ||||||||||||||||||||
|
||||||||||||||||||||
# Setup Node if we need to publish | ||||||||||||||||||||
- name: 📦 Setup Node.js | ||||||||||||||||||||
if: steps.check-pattern.outputs.should_publish == 'true' | ||||||||||||||||||||
uses: actions/setup-node@v4 | ||||||||||||||||||||
with: | ||||||||||||||||||||
node-version-file: .nvmrc | ||||||||||||||||||||
cache: "npm" | ||||||||||||||||||||
registry-url: "https://registry.npmjs.org" | ||||||||||||||||||||
|
||||||||||||||||||||
# Enable corepack | ||||||||||||||||||||
- name: ⚙️ Enable corepack | ||||||||||||||||||||
if: steps.check-pattern.outputs.should_publish == 'true' | ||||||||||||||||||||
run: corepack enable && corepack enable npm | ||||||||||||||||||||
|
||||||||||||||||||||
# Install dependencies | ||||||||||||||||||||
- name: 📦 Install dependencies | ||||||||||||||||||||
if: steps.check-pattern.outputs.should_publish == 'true' | ||||||||||||||||||||
run: npm ci | ||||||||||||||||||||
|
||||||||||||||||||||
# Create preview package version | ||||||||||||||||||||
- name: 📋 Create preview version | ||||||||||||||||||||
if: steps.check-pattern.outputs.should_publish == 'true' | ||||||||||||||||||||
id: version | ||||||||||||||||||||
run: | | ||||||||||||||||||||
# Get current version from package.json | ||||||||||||||||||||
CURRENT_VERSION=$(node -p "require('./package.json').version") | ||||||||||||||||||||
echo "Current version: $CURRENT_VERSION" | ||||||||||||||||||||
|
||||||||||||||||||||
# Create preview version by incrementing patch and adding tag | ||||||||||||||||||||
TAG_NAME="${{ steps.check-pattern.outputs.tag_name }}" | ||||||||||||||||||||
|
||||||||||||||||||||
# Split version into parts | ||||||||||||||||||||
IFS='.' read -ra VERSION_PARTS <<< "$CURRENT_VERSION" | ||||||||||||||||||||
MAJOR=${VERSION_PARTS[0]} | ||||||||||||||||||||
MINOR=${VERSION_PARTS[1]} | ||||||||||||||||||||
PATCH=${VERSION_PARTS[2]} | ||||||||||||||||||||
|
||||||||||||||||||||
# Increment patch version | ||||||||||||||||||||
NEW_PATCH=$((PATCH + 1)) | ||||||||||||||||||||
BASE_VERSION="$MAJOR.$MINOR.$NEW_PATCH-$TAG_NAME" | ||||||||||||||||||||
|
||||||||||||||||||||
# Check npm for existing versions with this pattern to find next available counter | ||||||||||||||||||||
PACKAGE_NAME=$(node -p "require('./package.json').name") | ||||||||||||||||||||
echo "Checking npm for existing versions of pattern: $BASE_VERSION.*" | ||||||||||||||||||||
|
||||||||||||||||||||
# Get all published versions and filter for our pattern | ||||||||||||||||||||
EXISTING_VERSIONS=$(npm view "$PACKAGE_NAME" versions --json 2>/dev/null || echo "[]") | ||||||||||||||||||||
HIGHEST_COUNTER=0 | ||||||||||||||||||||
|
||||||||||||||||||||
# Find the highest counter for this base version pattern | ||||||||||||||||||||
if [ "$EXISTING_VERSIONS" != "[]" ]; then | ||||||||||||||||||||
while IFS= read -r version; do | ||||||||||||||||||||
# Remove quotes from version string | ||||||||||||||||||||
clean_version=$(echo "$version" | tr -d '"') | ||||||||||||||||||||
# Check if version matches our pattern (base-tag.counter) | ||||||||||||||||||||
if [[ "$clean_version" =~ ^${BASE_VERSION}\.([0-9]+)$ ]]; then | ||||||||||||||||||||
counter="${BASH_REMATCH[1]}" | ||||||||||||||||||||
if [ "$counter" -gt "$HIGHEST_COUNTER" ]; then | ||||||||||||||||||||
HIGHEST_COUNTER="$counter" | ||||||||||||||||||||
fi | ||||||||||||||||||||
fi | ||||||||||||||||||||
done <<< "$(echo "$EXISTING_VERSIONS" | jq -r '.[]?' 2>/dev/null || echo "$EXISTING_VERSIONS" | grep -o '"[^"]*"' || echo)" | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The complex fallback chain with jq and grep may not handle all npm response formats correctly. When jq fails, the grep pattern
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||
fi | ||||||||||||||||||||
|
||||||||||||||||||||
# Increment counter for new version | ||||||||||||||||||||
NEW_COUNTER=$((HIGHEST_COUNTER + 1)) | ||||||||||||||||||||
PREVIEW_VERSION="$BASE_VERSION.$NEW_COUNTER" | ||||||||||||||||||||
|
||||||||||||||||||||
echo "Base version pattern: $BASE_VERSION" | ||||||||||||||||||||
echo "Highest existing counter: $HIGHEST_COUNTER" | ||||||||||||||||||||
echo "New counter: $NEW_COUNTER" | ||||||||||||||||||||
echo "Preview version: $PREVIEW_VERSION" | ||||||||||||||||||||
echo "preview_version=$PREVIEW_VERSION" >> $GITHUB_OUTPUT | ||||||||||||||||||||
|
||||||||||||||||||||
# Update package.json with preview version | ||||||||||||||||||||
npm version "$PREVIEW_VERSION" --no-git-tag-version | ||||||||||||||||||||
|
||||||||||||||||||||
# Publish preview package to npm | ||||||||||||||||||||
- name: 🚀 Publish preview package | ||||||||||||||||||||
if: steps.check-pattern.outputs.should_publish == 'true' | ||||||||||||||||||||
run: | | ||||||||||||||||||||
TAG_NAME="${{ steps.check-pattern.outputs.tag_name }}" | ||||||||||||||||||||
PREVIEW_VERSION="${{ steps.version.outputs.preview_version }}" | ||||||||||||||||||||
|
||||||||||||||||||||
echo "Publishing version $PREVIEW_VERSION with tag $TAG_NAME" | ||||||||||||||||||||
npm publish --tag "$TAG_NAME" --access public | ||||||||||||||||||||
|
||||||||||||||||||||
echo "✅ Preview package published successfully!" | ||||||||||||||||||||
echo "📦 Install with: npm install astro-loader-pocketbase@$TAG_NAME" | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The package name 'astro-loader-pocketbase' is hardcoded in the installation command, but the actual package name is already retrieved from package.json on line 92. Use the
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||
echo "🔖 Version: $PREVIEW_VERSION" | ||||||||||||||||||||
env: | ||||||||||||||||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | ||||||||||||||||||||
|
||||||||||||||||||||
# Comment on PR if this is from a pull request | ||||||||||||||||||||
- name: 💬 Comment on PR | ||||||||||||||||||||
if: steps.check-pattern.outputs.should_publish == 'true' | ||||||||||||||||||||
uses: actions/github-script@v7 | ||||||||||||||||||||
with: | ||||||||||||||||||||
script: | | ||||||||||||||||||||
const tagName = '${{ steps.check-pattern.outputs.tag_name }}'; | ||||||||||||||||||||
const previewVersion = '${{ steps.version.outputs.preview_version }}'; | ||||||||||||||||||||
|
||||||||||||||||||||
const comment = `🎭 **Preview Package Published** | ||||||||||||||||||||
|
||||||||||||||||||||
A preview version of this package has been published to npm: | ||||||||||||||||||||
|
||||||||||||||||||||
\`\`\`bash | ||||||||||||||||||||
npm install astro-loader-pocketbase@${tagName} | ||||||||||||||||||||
\`\`\` | ||||||||||||||||||||
|
||||||||||||||||||||
**Version:** \`${previewVersion}\` | ||||||||||||||||||||
**Tag:** \`${tagName}\` | ||||||||||||||||||||
|
||||||||||||||||||||
This preview package can be used to test changes before merging.`; | ||||||||||||||||||||
|
||||||||||||||||||||
// Find the PR number from the workflow run | ||||||||||||||||||||
const prs = await github.rest.pulls.list({ | ||||||||||||||||||||
owner: context.repo.owner, | ||||||||||||||||||||
repo: context.repo.repo, | ||||||||||||||||||||
head: `${context.repo.owner}:${{ github.event.workflow_run.head_branch }}`, | ||||||||||||||||||||
state: 'open' | ||||||||||||||||||||
}); | ||||||||||||||||||||
|
||||||||||||||||||||
if (prs.data.length > 0) { | ||||||||||||||||||||
await github.rest.issues.createComment({ | ||||||||||||||||||||
owner: context.repo.owner, | ||||||||||||||||||||
repo: context.repo.repo, | ||||||||||||||||||||
issue_number: prs.data[0].number, | ||||||||||||||||||||
body: comment | ||||||||||||||||||||
}); | ||||||||||||||||||||
} |
Uh oh!
There was an error while loading. Please reload this page.