name: build-and-deploy # Прод — единственное окружение деплоя, поэтому катим при каждом пуше в main. # Раннер должен быть self-hosted во внутренней сети: Nexus (nexus.tnsu.kz) снаружи # не достаётся. workflow_dispatch — на случай ручного передеплоя (например, старым тегом). on: push: branches: [main] workflow_dispatch: inputs: image_tag: description: "Тег образа (по умолчанию — короткий sha коммита)" required: false default: "" env: REGISTRY: nexus.tnsu.kz:8082 IMAGE: hr-appeals-web jobs: # Единый источник тега для образа и для деплоя prepare: runs-on: ubuntu-22.04 outputs: tag: ${{ steps.vars.outputs.tag }} steps: - name: Resolve image tag id: vars run: | TAG="${{ github.event.inputs.image_tag }}" if [ -z "$TAG" ]; then TAG="${GITHUB_SHA::8}"; fi echo "tag=$TAG" >> "$GITHUB_OUTPUT" build-and-push: needs: prepare runs-on: ubuntu-22.04 steps: - name: Checkout uses: actions/checkout@v4 - name: Ensure docker CLI is installed run: | set -e SUDO="" if [ "$(id -u)" -ne 0 ]; then SUDO="sudo"; fi if ! command -v docker >/dev/null 2>&1; then $SUDO apt-get update $SUDO env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends docker.io fi - name: Docker login to Nexus run: echo "${{ secrets.NEXUS_PASSWORD }}" | docker login "$REGISTRY" -u "${{ secrets.NEXUS_USER }}" --password-stdin - name: Build image run: | docker build \ -t "$REGISTRY/$IMAGE:${{ needs.prepare.outputs.tag }}" \ -t "$REGISTRY/$IMAGE:latest" \ . - name: Push image run: | docker push "$REGISTRY/$IMAGE:${{ needs.prepare.outputs.tag }}" docker push "$REGISTRY/$IMAGE:latest" - name: Docker logout if: always() run: docker logout "$REGISTRY" deploy: needs: [prepare, build-and-push] runs-on: ubuntu-22.04 steps: - name: Checkout uses: actions/checkout@v4 - name: Ensure ssh client is installed run: | set -e SUDO="" if [ "$(id -u)" -ne 0 ]; then SUDO="sudo"; fi if ! command -v ssh >/dev/null 2>&1 || ! command -v scp >/dev/null 2>&1 || ! command -v ssh-keyscan >/dev/null 2>&1; then $SUDO apt-get update $SUDO env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends openssh-client fi - name: Configure SSH run: | mkdir -p ~/.ssh printf '%s\n' "${{ secrets.DEPLOY_SSH_KEY }}" > ~/.ssh/deploy_key chmod 600 ~/.ssh/deploy_key ssh-keyscan -H "${{ vars.DEPLOY_HOST }}" >> ~/.ssh/known_hosts - name: Upload compose file run: | scp -i ~/.ssh/deploy_key docker-compose.yml \ "${{ vars.DEPLOY_USER }}@${{ vars.DEPLOY_HOST }}:${{ vars.DEPLOY_PATH }}/docker-compose.yml" - name: Roll out run: | ssh -i ~/.ssh/deploy_key "${{ vars.DEPLOY_USER }}@${{ vars.DEPLOY_HOST }}" " set -e cd '${{ vars.DEPLOY_PATH }}' sed -i '/^IMAGE_TAG=/d' .env echo 'IMAGE_TAG=${{ needs.prepare.outputs.tag }}' >> .env docker compose pull docker compose up -d --remove-orphans docker image prune -f " - name: Cleanup SSH key if: always() run: rm -f ~/.ssh/deploy_key