name: Continuous Deployment  # Name of this workflow as shown in the CI/CD UI

on:  # Section defining which events trigger this workflow
  push:  # Trigger when a push event occurs
    tags:  # Limit triggers to pushes involving tags
      - 'v*'  # Only run for version tags that start with 'v' (e.g., v0.0.1, v1.2.3)

  workflow_dispatch:  # Allow this workflow to be triggered manually from the UI
    inputs:  # Optional inputs for manual deployments
      version:  # Input used to document which version is being deployed manually
        description: "Version to deploy when triggering manually (informational only)"  # Help text for the version input
        required: false  # This input is optional
        default: "manual-trigger"  # Default value when no explicit version is supplied

permissions:  # Default permissions for the token used in this workflow
  contents: read  # Allow reading repository contents (needed for checkout)
  packages: write  # Allow pushing packages/images to registries (adjust or remove if not needed)
  id-token: write  # Allow issuing OIDC tokens for cloud providers (remove if not used)

jobs:  # Collection of jobs defined in this workflow
  deploy:  # Job responsible for deploying tagged releases
    name: Deploy tagged release  # Human-readable name for this deployment job
    runs-on: ubuntu-latest  # Use the latest Ubuntu Linux runner image

    timeout-minutes: 30  # Automatically fail the job if it runs longer than 30 minutes

    concurrency:  # Prevent overlapping deployments
      group: deploy-main-tags  # Group key: serialize all deployments that share this identifier
      cancel-in-progress: true  # Cancel any running deployment in this group when a new one starts

    environment:  # Associate this job with a deployment environment
      name: production  # Label the environment as 'production' for visibility and protections

    steps:  # Ordered list of steps in this job
      - name: Checkout Code  # Step to check out the repository at the tagged commit
        uses: actions/checkout@v6  # Standard checkout action (Gitea-compatible)
        with:  # Options for configuring the checkout behavior
          ref: ${{ gitea.ref }}  # Check out the specific commit referenced by the pushed tag
          fetch-depth: 0  # Fetch full history so ancestry checks and branch analysis are reliable

      - name: Verify tag commit is on current or historical commit of 'remote/main'  # Ensure the tag commit comes from the assumed main branch
        shell: bash  # Explicitly use bash for this script
        run: |  # Begin multi-line bash script
          set -euo pipefail  # Enable strict mode: exit on error, unset var, or failed pipeline command

          REMOTE_NAME="remote"  # Fixed assumption: the relevant remote is named "remote"
          MAIN_BRANCH_NAME="main"  # Fixed assumption: the primary branch on the remote is named "main"

          echo "Assuming remote name: ${REMOTE_NAME}"  # Log the assumed remote name
          echo "Assuming main branch name on remote: ${MAIN_BRANCH_NAME}"  # Log the assumed main branch name

          if ! git remote | grep -qx "${REMOTE_NAME}"; then  # Check that the assumed remote actually exists
            echo "❌ Expected remote '${REMOTE_NAME}' not found in repository remotes."  # Explain missing remote
            git remote -v  # Show the actual configured remotes for debugging
            exit 1  # Fail the job because we cannot safely validate without the expected remote
          fi  # End of remote existence check

          TAG_COMMIT="$(git rev-parse HEAD)"  # Determine the commit hash currently checked out (the tag target)
          echo "Tag points to commit: ${TAG_COMMIT}"  # Log which commit the tag references

          echo "Fetching '${MAIN_BRANCH_NAME}' from remote '${REMOTE_NAME}'..."  # Log the fetch action
          if ! git fetch "${REMOTE_NAME}" "${MAIN_BRANCH_NAME}" > /dev/null 2>&1; then  # Fetch remote/main silently and detect failure
            echo "❌ Failed to fetch branch '${MAIN_BRANCH_NAME}' from remote '${REMOTE_NAME}'."  # Explain fetch failure
            echo "   Ensure '${REMOTE_NAME}/${MAIN_BRANCH_NAME}' exists and is accessible."  # Suggest verifying remote branch presence
            exit 1  # Fail the job because we cannot validate against main
          fi  # End of fetch error check

          MAIN_REF="${REMOTE_NAME}/${MAIN_BRANCH_NAME}"  # Construct the fully qualified remote/main reference

          echo "Discovering remote branches that contain the tag commit ${TAG_COMMIT}..."  # Log start of branch discovery
          BRANCHES_RAW="$(git branch -r --contains "${TAG_COMMIT}" || true)"  # List remote branches whose history contains the tag commit (may be empty)
          echo "Raw remote branches containing tag commit:"  # Introductory log for raw remote-branch list
          echo "${BRANCHES_RAW}"  # Output the raw remote-tracking branches

          BRANCHES_CLEANED="$(echo "${BRANCHES_RAW}" | sed 's|^[[:space:]]*||;s|.*/||')"  # Trim spaces and strip remote prefixes, leaving branch names only
          echo "Branch names containing tag commit (remote prefixes stripped):"  # Introductory log for cleaned branch names
          echo "${BRANCHES_CLEANED}"  # Output the cleaned list of branch names for human inspection

          if echo "${BRANCHES_RAW}" | sed 's|^[[:space:]]*||' | grep -qx "${MAIN_REF}"; then  # Check if remote/main itself contains the tag commit
            echo "${MAIN_REF} is listed as containing the tag commit."  # Log that remote/main is explicitly reported as containing the commit
          else  # Branch taken when remote/main is not listed among the containing branches
            echo "Note: '${MAIN_REF}' is not explicitly listed among branches containing the tag commit;"  # Note about absence in the listing
            echo "      proceeding to verify via merge-base ancestry check as the final source of truth."  # Explain that merge-base will be used to decide
          fi  # End of explicit listing check

          echo "Verifying that tag commit ${TAG_COMMIT} is an ancestor of '${MAIN_REF}'..."  # Log the start of ancestry verification
          if git merge-base --is-ancestor "${TAG_COMMIT}" "${MAIN_REF}"; then  # Check if the tag commit is contained in the history of remote/main
            echo "✅ Tag commit is part of '${MAIN_REF}' history."  # Success: tag commit is in remote/main history
            echo "   This means the tag was created on the current or historical commit of the main branch on remote '${REMOTE_NAME}'."  # Clarify the semantic meaning
          else  # Branch taken when the tag commit is not reachable from remote/main
            echo "❌ Tag commit is NOT part of '${MAIN_REF}' history."  # Failure: invalid tag source
            echo "   Deployment is only allowed for tags created on the current or historical commit of '${MAIN_REF}'."  # Explain the policy being enforced
            exit 1  # Fail the job to prevent deployment from a non-main branch
          fi  # End of ancestry validation conditional

      - name: Build and Publish Release  # Step that builds and deploys the validated tagged release
        shell: bash  # Use bash for this deployment script
        env:  # Environment variables used during build and deployment
          TAG_NAME: ${{ gitea.ref_name }}  # Tag name (e.g., v0.0.1, v1.2.3) from the workflow context
          CI: "true"  # Conventional flag signaling that commands run in a CI/CD environment
        run: |  # Begin multi-line bash script for build and deploy
          set -euo pipefail  # Enforce strict error handling during deployment

          echo "Proceeding with building and deploying version ${TAG_NAME}..."  # Log which version is being deployed

          # --- Begin placeholder for production build and deployment logic ---  # Marker for project-specific deployment implementation
          # Example for container-based deployments:  # Example of a containerized deployment sequence
          #   make test  # Run tests one more time as a safeguard before deployment
          #   make build-release  # Build application artifacts for production
          #   docker build -t myorg/myapp:${TAG_NAME} .  # Build Docker image tagged with the version
          #   docker push myorg/myapp:${TAG_NAME}  # Push Docker image to the container registry
          #   ./deploy_to_production.sh "${TAG_NAME}"  # Run custom deployment script using the version tag
          # Example for non-container deployments:  # Example of a file-based or script-based deployment sequence
          #   ./scripts/package.sh "${TAG_NAME}"  # Package application into production-ready artifacts
          #   ./scripts/deploy.sh "${TAG_NAME}"  # Deploy artifacts to servers or hosting platform
          # --- End placeholder for production build and deployment logic ---  # End of deployment example section

          echo "Build and deployment steps completed for version ${TAG_NAME} (assuming real commands are configured above)."  # Summary log for successful deployment step
