From 28481cf55e107ff10892a8e6bdaa385d7a49412d Mon Sep 17 00:00:00 2001 From: Luke Tainton Date: Thu, 2 Jan 2025 13:08:27 +0000 Subject: [PATCH] Initial draft of Gitea-oriented actions --- .gitea/workflows/build-push-docker.yml | 65 +++++++++++ .gitea/workflows/ci-docker.yml | 37 +++++++ .../ci-python-poetry-with-docker.yml | 85 +++++++++++++++ .gitea/workflows/ci-python-poetry.yml | 76 +++++++++++++ .gitea/workflows/ci-python-with-docker.yml | 77 +++++++++++++ .gitea/workflows/ci-python.yml | 70 ++++++++++++ .gitea/workflows/create-release-old.yml | 52 +++++++++ .gitea/workflows/create-release.yml | 101 ++++++++++++++++++ 8 files changed, 563 insertions(+) create mode 100644 .gitea/workflows/build-push-docker.yml create mode 100644 .gitea/workflows/ci-docker.yml create mode 100644 .gitea/workflows/ci-python-poetry-with-docker.yml create mode 100644 .gitea/workflows/ci-python-poetry.yml create mode 100644 .gitea/workflows/ci-python-with-docker.yml create mode 100644 .gitea/workflows/ci-python.yml create mode 100644 .gitea/workflows/create-release-old.yml create mode 100644 .gitea/workflows/create-release.yml diff --git a/.gitea/workflows/build-push-docker.yml b/.gitea/workflows/build-push-docker.yml new file mode 100644 index 0000000..745f865 --- /dev/null +++ b/.gitea/workflows/build-push-docker.yml @@ -0,0 +1,65 @@ +name: Publish Docker Image + +on: + workflow_call: + inputs: + release: + required: true + type: string + outputs: + success: + description: "Did the flow succeed?" + value: ${{ jobs.publish.outputs.success }} + +env: + REGISTRY_URL: git.tainton.uk + +jobs: + publish: + runs-on: ubuntu-latest + # permissions: + # packages: write + # contents: read + # attestations: write + # id-token: write + outputs: + success: ${{ steps.set_flag.outputs.success }} + steps: + - name: Check out repository code + uses: actions/checkout@v4.1.7 + with: + ref: ${{ inputs.release }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Gitea Package Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY_URL }} + username: ${{ gitea.actor }} + password: ${{ secrets.GITEA_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: | + ${{ env.REGISTRY_URL }}/${{ gitea.repository }} + tags: | + type=semver,pattern=v{{version}},value=${{ inputs.release }} + + - name: Build and push Docker image + id: push + uses: docker/build-push-action@v6 + with: + context: . + push: true + labels: ${{ steps.meta.outputs.labels }} + tags: | + ${{ env.REGISTRY_URL }}/${{ gitea.repository }}:latest + ${{ env.REGISTRY_URL }}/${{ gitea.repository }}:${{ inputs.release }} + + - name: Set success flag + id: set_flag + run: echo "success=true" >> "$GITEA_OUTPUT" diff --git a/.gitea/workflows/ci-docker.yml b/.gitea/workflows/ci-docker.yml new file mode 100644 index 0000000..f9d28d3 --- /dev/null +++ b/.gitea/workflows/ci-docker.yml @@ -0,0 +1,37 @@ +name: Docker CI +on: + workflow_call: + secrets: + SONAR_TOKEN: + required: true + SNYK_TOKEN: + required: true + +jobs: + ci: + runs-on: ubuntu-latest + steps: + - name: Check out repository code + uses: actions/checkout@v4.1.7 + with: + fetch-depth: 0 + + - uses: hadolint/hadolint-action@v3.1.0 + with: + dockerfile: Dockerfile + output-file: hadolint.out + format: sonarqube + no-fail: true + + - name: SonarQube Cloud Scan + uses: SonarSource/sonarqube-scan-action@v4.2.1 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + + - name: Snyk Vulnerability Scan + uses: snyk/actions/python-3.10@master + continue-on-error: true # To make sure that SARIF upload gets called + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + with: + args: --sarif-file-output=snyk.sarif --all-projects diff --git a/.gitea/workflows/ci-python-poetry-with-docker.yml b/.gitea/workflows/ci-python-poetry-with-docker.yml new file mode 100644 index 0000000..1e1042f --- /dev/null +++ b/.gitea/workflows/ci-python-poetry-with-docker.yml @@ -0,0 +1,85 @@ +name: Python w/ Poetry + Docker CI +on: + workflow_call: + inputs: + python-version: + type: string + default: "3.11" + description: "Version of Python to use for testing environment" + secrets: + SONAR_TOKEN: + required: true + SNYK_TOKEN: + required: true + +env: + PATH: ${{ env.PATH }}:/root/.poetry/bin + +jobs: + ci: + runs-on: ubuntu-latest + steps: + - name: Set python-version + id: python-version + run: | + PYTHON_VERSION=${{ inputs.python-version }} + echo "value=${PYTHON_VERSION:-"3.11"}" >> $GITEA_OUTPUT + + - name: Check out repository code + uses: actions/checkout@v4.1.7 + with: + fetch-depth: 0 + + - uses: hadolint/hadolint-action@v3.1.0 + with: + dockerfile: Dockerfile + output-file: hadolint.out + format: sonarqube + no-fail: true + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "${{ steps.python-version.outputs.value }}" + + - name: Setup Poetry + uses: abatilo/actions-poetry@v4 + + - name: Setup virtual environment + run: | + poetry config virtualenvs.create true --local + poetry config virtualenvs.in-project true --local + + - uses: actions/cache@v3 + name: Define cache for dependencies + with: + path: ./.venv + key: venv-${{ hashFiles('poetry.lock') }} + restore-keys: venv-${{ hashFiles('poetry.lock') }} + + - name: Install dependencies + run: poetry install + + - name: Lint + run: | + poetry run pylint --fail-under=8 --recursive=yes --output-format=parseable --output=lintreport.txt . + cat lintreport.txt + + - name: Unit Test + run: | + poetry run coverage run -m pytest -v --junitxml=testresults.xml + poetry run coverage xml + sed -i 's@${{ gitea.workspace }}@/github/workspace@g' coverage.xml + + - name: SonarQube Cloud Scan + uses: SonarSource/sonarqube-scan-action@v4.2.1 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + + - name: Snyk Vulnerability Scan + uses: snyk/actions/python-3.10@master + continue-on-error: true # To make sure that SARIF upload gets called + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + with: + args: --sarif-file-output=snyk.sarif --all-projects diff --git a/.gitea/workflows/ci-python-poetry.yml b/.gitea/workflows/ci-python-poetry.yml new file mode 100644 index 0000000..8f1c294 --- /dev/null +++ b/.gitea/workflows/ci-python-poetry.yml @@ -0,0 +1,76 @@ +name: Python w/ Poetry CI +on: + workflow_call: + inputs: + python-version: + type: string + default: "3.11" + description: "Version of Python to use for testing environment" + secrets: + SONAR_TOKEN: + required: true + SNYK_TOKEN: + required: true + +env: + PATH: ${{ env.PATH }}:/root/.poetry/bin + +jobs: + ci: + runs-on: ubuntu-latest + steps: + - name: Set python-version + id: python-version + run: | + PYTHON_VERSION=${{ inputs.python-version }} + echo "value=${PYTHON_VERSION:-"3.11"}" >> $GITEA_OUTPUT + + - name: Check out repository code + uses: actions/checkout@v4.1.7 + with: + fetch-depth: 0 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "${{ steps.python-version.outputs.value }}" + + - name: Setup Poetry + uses: abatilo/actions-poetry@v3 + + - name: Setup virtual environment + run: | + poetry config virtualenvs.create true --local + poetry config virtualenvs.in-project true --local + + - uses: actions/cache@v3 + name: Define cache for dependencies + with: + path: ./.venv + key: venv-${{ hashFiles('poetry.lock') }} + restore-keys: venv-${{ hashFiles('poetry.lock') }} + + - name: Install dependencies + run: poetry install + + - name: Lint + run: poetry run pylint --fail-under=8 --recursive=yes --output-format=parseable --output=lintreport.txt . + + - name: Unit Test + run: | + poetry run coverage run -m pytest -v --junitxml=testresults.xml + poetry run coverage xml + sed -i 's@${{ github.workspace }}@/github/workspace@g' coverage.xml + + - name: SonarQube Cloud Scan + uses: SonarSource/sonarqube-scan-action@v4.2.1 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + + - name: Snyk Vulnerability Scan + uses: snyk/actions/python-3.10@master + continue-on-error: true # To make sure that SARIF upload gets called + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + with: + args: --sarif-file-output=snyk.sarif --all-projects diff --git a/.gitea/workflows/ci-python-with-docker.yml b/.gitea/workflows/ci-python-with-docker.yml new file mode 100644 index 0000000..be33c1c --- /dev/null +++ b/.gitea/workflows/ci-python-with-docker.yml @@ -0,0 +1,77 @@ +name: Python + Docker CI +on: + workflow_call: + inputs: + python-version: + type: string + default: "3.11" + description: "Version of Python to use for testing environment" + secrets: + SONAR_TOKEN: + required: true + SNYK_TOKEN: + required: true + +jobs: + ci: + runs-on: ubuntu-latest + steps: + - name: Set python-version + id: python-version + run: | + PYTHON_VERSION=${{ inputs.python-version }} + echo "value=${PYTHON_VERSION:-"3.11"}" >> $GITEA_OUTPUT + + - name: Check out repository code + uses: actions/checkout@v4.1.7 + with: + fetch-depth: 0 + + - uses: hadolint/hadolint-action@v3.1.0 + with: + dockerfile: Dockerfile + output-file: hadolint.out + format: sonarqube + no-fail: true + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "${{ steps.python-version.outputs.value }}" + + - name: Update Pip + run: pip install -U pip + + - uses: actions/cache@v3 + name: Define cache for dependencies + with: + path: . + key: venv-${{ hashFiles('requirements**.txt') }} + restore-keys: venv-${{ hashFiles('requirements**.txt') }} + + - name: Install dependencies + run: | + pip install -r requirements.txt + pip install -r requirements-dev.txt + + - name: Lint + run: pylint --fail-under=8 --recursive=yes --output-format=parseable --output=lintreport.txt . + + - name: Unit Test + run: | + coverage run -m pytest -v --junitxml=testresults.xml + coverage xml + sed -i 's@${{ github.workspace }}@/github/workspace@g' coverage.xml + + - name: SonarQube Cloud Scan + uses: SonarSource/sonarqube-scan-action@v4.2.1 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + + - name: Snyk Vulnerability Scan + uses: snyk/actions/python-3.10@master + continue-on-error: true # To make sure that SARIF upload gets called + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + with: + args: --sarif-file-output=snyk.sarif --all-projects diff --git a/.gitea/workflows/ci-python.yml b/.gitea/workflows/ci-python.yml new file mode 100644 index 0000000..2eb09b9 --- /dev/null +++ b/.gitea/workflows/ci-python.yml @@ -0,0 +1,70 @@ +name: Python CI +on: + workflow_call: + inputs: + python-version: + type: string + default: "3.11" + description: "Version of Python to use for testing environment" + secrets: + SONAR_TOKEN: + required: true + SNYK_TOKEN: + required: true + +jobs: + ci: + runs-on: ubuntu-latest + steps: + - name: Set python-version + id: python-version + run: | + PYTHON_VERSION=${{ inputs.python-version }} + echo "value=${PYTHON_VERSION:-"3.11"}" >> $GITEA_OUTPUT + + - name: Check out repository code + uses: actions/checkout@v4.1.7 + with: + fetch-depth: 0 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "${{ steps.python-version.outputs.value }}" + + - name: Update Pip + run: pip install -U pip + + - uses: actions/cache@v3 + name: Define cache for dependencies + with: + path: . + key: venv-${{ hashFiles('requirements**.txt') }} + restore-keys: venv-${{ hashFiles('requirements**.txt') }} + + - name: Install dependencies + run: | + pip install -r requirements.txt + pip install -r requirements-dev.txt + + - name: Lint + run: pylint --fail-under=8 --recursive=yes --output-format=parseable --output=lintreport.txt . + + - name: Unit Test + run: | + coverage run -m pytest -v --junitxml=testresults.xml + coverage xml + sed -i 's@${{ github.workspace }}@/github/workspace@g' coverage.xml + + - name: SonarQube Cloud Scan + uses: SonarSource/sonarqube-scan-action@v4.2.1 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + + - name: Snyk Vulnerability Scan + uses: snyk/actions/python-3.10@master + continue-on-error: true # To make sure that SARIF upload gets called + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + with: + args: --sarif-file-output=snyk.sarif --all-projects diff --git a/.gitea/workflows/create-release-old.yml b/.gitea/workflows/create-release-old.yml new file mode 100644 index 0000000..3bdee60 --- /dev/null +++ b/.gitea/workflows/create-release-old.yml @@ -0,0 +1,52 @@ +name: Create Release +on: + workflow_call: + outputs: + release_name: + description: "Name of the created release" + value: ${{ jobs.create_release.outputs.release_name }} + success: + description: "Was the release created successfully?" + value: ${{ jobs.create_release.outputs.success }} + +jobs: + create_release: + name: Create Release + runs-on: ubuntu-latest + outputs: + release_name: ${{ steps.tag_version.outputs.new_tag }} + success: ${{ steps.set_flag.outputs.success }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Changes since last tag + id: changes + run: | + CHANGES=$(git log $(git describe --tags --abbrev=0)..HEAD --no-merges --oneline) + echo "$CHANGES" + if [ -z "$CHANGES" ]; then echo "changes=false" >> "$GITEA_OUTPUT"; else echo "changes=true" >> "$GITEA_OUTPUT"; fi + + - name: Bump version and push tag + id: tag_version + if: steps.changes.outputs.changes == 'true' + uses: mathieudutour/github-tag-action@v6.2 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + default_bump: minor + # default_bump: false + + - name: Create a GitHub release + if: steps.changes.outputs.changes == 'true' + uses: ncipollo/release-action@v1 + with: + tag: ${{ steps.tag_version.outputs.new_tag }} + name: ${{ steps.tag_version.outputs.new_tag }} + body: ${{ steps.tag_version.outputs.changelog }} + generateReleaseNotes: true + + - name: Set success/fail flag + id: set_flag + if: steps.changes.outputs.changes == 'true' + run: if test "${{ steps.changes.outputs.changes }}" = "true"; then echo "success=true" >> "$GITEA_OUTPUT"; else echo "success=false" >> "$GITEA_OUTPUT"; fi diff --git a/.gitea/workflows/create-release.yml b/.gitea/workflows/create-release.yml new file mode 100644 index 0000000..f3c9a3c --- /dev/null +++ b/.gitea/workflows/create-release.yml @@ -0,0 +1,101 @@ +name: Create Release +on: + workflow_call: + outputs: + release_name: + description: "Name of the created release" + value: ${{ jobs.create_release.outputs.release_name }} + success: + description: "Was the release created successfully?" + value: ${{ jobs.create_release.outputs.success }} + +jobs: + create_release: + name: Create Release + runs-on: ubuntu-latest + outputs: + release_name: ${{ steps.tag_version.outputs.new_tag }} + success: ${{ steps.set_flag.outputs.success }} + steps: + - uses: actions/checkout@v4.2.2 + with: + fetch-depth: 0 + + - name: Changes since last tag + id: changes + run: | + rm -f .changes .changes_feat .changes_fix .changes_dep .changes_other + git log $(git describe --tags --abbrev=0)..HEAD --no-merges --oneline >> .changes + cat .changes + if [[ -z $(grep '[^[:space:]]' .changes) ]] ; then + echo "changes=false" + echo "changes=false" >> "$GITEA_OUTPUT" + else + echo "changes=true" + echo "changes=true" >> "$GITEA_OUTPUT" + grep -i "feat" .changes >> .changes_feat + grep -i "fix" .changes >> .changes_fix + grep -i "dependencies" .changes >> .changes_dep + grep -i "other" .changes >> .changes_other + fi + + - name: Cancel if no changes + if: steps.changes.outputs.changes == 'false' + run: exit 1 + + - name: Create changelog + id: create_changelog + if: steps.changes.outputs.changes == 'true' + run: | + rm -f .changelog + if [[ -z $(grep '[^[:space:]]' .changes_feat) ]] ; then + printf "## 🚀 Features" > .changelog + cat .changes_feat >> .changelog + fi + if [[ -z $(grep '[^[:space:]]' .changes_fix) ]] ; then + printf "## 🐛 Bug Fixes" >> .changelog + cat .changes_fix >> .changelog + fi + if [[ -z $(grep '[^[:space:]]' .changes_dep) ]] ; then + printf "## 📦 Dependencies" >> .changelog + cat .changes_dep >> .changelog + fi + if [[ -z $(grep '[^[:space:]]' .changes_other) ]] ; then + printf "## 💬 Other" >> .changelog + cat .changes_other >> .changelog + fi + + - name: Set server URL + id: set_srvurl + run: | + SRVURL=$(echo "${{ gitea.server_url }}" | sed 's/https:\/\/\(.*\)/\1/') + echo "srvurl=$SRVURL" >> "$GITEA_OUTPUT" + + - name: Get next version + uses: TriPSs/conventional-changelog-action@v6 + id: get_next_version + with: + git-url: ${{ steps.set_srvurl.outputs.srvurl }} + github-token: ${{ gitea.token }} + skip-commit: true + release-count: 1 + output-file: false + create-summary: true + skip-on-empty: true + skip-version-file: true + skip-tag: true + + - name: Create release + id: create_release + uses: akkuman/gitea-release-action@v1 + env: + NODE_OPTIONS: '--experimental-fetch' # if nodejs < 18 + with: + tag: ${{ steps.get_next_version.outputs.tag }} + name: ${{ steps.get_next_version.outputs.tag }} + body_path: .changelog + + - name: Set success/fail flag + id: set_flag + if: steps.changes.outputs.changes == 'true' + run: if test "${{ steps.changes.outputs.changes }}" = "true"; then echo "success=true" >> "$GITEA_OUTPUT"; else echo "success=false" >> "$GITEA_OUTPUT"; fi