From d32ec79c9b8bac90555e7dd992e1e1b317ebdc31 Mon Sep 17 00:00:00 2001 From: MountainGod2 Date: Mon, 7 Oct 2024 13:40:02 -0600 Subject: [PATCH] feat: add GitHub workflows for building and deploying Docker image and continuous deployment - Added a new file `.github/workflows/build.yml` for building and deploying Docker image to GitHub Container Registry. - Added a new file `.github/workflows/cd.yml` for handling release and deployment. - Deleted the file `.github/workflows/ci-cd.yml`. - Added a new file `.github/workflows/ci.yml` for continuous integration. These changes introduce GitHub workflows to automate the build, deployment, and continuous integration processes for the project. --- .github/workflows/build.yml | 55 ++++++++++++ .github/workflows/cd.yml | 59 ++++++++++++ .github/workflows/ci-cd.yml | 175 ------------------------------------ .github/workflows/ci.yml | 68 ++++++++++++++ 4 files changed, 182 insertions(+), 175 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/cd.yml delete mode 100644 .github/workflows/ci-cd.yml create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..fb218a48 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,55 @@ +name: Build and Deploy Docker Image + +on: + push: + branches: + - main + +jobs: + build: + name: Build and Push Docker Image to GitHub Container Registry + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up QEMU for Multi-Architecture Builds + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx for Multi-Platform Builds + uses: docker/setup-buildx-action@v3 + + - name: Generate Docker Image Metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/mountaingod2/chaturbate_poller + tags: | + type=schedule + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha + type=raw,value=latest,enable={{is_default_branch}} + + - name: Log in to GitHub Container Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: '${{ github.repository_owner }}' + password: '${{ secrets.GITHUB_TOKEN }}' + + - name: Build and Push Docker Image + uses: docker/build-push-action@v6 + with: + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + - name: Run Docker Image Tests + run: docker run --rm ghcr.io/mountaingod2/chaturbate_poller:latest --version diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 00000000..0f9ad357 --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,59 @@ +name: Continuous Deployment + +on: + push: + branches: + - main + +jobs: + cd: + name: Handle Release and Deployment + permissions: + id-token: write + contents: write + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up UV Environment + uses: astral-sh/setup-uv@v3.1.3 + with: + enable-cache: true + cache-dependency-glob: uv.lock + + - name: Run Python Semantic Release + id: release + uses: python-semantic-release/python-semantic-release@v9.10.0 + with: + github_token: '${{ secrets.GITHUB_TOKEN }}' + git_committer_name: 'MountainGod2' + git_committer_email: 'admin@reid.ca' + ssh_private_signing_key: '${{ secrets.GIT_COMMIT_SSH_PRIV_KEY }}' + ssh_public_signing_key: '${{ secrets.GIT_COMMIT_SSH_PUB_KEY }}' + + - name: Publish to TestPyPI + if: steps.release.outputs.released == 'true' + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: 'https://test.pypi.org/legacy/' + password: '${{ secrets.TEST_PYPI_API_TOKEN }}' + + - name: Test Install from TestPyPI + if: steps.release.outputs.released == 'true' + run: | + pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple chaturbate-poller + + - name: Publish to PyPI + if: steps.release.outputs.released == 'true' + uses: pypa/gh-action-pypi-publish@release/v1 + with: + password: '${{ secrets.PYPI_API_TOKEN }}' + + - name: Publish to GitHub Releases + if: steps.release.outputs.released == 'true' + uses: python-semantic-release/upload-to-gh-release@main + with: + github_token: '${{ secrets.GITHUB_TOKEN }}' diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml deleted file mode 100644 index 199e3ac7..00000000 --- a/.github/workflows/ci-cd.yml +++ /dev/null @@ -1,175 +0,0 @@ -name: ci-cd - -'on': - push: - branches: - - main - pull_request: - branches: - - main - -env: - UV_CACHE_DIR: /tmp/.uv-cache - -jobs: - ci: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up UV environment - uses: astral-sh/setup-uv@v3.1.3 - with: - enable-cache: true - cache-dependency-glob: uv.lock - - - name: Restore uv cache - uses: actions/cache@v4 - with: - path: /tmp/.uv-cache - key: "uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}" - restore-keys: | - uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} - uv-${{ runner.os }} - - - name: Install dependencies and project - run: uv sync - - - name: Run format, lint, type check, and tests - run: | - uv run ruff format ./ - uv run ruff check --fix ./ - uv run mypy ./ - uv run pytest - env: - CB_USERNAME: '${{ secrets.CB_USERNAME }}' - CB_TOKEN: '${{ secrets.CB_TOKEN }}' - - - name: Scan with SonarCloud - uses: SonarSource/sonarcloud-github-action@v3.0.0 - env: - SONAR_TOKEN: '${{ secrets.SONAR_TOKEN }}' - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 - with: - token: '${{ secrets.CODECOV_TOKEN }}' - file: ./coverage.xml - fail_ci_if_error: true - - - name: Build documentation - run: uv run make clean html --directory docs/ - - - name: Deploy documentation to GitHub Pages - uses: peaceiris/actions-gh-pages@v4 - with: - personal_token: '${{ secrets.PERSONAL_TOKEN }}' - publish_dir: docs/_build/html - - - name: Minimize uv cache - run: uv cache prune --ci - - cd: - permissions: - id-token: write - contents: write - needs: ci - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up UV environment - uses: astral-sh/setup-uv@v3.1.3 - with: - enable-cache: true - cache-dependency-glob: uv.lock - - - name: Set up Python Semantic Release - id: release - uses: python-semantic-release/python-semantic-release@v9.10.0 - with: - github_token: '${{ secrets.GITHUB_TOKEN }}' - git_committer_name: 'MountainGod2' - git_committer_email: 'admin@reid.ca' - ssh_private_signing_key: '${{ secrets.GIT_COMMIT_SSH_PRIV_KEY }}' - ssh_public_signing_key: '${{ secrets.GIT_COMMIT_SSH_PUB_KEY }}' - - - name: Publish to TestPyPI - if: steps.release.outputs.released == 'true' - uses: pypa/gh-action-pypi-publish@release/v1 - with: - repository-url: 'https://test.pypi.org/legacy/' - password: '${{ secrets.TEST_PYPI_API_TOKEN }}' - - - name: Test install from TestPyPI - if: steps.release.outputs.released == 'true' - run: | - pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple chaturbate-poller - - - name: Publish to PyPI - if: steps.release.outputs.released == 'true' - uses: pypa/gh-action-pypi-publish@release/v1 - with: - password: '${{ secrets.PYPI_API_TOKEN }}' - - - name: Publish package distributions to GitHub Releases - if: steps.release.outputs.released == 'true' - uses: python-semantic-release/upload-to-gh-release@main - with: - github_token: '${{ secrets.GITHUB_TOKEN }}' - - build: - runs-on: ubuntu-latest - needs: cd - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - steps: - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: ghcr.io/mountaingod2/chaturbate_poller - tags: | - type=schedule - type=ref,event=branch - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=sha - type=raw,value=latest,enable={{is_default_branch}} - - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to GitHub Container Registry - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: '${{ github.repository_owner }}' - password: '${{ secrets.GITHUB_TOKEN }}' - - - name: Build and push Docker image - uses: docker/build-push-action@v6 - with: - push: '${{ github.event_name != ''pull_request'' }}' - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - - - name: Run tests on Docker image - run: docker run --rm ghcr.io/mountaingod2/chaturbate_poller:latest --version diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..e9040e73 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,68 @@ +name: Continuous Integration + +on: + push: + branches: + - main + pull_request: + branches: + - main + +env: + UV_CACHE_DIR: /tmp/.uv-cache + +jobs: + ci: + name: Run Tests, Lint, Type Check, and Build Docs + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up UV Environment + uses: astral-sh/setup-uv@v3.1.3 + with: + enable-cache: true + cache-dependency-glob: uv.lock + + - name: Restore UV Cache + uses: actions/cache@v4 + with: + path: /tmp/.uv-cache + key: "uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}" + restore-keys: | + uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} + uv-${{ runner.os }} + + - name: Install Dependencies and Sync Project + run: uv sync + + - name: Run Formatting, Linting, Type Checks, and Tests + run: | + uv run ruff format ./ + uv run ruff check --fix ./ + uv run mypy ./ + uv run pytest + env: + CB_USERNAME: '${{ secrets.CB_USERNAME }}' + CB_TOKEN: '${{ secrets.CB_TOKEN }}' + + - name: Upload Test Coverage to Codecov + uses: codecov/codecov-action@v4 + with: + token: '${{ secrets.CODECOV_TOKEN }}' + file: ./coverage.xml + fail_ci_if_error: true + + - name: Scan with SonarCloud + uses: SonarSource/sonarcloud-github-action@v3.0.0 + env: + SONAR_TOKEN: '${{ secrets.SONAR_TOKEN }}' + + - name: Build Documentation + run: uv run make clean html --directory docs/ + + - name: Minimize UV Cache + run: uv cache prune --ci