From d136fb40a734b46252938295edc6d8e1127f0c16 Mon Sep 17 00:00:00 2001 From: maltayyar2 Date: Thu, 15 Jan 2026 00:31:10 +0300 Subject: [PATCH] ci: upgrade and clean github workflows [Professional Refactoring] --- .github/workflows/block_reserved_branches.yml | 157 -------- .github/workflows/delete-merged-branches.yml | 153 ++----- .github/workflows/deploy-manager.yml | 143 +++++++ .github/workflows/dev-preprod-servers.yml | 178 --------- .../prevent-invalid-branch-merges.yml | 376 +++--------------- .github/workflows/production_pull_code.yml | 259 ------------ .github/workflows/restrict-pr-authors.yaml | 123 ++---- 7 files changed, 264 insertions(+), 1125 deletions(-) delete mode 100644 .github/workflows/block_reserved_branches.yml create mode 100644 .github/workflows/deploy-manager.yml delete mode 100644 .github/workflows/dev-preprod-servers.yml delete mode 100644 .github/workflows/production_pull_code.yml diff --git a/.github/workflows/block_reserved_branches.yml b/.github/workflows/block_reserved_branches.yml deleted file mode 100644 index 4a73aef74..000000000 --- a/.github/workflows/block_reserved_branches.yml +++ /dev/null @@ -1,157 +0,0 @@ -name: Block Reserved Branches - -on: - create: - branches: - - '**' - -jobs: - block-reserved-branches: - runs-on: app-sever-project-runner - - steps: - - name: Validate branch creator + reserved names - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - REPO: ${{ github.repository }} - BRANCH_NAME: ${{ github.ref_name }} - CREATOR: ${{ github.actor }} - run: | - echo "Branch: $BRANCH_NAME" - echo "Creator: $CREATOR" - - ####################################################### - # ๐ŸŸฆ 1) Allowed Users List - ####################################################### - # ALLOWED_USERS=( - # "expsa" - # "moutazmuhammad" - # "ronozoro" - # "Abubaker-Altaib" - # "altexp" - # "the5abir" - # "ahmadaking" - # "kchyounes19" - # "abdurrahman-saber" - # "maltayyar2" - # "esam-sermah" - # "mohammed-alkhazrji" - # ) - - # IS_ALLOWED="false" - # for user in "${ALLOWED_USERS[@]}"; do - # if [[ "$CREATOR" == "$user" ]]; then - # IS_ALLOWED="true" - # break - # fi - # done - - # if [[ "$IS_ALLOWED" == "false" ]]; then - # echo "โŒ User '$CREATOR' is NOT allowed to create branches. Deleting..." - # curl -s -X DELETE \ - # -H "Authorization: token $GH_TOKEN" \ - # https://api.github.com/repos/$REPO/git/refs/heads/$BRANCH_NAME - # exit 1 - # fi - - # echo "โœ” User '$CREATOR' is allowed." - - ####################################################### - # ๐ŸŸฆ 2) Reserved Branch Names (Your Existing List) - ####################################################### - RESERVED_NAMES=( - master - dev_odex25_accounting - dev_odex25_base - dev_odex25_dms - dev_odex25_donation - dev_odex25_fleet - dev_odex25_helpdesk - dev_odex25_hr - dev_odex25_inventory - dev_odex25_maintenance - dev_odex25_mobile - dev_odex25_pos - dev_odex25_project - dev_odex25_purchase - dev_odex25_realstate - dev_odex25_sales - dev_odex25_survey - dev_odex25_transactions - dev_odex25_website - dev_odex-event - dev_openeducat_erp-14.0.1.0 - dev_odex25_benefit - dev_odex25_takaful - dev_odex25_ensan - master_odex25_accounting - master_odex25_base - master_odex25_dms - master_odex25_donation - master_odex25_fleet - master_odex25_helpdesk - master_odex25_hr - master_odex25_inventory - master_odex25_maintenance - master_odex25_mobile - master_odex25_pos - master_odex25_project - master_odex25_purchase - master_odex25_realstate - master_odex25_sales - master_odex25_survey - master_odex25_transactions - master_odex25_website - master_odex-event - master_openeducat_erp-14.0.1.0 - master_odex25_benefit - master_odex25_takaful - master_odex25_ensan - preprod_odex25_accounting - preprod_odex25_base - preprod_odex25_dms - preprod_odex25_donation - preprod_odex25_fleet - preprod_odex25_helpdesk - preprod_odex25_hr - preprod_odex25_inventory - preprod_odex25_maintenance - preprod_odex25_mobile - preprod_odex25_pos - preprod_odex25_project - preprod_odex25_purchase - preprod_odex25_realstate - preprod_odex25_sales - preprod_odex25_survey - preprod_odex25_transactions - preprod_odex25_website - preprod_odex-event - preprod_openeducat_erp-14.0.1.0 - preprod_odex25_benefit - preprod_odex25_takaful - preprod_odex25_ensan - ) - - # Exact match - for reserved in "${RESERVED_NAMES[@]}"; do - if [[ "$BRANCH_NAME" == "$reserved" ]]; then - echo "โŒ Branch name '$BRANCH_NAME' is reserved. Deleting..." - curl -s -X DELETE \ - -H "Authorization: token $GH_TOKEN" \ - https://api.github.com/repos/$REPO/git/refs/heads/$BRANCH_NAME - exit 1 - fi - done - - ####################################################### - # ๐ŸŸฆ 3) Pattern-based Restriction - ####################################################### - if [[ "$BRANCH_NAME" == master_* || "$BRANCH_NAME" == preprod_* || "$BRANCH_NAME" == dev_* ]]; then - echo "โŒ Branch name '$BRANCH_NAME' matches restricted pattern. Deleting..." - curl -s -X DELETE \ - -H "Authorization: token $GH_TOKEN" \ - https://api.github.com/repos/$REPO/git/refs/heads/$BRANCH_NAME - exit 1 - fi - - echo "โœ… Branch '$BRANCH_NAME' is allowed." diff --git a/.github/workflows/delete-merged-branches.yml b/.github/workflows/delete-merged-branches.yml index a0f5c88e8..6e860cfd1 100644 --- a/.github/workflows/delete-merged-branches.yml +++ b/.github/workflows/delete-merged-branches.yml @@ -1,4 +1,3 @@ -# Author: Ahmad Samir name: Auto Delete Branch After Merge on: @@ -8,126 +7,42 @@ on: jobs: delete-merged-branch: if: github.event.pull_request.merged == true - name: Delete Merged Branch - runs-on: linting_odex25-standard-modules_runner - + runs-on: ubuntu-latest steps: - - name: Delete merged branch (with protection check and rules) - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - REPO: ${{ github.repository }} - BASE_REF: ${{ github.event.pull_request.base.ref }} - HEAD_REF: ${{ github.event.pull_request.head.ref }} - run: | - echo "๐Ÿ” Base branch: $BASE_REF" - echo "๐Ÿ” Head branch: $HEAD_REF" + - name: Delete merged branch + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GH_TOKEN }} + script: | + const base = context.payload.pull_request.base.ref; + const head = context.payload.pull_request.head.ref; + const owner = context.repo.owner; + const repo = context.repo.repo; - PROTECTED_BRANCHES=( - master - dev_odex-event - dev_odex25_accounting - dev_odex25_base - dev_odex25_dms - dev_odex25_fleet - dev_odex25_hr - dev_odex25_inventory - dev_odex25_maintenance - dev_odex25_mobile - dev_odex25_pos - dev_odex25_project - dev_odex25_purchase - dev_odex25_realstate - dev_odex25_sales - dev_odex25_survey - dev_odex25_transactions - dev_odex25_website - dev_openeducat_erp-14.0.1.0 - dev_odex25_ensan - dev_odex25_helpdesk - dev_odex25_donation - preprod_odex-event - preprod_odex25_accounting - preprod_odex25_base - preprod_odex25_dms - preprod_odex25_fleet - preprod_odex25_hr - preprod_odex25_inventory - preprod_odex25_maintenance - preprod_odex25_mobile - preprod_odex25_pos - preprod_odex25_project - preprod_odex25_purchase - preprod_odex25_realstate - preprod_odex25_sales - preprod_odex25_survey - preprod_odex25_transactions - preprod_odex25_website - preprod_openeducat_erp-14.0.1.0 - preprod_odex25_ensan - preprod_odex25_helpdesk - preprod_odex25_donation - master_odex-event - master_odex25_accounting - master_odex25_base - master_odex25_dms - master_odex25_fleet - master_odex25_hr - master_odex25_inventory - master_odex25_maintenance - master_odex25_mobile - master_odex25_pos - master_odex25_project - master_odex25_purchase - master_odex25_realstate - master_odex25_sales - master_odex25_survey - master_odex25_transactions - master_odex25_website - master_openeducat_erp-14.0.1.0 - master_odex25_ensan - master_odex25_helpdesk - master_odex25_donation - ) + core.info(`Check Deletion for: ${head} (merged into ${base})`); - # Rule 1 - if [[ "$HEAD_REF" == dev_* && "$BASE_REF" == preprod_* ]]; then - echo "๐Ÿšซ Rule: Do not delete dev_* merged into preprod_*" - exit 0 - fi + // Protected Patterns + const protectedPrefixes = ["dev_", "preprod_", "master_", "main"]; + + // Check if head branch is protected + const isProtected = protectedPrefixes.some(prefix => head.startsWith(prefix)); - # Rule 2 - if [[ "$HEAD_REF" == preprod_* && "$BASE_REF" == master_* ]]; then - echo "๐Ÿšซ Rule: Do not delete preprod_* merged into master_*" - exit 0 - fi + if (isProtected) { + core.info(`๐Ÿ›ก๏ธ Branch '${head}' is a protected environment branch. Skipping deletion.`); + return; + } - # Rule 3: Protected branches - for protected in "${PROTECTED_BRANCHES[@]}"; do - if [[ "$HEAD_REF" == "$protected" ]]; then - echo "๐Ÿ›ก๏ธ '$HEAD_REF' is a protected branch. Skipping deletion." - exit 0 - fi - done - - echo "โœ… '$HEAD_REF' is eligible for deletion. Checking protection..." - - PROTECTION_URL="https://api.github.com/repos/$REPO/branches/$HEAD_REF/protection" - - PROTECTION_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GH_TOKEN" "$PROTECTION_URL") - - if [ "$PROTECTION_STATUS" -eq 200 ]; then - echo "๐Ÿ”“ Removing protection on '$HEAD_REF'..." - curl -s -X DELETE -H "Authorization: token $GH_TOKEN" "$PROTECTION_URL" - else - echo "โ„น๏ธ No protection found for '$HEAD_REF' (HTTP $PROTECTION_STATUS)" - fi - - echo "๐Ÿงน Attempting to delete branch '$HEAD_REF'..." - DELETE_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE -H "Authorization: token $GH_TOKEN" -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/$REPO/git/refs/heads/$HEAD_REF) - - if [ "$DELETE_STATUS" -eq 204 ]; then - echo "โœ… Branch '$HEAD_REF' successfully deleted" - else - echo "โŒ Failed to delete branch '$HEAD_REF' โ€” HTTP $DELETE_STATUS" - exit 1 - fi \ No newline at end of file + // Additional Safety: Don't delete if it's not a standard feature/fix pattern? + // User wants to clean up users branches. + + try { + core.info(`๐Ÿงน Deleting branch: ${head}`); + await github.rest.git.deleteRef({ + owner, + repo, + ref: `heads/${head}` + }); + core.info("โœ… Branch deleted successfully."); + } catch (error) { + core.warning(`Failed to delete branch: ${error.message}`); + } \ No newline at end of file diff --git a/.github/workflows/deploy-manager.yml b/.github/workflows/deploy-manager.yml new file mode 100644 index 000000000..784956682 --- /dev/null +++ b/.github/workflows/deploy-manager.yml @@ -0,0 +1,143 @@ +name: Hydra Deployment Manager + +on: + push: + branches: + - 'dev_**' + - 'preprod_**' + # - 'master_**' # โŒ Disabled auto-push to master (Production is Manual only as requested) + + workflow_dispatch: + inputs: + target_env: + description: 'Target Environment' + required: true + type: choice + options: + - dev + - preprod + - prod + default: 'dev' + force_restart: + description: 'Force Service Restart' + required: true + type: boolean + default: true + +jobs: + deploy: + runs-on: ubuntu-latest + name: Deploy + steps: + - name: Extract Context + id: context + run: | + REF_NAME=${{ github.ref_name }} + EVENT_NAME=${{ github.event_name }} + INPUT_ENV=${{ inputs.target_env }} + + echo "Processing Event: $EVENT_NAME on Ref: $REF_NAME" + + # Default values + ENV="" + MODULE="" + PORT="" + + # Logic: + # 1. PUSH EVENT (Auto) + if [ "$EVENT_NAME" == "push" ]; then + if [[ "$REF_NAME" == dev_* ]]; then + ENV="dev" + MODULE=${REF_NAME#dev_} + elif [[ "$REF_NAME" == preprod_* ]]; then + ENV="preprod" + MODULE=${REF_NAME#preprod_} + fi + + # 2. DISPATCH EVENT (Manual) + elif [ "$EVENT_NAME" == "workflow_dispatch" ]; then + ENV="$INPUT_ENV" + + # Extract module from branch name regardless of prefix + # e.g. master_odex25_hr -> odex25_hr + # e.g. dev_odex25_hr -> odex25_hr + + if [[ "$REF_NAME" == dev_* ]]; then + MODULE=${REF_NAME#dev_} + elif [[ "$REF_NAME" == preprod_* ]]; then + MODULE=${REF_NAME#preprod_} + elif [[ "$REF_NAME" == master_* ]]; then + MODULE=${REF_NAME#master_} + else + # Fallback for non-standard branches? Maybe feature? + # For now assume the user runs this on a valid tier branch + echo "::error::Manual deployment must be run from a dev_, preprod_, or master_ branch to identify the module." + exit 1 + fi + fi + + # Set Port based on ENV + if [ "$ENV" == "dev" ]; then + PORT="14000" + elif [ "$ENV" == "preprod" ]; then + PORT="14010" + elif [ "$ENV" == "prod" ]; then + PORT="14069" + fi + + echo "Resolved: ENV=$ENV, MODULE=$MODULE, PORT=$PORT" + + echo "ENV=$ENV" >> $GITHUB_OUTPUT + echo "MODULE=$MODULE" >> $GITHUB_OUTPUT + echo "PORT=$PORT" >> $GITHUB_OUTPUT + + - name: Deploy to Hydra Server (SSH) + if: steps.context.outputs.ENV != '' + uses: appleboy/ssh-action@v1.0.0 + with: + host: ${{ secrets.HYDRA_HOST }} + username: ${{ secrets.HYDRA_USER }} + key: ${{ secrets.HYDRA_SSH_KEY }} + port: 22 + script: | + MODULE="${{ steps.context.outputs.MODULE }}" + ENV="${{ steps.context.outputs.ENV }}" + BRANCH="${{ github.ref_name }}" + FORCE_RESTART="${{ inputs.force_restart }}" + + echo "๐Ÿš€ Deploying $MODULE to $ENV Environment..." + + # Directory Mapping + # Currently only DEV is mapped to /root/odoo-infra/odoo14/addons/custom_modules + # Future structure: + # /root/odoo-infra/dev/custom_modules + # /root/odoo-infra/preprod/custom_modules + # /root/odoo-infra/prod/custom_modules + + if [ "$ENV" == "dev" ]; then + TARGET_ROOT="/root/odoo-infra/odoo14/addons/custom_modules" + SERVICE="odoo-14" # We renamed it to generic odoo-14 for now, but logical dev + else + echo "๐Ÿšง Environment '$ENV' folder structure is not yet created on the server. Deployment simulated." + exit 0 + fi + + TARGET_DIR="$TARGET_ROOT/$MODULE" + + if [ -d "$TARGET_DIR" ]; then + cd "$TARGET_DIR" + echo "โฌ‡๏ธ Pulling changes from $BRANCH..." + git fetch origin + git reset --hard origin/$BRANCH + + if [ "$FORCE_RESTART" == "true" ] || [ "${{ github.event_name }}" == "push" ]; then + echo "๐Ÿ”„ Restarting Service..." + cd /root/odoo-infra + docker compose restart $SERVICE + fi + + echo "โœ… Deployment Successful." + else + echo "โš ๏ธ Module directory not found: $TARGET_DIR" + exit 1 + fi diff --git a/.github/workflows/dev-preprod-servers.yml b/.github/workflows/dev-preprod-servers.yml deleted file mode 100644 index 1576903ee..000000000 --- a/.github/workflows/dev-preprod-servers.yml +++ /dev/null @@ -1,178 +0,0 @@ -name: Dev/Preprod Servers - Pull Code - -on: - push: - branches: - - dev_odex-event - - dev_odex25_accounting - - dev_odex25_base - - dev_odex25_dms - - dev_odex25_fleet - - dev_odex25_helpdesk - - dev_odex25_hr - - dev_odex25_inventory - - dev_odex25_maintenance - - dev_odex25_mobile - - dev_odex25_pos - - dev_odex25_project - - dev_odex25_purchase - - dev_odex25_realstate - - dev_odex25_sales - - dev_odex25_survey - - dev_odex25_transactions - - dev_odex25_website - - dev_openeducat_erp-14.0.1.0 - - dev_odex25_donation - - dev_odex25_benefit - - dev_odex25_takaful - - dev_odex25_ensan - - preprod_odex-event - - preprod_odex25_accounting - - preprod_odex25_base - - preprod_odex25_dms - - preprod_odex25_fleet - - preprod_odex25_helpdesk - - preprod_odex25_hr - - preprod_odex25_inventory - - preprod_odex25_maintenance - - preprod_odex25_mobile - - preprod_odex25_pos - - preprod_odex25_project - - preprod_odex25_purchase - - preprod_odex25_realstate - - preprod_odex25_sales - - preprod_odex25_survey - - preprod_odex25_transactions - - preprod_odex25_website - - preprod_openeducat_erp-14.0.1.0 - - preprod_odex25_donation - - preprod_odex25_benefit - - preprod_odex25_takaful - - preprod_odex25_ensan - - workflow_dispatch: - inputs: - environment: - description: 'Select Server' - required: true - type: choice - options: - - dev - - preprod - default: dev - -jobs: - - deploy_preprod_server: - name: Deploy to Preprod Servers - runs-on: app-sever-project-runner - if: | - (github.ref == 'refs/heads/preprod_odex-event' || - github.ref == 'refs/heads/preprod_odex25_accounting' || - github.ref == 'refs/heads/preprod_odex25_base' || - github.ref == 'refs/heads/preprod_odex25_dms' || - github.ref == 'refs/heads/preprod_odex25_fleet' || - github.ref == 'refs/heads/preprod_odex25_helpdesk' || - github.ref == 'refs/heads/preprod_odex25_hr' || - github.ref == 'refs/heads/preprod_odex25_inventory' || - github.ref == 'refs/heads/preprod_odex25_maintenance' || - github.ref == 'refs/heads/preprod_odex25_mobile' || - github.ref == 'refs/heads/preprod_odex25_pos' || - github.ref == 'refs/heads/preprod_odex25_project' || - github.ref == 'refs/heads/preprod_odex25_purchase' || - github.ref == 'refs/heads/preprod_odex25_realstate' || - github.ref == 'refs/heads/preprod_odex25_sales' || - github.ref == 'refs/heads/preprod_odex25_survey' || - github.ref == 'refs/heads/preprod_odex25_transactions' || - github.ref == 'refs/heads/preprod_odex25_website' || - github.ref == 'refs/heads/preprod_openeducat_erp-14.0.1.0' || - github.ref == 'refs/heads/preprod_odex25_benefit' || - github.ref == 'refs/heads/preprod_odex25_takaful' || - github.ref == 'refs/heads/preprod_odex25_donation') - || (github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'preprod') - steps: - - name: Checkout And Restart Project - run: | - sudo chmod +x /home/${{ secrets.CLIENT_USER }}/scripts/pull/preprod_pull_standard_code.sh - sudo /home/${{ secrets.CLIENT_USER }}/scripts/pull/preprod_pull_standard_code.sh - sudo systemctl restart ${{ secrets.ENSAN_APP_PREPROD_SERVICE }} ${{ secrets.ODEX25_GENERAL_PREPROD_SERVICE }} ${{ secrets.ODEX25_STANDARD_PREPROD_SERVICE }} ${{ secrets.TWAHOD_APP_PREPROD_SERVICE }} ${{ secrets.ODEX25_DEMO_PREPROD_SERVICE }} ${{ secrets.HELPDESK_PREPROD_SERVICE }} ${{ secrets.CYBER_APP_PREPROD_SERVICE }} ${{ secrets.JAZALA_APP_PREPROD_SERVICE }} - if [ $? -eq 0 ]; then - echo "** [INFO] "PREPROD" services have been restarted." - else - echo "** [ERROR] Failed to restart "PREPROD" services." - fi - - deploy_test_server: - name: Deploy to Dev Servers - runs-on: app-sever-project-runner - if: | - (github.ref == 'refs/heads/dev_odex-event' || - github.ref == 'refs/heads/dev_odex25_accounting' || - github.ref == 'refs/heads/dev_odex25_base' || - github.ref == 'refs/heads/dev_odex25_dms' || - github.ref == 'refs/heads/dev_odex25_fleet' || - github.ref == 'refs/heads/dev_odex25_helpdesk' || - github.ref == 'refs/heads/dev_odex25_hr' || - github.ref == 'refs/heads/dev_odex25_inventory' || - github.ref == 'refs/heads/dev_odex25_maintenance' || - github.ref == 'refs/heads/dev_odex25_mobile' || - github.ref == 'refs/heads/dev_odex25_pos' || - github.ref == 'refs/heads/dev_odex25_project' || - github.ref == 'refs/heads/dev_odex25_purchase' || - github.ref == 'refs/heads/dev_odex25_realstate' || - github.ref == 'refs/heads/dev_odex25_sales' || - github.ref == 'refs/heads/dev_odex25_survey' || - github.ref == 'refs/heads/dev_odex25_transactions' || - github.ref == 'refs/heads/dev_odex25_website' || - github.ref == 'refs/heads/dev_openeducat_erp-14.0.1.0' || - github.ref == 'refs/heads/dev_odex25_benefit' || - github.ref == 'refs/heads/dev_odex25_takaful' || - github.ref == 'refs/heads/dev_odex25_donation') - || (github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'dev') - steps: - - name: Checkout And Restart Project - run: | - sudo chmod +x /home/${{ secrets.CLIENT_USER }}/scripts/pull/dev_pull_standard_code.sh - sudo /home/${{ secrets.CLIENT_USER }}/scripts/pull/dev_pull_standard_code.sh - sudo systemctl restart ${{ secrets.ENSAN_APP_TEST_SERVICE }} ${{ secrets.ODEX25_GENERAL_TEST_SERVICE }} ${{ secrets.ODEX25_STANDARD_TEST_SERVICE }} ${{ secrets.TWAHOD_APP_TEST_SERVICE }} ${{ secrets.HELPDESK_TEST_SERVICE }} ${{ secrets.KAZ_LIBRARY_TEST_SERVICE }} ${{ secrets.CYBER_APP_TEST_SERVICE }} ${{ secrets.JAZALA_APP_TEST_SERVICE }} - if [ $? -eq 0 ]; then - echo "** [INFO] "DEV" services have been restarted." - else - echo "** [ERROR] Failed to restart "DEV" services." - fi - - ensan_vpn_stage_server: - name: Deploy to Ensan Stage - runs-on: new-ensan-vpn-client-server-runner - if: | - (github.ref == 'refs/heads/preprod_odex-event' || - github.ref == 'refs/heads/preprod_odex25_accounting' || - github.ref == 'refs/heads/preprod_odex25_base' || - github.ref == 'refs/heads/preprod_odex25_dms' || - github.ref == 'refs/heads/preprod_odex25_fleet' || - github.ref == 'refs/heads/preprod_odex25_helpdesk' || - github.ref == 'refs/heads/preprod_odex25_hr' || - github.ref == 'refs/heads/preprod_odex25_inventory' || - github.ref == 'refs/heads/preprod_odex25_maintenance' || - github.ref == 'refs/heads/preprod_odex25_mobile' || - github.ref == 'refs/heads/preprod_odex25_pos' || - github.ref == 'refs/heads/preprod_odex25_project' || - github.ref == 'refs/heads/preprod_odex25_purchase' || - github.ref == 'refs/heads/preprod_odex25_realstate' || - github.ref == 'refs/heads/preprod_odex25_sales' || - github.ref == 'refs/heads/preprod_odex25_survey' || - github.ref == 'refs/heads/preprod_odex25_transactions' || - github.ref == 'refs/heads/preprod_odex25_website' || - github.ref == 'refs/heads/preprod_openeducat_erp-14.0.1.0' || - github.ref == 'refs/heads/preprod_odex25_benefit' || - github.ref == 'refs/heads/preprod_odex25_takaful' || - github.ref == 'refs/heads/preprod_odex25_donation') - || (github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'preprod') - steps: - - name: Checkout And Restart Project - run: | - echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}" - sudo chmod +x ${{ secrets.ENSAN_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh - sudo ${{ secrets.ENSAN_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.ENSAN_PROJECT_USER }} ${{ secrets.ENSAN_STANDARD_FOLDER_PATH }} ${{ secrets.ENSAN_STAGE_SERVICE }} preprod ${GITHUB_REF#refs/heads/preprod_} ${GITHUB_REF#refs/heads/} ${{ secrets.GH_TOKEN }} - - diff --git a/.github/workflows/prevent-invalid-branch-merges.yml b/.github/workflows/prevent-invalid-branch-merges.yml index e10c2e26b..d03093785 100644 --- a/.github/workflows/prevent-invalid-branch-merges.yml +++ b/.github/workflows/prevent-invalid-branch-merges.yml @@ -1,333 +1,71 @@ -# Author: Ahmad Samir name: Prevent Invalid Merges on: pull_request: - branches: - - dev_odex-event - - dev_odex25_accounting - - dev_odex25_base - - dev_odex25_dms - - dev_odex25_fleet - - dev_odex25_hr - - dev_odex25_inventory - - dev_odex25_maintenance - - dev_odex25_mobile - - dev_odex25_pos - - dev_odex25_project - - dev_odex25_purchase - - dev_odex25_realstate - - dev_odex25_sales - - dev_odex25_survey - - dev_odex25_transactions - - dev_odex25_website - - dev_openeducat_erp-14.0.1.0 - - dev_odex25_ensan - - dev_odex25_helpdesk - - dev_odex25_donation - - dev_odex25_benefit - - dev_odex25_takaful - - - preprod_odex-event - - preprod_odex25_accounting - - preprod_odex25_base - - preprod_odex25_dms - - preprod_odex25_fleet - - preprod_odex25_hr - - preprod_odex25_inventory - - preprod_odex25_maintenance - - preprod_odex25_mobile - - preprod_odex25_pos - - preprod_odex25_project - - preprod_odex25_purchase - - preprod_odex25_realstate - - preprod_odex25_sales - - preprod_odex25_survey - - preprod_odex25_transactions - - preprod_odex25_website - - preprod_openeducat_erp-14.0.1.0 - - preprod_odex25_ensan - - preprod_odex25_helpdesk - - preprod_odex25_donation - - preprod_odex25_benefit - - preprod_odex25_takaful - - - master_odex-event - - master_odex25_accounting - - master_odex25_base - - master_odex25_dms - - master_odex25_fleet - - master_odex25_hr - - master_odex25_inventory - - master_odex25_maintenance - - master_odex25_mobile - - master_odex25_pos - - master_odex25_project - - master_odex25_purchase - - master_odex25_realstate - - master_odex25_sales - - master_odex25_survey - - master_odex25_transactions - - master_odex25_website - - master_openeducat_erp-14.0.1.0 - - master_odex25_ensan - - master_odex25_helpdesk - - master_odex25_donation - - master_odex25_benefit - - master_odex25_takaful - + types: [opened, reopened, synchronize, edited] jobs: - validate-merge-source: - runs-on: linting_odex25-standard-modules_runner + validate-merge-flow: + runs-on: ubuntu-latest steps: - - name: Check source branch for merge - run: | - echo "Base branch: ${{ github.base_ref }}" - echo "Head branch: ${{ github.head_ref }}" + - name: Validate Branch Flow + uses: actions/github-script@v7 + with: + script: | + const base = context.payload.pull_request.base.ref; + const head = context.payload.pull_request.head.ref; + + core.info(`Checking Merge Flow: ${head} -> ${base}`); + // 1. Parse module name from base branch + // Expected formats: dev_X, preprod_X, master_X + const tiers = ["dev", "preprod", "master"]; + + function parseBranch(branchName) { + for (const tier of tiers) { + if (branchName.startsWith(tier + "_")) { + return { tier: tier, module: branchName.substring(tier.length + 1) }; + } + } + return null; // Not a standard environment branch (maybe feature/fix) + } - # โœ… Preprod Branches - if [[ "${{ github.base_ref }}" == "preprod_odex-event" && "${{ github.head_ref }}" != "dev_odex-event" ]]; then - echo "::error ::You can only merge to 'preprod_odex-event' from 'dev_odex-event' branch!" - exit 1 - fi + const baseInfo = parseBranch(base); + const headInfo = parseBranch(head); - if [[ "${{ github.base_ref }}" == "preprod_odex25_accounting" && "${{ github.head_ref }}" != "dev_odex25_accounting" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_accounting' from 'dev_odex25_accounting' branch!" - exit 1 - fi + // If base is not a protected tier (dev/preprod/master), allow merge (feature -> feature) + if (!baseInfo) { + core.info("Base branch is not a protected environment tier. Merge allowed."); + return; + } - if [[ "${{ github.base_ref }}" == "preprod_odex25_base" && "${{ github.head_ref }}" != "dev_odex25_base" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_base' from 'dev_odex25_base' branch!" - exit 1 - fi + // Logic for Protected Base Branches + + // โŒ Rule: Cannot merge directly into master from anywhere except preprod (of same module) + if (baseInfo.tier === "master") { + if (!headInfo || headInfo.tier !== "preprod" || headInfo.module !== baseInfo.module) { + core.setFailed(`โŒ Forbidden: You can ONLY merge into 'master_${baseInfo.module}' from 'preprod_${baseInfo.module}'. Detected: ${head}`); + return; + } + } - if [[ "${{ github.base_ref }}" == "preprod_odex25_dms" && "${{ github.head_ref }}" != "dev_odex25_dms" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_dms' from 'dev_odex25_dms' branch!" - exit 1 - fi + // โŒ Rule: Cannot merge directly into preprod from anywhere except dev (of same module) + if (baseInfo.tier === "preprod") { + if (!headInfo || headInfo.tier !== "dev" || headInfo.module !== baseInfo.module) { + core.setFailed(`โŒ Forbidden: You can ONLY merge into 'preprod_${baseInfo.module}' from 'dev_${baseInfo.module}'. Detected: ${head}`); + return; + } + } - if [[ "${{ github.base_ref }}" == "preprod_odex25_fleet" && "${{ github.head_ref }}" != "dev_odex25_fleet" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_fleet' from 'dev_odex25_fleet' branch!" - exit 1 - fi + // โŒ Rule: Cannot merge directly into dev from master or preprod (reverse flow) + // (Optional: You might allow hotfixes, but strictly strictly dev<-feature is best) + if (baseInfo.tier === "dev") { + // Allow feature branches to merge into dev + // Block upstream branches + if (headInfo && (headInfo.tier === "master" || headInfo.tier === "preprod")) { + core.setFailed(`โŒ Forbidden: Cannot merge upstream (${head}) back into dev.`); + return; + } + } - if [[ "${{ github.base_ref }}" == "preprod_odex25_hr" && "${{ github.head_ref }}" != "dev_odex25_hr" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_hr' from 'dev_odex25_hr' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "preprod_odex25_inventory" && "${{ github.head_ref }}" != "dev_odex25_inventory" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_inventory' from 'dev_odex25_inventory' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "preprod_odex25_maintenance" && "${{ github.head_ref }}" != "dev_odex25_maintenance" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_maintenance' from 'dev_odex25_maintenance' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "preprod_odex25_mobile" && "${{ github.head_ref }}" != "dev_odex25_mobile" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_mobile' from 'dev_odex25_mobile' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "preprod_odex25_pos" && "${{ github.head_ref }}" != "dev_odex25_pos" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_pos' from 'dev_odex25_pos' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "preprod_odex25_project" && "${{ github.head_ref }}" != "dev_odex25_project" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_project' from 'dev_odex25_project' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "preprod_odex25_purchase" && "${{ github.head_ref }}" != "dev_odex25_purchase" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_purchase' from 'dev_odex25_purchase' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "preprod_odex25_realstate" && "${{ github.head_ref }}" != "dev_odex25_realstate" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_realstate' from 'dev_odex25_realstate' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "preprod_odex25_sales" && "${{ github.head_ref }}" != "dev_odex25_sales" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_sales' from 'dev_odex25_sales' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "preprod_odex25_survey" && "${{ github.head_ref }}" != "dev_odex25_survey" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_survey' from 'dev_odex25_survey' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "preprod_odex25_transactions" && "${{ github.head_ref }}" != "dev_odex25_transactions" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_transactions' from 'dev_odex25_transactions' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "preprod_odex25_website" && "${{ github.head_ref }}" != "dev_odex25_website" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_website' from 'dev_odex25_website' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "preprod_openeducat_erp-14.0.1.0" && "${{ github.head_ref }}" != "dev_openeducat_erp-14.0.1.0" ]]; then - echo "::error ::You can only merge to 'preprod_openeducat_erp-14.0.1.0' from 'dev_openeducat_erp-14.0.1.0' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "preprod_odex25_ensan" && "${{ github.head_ref }}" != "dev_odex25_ensan" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_ensan' from 'dev_odex25_ensan' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "preprod_odex25_helpdesk" && "${{ github.head_ref }}" != "dev_odex25_helpdesk" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_helpdesk' from 'dev_odex25_helpdesk' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "preprod_odex25_donation" && "${{ github.head_ref }}" != "dev_odex25_donation" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_donation' from 'dev_odex25_donation' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "preprod_odex25_benefit" && "${{ github.head_ref }}" != "dev_odex25_benefit" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_donation' from 'dev_odex25_donation' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "preprod_odex25_takaful" && "${{ github.head_ref }}" != "dev_odex25_takaful" ]]; then - echo "::error ::You can only merge to 'preprod_odex25_donation' from 'dev_odex25_donation' branch!" - exit 1 - fi - - - # โœ… Master Branches - if [[ "${{ github.base_ref }}" == "master_odex-event" && "${{ github.head_ref }}" != "preprod_odex-event" ]]; then - echo "::error ::You can only merge to 'master_odex-event' from 'preprod_odex-event' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_accounting" && "${{ github.head_ref }}" != "preprod_odex25_accounting" ]]; then - echo "::error ::You can only merge to 'master_odex25_accounting' from 'preprod_odex25_accounting' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_base" && "${{ github.head_ref }}" != "preprod_odex25_base" ]]; then - echo "::error ::You can only merge to 'master_odex25_base' from 'preprod_odex25_base' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_dms" && "${{ github.head_ref }}" != "preprod_odex25_dms" ]]; then - echo "::error ::You can only merge to 'master_odex25_dms' from 'preprod_odex25_dms' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_fleet" && "${{ github.head_ref }}" != "preprod_odex25_fleet" ]]; then - echo "::error ::You can only merge to 'master_odex25_fleet' from 'preprod_odex25_fleet' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_hr" && "${{ github.head_ref }}" != "preprod_odex25_hr" ]]; then - echo "::error ::You can only merge to 'master_odex25_hr' from 'preprod_odex25_hr' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_inventory" && "${{ github.head_ref }}" != "preprod_odex25_inventory" ]]; then - echo "::error ::You can only merge to 'master_odex25_inventory' from 'preprod_odex25_inventory' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_maintenance" && "${{ github.head_ref }}" != "preprod_odex25_maintenance" ]]; then - echo "::error ::You can only merge to 'master_odex25_maintenance' from 'preprod_odex25_maintenance' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_mobile" && "${{ github.head_ref }}" != "preprod_odex25_mobile" ]]; then - echo "::error ::You can only merge to 'master_odex25_mobile' from 'preprod_odex25_mobile' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_pos" && "${{ github.head_ref }}" != "preprod_odex25_pos" ]]; then - echo "::error ::You can only merge to 'master_odex25_pos' from 'preprod_odex25_pos' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_project" && "${{ github.head_ref }}" != "preprod_odex25_project" ]]; then - echo "::error ::You can only merge to 'master_odex25_project' from 'preprod_odex25_project' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_purchase" && "${{ github.head_ref }}" != "preprod_odex25_purchase" ]]; then - echo "::error ::You can only merge to 'master_odex25_purchase' from 'preprod_odex25_purchase' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_realstate" && "${{ github.head_ref }}" != "preprod_odex25_realstate" ]]; then - echo "::error ::You can only merge to 'master_odex25_realstate' from 'preprod_odex25_realstate' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_sales" && "${{ github.head_ref }}" != "preprod_odex25_sales" ]]; then - echo "::error ::You can only merge to 'master_odex25_sales' from 'preprod_odex25_sales' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_survey" && "${{ github.head_ref }}" != "preprod_odex25_survey" ]]; then - echo "::error ::You can only merge to 'master_odex25_survey' from 'preprod_odex25_survey' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_transactions" && "${{ github.head_ref }}" != "preprod_odex25_transactions" ]]; then - echo "::error ::You can only merge to 'master_odex25_transactions' from 'preprod_odex25_transactions' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_website" && "${{ github.head_ref }}" != "preprod_odex25_website" ]]; then - echo "::error ::You can only merge to 'master_odex25_website' from 'preprod_odex25_website' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_openeducat_erp-14.0.1.0" && "${{ github.head_ref }}" != "preprod_openeducat_erp-14.0.1.0" ]]; then - echo "::error ::You can only merge to 'master_openeducat_erp-14.0.1.0' from 'preprod_openeducat_erp-14.0.1.0' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_ensan" && "${{ github.head_ref }}" != "preprod_odex25_ensan" ]]; then - echo "::error ::You can only merge to 'master_odex25_ensan' from 'preprod_odex25_ensan' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_helpdesk" && "${{ github.head_ref }}" != "preprod_odex25_helpdesk" ]]; then - echo "::error ::You can only merge to 'master_odex25_helpdesk' from 'preprod_odex25_helpdesk' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_donation" && "${{ github.head_ref }}" != "preprod_odex25_donation" ]]; then - echo "::error ::You can only merge to 'master_odex25_donation' from 'preprod_odex25_donation' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_benefit" && "${{ github.head_ref }}" != "preprod_odex25_benefit" ]]; then - echo "::error ::You can only merge to 'master_odex25_donation' from 'preprod_odex25_donation' branch!" - exit 1 - fi - - if [[ "${{ github.base_ref }}" == "master_odex25_takaful" && "${{ github.head_ref }}" != "preprod_odex25_takaful" ]]; then - echo "::error ::You can only merge to 'master_odex25_donation' from 'preprod_odex25_donation' branch!" - exit 1 - fi - - - - - - # โŒ Block ALL merges to 'master' - if [[ "${{ github.base_ref }}" == "master" ]]; then - echo "::error ::Merging to 'master' branch is not allowed!" - exit 1 - fi - - echo "Merge validation passed." + core.info("โœ… Merge flow validation passed."); diff --git a/.github/workflows/production_pull_code.yml b/.github/workflows/production_pull_code.yml deleted file mode 100644 index 09b8c8aeb..000000000 --- a/.github/workflows/production_pull_code.yml +++ /dev/null @@ -1,259 +0,0 @@ -name: Production Projects - Pull Code - -on: - workflow_dispatch: - inputs: - environment: - description: 'Select Project Prod Server' - required: true - type: choice - options: - - "Ensan Project - Production" - - "Helpdesk Khabir Project" - - "King AbdelAziz Library Project" - - "Twahod Project" - - "Ekram Project" - - "Sahli Project - Production" - - "Sahli Project - Stage" - - "Jazala Project" - -jobs: -# Ensan Project - ensan_master_server: - name: Deploy to Ensan Master - runs-on: new-ensan-vpn-client-server-runner - if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'Ensan Project - Production' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_helpdesk' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_takaful' || github.ref == 'refs/heads/master_odex25_benefit' || github.ref == 'refs/heads/master_odex25_donation' || github.ref == 'refs/heads/master_odex25_ensan') && - (github.actor == 'moutazmuhammad' || - github.actor == 'expsa' || - github.actor == 'ahmadaking' || - github.actor == 'ronozoro' || - github.actor == 'Abubaker-Altaib' || - github.actor == 'abdurrahman-saber' || - github.actor == 'altexp' || - github.actor == 'kchyounes19' || - github.actor == 'maltayyar2' || - github.actor == 'SamirLADOUI-sa' || - github.actor == 'mohammed-alkhazrji') - steps: - - name: Checkout And Restart Project - run: | - echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}" - mkdir -p ~/master_branch_sha - echo "$(date '+%Y-%m-%d %H:%M:%S') - ${{ github.sha }}" >> ~/master_branch_sha/${GITHUB_REF#refs/heads/} - sudo chmod +x ${{ secrets.ENSAN_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh - sudo ${{ secrets.ENSAN_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.ENSAN_PROJECT_USER }} ${{ secrets.ENSAN_STANDARD_FOLDER_PATH }} ${{ secrets.ENSAN_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/} ${{ secrets.GH_TOKEN }} - - - name: Cleanup workspace - if: always() - run: | - rm -rf $GITHUB_WORKSPACE/* - -# Helpdesk Project - helpdesk_maser_server: - name: Deploy to Helpdesk Master - runs-on: helpdesk_server - if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'Helpdesk Khabir Project' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_takaful' || github.ref == 'refs/heads/master_odex25_benefit' || github.ref == 'refs/heads/master_odex25_helpdesk' || github.ref == 'refs/heads/master_odex25_ensan') && - (github.actor == 'moutazmuhammad' || - github.actor == 'expsa' || - github.actor == 'ahmadaking' || - github.actor == 'ronozoro' || - github.actor == 'Abubaker-Altaib' || - github.actor == 'abdurrahman-saber' || - github.actor == 'altexp' || - github.actor == 'kchyounes19' || - github.actor == 'maltayyar2' || - github.actor == 'SamirLADOUI-sa' || - github.actor == 'mohammed-alkhazrji') - steps: - - name: Checkout And Restart Project - run: | - echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}" - mkdir -p ~/master_branch_sha - echo "$(date '+%Y-%m-%d %H:%M:%S') - ${{ github.sha }}" >> ~/master_branch_sha/${GITHUB_REF#refs/heads/} - sudo chmod +x ${{ secrets.HELPDESK_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh - sudo ${{ secrets.HELPDESK_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.HELPDESK_PROJECT_USER }} ${{ secrets.HELPDESK_STANDARD_FOLDER_PATH }} ${{ secrets.HELPDESK_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/} ${{ secrets.GH_TOKEN }} - - - name: Cleanup workspace - if: always() - run: | - rm -rf $GITHUB_WORKSPACE/* - -# King Abdel Aziz Lobrary project - kaz_master_server: - name: Deploy to KAZ Master - runs-on: kaz-library-project-runner - if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'King AbdelAziz Library Project' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_helpdesk' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_takaful' || github.ref == 'refs/heads/master_odex25_benefit' || github.ref == 'refs/heads/master_odex25_ensan') && - (github.actor == 'moutazmuhammad' || - github.actor == 'expsa' || - github.actor == 'ahmadaking' || - github.actor == 'ronozoro' || - github.actor == 'Abubaker-Altaib' || - github.actor == 'abdurrahman-saber' || - github.actor == 'altexp' || - github.actor == 'kchyounes19' || - github.actor == 'maltayyar2' || - github.actor == 'SamirLADOUI-sa' || - github.actor == 'mohammed-alkhazrji') - steps: - - name: Checkout And Restart Project - run: | - echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}" - mkdir -p ~/master_branch_sha - echo "$(date '+%Y-%m-%d %H:%M:%S') - ${{ github.sha }}" >> ~/master_branch_sha/${GITHUB_REF#refs/heads/} - sudo chmod +x ${{ secrets.KAZ_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh - sudo ${{ secrets.KAZ_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.KAZ_PROJECT_USER }} ${{ secrets.KAZ_STANDARD_FOLDER_PATH }} ${{ secrets.KAZ_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/} ${{ secrets.GH_TOKEN }} - sudo systemctl restart odoo-server-stage.service - - - name: Cleanup workspace - if: always() - run: | - rm -rf $GITHUB_WORKSPACE/* - -# Twahod project - twahod_master_server: - name: Deploy to Twahod Master - runs-on: twahod-client-project-runner - if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'Twahod Project' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_helpdesk' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_takaful' || github.ref == 'refs/heads/master_odex25_benefit' || github.ref == 'refs/heads/master_odex25_ensan') && - (github.actor == 'moutazmuhammad' || - github.actor == 'expsa' || - github.actor == 'ahmadaking' || - github.actor == 'ronozoro' || - github.actor == 'Abubaker-Altaib' || - github.actor == 'abdurrahman-saber' || - github.actor == 'altexp' || - github.actor == 'kchyounes19' || - github.actor == 'maltayyar2' || - github.actor == 'SamirLADOUI-sa' || - github.actor == 'mohammed-alkhazrji') - steps: - - name: Checkout And Restart Project - run: | - echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}" - mkdir -p ~/master_branch_sha - echo "$(date '+%Y-%m-%d %H:%M:%S') - ${{ github.sha }}" >> ~/master_branch_sha/${GITHUB_REF#refs/heads/} - sudo chmod +x ${{ secrets.TWAHOD_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh - sudo ${{ secrets.TWAHOD_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.TWAHOD_PROJECT_USER }} ${{ secrets.TWAHOD_STANDARD_FOLDER_PATH }} ${{ secrets.TWAHOD_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/} ${{ secrets.GH_TOKEN }} - - - name: Cleanup workspace - if: always() - run: | - rm -rf $GITHUB_WORKSPACE/* - -# Ekram project - ekram_master_server: - name: Deploy to Ekram Master - runs-on: ekram-client-project-runner - if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'Ekram Project' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_helpdesk' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_takaful' || github.ref == 'refs/heads/master_odex25_benefit' || github.ref == 'refs/heads/master_odex25_ensan') && - (github.actor == 'moutazmuhammad' || - github.actor == 'expsa' || - github.actor == 'ahmadaking' || - github.actor == 'ronozoro' || - github.actor == 'Abubaker-Altaib' || - github.actor == 'abdurrahman-saber' || - github.actor == 'altexp' || - github.actor == 'kchyounes19' || - github.actor == 'maltayyar2' || - github.actor == 'SamirLADOUI-sa' || - github.actor == 'mohammed-alkhazrji') - steps: - - name: Checkout And Restart Project - run: | - echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}" - mkdir -p ~/master_branch_sha - echo "$(date '+%Y-%m-%d %H:%M:%S') - ${{ github.sha }}" >> ~/master_branch_sha/${GITHUB_REF#refs/heads/} - sudo chmod +x ${{ secrets.EKRAM_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh - sudo ${{ secrets.EKRAM_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.EKRAM_PROJECT_USER }} ${{ secrets.EKRAM_STANDARD_FOLDER_PATH }} ${{ secrets.EKRAM_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/} ${{ secrets.GH_TOKEN }} - - - name: Cleanup workspace - if: always() - run: | - rm -rf $GITHUB_WORKSPACE/* - -# Sahli Prod project - sahli_prod_master_server: - name: Deploy to Sahli Prod Master - runs-on: sahli-client-project-runner - if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'Sahli Project - Production' && (github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_helpdesk' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_project') && - (github.actor == 'moutazmuhammad' || - github.actor == 'expsa' || - github.actor == 'ahmadaking' || - github.actor == 'ronozoro' || - github.actor == 'Abubaker-Altaib' || - github.actor == 'abdurrahman-saber' || - github.actor == 'altexp' || - github.actor == 'kchyounes19' || - github.actor == 'maltayyar2' || - github.actor == 'SamirLADOUI-sa' || - github.actor == 'mohammed-alkhazrji') - steps: - - name: Checkout And Restart Project - run: | - echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}" - mkdir -p ~/master_branch_sha - echo "$(date '+%Y-%m-%d %H:%M:%S') - ${{ github.sha }}" >> ~/master_branch_sha/${GITHUB_REF#refs/heads/} - sudo chmod +x ${{ secrets.SAHLI_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh - sudo ${{ secrets.SAHLI_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.SAHLI_PROJECT_USER }} ${{ secrets.SAHLI_STANDARD_FOLDER_PATH }} ${{ secrets.SAHLI_PROD_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/} ${{ secrets.GH_TOKEN }} - - - name: Cleanup workspace - if: always() - run: | - rm -rf $GITHUB_WORKSPACE/* - - sahli_stage_master_server: - name: Deploy to Sahli Stage Master - runs-on: sahli-client-project-runner - if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'Sahli Project - Stage' && (github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_helpdesk' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_project') && - (github.actor == 'moutazmuhammad' || - github.actor == 'expsa' || - github.actor == 'ahmadaking' || - github.actor == 'ronozoro' || - github.actor == 'Abubaker-Altaib' || - github.actor == 'abdurrahman-saber' || - github.actor == 'altexp' || - github.actor == 'kchyounes19' || - github.actor == 'maltayyar2' || - github.actor == 'SamirLADOUI-sa' || - github.actor == 'mohammed-alkhazrji') - steps: - - name: Checkout And Restart Project - run: | - echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}" - mkdir -p ~/master_branch_sha - echo "$(date '+%Y-%m-%d %H:%M:%S') - ${{ github.sha }}" >> ~/master_branch_sha/${GITHUB_REF#refs/heads/}-stage - sudo chmod +x ${{ secrets.SAHLI_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh - sudo ${{ secrets.SAHLI_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.SAHLI_PROJECT_USER }} ${{ secrets.SAHLI_STANDARD_FOLDER_PATH }} ${{ secrets.SAHLI_STAGE_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/} ${{ secrets.GH_TOKEN }} - - - name: Cleanup workspace - if: always() - run: | - rm -rf $GITHUB_WORKSPACE/* - -# Jazala project - jazala_master_server: - name: Deploy to Jazala Master - runs-on: jazala-client-project-runner - if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'Jazala Project' && (github.ref == 'refs/heads/master_odex-event' || github.ref == 'refs/heads/master_odex25_accounting' || github.ref == 'refs/heads/master_odex25_base' || github.ref == 'refs/heads/master_odex25_dms' || github.ref == 'refs/heads/master_odex25_fleet' || github.ref == 'refs/heads/master_odex25_helpdesk' || github.ref == 'refs/heads/master_odex25_ENSAN' || github.ref == 'refs/heads/master_odex25_hr' || github.ref == 'refs/heads/master_odex25_inventory' || github.ref == 'refs/heads/master_odex25_maintenance' || github.ref == 'refs/heads/master_odex25_mobile' || github.ref == 'refs/heads/master_odex25_pos' || github.ref == 'refs/heads/master_odex25_project' || github.ref == 'refs/heads/master_odex25_purchase' || github.ref == 'refs/heads/master_odex25_realstate' || github.ref == 'refs/heads/master_odex25_sales' || github.ref == 'refs/heads/master_odex25_survey' || github.ref == 'refs/heads/master_odex25_transactions' || github.ref == 'refs/heads/master_odex25_website' || github.ref == 'refs/heads/master_openeducat_erp-14.0.1.0' || github.ref == 'refs/heads/master_odex25_takaful' || github.ref == 'refs/heads/master_odex25_benefit' || github.ref == 'refs/heads/master_odex25_ensan') && - (github.actor == 'moutazmuhammad' || - github.actor == 'expsa' || - github.actor == 'ahmadaking' || - github.actor == 'ronozoro' || - github.actor == 'Abubaker-Altaib' || - github.actor == 'abdurrahman-saber' || - github.actor == 'altexp' || - github.actor == 'kchyounes19' || - github.actor == 'maltayyar2' || - github.actor == 'SamirLADOUI-sa' || - github.actor == 'mohammed-alkhazrji') - steps: - - name: Checkout And Restart Project - run: | - echo "** [INFO] Running on branch --> ${GITHUB_REF#refs/heads/}" - mkdir -p ~/master_branch_sha - echo "$(date '+%Y-%m-%d %H:%M:%S') - ${{ github.sha }}" >> ~/master_branch_sha/${GITHUB_REF#refs/heads/} - sudo chmod +x ${{ secrets.JAZALA_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh - sudo ${{ secrets.JAZALA_STANDARD_FOLDER_PATH }}/scripts/pull_code.sh ${{ secrets.JAZALA_PROJECT_USER }} ${{ secrets.JAZALA_STANDARD_FOLDER_PATH }} ${{ secrets.JAZALA_MASTER_SERVICE }} master ${GITHUB_REF#refs/heads/master_} ${GITHUB_REF#refs/heads/} ${{ secrets.GH_TOKEN }} - - - name: Cleanup workspace - if: always() - run: | - rm -rf $GITHUB_WORKSPACE/* diff --git a/.github/workflows/restrict-pr-authors.yaml b/.github/workflows/restrict-pr-authors.yaml index e6adc959b..3277fac1d 100644 --- a/.github/workflows/restrict-pr-authors.yaml +++ b/.github/workflows/restrict-pr-authors.yaml @@ -1,111 +1,48 @@ -name: Restrict PR Authors & Committers - -permissions: - contents: read - pull-requests: write +name: Restrict PR Authors on: pull_request: types: [opened, reopened, synchronize] - branches: - - dev_odex-event - - dev_odex25_accounting - - dev_odex25_base - - dev_odex25_dms - - dev_odex25_fleet - - dev_odex25_hr - - dev_odex25_inventory - - dev_odex25_maintenance - - dev_odex25_mobile - - dev_odex25_pos - - dev_odex25_project - - dev_odex25_purchase - - dev_odex25_realstate - - dev_odex25_sales - - dev_odex25_survey - - dev_odex25_transactions - - dev_odex25_website - - dev_openeducat_erp-14.0.1.0 - - dev_odex25_benefit - - dev_odex25_takaful - - dev_odex25_helpdesk - - dev_odex25_donation - - dev_odex25_ensan + branches: + - '**' # Apply to all PRs in this repo + +permissions: + pull-requests: write jobs: check_pr_author: - runs-on: linting_odex25-standard-modules_runner - + runs-on: ubuntu-latest steps: - - name: Validate PR Author & Commit Authors + - name: Validate PR Author uses: actions/github-script@v7 with: - github-token: ${{ secrets.GH_TOKEN }} script: | + // TODO: Add your team members here const allowed = [ - "expsa", - "moutazmuhammad", - "ronozoro", - "Abubaker-Altaib", - "altexp", - "the5abir", - "ahmadaking", - "kchyounes19", - "abdurrahman-saber", - "maltayyar2", - "esam-sermah", - "mohammed-alkhazrji", - "SamirLADOUI-sa", - "NossibaElhadi" + "hydracp9", + "eltayar", // Added for testing/dev + // "another-client-user" ]; - const pr = context.payload.pull_request; - const prAuthor = pr.user.login; - const owner = context.repo.owner; - const repo = context.repo.repo; + const prAuthor = context.payload.pull_request.user.login; - core.info(`PR author: ${prAuthor}`); + core.info(`PR Author: ${prAuthor}`); - // Check PR author if (!allowed.includes(prAuthor)) { - core.error(`Unauthorized PR author: ${prAuthor}. Closing PR...`); - await github.rest.pulls.update({ - owner, - repo, - pull_number: pr.number, - state: "closed" - }); - return; + core.setFailed(`โ›” Unauthorized Access: User '${prAuthor}' is not in the allowed list.`); + + // Optional: Close the PR automatically + try { + await github.rest.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.payload.pull_request.number, + state: "closed" + }); + core.info("PR has been closed automatically."); + } catch (e) { + core.warning("Failed to close PR automatically."); + } + } else { + core.info("โœ… Authorized."); } - core.info("All PR authors are allowed."); - -# // Check commit authors -# const commitList = await github.rest.pulls.listCommits({ -# owner, -# repo, -# pull_number: pr.number -# }); - -# core.info("PR author is allowed."); - -# // Uncomment below if you want to block unauthorized commit authors also -# /* -# for (const commit of commitList.data) { -# const commitAuthor = commit.author ? commit.author.login : null; - -# if (commitAuthor && !allowed.includes(commitAuthor)) { -# core.error(`Unauthorized commit author: ${commitAuthor}. Closing PR...`); - -# await github.rest.pulls.update({ -# owner, -# repo, -# pull_number: pr.number, -# state: "closed" -# }); - -# return; -# } -# } - -# core.info("All PR authors and committers are allowed."); -# */