diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..6da7ad3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,22 @@ +version: 2 +updates: + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + labels: + - "dependencies" + commit-message: + prefix: "chore" + groups: + patch-updates: + patterns: + - "*" + update-types: + - "patch" + minor-updates: + patterns: + - "*" + update-types: + - "minor" diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..76811d8 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,19 @@ +changelog: + exclude: + labels: + - ignore-for-release + authors: + - octocat + categories: + - title: Breaking Changes 🚨 + labels: + - breaking + - title: New Features 🎉 + labels: + - feature + - title: Fixes 🔧 + labels: + - fix + - title: Other Changes + labels: + - "*" \ No newline at end of file diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml new file mode 100644 index 0000000..8247e0e --- /dev/null +++ b/.github/workflows/auto-merge.yml @@ -0,0 +1,23 @@ +name: Dependabot auto-approve +on: pull_request_target + +permissions: + contents: write + pull-requests: write + +jobs: + dependabot: + runs-on: ubuntu-latest + if: ${{ github.actor == 'dependabot[bot]' }} + steps: + - name: Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@v1.1.1 + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" + - name: Enable auto-merge for Dependabot PRs + if: ${{ steps.metadata.outputs.update-type != 'version-update:semver-major'}} + run: gh pr merge --auto --squash "$PR_URL" + env: + PR_URL: ${{github.event.pull_request.html_url}} + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/bumpversion.yml b/.github/workflows/bumpversion.yml new file mode 100644 index 0000000..b492be7 --- /dev/null +++ b/.github/workflows/bumpversion.yml @@ -0,0 +1,30 @@ +name: Bump version + +on: + workflow_dispatch: + +jobs: + bump_version: + if: ${{ !startsWith(github.event.head_commit.message, 'bump:') && github.ref == 'refs/heads/main' }} + runs-on: ubuntu-latest + name: "Bump version and create changelog with commitizen" + steps: + - uses: actions/create-github-app-token@v1 + id: app-token + with: + app-id: ${{ vars.ELEMENTSINTERACTIVE_BOT_APP_ID }} + private-key: ${{ secrets.ELEMENTSINTERACTIVE_BOT_PRIVATE_KEY }} + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ steps.app-token.outputs.token }} + ref: ${{ github.head_ref }} + # Make sure the value of GITHUB_TOKEN will not be persisted in repo's config + persist-credentials: false + - id: cz + name: Create bump and changelog + uses: commitizen-tools/commitizen-action@master + with: + github_token: ${{ steps.app-token.outputs.token }} + - name: Print Version + run: echo "Bumped to version ${{ steps.cz.outputs.version }}" diff --git a/.github/workflows/conventional-label.yaml b/.github/workflows/conventional-label.yaml new file mode 100644 index 0000000..ea241f2 --- /dev/null +++ b/.github/workflows/conventional-label.yaml @@ -0,0 +1,11 @@ +on: + pull_request_target: + types: [ opened, edited ] +name: conventional-release-labels +jobs: + label: + runs-on: ubuntu-latest + steps: + - uses: bcoe/conventional-release-labels@v1 + with: + type_labels: '{"feat": "feature", "fix": "fix", "breaking": "breaking", "ci": "CI"}' \ No newline at end of file diff --git a/.github/workflows/lgtm.yml b/.github/workflows/lgtm.yml new file mode 100644 index 0000000..24894f3 --- /dev/null +++ b/.github/workflows/lgtm.yml @@ -0,0 +1,49 @@ +name: LGTM Review + +on: + issue_comment: + types: [created] + +jobs: + lgtm-review: + if: | + github.event.issue.pull_request && + startsWith(github.event.comment.body, '/lgtm review') + runs-on: ubuntu-latest + steps: + - name: Check if commenter has write access + id: check-permission + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + USER=${{ github.event.comment.user.login }} + REPO=${{ github.repository }} + PERMISSION=$(curl -s -H "Authorization: Bearer $GITHUB_TOKEN" \ + https://api.github.com/repos/$REPO/collaborators/$USER/permission \ + | jq -r '.permission') + + if [[ "$PERMISSION" == "admin" || "$PERMISSION" == "maintain" || "$PERMISSION" == "write" ]]; then + echo "HAS_PERMISSION=true" >> $GITHUB_ENV + else + echo "HAS_PERMISSION=false" >> $GITHUB_ENV + fi + + - name: Fail if unauthorized + if: env.HAS_PERMISSION == 'false' + run: | + echo "User ${{ github.event.comment.user.login }} is not authorized to trigger this workflow." + exit 1 + + - name: Checkout PR code + uses: actions/checkout@v4 + with: + ref: refs/pull/${{ github.event.issue.number }}/merge + + - name: Run LGTM Review + run: | + docker run --rm elementsinteractive/lgtm-ai \ + review \ + --pr-url "https://github.com/${{ github.repository }}/pull/${{ github.event.issue.number }}" \ + --git-api-key "${{ secrets.GITHUB_TOKEN }}" \ + --ai-api-key "${{ secrets.AI_API_TOKEN }}" \ + -vv diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..ee3dc92 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,45 @@ +# This workflow will check our code for having a proper format, as well as the commit message to meet the expected ones + +name: Lint + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python 3.13 + uses: actions/setup-python@v4 + with: + python-version: "3.13" + - name: Install just + run: | + sudo apt update + sudo snap install --edge --classic just + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install poetry + poetry install + + - name: Lint + run: | + just lint + + lint-commit: + runs-on: ubuntu-latest + name: "Lint commit message" + steps: + - name: Check out + uses: actions/checkout@v4 + - name: Install commitizen + run: | + python -m pip install --upgrade pip + python -m pip install commitizen + - name: Check commit message + run: cz check --rev-range HEAD diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..ba852f8 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,79 @@ +name: Publish + +on: + workflow_dispatch: + +jobs: + push_to_pypi: + runs-on: ubuntu-latest + + permissions: + id-token: write + contents: read + + steps: + - uses: actions/checkout@v4 + - name: Checkout + uses: actions/setup-python@v4 + with: + python-version: "3.13" + - name: Build distributions + run: | + python -m pip install --upgrade pip + python -m pip install build + python -m build + - name: Publish release distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + + push_to_docker_hub: + needs: push_to_pypi + name: Push Docker image to Docker Hub + runs-on: ubuntu-latest + permissions: + contents: write + packages: write + + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: elementsinteractive/lightman-ai + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=registry,ref=ghcr.io/elementsinteractive/lightman-ai:buildcache + cache-to: type=registry,ref=ghcr.io/elementsinteractive/lightman-ai:buildcache,mode=max + + release_notes: + runs-on: ubuntu-latest + needs: push_to_docker_hub + steps: + - uses: actions/checkout@v4 + - name: Release + uses: softprops/action-gh-release@v2 + with: + generate_release_notes: true + token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 0000000..aad3d2b --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,38 @@ +# This workflow will run some security checks against our project + +name: Security + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + osv-scanner: + runs-on: ubuntu-latest + container: + image: ghcr.io/google/osv-scanner:v1.9.2 + steps: + - uses: actions/checkout@v4 + - name: Run OSV Scanner + run: | + /osv-scanner --skip-git --format table -r . + semgrep: + runs-on: ubuntu-latest + container: + image: returntocorp/semgrep:latest + steps: + - uses: actions/checkout@v4 + - name: Run Semgrep + run: | + semgrep scan --config auto + twyn: + runs-on: ubuntu-latest + container: + image: elementsinteractive/twyn:v2.8.27 + steps: + - uses: actions/checkout@v4 + - name: Run Twyn against our dependencies + run: | + twyn run -vv diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..90238b7 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,32 @@ +# This workflow will install Python dependencies, and run the tests for our project + +name: Test + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.13" + - name: Install just + run: | + sudo apt update + sudo snap install --edge --classic just + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install poetry + poetry install + + - name: Test with pytest + run: | + just test