From ebf431217476a6a3239cd1072a5a3f0a356e3e7b Mon Sep 17 00:00:00 2001 From: Alex <25013571+alexhb1@users.noreply.github.com> Date: Fri, 13 Mar 2026 17:09:49 +0000 Subject: [PATCH] Repo spring cleaning (#746) - Add CI workflow (pytest + frontend typecheck/tests) on PRs - Add CodeQL static analysis for Python and JS/TS - Add Dependabot for pip, npm, Docker, and GitHub Actions - Tighten workflow permissions --- .github/dependabot.yml | 29 ++++++++++ .../build-and-publish-docker-image.yml | 28 +++++----- .github/workflows/ci.yml | 55 +++++++++++++++++++ .github/workflows/codeql.yml | 38 +++++++++++++ src/frontend/package.json | 2 +- tests/core/test_admin_users_api.py | 1 + 6 files changed, 139 insertions(+), 14 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/codeql.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..369d3e1 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,29 @@ +version: 2 +updates: + # Python dependencies + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + + # Frontend npm dependencies + - package-ecosystem: "npm" + directory: "/src/frontend" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + + # Dockerfile base images + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 + + # GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 diff --git a/.github/workflows/build-and-publish-docker-image.yml b/.github/workflows/build-and-publish-docker-image.yml index 2c96039..caf9fd5 100644 --- a/.github/workflows/build-and-publish-docker-image.yml +++ b/.github/workflows/build-and-publish-docker-image.yml @@ -6,6 +6,8 @@ on: tags: - 'v*' workflow_dispatch: +permissions: read-all + env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository_owner }}/shelfmark @@ -29,18 +31,18 @@ jobs: run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT - name: Checkout repository - uses: actions/checkout@v4 - + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - name: Log in to the Container registry - uses: docker/login-action@v3 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - + - name: Extract metadata for ${{ matrix.target }} image id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}${{ matrix.image_name_suffix }} tags: | @@ -50,13 +52,13 @@ jobs: type=semver,pattern={{major}}.{{minor}} type=sha type=ref,event=tag - + - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 + - name: Build and push ${{ matrix.target }} Docker image id: push - uses: docker/build-push-action@v5 + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5 with: platforms: linux/amd64,linux/arm64 context: . @@ -67,10 +69,10 @@ jobs: RELEASE_VERSION=${{ github.ref_name }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - + - name: Generate artifact attestation for ${{ matrix.target }} image if: github.event_name != 'pull_request' - uses: actions/attest-build-provenance@v2 + uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2 with: subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}${{ matrix.image_name_suffix }} subject-digest: ${{ steps.push.outputs.digest }} @@ -89,14 +91,14 @@ jobs: LEGACY_NAME: calibre-web-automated-book-downloader steps: - name: Log in to registry - uses: docker/login-action@v3 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 - name: Create legacy aliases run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c414105 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,55 @@ +name: CI + +on: + pull_request: + branches: [main] + +permissions: + contents: read + +jobs: + backend-tests: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.10" + cache: "pip" + + - name: Install dependencies + run: | + pip install -r requirements-base.txt + pip install -r requirements-shelfmark.txt + pip install pytest + + - name: Run tests + run: pytest tests/ -x --tb=short + + frontend-checks: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: Set up Node + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: 20 + cache: "npm" + cache-dependency-path: src/frontend/package-lock.json + + - name: Install dependencies + working-directory: src/frontend + run: npm ci + + - name: Typecheck + working-directory: src/frontend + run: npm run typecheck + + - name: Unit tests + working-directory: src/frontend + run: npm run test:unit diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..dd70da8 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,38 @@ +name: CodeQL + +on: + push: + branches: [main] + pull_request: + branches: [main] + schedule: + - cron: "0 6 * * 1" # Weekly on Monday at 6am UTC + +permissions: + contents: read + +jobs: + analyze: + runs-on: ubuntu-latest + permissions: + security-events: write + strategy: + fail-fast: false + matrix: + language: [python, javascript-typescript] + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@820e3160e279568db735cee8ed8f8e77a6da7818 # v3 + with: + languages: ${{ matrix.language }} + + - name: Autobuild + uses: github/codeql-action/autobuild@820e3160e279568db735cee8ed8f8e77a6da7818 # v3 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@820e3160e279568db735cee8ed8f8e77a6da7818 # v3 + with: + category: "/language:${{ matrix.language }}" diff --git a/src/frontend/package.json b/src/frontend/package.json index 106a8b5..711a565 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -8,7 +8,7 @@ "build": "tsc && vite build", "preview": "vite preview", "typecheck": "tsc --noEmit", - "test:unit": "npm run test:unit:build && node --experimental-specifier-resolution=node --test ../../.local/frontend-test-dist/tests/**/*.node.test.js", + "test:unit": "npm run test:unit:build && node --experimental-specifier-resolution=node --test ../../.local/frontend-test-dist/tests/*.node.test.js", "test:unit:build": "rm -rf ../../.local/frontend-test-dist && tsc -p tsconfig.tests.json" }, "dependencies": { diff --git a/tests/core/test_admin_users_api.py b/tests/core/test_admin_users_api.py index 894fffb..6ee7875 100644 --- a/tests/core/test_admin_users_api.py +++ b/tests/core/test_admin_users_api.py @@ -1122,6 +1122,7 @@ class TestAdminDeliveryPreferences: "BOOKLORE_PATH_ID", "EMAIL_RECIPIENT", "DESTINATION_AUDIOBOOK", + "DOWNLOAD_TO_BROWSER_CONTENT_TYPES", ] field_keys = [field["key"] for field in data["fields"]]