diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml new file mode 100644 index 0000000..cab2eb1 --- /dev/null +++ b/.github/workflows/autofix.yml @@ -0,0 +1,99 @@ +name: Autofix + +# Fixes what can be fixed without a person on pull requests: model and route +# annotations (annotaterb) and safe RuboCop corrections. When something changes, +# it commits the fix to the PR branch and starts CI again for the new commit. +# +# A push made with GITHUB_TOKEN does not trigger other workflows, so this job +# cannot loop, and it starts CI itself through workflow_dispatch. +# +# Pull requests from forks are skipped: GITHUB_TOKEN can't push to them. + +on: + pull_request: + branches: + - main + types: [opened, synchronize, reopened] + +concurrency: + group: autofix-${{ github.event.pull_request.number }} + cancel-in-progress: true + +permissions: + contents: write + actions: write + +jobs: + autofix: + if: github.event.pull_request.head.repo.full_name == github.repository + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:17 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 5s + --health-timeout 5s + --health-retries 10 + + env: + RAILS_ENV: test + PGUSER: postgres + PGPASSWORD: postgres + + steps: + - name: Checkout PR branch + uses: actions/checkout@v6 + with: + ref: ${{ github.event.pull_request.head.ref }} + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: .ruby-version + bundler-cache: true + + - name: Load database schema + run: bin/rails db:create db:schema:load + + - name: Update model annotations + run: bundle exec annotaterb models + + # Some routes (letter_opener, actual_db_schema) exist only in development, + # and the committed annotations include them. + - name: Update route annotations + env: + RAILS_ENV: development + run: bundle exec annotaterb routes + + - name: Apply safe RuboCop corrections + # Offenses that can't be corrected safely are left for CI's lint job. + run: bin/rubocop -a || true + + - name: Commit and push fixes + id: commit + run: | + if git diff --quiet; then + echo "Nothing to fix." + echo "pushed=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + + git diff --stat + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git commit -am "chore: autofix annotations and lint" + git push origin HEAD:${{ github.event.pull_request.head.ref }} + echo "pushed=true" >> "$GITHUB_OUTPUT" + + - name: Start CI for the fixed commit + if: steps.commit.outputs.pushed == 'true' + env: + GH_TOKEN: ${{ github.token }} + run: gh workflow run ci.yml --repo "${{ github.repository }}" --ref "${{ github.event.pull_request.head.ref }}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed2f152..baceab8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,6 +58,28 @@ jobs: annotate_check: runs-on: ubuntu-latest + + # annotaterb reads the columns from a real database. Without one it skips + # every model and reports them as unchanged. + services: + postgres: + image: postgres:17 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 5s + --health-timeout 5s + --health-retries 10 + + env: + RAILS_ENV: test + PGUSER: postgres + PGPASSWORD: postgres + steps: - name: Checkout code uses: actions/checkout@v6 @@ -68,7 +90,15 @@ jobs: ruby-version: .ruby-version bundler-cache: true - - name: Check if annotations are up to date - run: | - bundle exec annotaterb models --frozen --show-migration - bundle exec annotaterb routes --frozen + - name: Load database schema + run: bin/rails db:create db:schema:load + + - name: Check if model annotations are up to date + run: bundle exec annotaterb models --frozen --show-migration + + # Some routes (letter_opener, actual_db_schema) exist only in development, + # and the committed annotations include them. + - name: Check if route annotations are up to date + env: + RAILS_ENV: development + run: bundle exec annotaterb routes --frozen diff --git a/config/routes.rb b/config/routes.rb index 675282f..1d18777 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -42,6 +42,7 @@ # POST /login(.:format) auth#login # send_magic_link POST /auth/magic_link(.:format) auth#send_magic_link # magic_link_login GET /auth/magic_link/:token(.:format) auth#magic_link_login +# confirm_magic_link POST /auth/magic_link/:token(.:format) auth#confirm_magic_link # check_password_login POST /auth/check_password_login(.:format) auth#check_password_login # logout DELETE /logout(.:format) auth#logout # me GET /auth/me(.:format) auth#me @@ -54,6 +55,11 @@ # email_confirmation GET /email_confirmation(.:format) email_confirmations#show # confirm_email GET /confirm_email/:token(.:format) email_confirmations#confirm # resend_email_confirmation POST /email_confirmation/resend(.:format) email_confirmations#resend +# make_primary_email_address PATCH /profile/emails/:id/make_primary(.:format) email_addresses#make_primary +# resend_confirmation_email_address POST /profile/emails/:id/resend_confirmation(.:format) email_addresses#resend_confirmation +# email_addresses POST /profile/emails(.:format) email_addresses#create +# email_address DELETE /profile/emails/:id(.:format) email_addresses#destroy +# confirm_email_address GET /emails/confirm/:token(.:format) email_addresses#confirm # user_profile_photo GET /user/:p_id/pfp(.:format) profile_photos#show # user_avatar GET /user/:p_id/avatar/:variant(.:format) profile_photos#avatar # user_avatar_square GET /user/:p_id/avatar/:variant/square(.:format) profile_photos#avatar_square