diff --git a/.github/workflows/notify-dependents.yml b/.github/workflows/notify-dependents.yml new file mode 100644 index 0000000..c63fa06 --- /dev/null +++ b/.github/workflows/notify-dependents.yml @@ -0,0 +1,182 @@ +name: Notify Dependent Projects + +on: + push: + branches: + - dev + - int + - stg + - prd + - test + - 'release**' + +permissions: + contents: read + +jobs: + notify-dependents: + name: Notify Dependent Projects + runs-on: ubuntu-latest + environment: dependency-management + + outputs: + dependent-repos: ${{ steps.parse-dependents.outputs.dependent-repos }} + repo-count: ${{ steps.parse-dependents.outputs.repo-count }} + commit-hash: ${{ steps.commit-info.outputs.commit-hash }} + branch-name: ${{ steps.commit-info.outputs.branch-name }} + project-name: ${{ steps.commit-info.outputs.project-name }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + + - name: Get commit information + id: commit-info + run: | + COMMIT_HASH="${{ github.sha }}" + BRANCH_NAME="${{ github.ref_name }}" + PROJECT_NAME="${{ github.repository }}" + + echo "commit-hash=$COMMIT_HASH" >> $GITHUB_OUTPUT + echo "branch-name=$BRANCH_NAME" >> $GITHUB_OUTPUT + echo "project-name=$PROJECT_NAME" >> $GITHUB_OUTPUT + + echo "Commit information:" + echo "- Hash: $COMMIT_HASH" + echo "- Branch: $BRANCH_NAME" + echo "- Project: $PROJECT_NAME" + + - name: create-json + id: create-json + uses: jsdaniell/create-json@v1.2.3 + with: + name: "dependent-projects.json" + json: ${{ vars.DEPENDENT_PROJECTS }} + + - name: Parse dependent projects + id: parse-dependents + run: | + # Install jq for JSON parsing + sudo apt-get update && sudo apt-get install -y jq + + # Validate and parse JSON + if ! cat dependent-projects.json | jq empty; then + echo "Error: DEPENDENT_PROJECTS is not valid JSON" + exit 1 + fi + + if [ ! -s dependent-projects.json ]; then + echo "No dependent projects configured in DEPENDENT_PROJECTS environment variable." + echo "dependent-repos=[]" >> $GITHUB_OUTPUT + REPO_COUNT=$(cat dependent-projects.json | jq length) + echo "repo-count=0" >> $GITHUB_OUTPUT + exit 0 + fi + + # Extract array of repositories + REPOS=$(cat dependent-projects.json | jq -r '.[]' | tr '\n' ' ') + echo "Parsed repositories: $REPOS" + + # Convert to JSON array for matrix + REPOS_JSON=$(cat dependent-projects.json | jq -c .) + echo "dependent-repos=$REPOS_JSON" >> $GITHUB_OUTPUT + + # Count repositories + REPO_COUNT=$(cat dependent-projects.json | jq length) + echo "repo-count=$REPO_COUNT" >> $GITHUB_OUTPUT + + echo "Found $REPO_COUNT dependent repositories" + + - name: Validate dependent repositories + if: fromJson(steps.parse-dependents.outputs.repo-count) > 0 + run: | + REPOS='${{ steps.parse-dependents.outputs.dependent-repos }}' + + echo "$REPOS" | jq -r '.[]' | while read -r repo; do + if [[ ! "$repo" =~ ^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$ ]]; then + echo "Error: Invalid repository format: $repo" + echo "Expected format: organization/repository" + exit 1 + fi + echo "✓ Valid repository format: $repo" + done + + dispatch-updates: + name: Dispatch to Dependent Projects + runs-on: ubuntu-latest + needs: notify-dependents + if: fromJson(needs.notify-dependents.outputs.repo-count) > 0 + environment: dependency-management + strategy: + matrix: + repository: ${{ fromJson(needs.notify-dependents.outputs.dependent-repos) }} + fail-fast: false + max-parallel: 5 + + steps: + - name: Generate GitHub App Token + id: app-token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ secrets.IR_REPO_AUTH_APP_ID }} + private-key: ${{ secrets.IR_REPO_AUTH_PRIVATE_KEY }} + owner: theinfinitereality + + - name: Dispatch repository update + uses: peter-evans/repository-dispatch@v3 + with: + token: ${{ steps.app-token.outputs.token }} + repository: ${{ matrix.repository }} + event-type: update-dependency + client-payload: | + { + "project_name": "${{ needs.notify-dependents.outputs.project-name }}", + "commit_hash": "${{ needs.notify-dependents.outputs.commit-hash }}", + "branch": "${{ needs.notify-dependents.outputs.branch-name }}" + } + + - name: Log dispatch + run: | + echo "Successfully dispatched update to ${{ matrix.repository }}" + echo "Payload sent:" + echo "- project_name: ${{ needs.notify-dependents.outputs.project-name }}" + echo "- commit_hash: ${{ needs.notify-dependents.outputs.commit-hash }}" + echo "- branch: ${{ needs.notify-dependents.outputs.branch-name }}" + + summary: + name: Create Summary + runs-on: ubuntu-latest + needs: [notify-dependents, dispatch-updates] + if: always() + + steps: + - name: Create dispatch summary + run: | + REPO_COUNT="${{ needs.notify-dependents.outputs.repo-count }}" + PROJECT_NAME="${{ needs.notify-dependents.outputs.project-name }}" + COMMIT_HASH="${{ needs.notify-dependents.outputs.commit-hash }}" + BRANCH_NAME="${{ needs.notify-dependents.outputs.branch-name }}" + + echo "## Dependency Notification Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "- **Source Project**: \`$PROJECT_NAME\`" >> $GITHUB_STEP_SUMMARY + echo "- **Commit**: \`$COMMIT_HASH\`" >> $GITHUB_STEP_SUMMARY + echo "- **Branch**: \`$BRANCH_NAME\`" >> $GITHUB_STEP_SUMMARY + echo "- **Dependent Projects**: $REPO_COUNT" >> $GITHUB_STEP_SUMMARY + + if [ "$REPO_COUNT" -gt 0 ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Notified Repositories" >> $GITHUB_STEP_SUMMARY + REPOS='${{ needs.notify-dependents.outputs.dependent-repos }}' + echo "$REPOS" | jq -r '.[]' | while read -r repo; do + echo "- \`$repo\`" >> $GITHUB_STEP_SUMMARY + done + else + echo "" >> $GITHUB_STEP_SUMMARY + echo "No dependent projects configured in DEPENDENT_PROJECTS environment variable." >> $GITHUB_STEP_SUMMARY + fi diff --git a/.github/workflows/update-dependency.yml b/.github/workflows/update-dependency.yml new file mode 100644 index 0000000..5abae94 --- /dev/null +++ b/.github/workflows/update-dependency.yml @@ -0,0 +1,168 @@ +name: Update Dependency + +on: + repository_dispatch: + types: + - update-dependency + +permissions: + contents: write + pull-requests: write + +jobs: + update-manifest: + name: Update Project Manifest + runs-on: ubuntu-latest + + steps: + - name: Generate GitHub App Token + id: app-token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ secrets.IR_REPO_AUTH_APP_ID }} + private-key: ${{ secrets.IR_REPO_AUTH_PRIVATE_KEY }} + owner: theinfinitereality + + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ github.event.client_payload.branch }} + token: ${{ steps.app-token.outputs.token }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + + - name: Validate payload + run: | + echo "Received payload:" + echo "Project name: ${{ github.event.client_payload.project_name }}" + echo "Commit hash: ${{ github.event.client_payload.commit_hash }}" + echo "Branch: ${{ github.event.client_payload.branch }}" + + if [ -z "${{ github.event.client_payload.project_name }}" ]; then + echo "Error: project_name is required" + exit 1 + fi + + if [ -z "${{ github.event.client_payload.commit_hash }}" ]; then + echo "Error: commit_hash is required" + exit 1 + fi + + if [ -z "${{ github.event.client_payload.branch }}" ]; then + echo "Error: branch is required" + exit 1 + fi + + - name: Check if manifest.json exists + run: | + if [ ! -f "manifest.json" ]; then + echo "Error: manifest.json not found in repository root" + exit 1 + fi + + - name: Update manifest.json + run: | + PROJECT_NAME="${{ github.event.client_payload.project_name }}" + COMMIT_HASH="${{ github.event.client_payload.commit_hash }}" + + # Install jq for JSON manipulation + sudo apt-get update && sudo apt-get install -y jq + + # Create a backup of the original manifest + cp manifest.json manifest.json.backup + + # Check if dependencies array exists, create if it doesn't + if ! jq -e '.dependencies' manifest.json > /dev/null; then + echo "Creating dependencies array in manifest.json" + jq '. + {"dependencies": []}' manifest.json > manifest.json.tmp && mv manifest.json.tmp manifest.json + fi + + # Check if the project already exists in dependencies + EXISTING_INDEX=$(jq --arg name "$PROJECT_NAME" '.dependencies | map(.name) | index($name)' manifest.json) + + if [ "$EXISTING_INDEX" != "null" ]; then + echo "Updating existing dependency: $PROJECT_NAME" + # Update existing entry's commit hash + jq --arg name "$PROJECT_NAME" --arg commit "$COMMIT_HASH" \ + '.dependencies = (.dependencies | map(if .name == $name then .commit = $commit else . end))' \ + manifest.json > manifest.json.tmp && mv manifest.json.tmp manifest.json + else + echo "Adding new dependency: $PROJECT_NAME" + # Add new dependency entry + jq --arg name "$PROJECT_NAME" --arg commit "$COMMIT_HASH" \ + '.dependencies += [{"name": $name, "commit": $commit}]' \ + manifest.json > manifest.json.tmp && mv manifest.json.tmp manifest.json + fi + + # Validate the updated JSON + if ! jq empty manifest.json; then + echo "Error: Invalid JSON generated. Restoring backup." + mv manifest.json.backup manifest.json + exit 1 + fi + + echo "Successfully updated manifest.json" + echo "Updated dependencies:" + jq '.dependencies' manifest.json + + - name: Check for changes + id: check-changes + run: | + if git diff --quiet manifest.json; then + echo "No changes detected in manifest.json" + echo "has-changes=false" >> $GITHUB_OUTPUT + else + echo "Changes detected in manifest.json" + echo "has-changes=true" >> $GITHUB_OUTPUT + fi + + - name: Commit and push changes + if: steps.check-changes.outputs.has-changes == 'true' + env: + token: ${{ steps.app-token.outputs.token }} + run: | + PROJECT_NAME="${{ github.event.client_payload.project_name }}" + COMMIT_HASH="${{ github.event.client_payload.commit_hash }}" + SHORT_HASH="${COMMIT_HASH:0:8}" + + # Configure git + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + + # Add and commit changes + git add manifest.json + git commit -m "Update dependency $PROJECT_NAME to commit $SHORT_HASH + + - Project: $PROJECT_NAME + - Commit: $COMMIT_HASH + - Updated via: repository_dispatch" + + # Push changes + git push origin ${{ github.event.client_payload.branch }} + + echo "Successfully committed and pushed dependency update" + + - name: Create summary + run: | + PROJECT_NAME="${{ github.event.client_payload.project_name }}" + COMMIT_HASH="${{ github.event.client_payload.commit_hash }}" + BRANCH="${{ github.event.client_payload.branch }}" + HAS_CHANGES="${{ steps.check-changes.outputs.has-changes }}" + + echo "## Dependency Update Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "- **Project**: \`$PROJECT_NAME\`" >> $GITHUB_STEP_SUMMARY + echo "- **Commit**: \`$COMMIT_HASH\`" >> $GITHUB_STEP_SUMMARY + echo "- **Branch**: \`$BRANCH\`" >> $GITHUB_STEP_SUMMARY + echo "- **Changes Made**: $HAS_CHANGES" >> $GITHUB_STEP_SUMMARY + + if [ "$HAS_CHANGES" = "true" ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Updated Dependencies" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`json" >> $GITHUB_STEP_SUMMARY + jq '.dependencies' manifest.json >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + fi diff --git a/manifest.json b/manifest.json index 84a0d44..9d3187c 100644 --- a/manifest.json +++ b/manifest.json @@ -3,5 +3,6 @@ "version": "0.0.0", "engineVersion": "1.6.0", "description": "The default project for iR Engine", - "thumbnail": "/static/IR_thumbnail.jpg" + "thumbnail": "/static/IR_thumbnail.jpg", + "dependencies": [] } \ No newline at end of file