From 086ba5aa3da821bab3856be665325d426d335c65 Mon Sep 17 00:00:00 2001 From: Benjamin Labrecque Date: Thu, 30 Jul 2026 10:03:49 +0200 Subject: [PATCH] chore: ansible -> gitea worklow --- .gitea/workflows/add-new-service-ansible.yml | 73 ++++++++++++++++ .gitea/workflows/add-new-service.yml | 37 -------- .gitea/workflows/deploy-service.yml | 63 ++++++++++++++ .gitea/workflows/deploy.yml | 88 +++++++++----------- 4 files changed, 174 insertions(+), 87 deletions(-) create mode 100644 .gitea/workflows/add-new-service-ansible.yml create mode 100644 .gitea/workflows/deploy-service.yml diff --git a/.gitea/workflows/add-new-service-ansible.yml b/.gitea/workflows/add-new-service-ansible.yml new file mode 100644 index 0000000..1471f16 --- /dev/null +++ b/.gitea/workflows/add-new-service-ansible.yml @@ -0,0 +1,73 @@ +name: Add new service + +on: + push: + branches: + - 'feature/add-service-*' + +# TODO: when to deploy to prod? Manual (i.e. cli command)? +jobs: + deploy: + runs-on: hla-dev + + env: + ANSIBLE_CONFIG: "${{ github.workspace }}/ansible/ansible.cfg" + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install and setup uv + uses: actions/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + with: + version: "latest" + enable-cache: true # Speeds up runs by caching python dependencies # TODO: does this work? + + - name: Install Python 3.10 + run: uv python install 3.10 + + - name: Run tests + run: | + cd cli && uv run pytest + + - name: Parse Service Directory Name + id: parse_branch + # Uses bash shell parameter elimination to strip 'feature/add-service-' from the front + run: | + BRANCH="${{ github.ref_name }}" + SERVICE_NAME="${BRANCH#feature/add-service-}" + echo "service_name_lower=$SERVICE_NAME" >> $GITHUB_OUTPUT + + # TODO: look into venv caching (will do later in case we move from uv to pixi) + # - name: Cache Python Virtual Environment + # uses: actions/cache@v4 + # with: + # path: .venv + # # Changes uv.lock will automatically invalidate the cache and rebuild + # key: ${{ runner.os }}-uv-cli-venv-${{ hashFiles('cli/uv.lock') }} + # restore-keys: | + # ${{ runner.os }}-uv-cli-venv- + + # # Only create the venv if the cache didn't restore an existing one + # if [ ! -d ".venv" ]; then + # echo "Building new .venv" + # uv venv .venv + # fi + - name: Initialize Virtual Environment from cli/uv.lock + run: | + uv venv .venv + uv sync --directory cli + + - name: Install Ansible Galaxy Collections + run: | + uv run ansible-galaxy collection install -r ansible/collections/requirements.yml -p ./ansible/installed-collections + + # TODO: dev/prod + - name: Run New Service Playbook + working-directory: ansible + run: | + uv run ansible-playbook playbooks/add-new-service.yml \ + -i "inventories/dev/hosts.yml" \ + --extra-vars="repo_root=${{ github.workspace }}" \ + --extra-vars="service_name_lower=${{ steps.parse_branch.outputs.service_name_lower }}" \ + -v diff --git a/.gitea/workflows/add-new-service.yml b/.gitea/workflows/add-new-service.yml index 1471f16..c32fa0e 100644 --- a/.gitea/workflows/add-new-service.yml +++ b/.gitea/workflows/add-new-service.yml @@ -10,9 +10,6 @@ jobs: deploy: runs-on: hla-dev - env: - ANSIBLE_CONFIG: "${{ github.workspace }}/ansible/ansible.cfg" - steps: - name: Checkout repository uses: actions/checkout@v4 @@ -37,37 +34,3 @@ jobs: BRANCH="${{ github.ref_name }}" SERVICE_NAME="${BRANCH#feature/add-service-}" echo "service_name_lower=$SERVICE_NAME" >> $GITHUB_OUTPUT - - # TODO: look into venv caching (will do later in case we move from uv to pixi) - # - name: Cache Python Virtual Environment - # uses: actions/cache@v4 - # with: - # path: .venv - # # Changes uv.lock will automatically invalidate the cache and rebuild - # key: ${{ runner.os }}-uv-cli-venv-${{ hashFiles('cli/uv.lock') }} - # restore-keys: | - # ${{ runner.os }}-uv-cli-venv- - - # # Only create the venv if the cache didn't restore an existing one - # if [ ! -d ".venv" ]; then - # echo "Building new .venv" - # uv venv .venv - # fi - - name: Initialize Virtual Environment from cli/uv.lock - run: | - uv venv .venv - uv sync --directory cli - - - name: Install Ansible Galaxy Collections - run: | - uv run ansible-galaxy collection install -r ansible/collections/requirements.yml -p ./ansible/installed-collections - - # TODO: dev/prod - - name: Run New Service Playbook - working-directory: ansible - run: | - uv run ansible-playbook playbooks/add-new-service.yml \ - -i "inventories/dev/hosts.yml" \ - --extra-vars="repo_root=${{ github.workspace }}" \ - --extra-vars="service_name_lower=${{ steps.parse_branch.outputs.service_name_lower }}" \ - -v diff --git a/.gitea/workflows/deploy-service.yml b/.gitea/workflows/deploy-service.yml new file mode 100644 index 0000000..39c8ec3 --- /dev/null +++ b/.gitea/workflows/deploy-service.yml @@ -0,0 +1,63 @@ +name: Service Deployer + +on: + workflow_call: + inputs: + service_name: + required: true + type: string + description: "Target service name lower (e.g. master)" + environment: + required: true + type: string + # default: "dev" + description: "Target deployment environment: 'dev' or 'prod'" + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Resolve service name parameters + id: vars + run: | + SERVICE_NAME="${{ inputs.service_name }}" + SERVICE_NAME_LOWER=$(echo "$SERVICE_NAME" | tr '[:upper:]' '[:lower:]') + SERVICE_NAME_UPPER=$(echo "$SERVICE_NAME" | tr '[:lower:]' '[:upper:]') + + echo "service_name_lower=$SERVICE_NAME_LOWER" >> $GITHUB_OUTPUT + echo "service_name_upper=$SERVICE_NAME_UPPER" >> $GITHUB_OUTPUT + echo "systemd_unit_name=AGEBD-SERVICE-${SERVICE_NAME_UPPER}.service" >> $GITHUB_OUTPUT + echo "service_dir=/sls/bd/hla/${{ inputs.environment }}/services/${SERVICE_NAME_LOWER}/current" >> $GITHUB_OUTPUT + + - name: Ensure service directory exists + run: | + mkdir -p ${{ steps.vars.outputs.service_dir }} + + - name: Sync service deployment files + run: | + rsync -avz --delete --exclude='.venv' \ + ./services/${{ steps.vars.outputs.service_name_lower }}/current/ \ + ${{ steps.vars.outputs.service_dir }}/ + + - name: Substitute environment variables & setup systemd service + run: | + SERVICE_DIR="${{ steps.vars.outputs.service_dir }}" + SYSTEMD_UNIT_NAME="${{ steps.vars.outputs.systemd_unit_name }}" + AGEBD_ENV="${{ inputs.environment }}" + + SYSTEMD_UNIT_FILE_PATH="${SERVICE_DIR}/systemd/${SYSTEMD_UNIT_NAME}" + if [ -f "\$SYSTEMD_UNIT_FILE_PATH" ]; then + sed -i "s/{{ *agebd_env *}}/${AGEBD_ENV}/g" "\$SYSTEMD_UNIT_FILE_PATH" + fi + + mkdir -p ~/.config/systemd/user + ln -sf "\$SYSTEMD_UNIT_FILE_PATH" "~/.config/systemd/user/${SYSTEMD_UNIT_NAME}" + + export XDG_RUNTIME_DIR="/run/user/\$(id -u)" + systemctl --user daemon-reload + systemctl --user enable "${SYSTEMD_UNIT_NAME}" + systemctl --user restart "${SYSTEMD_UNIT_NAME}" diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 09353e2..920780c 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -4,6 +4,8 @@ on: push: branches: - main + # TODO: remove + - chore/migrate-ansible-logic-to-workflow-steps tags: - 'prod' - 'v*' @@ -52,76 +54,62 @@ jobs: run: | cd scripts && uv run pytest - # TODO: maybe this is better: `rsync -av --delete ./ "${DEST_DIR}/"` # Sync everything perfectly, including hidden files, and delete old stale files - name: Bin - deploy if: steps.filter.outputs.bin == 'true' env: - # commit tagged ? yes->prod : no->dev - DEST_DIR: /sls/bd/hla/${{ github.ref_type == 'tag' && 'prod' || 'dev' }}/bin - working-directory: bin + DEST_DIR: /sls/bd/hla/${{ env.AGEBD_ENV }}/bin run: | mkdir -p ${DEST_DIR} - cp -r ./* ${DEST_DIR} + rsync -av --delete ./bin/ "${DEST_DIR}/" - # TODO: maybe this is better: `rsync -av --delete ./ "${DEST_DIR}/"` # Sync everything perfectly, including hidden files, and delete old stale files - name: Agebd - deploy if: steps.filter.outputs.agebd == 'true' env: - # commit tagged ? yes->prod : no->dev - DEST_DIR: /sls/bd/hla/${{ github.ref_type == 'tag' && 'prod' || 'dev' }}/packages/agebd - working-directory: packages/agebd + DEST_DIR: /sls/bd/hla/${{ env.AGEBD_ENV }}/packages/agebd run: | mkdir -p ${DEST_DIR} - cp -r ./* ${DEST_DIR} + rsync -av --delete ./packages/agebd/ "${DEST_DIR}/" - # TODO: maybe this is better: `rsync -av --delete ./ "${DEST_DIR}/"` # Sync everything perfectly, including hidden files, and delete old stale files - name: Qt - deploy if: steps.filter.outputs.qt == 'true' env: - # commit tagged ? yes->prod : no->dev - DEST_DIR: /sls/bd/hla/${{ github.ref_type == 'tag' && 'prod' || 'dev' }}/qt - working-directory: qt + DEST_DIR: /sls/bd/hla/${{ env.AGEBD_ENV }}/qt run: | mkdir -p ${DEST_DIR} - cp -r ./* ${DEST_DIR} + rsync -av --delete ./qt/ "${DEST_DIR}/" # TODO: (when) do we need to restart the master service or reinstall/restart the master ioc? - - name: Services - Initialize Virtual Environment from cli/uv.lock - if: steps.filter.outputs.services == 'true' + detect-changed-services: + runs-on: hla-dev + needs: [deploy] # Need filters + if: steps.filter.outputs.services == 'true' + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - uses: actions/checkout@v4 + with: { fetch-depth: 0 } + - id: set-matrix run: | - uv venv .venv - uv sync --directory cli - - - name: Services - Install Ansible Galaxy Collections - if: steps.filter.outputs.services == 'true' - run: | - uv run ansible-galaxy collection install -r ansible/collections/requirements.yml -p ./ansible/installed-collections - - - name: Services - Run Ansible Orchestrator - if: steps.filter.outputs.services == 'true' - working-directory: ansible - run: | - set -x - - # Disable pipefail temporarily or add an '|| true' fallback so grep doesn't kill the script - set +e - CHANGED_FILES=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }}) - set -e - - # 1. Parse changed directory names into space-separated string (e.g. "master other-service") - CHANGED_SVC=$(echo "$CHANGED_FILES" | awk -F/ '$1=="services" {print $2}' | sort -u | xargs) - - echo "Detected changed services: '$CHANGED_SVC'" - - # Safely halt the execution if there is nothing to pass to Ansible - if [ -z "$CHANGED_SVC" ]; then - echo "No services changed in this commit range. Skipping deployment smoothly." - exit 0 + # Fallback if github.event.before is zeroed out (e.g. initial branch push or tag) + BEFORE="${{ github.event.before }}" + if [ -z "$BEFORE" ] || [ "$BEFORE" = "0000000000000000000000000000000000000000" ]; then + BEFORE="HEAD~1" fi + + # Generate JSON array of changed service folders + SERVICES=$(git diff --name-only "$BEFORE" "${{ github.sha }}" | awk -F/ '$1=="services" {print $2}' | sort -u | jq -R . | jq -s -c .) + echo "matrix=$SERVICES" >> $GITHUB_OUTPUT - # 3. Fire the playbook passing variables down - ansible-playbook playbooks/deploy-and-restart-modified-services.yml \ - -i "inventories/$AGEBD_ENV/hosts.yml" \ - --extra-vars="changed_services_raw='$CHANGED_SVC'" \ - -v + deploy-services: + needs: detect-services + if: ${{ needs.detect-services.outputs.matrix != '[]' }} + strategy: + fail-fast: false + matrix: + service: ${{ fromJson(needs.detect-services.outputs.matrix) }} + + uses: ./.gitea/workflows/deploy-service.yml + with: + service_name: ${{ matrix.service }} + environment: ${{ env.AGEBD_ENV }}