Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,19 @@ updates:
groups:
development-dependencies:
dependency-type: "development"
cooldown:
semver-major-days: 7
semver-minor-days: 3
semver-patch-days: 2
default-days: 7
Comment on lines +11 to +15

Copilot AI Mar 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says a 10-day Dependabot cooldown, but this bundler entry sets shorter values (e.g., default/major 7 days, minor 3, patch 2). Please align the configuration with the stated 10-day cooldown (or update the PR description if 7/3/2 is intended).

Copilot uses AI. Check for mistakes.
- package-ecosystem: github-actions
directory: "/"
groups:
github-actions:
patterns:
- "*"
schedule:
interval: weekly
open-pull-requests-limit: 10
cooldown:
default-days: 7
Comment thread
flavorjones marked this conversation as resolved.
55 changes: 46 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,22 @@ on:
push:
branches: [ main ]

permissions: {}

jobs:
scan_ruby:
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
persist-credentials: false

- name: Set up Ruby
uses: ruby/setup-ruby@v1
uses: ruby/setup-ruby@319994f95fa847cf3fb3cd3dbe89f6dcde9f178f # v1.295.0
with:
ruby-version: .ruby-version
bundler-cache: true
Expand All @@ -24,13 +30,17 @@ jobs:

scan_js:
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
persist-credentials: false

- name: Set up Ruby
uses: ruby/setup-ruby@v1
uses: ruby/setup-ruby@319994f95fa847cf3fb3cd3dbe89f6dcde9f178f # v1.295.0
with:
ruby-version: .ruby-version
bundler-cache: true
Expand All @@ -40,21 +50,46 @@ jobs:

lint:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
persist-credentials: false

- name: Set up Ruby
uses: ruby/setup-ruby@v1
uses: ruby/setup-ruby@319994f95fa847cf3fb3cd3dbe89f6dcde9f178f # v1.295.0
with:
ruby-version: .ruby-version
bundler-cache: true

- name: Lint code for consistent style
run: bin/rubocop -f github

lint-actions:
name: GitHub Actions audit
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
persist-credentials: false

- name: Run actionlint
uses: rhysd/actionlint@393031adb9afb225ee52ae2ccd7a5af5525e03e8 # v1.7.11

- name: Run zizmor
uses: zizmorcore/zizmor-action@71321a20a9ded102f6e9ce5718a2fcec2c4f70d8 # v0.5.2
with:
advanced-security: false

test:
runs-on: ubuntu-latest
permissions:
contents: read

# services:
# redis:
Expand All @@ -67,10 +102,12 @@ jobs:
run: sudo apt-get update && sudo apt-get install --no-install-recommends -y google-chrome-stable curl libjemalloc2 libsqlite3-0 libvips

- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
persist-credentials: false

- name: Set up Ruby
uses: ruby/setup-ruby@v1
uses: ruby/setup-ruby@319994f95fa847cf3fb3cd3dbe89f6dcde9f178f # v1.295.0
with:
ruby-version: .ruby-version
bundler-cache: true
Expand All @@ -82,7 +119,7 @@ jobs:
run: bin/rails db:setup test test:system

- name: Keep screenshots from failed system tests
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: failure()
with:
name: screenshots
Expand Down
41 changes: 25 additions & 16 deletions .github/workflows/publish-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,7 @@ concurrency:
group: publish-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read
packages: write
id-token: write
attestations: write
permissions: {}

env:
IMAGE_DESCRIPTION: Instantly publish your own books on the web for free, no publisher required.
Expand All @@ -28,6 +24,9 @@ jobs:
name: Build and push image (${{ matrix.arch }})
runs-on: ${{ matrix.runner }}
timeout-minutes: 45

Copilot AI Mar 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build job requests packages: write, but on pull_request runs it never pushes images (and can be configured to skip registry login). This is broader than necessary for PR builds, and undermines the least-privilege goal of the PR. To fully minimize privileges, consider splitting PR builds vs. publish builds into separate jobs/workflows so only the publish path gets packages: write.

Suggested change
timeout-minutes: 45
timeout-minutes: 45
if: github.event_name != 'pull_request'

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build job needs packages: write because it pushes images on non-PR events (tag pushes). The workflow uses a single job definition for both paths. Splitting by event trigger would add complexity without meaningful security benefit since the token is scoped to this repo's packages.

permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
Expand All @@ -43,13 +42,15 @@ jobs:
IMAGE_NAME: ${{ github.repository }}
steps:
- name: Checkout
uses: actions/checkout@v5.0.0
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.11.1
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1

- name: Log in to GHCR
uses: docker/login-action@v3.5.0
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
Expand All @@ -66,7 +67,7 @@ jobs:

- name: Extract Docker metadata (tags, labels) with arch suffix
id: meta
uses: docker/metadata-action@v5.8.0
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
with:
images: ${{ steps.vars.outputs.canonical }}
tags: |
Expand All @@ -84,7 +85,7 @@ jobs:

- name: Build and push (${{ matrix.platform }})
id: build
uses: docker/build-push-action@v6.18.0
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: .
file: Dockerfile
Expand Down Expand Up @@ -114,15 +115,19 @@ jobs:
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
packages: write
id-token: write
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
steps:
- name: Set up Docker Buildx (for imagetools)
uses: docker/setup-buildx-action@v3.11.1
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1

- name: Log in to GHCR
uses: docker/login-action@v3.5.0
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
Expand All @@ -139,7 +144,7 @@ jobs:

- name: Compute base tags (no suffix)
id: meta
uses: docker/metadata-action@v5.8.0
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
with:
images: ${{ steps.vars.outputs.canonical }}
tags: |
Expand All @@ -159,7 +164,7 @@ jobs:
shell: bash
run: |
set -eu
tags="${{ steps.meta.outputs.tags }}"
tags="${STEPS_META_OUTPUTS_TAGS}"
echo "Creating manifests for tags:"
printf '%s\n' "$tags"
while IFS= read -r tag; do
Expand All @@ -183,18 +188,22 @@ jobs:
"${src_tag}-arm64"
fi
done <<< "$tags"
env:
STEPS_META_OUTPUTS_TAGS: ${{ steps.meta.outputs.tags }}

- name: Install Cosign
uses: sigstore/cosign-installer@v3.9.2
uses: sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # v3.9.2

- name: Cosign sign all tags (keyless OIDC)
shell: bash
run: |
set -eu
tags="${{ steps.meta.outputs.tags }}"
tags="${STEPS_META_OUTPUTS_TAGS}"
printf '%s\n' "$tags"
while IFS= read -r tag; do
[ -z "$tag" ] && continue
echo "Signing $tag"
cosign sign --yes "$tag"
done <<< "$tags"
env:
STEPS_META_OUTPUTS_TAGS: ${{ steps.meta.outputs.tags }}
Loading