diff --git a/.github/workflows/auto-label-issues.yml b/.github/workflows/auto-label-issues.yml index 09057a4..fba84ce 100644 --- a/.github/workflows/auto-label-issues.yml +++ b/.github/workflows/auto-label-issues.yml @@ -2,7 +2,9 @@ name: šŸ·ļø Auto Label Issues on: issues: - types: [opened, edited] + types: [opened, edited, reopened] + issue_comment: + types: [created] permissions: issues: write @@ -13,85 +15,209 @@ jobs: runs-on: ubuntu-latest steps: - name: Label Bug Reports - if: contains(github.event.issue.title, '[BUG]') + if: success() && github.event.issue && contains(github.event.issue.title, '[BUG]') && (github.event.action == 'opened' || github.event.action == 'edited' || github.event.action == 'created' || github.event.action == 'reopened') uses: actions/github-script@v7 with: + github-token: ${{ secrets.GITHUB_TOKEN }} script: | - github.rest.issues.addLabels({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - labels: ['bug', 'needs-triage'] - }) + try { + await github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: ['bug', 'needs-triage'] + }); + console.log('Added bug labels successfully'); + } catch (error) { + console.error('Error adding bug labels:', error); + } - name: Label Feature Requests - if: contains(github.event.issue.title, '[FEATURE]') + if: success() && github.event.issue && contains(github.event.issue.title, '[FEATURE]') && (github.event.action == 'opened' || github.event.action == 'edited' || github.event.action == 'created' || github.event.action == 'reopened') uses: actions/github-script@v7 with: + github-token: ${{ secrets.GITHUB_TOKEN }} script: | - github.rest.issues.addLabels({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - labels: ['enhancement', 'needs-review'] - }) + try { + await github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: ['enhancement', 'needs-review'] + }); + console.log('Added feature labels successfully'); + } catch (error) { + console.error('Error adding feature labels:', error); + } - name: Label Deployment Tasks - if: contains(github.event.issue.title, '[DEPLOY]') + if: success() && github.event.issue && contains(github.event.issue.title, '[DEPLOY]') && (github.event.action == 'opened' || github.event.action == 'edited' || github.event.action == 'created' || github.event.action == 'reopened') uses: actions/github-script@v7 with: + github-token: ${{ secrets.GITHUB_TOKEN }} script: | - github.rest.issues.addLabels({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - labels: ['deployment', 'high-priority'] - }) + try { + await github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: ['deployment', 'high-priority'] + }); + console.log('Added deployment labels successfully'); + } catch (error) { + console.error('Error adding deployment labels:', error); + } - name: Label Critical Issues - if: contains(github.event.issue.body, 'Critical') || contains(github.event.issue.body, 'Must Have') + if: success() && github.event.issue && github.event.issue.body && (contains(github.event.issue.body, 'Critical') || contains(github.event.issue.body, 'Must Have') || contains(github.event.issue.body, 'wedding day') || contains(github.event.issue.body, 'URGENT')) uses: actions/github-script@v7 with: + github-token: ${{ secrets.GITHUB_TOKEN }} script: | - github.rest.issues.addLabels({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - labels: ['critical', 'urgent'] - }) + try { + const labels = ['critical', 'urgent']; + + // Check for wedding day criticality + if (context.payload.issue.body.toLowerCase().includes('wedding day') || + context.payload.issue.body.toLowerCase().includes('before wedding day')) { + labels.push('wedding-day-critical'); + } + + await github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: labels + }); + console.log('Added critical labels successfully:', labels); + } catch (error) { + console.error('Error adding critical labels:', error); + } - - name: Auto-assign to Owner - if: contains(github.event.issue.labels.*.name, 'critical') || contains(github.event.issue.title, '[DEPLOY]') + - name: Auto-assign Critical Issues + if: success() && github.event.issue && (contains(github.event.issue.title, '[DEPLOY]') || (github.event.issue.body && (contains(github.event.issue.body, 'Critical') || contains(github.event.issue.body, 'wedding day')))) uses: actions/github-script@v7 with: + github-token: ${{ secrets.GITHUB_TOKEN }} script: | - github.rest.issues.addAssignees({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - assignees: ['syed-reza98'] - }) + try { + await github.rest.issues.addAssignees({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + assignees: ['syed-reza98'] + }); + console.log('Auto-assigned to syed-reza98 successfully'); + } catch (error) { + console.error('Error auto-assigning:', error); + } - - name: Add Wedding Day Priority - if: contains(github.event.issue.body, 'Before Wedding Day') || contains(github.event.issue.body, 'wedding day') + - name: Add Wedding Day Priority Labels + if: success() && github.event.issue && github.event.issue.body && (contains(github.event.issue.body, 'Before Wedding Day') || contains(github.event.issue.body, 'wedding day') || contains(github.event.issue.body, 'Wedding Day')) uses: actions/github-script@v7 with: + github-token: ${{ secrets.GITHUB_TOKEN }} script: | - github.rest.issues.addLabels({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - labels: ['wedding-day-critical'] - }) + try { + await github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: ['wedding-day-critical'] + }); + console.log('Added wedding-day-critical label successfully'); + } catch (error) { + console.error('Error adding wedding-day-critical label:', error); + } + + - name: Add Priority Based on Keywords + if: success() && github.event.issue && github.event.issue.body + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + try { + const body = context.payload.issue.body.toLowerCase(); + const title = context.payload.issue.title.toLowerCase(); + const labels = []; + + // High priority keywords + if (body.includes('production') || body.includes('live') || + body.includes('blocking') || body.includes('urgent') || + title.includes('urgent') || title.includes('critical')) { + labels.push('high-priority'); + } + + // Mobile-specific issues + if (body.includes('mobile') || body.includes('iphone') || + body.includes('android') || body.includes('responsive')) { + labels.push('mobile'); + } + + // UI/UX issues + if (body.includes('ui') || body.includes('ux') || + body.includes('design') || body.includes('layout')) { + labels.push('ui-ux'); + } + + // Performance issues + if (body.includes('slow') || body.includes('performance') || + body.includes('loading') || body.includes('speed')) { + labels.push('performance'); + } + + if (labels.length > 0) { + await github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: labels + }); + console.log('Added priority/category labels successfully:', labels); + } + } catch (error) { + console.error('Error adding priority labels:', error); + } - name: Comment on Critical Issues - if: contains(github.event.issue.labels.*.name, 'critical') + if: success() && github.event.issue && (github.event.action == 'opened' || github.event.action == 'created') && github.event.issue.body && (contains(github.event.issue.body, 'Critical') || contains(github.event.issue.body, 'wedding day') || contains(github.event.issue.title, '[DEPLOY]')) uses: actions/github-script@v7 with: + github-token: ${{ secrets.GITHUB_TOKEN }} script: | - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: '🚨 **Critical Issue Detected**\n\nThis issue has been marked as critical and requires immediate attention. @syed-reza98 has been automatically assigned.\n\n**Next Steps:**\n- [ ] Investigate and assess impact\n- [ ] Create action plan\n- [ ] Implement fix\n- [ ] Test and validate\n- [ ] Deploy if necessary\n\n*This is an automated message from the Sharothee Wedding Project Management System.*' - }) + try { + const isCritical = context.payload.issue.body.toLowerCase().includes('critical'); + const isWeddingDay = context.payload.issue.body.toLowerCase().includes('wedding day'); + const isDeployment = context.payload.issue.title.includes('[DEPLOY]'); + + let message = '🚨 **High Priority Issue Detected**\n\n'; + + if (isWeddingDay) { + message = 'šŸ’’ **Wedding Day Critical Issue**\n\n'; + message += 'This issue affects wedding day functionality and requires immediate attention!\n\n'; + } else if (isCritical) { + message = '🚨 **Critical Issue Detected**\n\n'; + message += 'This issue has been marked as critical and requires immediate attention.\n\n'; + } else if (isDeployment) { + message = 'šŸš€ **Deployment Task**\n\n'; + message += 'This deployment task has been flagged for priority handling.\n\n'; + } + + message += `@syed-reza98 has been automatically assigned.\n\n**Next Steps:**\n- [ ] Investigate and assess impact\n- [ ] Create action plan\n- [ ] Implement fix\n- [ ] Test and validate\n- [ ] Deploy if necessary\n\n`; + + if (isWeddingDay) { + message += '**Emergency Contacts:**\n- Primary: codestromhub@gmail.com\n- Phone: +880 1234-567890\n\n'; + } + + message += '*This is an automated message from the [Sharothee Wedding Project Management System](https://github.com/users/syed-reza98/projects/5).*'; + + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: message + }); + console.log('Added critical issue comment successfully'); + } catch (error) { + console.error('Error adding critical issue comment:', error); + } diff --git a/.github/workflows/ci-cd-pipeline.yml b/.github/workflows/ci-cd-pipeline.yml index 5dbdab0..b2873ab 100644 --- a/.github/workflows/ci-cd-pipeline.yml +++ b/.github/workflows/ci-cd-pipeline.yml @@ -297,3 +297,5 @@ jobs: security: securityStatus, deployment: deploymentStatus }; + + diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 35b31d4..790dddd 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,15 +1,4 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL Advanced" +name: "šŸ”’ CodeQL Advanced Security Analysis" on: push: @@ -17,28 +6,21 @@ on: pull_request: branches: [ "main" ] schedule: - - cron: '15 9 * * 6' + - cron: '15 9 * * 6' # Weekly on Saturday at 9:15 AM + workflow_dispatch: # Allow manual triggering + +permissions: + contents: read + security-events: write + actions: read + packages: read jobs: analyze: name: Analyze (${{ matrix.language }}) - # Runner size impacts CodeQL analysis time. To learn more, please see: - # - https://gh.io/recommended-hardware-resources-for-running-codeql - # - https://gh.io/supported-runners-and-hardware-resources - # - https://gh.io/using-larger-runners (GitHub.com only) - # Consider using larger runners or machines with greater resources for possible analysis time improvements. runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} - permissions: - # required for all workflows - security-events: write - - # required to fetch internal or private CodeQL packs - packages: read - - # only required for workflows in private repositories - actions: read - contents: read - + timeout-minutes: 360 + strategy: fail-fast: false matrix: @@ -47,54 +29,73 @@ jobs: build-mode: none - language: javascript-typescript build-mode: none - # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift' - # Use `c-cpp` to analyze code written in C, C++ or both - # Use 'java-kotlin' to analyze code written in Java, Kotlin or both - # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both - # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, - # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. - # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how - # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - # Add any setup steps before running the `github/codeql-action/init` action. - # This includes steps like installing compilers or runtimes (`actions/setup-node` - # or others). This is typically only required for manual builds. - # - name: Setup runtime (example) - # uses: actions/setup-example@v1 + - name: Setup Node.js (for JavaScript/TypeScript analysis) + if: matrix.language == 'javascript-typescript' + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: 'client/package-lock.json' + + - name: Install dependencies (for better analysis) + if: matrix.language == 'javascript-typescript' + run: | + cd client + npm ci --omit=dev + continue-on-error: true - # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - #queries: security-extended,security-and-quality - - # If the analyze step fails for one of the languages you are analyzing with - # "We were unable to automatically build your code", modify the matrix above - # to set the build mode to "manual" for that language. Then modify this step - # to build your code. - # ā„¹ļø Command-line programs to run using the OS shell. - # šŸ“š See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - if: matrix.build-mode == 'manual' - shell: bash - run: | - echo 'If you are using a "manual" build mode for one or more of the' \ - 'languages you are analyzing, replace this with the commands to build' \ - 'your code, for example:' - echo ' make bootstrap' - echo ' make release' - exit 1 + config-file: ./.github/codeql/codeql-config.yml + queries: security-extended,security-and-quality - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" + + security-summary: + name: Security Analysis Summary + runs-on: ubuntu-latest + needs: analyze + if: always() + steps: + - name: Security Analysis Complete + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const workflow_run_url = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; + + console.log('šŸ”’ CodeQL Security Analysis completed for Sharothee Wedding Website'); + console.log('šŸ“Š Analysis covers:'); + console.log(' - GitHub Actions workflows'); + console.log(' - Next.js application code'); + console.log(' - TypeScript/JavaScript security patterns'); + console.log(' - Wedding website specific vulnerabilities'); + console.log(`šŸ“‹ Full report: ${workflow_run_url}`); + + // Only create issue if this is a scheduled run and there were failures + if (context.eventName === 'schedule' && '${{ needs.analyze.result }}' === 'failure') { + try { + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: '🚨 CodeQL Security Analysis Failed - Weekly Scan', + body: `# šŸ”’ Security Analysis Issue\n\nThe weekly CodeQL security analysis has failed and requires immediate attention.\n\n**Details:**\n- **Run ID:** ${context.runId}\n- **Workflow:** CodeQL Advanced Security Analysis\n- **Trigger:** Scheduled weekly scan\n- **Status:** āŒ Failed\n\n**Action Required:**\n- [ ] Review security scan results\n- [ ] Address any identified vulnerabilities\n- [ ] Fix workflow configuration if needed\n- [ ] Ensure wedding website security standards\n\n**Links:**\n- [Workflow Run](${workflow_run_url})\n- [Security Tab](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/security)\n\nāš ļø **This affects wedding website security and should be resolved promptly.**\n\n*Automated issue created by CodeQL workflow failure detection*`, + labels: ['security', 'critical', 'automated'], + assignees: ['syed-reza98'] + }); + console.log('Created security issue for failed analysis'); + } catch (error) { + console.error('Failed to create security issue:', error); + } + } diff --git a/.github/workflows/project-board-automation.yml b/.github/workflows/project-board-automation.yml index 7e4b369..3c08fdf 100644 --- a/.github/workflows/project-board-automation.yml +++ b/.github/workflows/project-board-automation.yml @@ -9,52 +9,233 @@ on: permissions: issues: write contents: read + repository-projects: write jobs: move-to-boards: runs-on: ubuntu-latest steps: - - name: Move Bug Reports to Bug Triage - if: contains(github.event.issue.title, '[BUG]') && github.event.action == 'opened' + # Check for both 'opened' (issues event) and 'created' (issue_comment event) actions + # to support issues created directly or via comments that create/tag issues + - name: Add Bug Reports to Project Board + if: success() && github.event.issue && contains(github.event.issue.title, '[BUG]') && (github.event.action == 'opened' || github.event.action == 'created') uses: actions/github-script@v7 with: + github-token: ${{ secrets.GITHUB_TOKEN }} script: | - // Add to Bug Tracking Board - New column - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: 'šŸ› **Bug Report Received**\n\nThis bug has been added to the Bug Tracking board for triage.\n\n**Next Steps:**\n1. Technical investigation\n2. Impact assessment\n3. Priority assignment\n4. Resolution planning\n\n*Automated by Sharothee Wedding Project Management*' - }) + try { + // Get the project + const projectQuery = ` + query($owner: String!) { + user(login: $owner) { + projectsV2(first: 20) { + nodes { + id + title + number + } + } + } + } + `; + + const projectResponse = await github.graphql(projectQuery, { + owner: 'syed-reza98' + }); + + const project = projectResponse.user.projectsV2.nodes.find(p => + p.title === 'Sharothee Wedding Project Management' || p.number === 5 + ); + + if (project) { + // Add issue to project + const addItemMutation = ` + mutation($projectId: ID!, $contentId: ID!) { + addProjectV2ItemByContentId(input: { + projectId: $projectId + contentId: $contentId + }) { + item { + id + } + } + } + `; + + await github.graphql(addItemMutation, { + projectId: project.id, + contentId: context.payload.issue.node_id + }); + + console.log(`Added bug report to project: ${project.title}`); + } + + // Add informative comment + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'šŸ› **Bug Report Received**\n\nThis bug has been automatically added to the [Sharothee Wedding Project Management](https://github.com/users/syed-reza98/projects/5) board for triage.\n\n**Next Steps:**\n1. Technical investigation\n2. Impact assessment\n3. Priority assignment\n4. Resolution planning\n\n*Automated by Sharothee Wedding Project Management System*' + }); + } catch (error) { + console.error('Error adding to project:', error); + // Still add comment even if project addition fails + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'šŸ› **Bug Report Received**\n\nThis bug has been logged for triage. Please check the [project board](https://github.com/users/syed-reza98/projects/5) for status updates.\n\n*Automated by Sharothee Wedding Project Management System*' + }); + } - - name: Move Feature Requests to Backlog - if: contains(github.event.issue.title, '[FEATURE]') && github.event.action == 'opened' + - name: Add Feature Requests to Project Board + if: success() && github.event.issue && contains(github.event.issue.title, '[FEATURE]') && (github.event.action == 'opened' || github.event.action == 'created') uses: actions/github-script@v7 with: + github-token: ${{ secrets.GITHUB_TOKEN }} script: | - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: '✨ **Feature Request Received**\n\nThis feature request has been added to the Product Backlog for review.\n\n**Next Steps:**\n1. Requirements analysis\n2. Technical feasibility review\n3. Priority assessment\n4. Sprint planning consideration\n\n*Automated by Sharothee Wedding Project Management*' - }) + try { + // Get the project + const projectQuery = ` + query($owner: String!) { + user(login: $owner) { + projectsV2(first: 20) { + nodes { + id + title + number + } + } + } + } + `; + + const projectResponse = await github.graphql(projectQuery, { + owner: 'syed-reza98' + }); + + const project = projectResponse.user.projectsV2.nodes.find(p => + p.title === 'Sharothee Wedding Project Management' || p.number === 5 + ); + + if (project) { + // Add issue to project + const addItemMutation = ` + mutation($projectId: ID!, $contentId: ID!) { + addProjectV2ItemByContentId(input: { + projectId: $projectId + contentId: $contentId + }) { + item { + id + } + } + } + `; + + await github.graphql(addItemMutation, { + projectId: project.id, + contentId: context.payload.issue.node_id + }); + + console.log(`Added feature request to project: ${project.title}`); + } + + // Add informative comment + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: '✨ **Feature Request Received**\n\nThis feature request has been automatically added to the [Sharothee Wedding Project Management](https://github.com/users/syed-reza98/projects/5) board for review.\n\n**Next Steps:**\n1. Requirements analysis\n2. Technical feasibility review\n3. Priority assessment\n4. Sprint planning consideration\n\n*Automated by Sharothee Wedding Project Management System*' + }); + } catch (error) { + console.error('Error adding to project:', error); + // Still add comment even if project addition fails + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: '✨ **Feature Request Received**\n\nThis feature request has been logged for review. Please check the [project board](https://github.com/users/syed-reza98/projects/5) for status updates.\n\n*Automated by Sharothee Wedding Project Management System*' + }); + } - - name: Move Deployment Tasks to Pipeline - if: contains(github.event.issue.title, '[DEPLOY]') && github.event.action == 'opened' + - name: Add Deployment Tasks to Project Board + if: success() && github.event.issue && contains(github.event.issue.title, '[DEPLOY]') && (github.event.action == 'opened' || github.event.action == 'created') uses: actions/github-script@v7 with: + github-token: ${{ secrets.GITHUB_TOKEN }} script: | - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: 'šŸš€ **Deployment Task Created**\n\nThis deployment has been added to the Deployment Pipeline board.\n\n**Pre-Deployment Checklist:**\n- [ ] Code review complete\n- [ ] Tests passing\n- [ ] Environment variables ready\n- [ ] Database backup created\n- [ ] Rollback plan confirmed\n\n*Automated by Sharothee Wedding Project Management*' - }) + try { + // Get the project + const projectQuery = ` + query($owner: String!) { + user(login: $owner) { + projectsV2(first: 20) { + nodes { + id + title + number + } + } + } + } + `; + + const projectResponse = await github.graphql(projectQuery, { + owner: 'syed-reza98' + }); + + const project = projectResponse.user.projectsV2.nodes.find(p => + p.title === 'Sharothee Wedding Project Management' || p.number === 5 + ); + + if (project) { + // Add issue to project + const addItemMutation = ` + mutation($projectId: ID!, $contentId: ID!) { + addProjectV2ItemByContentId(input: { + projectId: $projectId + contentId: $contentId + }) { + item { + id + } + } + } + `; + + await github.graphql(addItemMutation, { + projectId: project.id, + contentId: context.payload.issue.node_id + }); + + console.log(`Added deployment task to project: ${project.title}`); + } + + // Add informative comment + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'šŸš€ **Deployment Task Created**\n\nThis deployment task has been automatically added to the [Sharothee Wedding Project Management](https://github.com/users/syed-reza98/projects/5) board.\n\n**Pre-Deployment Checklist:**\n- [ ] Code review complete\n- [ ] Tests passing\n- [ ] Environment variables ready\n- [ ] Database backup created\n- [ ] Rollback plan confirmed\n\n*Automated by Sharothee Wedding Project Management System*' + }); + } catch (error) { + console.error('Error adding to project:', error); + // Still add comment even if project addition fails + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'šŸš€ **Deployment Task Created**\n\nThis deployment task has been logged. Please check the [project board](https://github.com/users/syed-reza98/projects/5) for status updates.\n\n*Automated by Sharothee Wedding Project Management System*' + }); + } + # Only celebrate when issues are actually closed (not on issue_comment events) - name: Celebrate Issue Completion - if: github.event.action == 'closed' + if: success() && github.event.issue && github.event.action == 'closed' uses: actions/github-script@v7 with: + github-token: ${{ secrets.GITHUB_TOKEN }} script: | const title = context.payload.issue.title; let message = 'šŸŽ‰ **Issue Completed!**\n\n'; @@ -69,9 +250,9 @@ jobs: message += 'Task completed successfully!'; } - message += '\n\n*Automated by Sharothee Wedding Project Management*'; + message += '\n\n*Completed via [Sharothee Wedding Project Management](https://github.com/users/syed-reza98/projects/5)*'; - github.rest.issues.createComment({ + await github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, diff --git a/.github/workflows/wedding-day-notifications.yml b/.github/workflows/wedding-day-notifications.yml index d922106..c2ad714 100644 --- a/.github/workflows/wedding-day-notifications.yml +++ b/.github/workflows/wedding-day-notifications.yml @@ -1,68 +1,277 @@ -name: šŸ“¢ Wedding Day Notifications +name: šŸ“¢ Wedding Day Notifications & Monitoring on: issues: - types: [opened, labeled] + types: [opened, labeled, closed] + issue_comment: + types: [created] schedule: - cron: '0 9,15,21 * * *' # 9 AM, 3 PM, 9 PM daily + workflow_dispatch: # Allow manual triggering permissions: issues: write contents: read + repository-projects: write jobs: wedding-day-alerts: runs-on: ubuntu-latest - if: contains(github.event.issue.labels.*.name, 'wedding-day-critical') || github.event_name == 'schedule' + if: (github.event.issue && (contains(github.event.issue.labels.*.name, 'wedding-day-critical') || contains(github.event.issue.labels.*.name, 'critical'))) || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' steps: - name: Alert on Wedding Day Critical Issues - if: contains(github.event.issue.labels.*.name, 'wedding-day-critical') + if: github.event.issue && (contains(github.event.issue.labels.*.name, 'wedding-day-critical') || (contains(github.event.issue.labels.*.name, 'critical') && github.event.issue.body && contains(github.event.issue.body, 'wedding day'))) uses: actions/github-script@v7 with: + github-token: ${{ secrets.GITHUB_TOKEN }} script: | - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: 'āš ļø **WEDDING DAY CRITICAL ALERT** āš ļø\n\nThis issue has been flagged as wedding day critical and requires immediate attention!\n\nšŸ“ž **Emergency Contacts:**\n- Primary: codestromhub@gmail.com\n- Phone: +880 1234-567890\n- Developer: @syed-reza98\n\nšŸ”“ **Action Required:**\n- [ ] Immediate assessment\n- [ ] Impact analysis\n- [ ] Emergency fix if needed\n- [ ] Communication to couple\n\n*This is a high-priority automated alert for Incia & Arvin\'s wedding website.*' - }) + try { + const priority = context.payload.issue.labels.some(label => + label.name === 'wedding-day-critical') ? 'WEDDING DAY CRITICAL' : 'HIGH PRIORITY'; + + const message = `āš ļø **${priority} ALERT** āš ļø\n\nThis issue has been flagged as ${priority.toLowerCase()} and requires immediate attention!\n\nšŸ“ž **Emergency Contacts:**\n- Primary: codestromhub@gmail.com\n- Phone: +880 1234-567890\n- Developer: @syed-reza98\n\nšŸ”“ **Action Required:**\n- [ ] Immediate assessment\n- [ ] Impact analysis on wedding functionality\n- [ ] Emergency fix if needed\n- [ ] Communication to couple if necessary\n- [ ] Update in [Project Board](https://github.com/users/syed-reza98/projects/5)\n\nā° **Timeline:** This issue affects wedding day functionality and should be resolved ASAP.\n\n*This is a high-priority automated alert for Incia & Arvin's wedding website.*`; + + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: message + }); + + console.log(`Posted ${priority} alert for issue #${context.issue.number}`); + } catch (error) { + console.error('Error posting critical alert:', error); + } - - name: Daily Status Check - if: github.event_name == 'schedule' + - name: Daily Status Check & Report + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' uses: actions/github-script@v7 with: + github-token: ${{ secrets.GITHUB_TOKEN }} script: | - // Get all open critical issues - const { data: issues } = await github.rest.issues.listForRepo({ - owner: context.repo.owner, - repo: context.repo.repo, - labels: 'wedding-day-critical', - state: 'open' - }); - - if (issues.length > 0) { - // Create daily status issue - await github.rest.issues.create({ + try { + // Get all open critical issues + const criticalLabels = ['wedding-day-critical', 'critical', 'urgent']; + const allCriticalIssues = []; + + for (const label of criticalLabels) { + const { data: issues } = await github.rest.issues.listForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + labels: label, + state: 'open' + }); + + // Avoid duplicates + issues.forEach(issue => { + if (!allCriticalIssues.find(existing => existing.number === issue.number)) { + allCriticalIssues.push(issue); + } + }); + } + + // Get deployment issues + const { data: deployIssues } = await github.rest.issues.listForRepo({ owner: context.repo.owner, repo: context.repo.repo, - title: `šŸ“Š Daily Wedding Status Report - ${new Date().toISOString().split('T')[0]}`, - body: `# šŸŽÆ Wedding Day Readiness Report\n\n## āš ļø Critical Issues (${issues.length})\n\n${issues.map(issue => `- #${issue.number}: ${issue.title}`).join('\n')}\n\n## šŸ“ˆ System Status\n- Website: 🟢 Operational\n- RSVP System: 🟢 Functional\n- Admin Dashboard: 🟢 Available\n- Email Notifications: 🟢 Working\n\n## šŸŽŠ Wedding Countdown\nDays until Incia & Arvin's wedding: **[Manual Update Required]**\n\n---\n*Automated daily report - resolve critical issues ASAP!*`, - labels: ['status-report', 'automated'], - assignees: ['syed-reza98'] + labels: 'deployment', + state: 'open' }); + + const currentDate = new Date().toISOString().split('T')[0]; + const weddingDate = new Date('2024-12-15'); // Update with actual date + const today = new Date(); + const daysUntilWedding = Math.ceil((weddingDate - today) / (1000 * 60 * 60 * 24)); + + // Only create report if there are issues or it's close to wedding + if (allCriticalIssues.length > 0 || deployIssues.length > 0 || daysUntilWedding <= 30) { + const weddingDayCritical = allCriticalIssues.filter(issue => + issue.labels.some(label => label.name === 'wedding-day-critical')); + + let reportBody = `# šŸŽÆ Wedding Day Readiness Report\n\n`; + reportBody += `**Report Date:** ${currentDate}\n`; + reportBody += `**Days Until Wedding:** ${daysUntilWedding > 0 ? daysUntilWedding : 'Wedding Day Passed'}\n\n`; + + if (weddingDayCritical.length > 0) { + reportBody += `## šŸ’’ Wedding Day Critical Issues (${weddingDayCritical.length})\n\n`; + weddingDayCritical.forEach(issue => { + reportBody += `- #${issue.number}: ${issue.title}\n`; + }); + reportBody += '\n'; + } + + if (allCriticalIssues.length > 0) { + reportBody += `## āš ļø All Critical Issues (${allCriticalIssues.length})\n\n`; + allCriticalIssues.forEach(issue => { + const labels = issue.labels.map(l => l.name).join(', '); + reportBody += `- #${issue.number}: ${issue.title} [${labels}]\n`; + }); + reportBody += '\n'; + } + + if (deployIssues.length > 0) { + reportBody += `## šŸš€ Pending Deployments (${deployIssues.length})\n\n`; + deployIssues.forEach(issue => { + reportBody += `- #${issue.number}: ${issue.title}\n`; + }); + reportBody += '\n'; + } + + reportBody += `## šŸ“ˆ System Status\n`; + reportBody += `- Website: 🟢 Operational\n`; + reportBody += `- RSVP System: 🟢 Functional\n`; + reportBody += `- Admin Dashboard: 🟢 Available\n`; + reportBody += `- Email Notifications: 🟢 Working\n`; + reportBody += `- Project Board: [šŸ“‹ View Status](https://github.com/users/syed-reza98/projects/5)\n\n`; + + if (daysUntilWedding <= 7 && daysUntilWedding > 0) { + reportBody += `## 🚨 FINAL WEEK ALERT\n`; + reportBody += `This is the final week before the wedding! All critical issues must be resolved immediately.\n\n`; + } else if (daysUntilWedding <= 30 && daysUntilWedding > 7) { + reportBody += `## ā° 30-Day Countdown\n`; + reportBody += `Wedding is approaching. Focus on resolving critical issues and testing all systems.\n\n`; + } + + reportBody += `---\n*Automated daily report - resolve critical issues ASAP! View all issues on the [Project Board](https://github.com/users/syed-reza98/projects/5)*`; + + const labels = ['status-report', 'automated']; + if (weddingDayCritical.length > 0) labels.push('wedding-day-critical'); + if (allCriticalIssues.length > 0) labels.push('urgent'); + + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: `šŸ“Š Wedding Status Report - ${currentDate} (${daysUntilWedding} days to go)`, + body: reportBody, + labels: labels, + assignees: ['syed-reza98'] + }); + + console.log('Created comprehensive wedding status report'); + } else { + console.log('No critical issues found, skipping status report'); + } + } catch (error) { + console.error('Error creating status report:', error); } deployment-success: runs-on: ubuntu-latest - if: contains(github.event.issue.title, '[DEPLOY]') && github.event.action == 'closed' + if: github.event.issue && contains(github.event.issue.title, '[DEPLOY]') && github.event.action == 'closed' steps: - name: Deployment Success Notification uses: actions/github-script@v7 with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + try { + const deploymentTitle = context.payload.issue.title; + const deploymentNumber = context.payload.issue.number; + + const message = `šŸš€ **Deployment Successful!** šŸš€\n\nāœ… The wedding website deployment has been completed successfully!\n\n**Deployment Details:**\n- **Issue:** #${deploymentNumber}\n- **Title:** ${deploymentTitle}\n- **Completed:** ${new Date().toISOString()}\n\n**Post-Deployment Verification:**\n- [ ] Website loading verified āœ…\n- [ ] RSVP system tested āœ…\n- [ ] Mobile compatibility confirmed āœ…\n- [ ] Admin access validated āœ…\n- [ ] Performance checked āœ…\n- [ ] Security scans passed āœ…\n\nšŸ“¢ **Communication Checklist:**\n- [ ] Couple has been notified\n- [ ] Wedding party informed\n- [ ] Key stakeholders updated\n- [ ] Project board updated\n\nšŸŽ‰ **Ready for Incia & Arvin's Special Day!**\n\n**Next Steps:**\n- Monitor system health\n- Address any user feedback\n- Prepare for increased traffic near wedding day\n\n*Automated deployment success notification from [Sharothee Wedding Project Management](https://github.com/users/syed-reza98/projects/5)*`; + + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: message + }); + + console.log(`Posted deployment success notification for issue #${deploymentNumber}`); + } catch (error) { + console.error('Error posting deployment notification:', error); + } + + health-check: + runs-on: ubuntu-latest + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + steps: + - name: Wedding Website Health Check + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} script: | - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: 'šŸš€ **Deployment Successful!** šŸš€\n\nāœ… The wedding website has been updated successfully!\n\n**Post-Deployment Status:**\n- [ ] Website loading verified\n- [ ] RSVP system tested\n- [ ] Mobile compatibility confirmed\n- [ ] Admin access validated\n\nšŸ“¢ **Communication:**\n- Couple has been notified\n- Wedding party informed\n- Social media announcement posted\n\nšŸŽ‰ **Ready for Incia & Arvin\'s Special Day!**\n\n*Automated deployment success notification*' - }) + try { + const healthChecks = []; + + // Check for recent failures in other workflows + const { data: workflowRuns } = await github.rest.actions.listWorkflowRunsForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + per_page: 20, + created: `>${new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString()}` + }); + + const failedRuns = workflowRuns.workflow_runs.filter(run => + run.conclusion === 'failure' && run.name.includes('Wedding') + ); + + if (failedRuns.length > 0) { + healthChecks.push(`āš ļø **${failedRuns.length} workflow failure(s)** in the last 24 hours`); + } + + // Check for overdue critical issues + const { data: overdueIssues } = await github.rest.issues.listForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + labels: 'wedding-day-critical', + state: 'open' + }); + + const oldCriticalIssues = overdueIssues.filter(issue => { + const createdDate = new Date(issue.created_at); + const daysSinceCreated = (Date.now() - createdDate.getTime()) / (1000 * 60 * 60 * 24); + return daysSinceCreated > 2; // Issues older than 2 days + }); + + if (oldCriticalIssues.length > 0) { + healthChecks.push(`šŸ• **${oldCriticalIssues.length} overdue critical issue(s)** (>2 days old)`); + } + + // If there are health concerns, create an alert + if (healthChecks.length > 0 || failedRuns.length > 0) { + const alertTitle = `šŸ„ Wedding Website Health Alert - ${new Date().toISOString().split('T')[0]}`; + let alertBody = `# 🚨 System Health Alert\n\n`; + alertBody += `**Health Check Results:**\n\n`; + + healthChecks.forEach(check => { + alertBody += `${check}\n`; + }); + + if (failedRuns.length > 0) { + alertBody += `\n**Recent Workflow Failures:**\n`; + failedRuns.forEach(run => { + alertBody += `- [${run.name}](${run.html_url}) - ${run.conclusion}\n`; + }); + } + + if (oldCriticalIssues.length > 0) { + alertBody += `\n**Overdue Critical Issues:**\n`; + oldCriticalIssues.forEach(issue => { + alertBody += `- #${issue.number}: ${issue.title}\n`; + }); + } + + alertBody += `\n**Immediate Action Required:**\n`; + alertBody += `- [ ] Review and resolve failed workflows\n`; + alertBody += `- [ ] Address overdue critical issues\n`; + alertBody += `- [ ] Verify website functionality\n`; + alertBody += `- [ ] Update project board status\n\n`; + alertBody += `*Automated health check from Wedding Day Monitoring System*`; + + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: alertTitle, + body: alertBody, + labels: ['health-check', 'urgent', 'automated'], + assignees: ['syed-reza98'] + }); + + console.log('Created health alert due to system concerns'); + } else { + console.log('āœ… All wedding website health checks passed'); + } + } catch (error) { + console.error('Error performing health check:', error); + }