New Extension #33
This file contains 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: Create or Update Extension | |
on: | |
issues: | |
types: [opened, edited] | |
jobs: | |
process-extension: | |
if: contains(github.event.issue.labels.*.name, 'new-extension') | |
runs-on: ubuntu-latest | |
permissions: | |
contents: write | |
issues: write | |
steps: | |
- uses: actions/checkout@v3 | |
- name: Setup Node.js | |
uses: actions/setup-node@v3 | |
with: | |
node-version: '18' | |
- name: Parse Issue and Download Files | |
id: parse | |
uses: actions/github-script@v6 | |
with: | |
script: | | |
const body = context.payload.issue.body; | |
const lines = body.split('\n'); | |
const extension = {}; | |
// Parse basic info | |
lines.forEach(line => { | |
if (line.startsWith('**Name:**')) extension.name = line.replace('**Name:**', '').trim(); | |
if (line.startsWith('**Description:**')) extension.description = line.replace('**Description:**', '').trim(); | |
if (line.startsWith('**Version:**')) extension.version = line.replace('**Version:**', '').trim(); | |
if (line.startsWith('**Author:**')) extension.author = line.replace('**Author:**', '').trim(); | |
if (line.toLowerCase().includes('tags') && line.includes('comma-separated')) { | |
const tagsMatch = line.match(/:(.*)/); | |
if (tagsMatch) { | |
const tagsStr = tagsMatch[1].trim(); | |
extension.tags = tagsStr.split(',').map(tag => tag.trim()).filter(tag => tag); | |
console.log('Found tags:', extension.tags); | |
} | |
} | |
}); | |
// Find ZIP attachment | |
const attachmentPatterns = [ | |
/https:\/\/user-images\.githubusercontent\.com\/[^\s)]+\.zip/g, | |
/https:\/\/github\.com\/[^\s)]+\/files\/[^\s)]+\.zip/g | |
]; | |
let attachments = []; | |
attachmentPatterns.forEach(pattern => { | |
const matches = body.match(pattern) || []; | |
attachments.push(...matches); | |
}); | |
const zipFile = attachments[0]; | |
if (!zipFile) { | |
console.log('No ZIP file found in attachments'); | |
throw new Error('Missing required ZIP file containing .crx and icon.'); | |
} | |
// Keep the original URL for GitHub-uploaded files | |
extension.zip_url = zipFile; | |
console.log('ZIP URL:', extension.zip_url); | |
return extension; | |
- name: Create Directory Structure | |
run: | | |
mkdir -p extensions | |
touch extensions/.gitkeep | |
- name: Download and Process ZIP | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
run: | | |
# Create temp directory | |
mkdir -p temp | |
cd temp | |
# Get extension name and create safe name | |
EXTENSION_NAME="${{ fromJSON(steps.parse.outputs.result).name }}" | |
if [ -z "$EXTENSION_NAME" ]; then | |
echo "Extension name not found in issue" | |
exit 1 | |
fi | |
# Generate safe name for directory | |
SAFE_NAME=$(echo "$EXTENSION_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-zA-Z0-9-]/-/g') | |
echo "Extension name: $EXTENSION_NAME" | |
echo "Safe name for directory: $SAFE_NAME" | |
# Create extension directory early | |
mkdir -p "../extensions/${SAFE_NAME}" | |
echo "Created directory: ../extensions/${SAFE_NAME}" | |
# Download and extract ZIP | |
ZIP_URL="${{ fromJSON(steps.parse.outputs.result).zip_url }}" | |
echo "Original ZIP URL: $ZIP_URL" | |
if [[ "$ZIP_URL" == *"user-images.githubusercontent.com"* ]]; then | |
curl -L -o package.zip "$ZIP_URL" | |
else | |
FILE_ID=$(echo "$ZIP_URL" | grep -o '/files/[0-9]\+/' | grep -o '[0-9]\+') | |
echo "File ID: $FILE_ID" | |
DOWNLOAD_URL=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \ | |
-H "Accept: application/vnd.github.v3+json" \ | |
"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments" | \ | |
jq -r --arg file_id "$FILE_ID" '.[] | | |
select(.body | contains($file_id)) | | |
capture("(?<url>https://github\\.com/[^)]+\\.zip)") | | |
.url') | |
echo "Download URL from API: $DOWNLOAD_URL" | |
if [ -z "$DOWNLOAD_URL" ]; then | |
DOWNLOAD_URL=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \ | |
-H "Accept: application/vnd.github.v3+json" \ | |
"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}" | \ | |
jq -r --arg file_id "$FILE_ID" '.body | | |
capture("(?<url>https://github\\.com/[^)]+\\.zip)") | | |
.url') | |
fi | |
if [ -z "$DOWNLOAD_URL" ]; then | |
DOWNLOAD_URL="$ZIP_URL" | |
fi | |
echo "Final download URL: $DOWNLOAD_URL" | |
curl -L -H "Authorization: token $GITHUB_TOKEN" \ | |
-H "Accept: application/octet-stream" \ | |
-o package.zip "$DOWNLOAD_URL" | |
fi | |
if [ ! -f package.zip ]; then | |
echo "Failed to download ZIP file" | |
exit 1 | |
fi | |
echo "Download successful. File size:" | |
ls -lh package.zip | |
echo "Extracting ZIP file..." | |
unzip -v package.zip | |
unzip package.zip | |
echo "Current directory contents:" | |
ls -la | |
echo "Parent directory contents:" | |
ls -la .. | |
echo "Extensions directory contents:" | |
ls -la ../extensions/ | |
# Find extracted directory (could be any name) | |
EXTRACTED_DIR=$(find . -type d -mindepth 1 -maxdepth 1 | head -n 1) | |
if [ -n "$EXTRACTED_DIR" ]; then | |
cd "$EXTRACTED_DIR" | |
echo "Entered extracted directory: $EXTRACTED_DIR" | |
echo "Contents:" | |
ls -la | |
fi | |
# Check for files with more flexible patterns | |
CRX_FILE=$(find . -type f -name "*.crx" | head -n 1) | |
if [ -z "$CRX_FILE" ]; then | |
echo "Looking for alternative CRX file..." | |
CRX_FILE=$(find . -type f -name "build.crx" -o -name "extension.crx" | head -n 1) | |
fi | |
ICON_FILE=$(find . -type f -name "icon*.png" | head -n 1) | |
if [ -z "$ICON_FILE" ]; then | |
echo "Looking for alternative icon file..." | |
ICON_FILE=$(find . -type f -name "*.png" | head -n 1) | |
fi | |
if [ -z "$CRX_FILE" ] || [ -z "$ICON_FILE" ]; then | |
echo "Missing required files" | |
echo "CRX file found: $CRX_FILE" | |
echo "Icon file found: $ICON_FILE" | |
echo "Directory contents:" | |
find . -type f | |
exit 1 | |
fi | |
echo "Found files:" | |
echo "CRX: $CRX_FILE" | |
echo "Icon: $ICON_FILE" | |
# Copy files to final location | |
echo "Copying files to: ../extensions/${SAFE_NAME}/" | |
cp "$CRX_FILE" "../extensions/${SAFE_NAME}/${SAFE_NAME}.crx" | |
cp "$ICON_FILE" "../extensions/${SAFE_NAME}/icon.png" | |
# Verify files were copied | |
echo "Final extension directory contents:" | |
ls -la "../extensions/${SAFE_NAME}/" | |
# Clean up | |
cd .. | |
rm -rf temp | |
- name: Update Extensions JSON | |
run: | | |
SAFE_NAME=$(echo "${{ fromJSON(steps.parse.outputs.result).name }}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-zA-Z0-9-]/-/g') | |
# Generate URLs using GitHub API format | |
REPO="${{ github.repository }}" | |
BRANCH="main" | |
PATH_PREFIX="extensions/${SAFE_NAME}" | |
DOWNLOAD_URL="https://api.github.com/repos/${REPO}/contents/${PATH_PREFIX}/${SAFE_NAME}.crx?ref=${BRANCH}" | |
ICON_URL="https://api.github.com/repos/${REPO}/contents/${PATH_PREFIX}/icon.png?ref=${BRANCH}" | |
GITHUB_URL="https://github.com/${REPO}/tree/${BRANCH}/${PATH_PREFIX}" | |
# Initialize extensions.json if it doesn't exist | |
if [ ! -f extensions.json ]; then | |
echo '{"extensions": []}' > extensions.json | |
fi | |
# Convert tags array to JSON string | |
TAGS_JSON=$(echo '${{ toJSON(fromJSON(steps.parse.outputs.result).tags) }}') | |
# Update existing entry or add new one | |
jq --arg name "${{ fromJSON(steps.parse.outputs.result).name }}" \ | |
--arg desc "${{ fromJSON(steps.parse.outputs.result).description }}" \ | |
--arg ver "${{ fromJSON(steps.parse.outputs.result).version }}" \ | |
--arg author "${{ fromJSON(steps.parse.outputs.result).author }}" \ | |
--arg download "$DOWNLOAD_URL" \ | |
--arg icon "$ICON_URL" \ | |
--arg github "$GITHUB_URL" \ | |
--argjson tags "$TAGS_JSON" \ | |
--arg now "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \ | |
' | |
def update_extension: | |
if .name == $name then | |
. + { | |
"description": $desc, | |
"version": $ver, | |
"author": $author, | |
"download_url": $download, | |
"icon_url": $icon, | |
"github_url": $github, | |
"tags": $tags, | |
"updated_at": $now | |
} | |
else | |
. | |
end; | |
if (.extensions | map(.name == $name) | any) | |
then | |
.extensions |= map(update_extension) | |
else | |
.extensions += [{ | |
"id": ((.extensions | length) + 1 | tostring), | |
"name": $name, | |
"description": $desc, | |
"version": $ver, | |
"author": $author, | |
"download_url": $download, | |
"icon_url": $icon, | |
"github_url": $github, | |
"tags": $tags, | |
"created_at": $now, | |
"updated_at": $now | |
}] | |
end | |
' extensions.json > temp.json && mv temp.json extensions.json | |
- name: Commit and Push Changes | |
run: | | |
git config --local user.email "[email protected]" | |
git config --local user.name "GitHub Action" | |
# Create directories if they don't exist | |
mkdir -p extensions | |
# Stage all changes | |
git add -f extensions/ | |
git add -f extensions.json | |
# Only commit if there are changes | |
if git diff --staged --quiet; then | |
echo "No changes to commit" | |
else | |
git commit -m "Update extension: ${{ fromJSON(steps.parse.outputs.result).name }}" | |
git push | |
fi | |
- name: Comment on Issue | |
uses: actions/github-script@v6 | |
with: | |
script: | | |
github.rest.issues.createComment({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
issue_number: context.payload.issue.number, | |
body: `Extension has been successfully ${context.payload.action === 'opened' ? 'added' : 'updated'}!\n\nDownload URL: ${process.env.DOWNLOAD_URL}\nIcon URL: ${process.env.ICON_URL}\nGitHub URL: ${process.env.GITHUB_URL}` | |
}); |