diff --git a/.github/workflows/elixir.yml b/.github/workflows/elixir.yml index dfdfab46..25558653 100644 --- a/.github/workflows/elixir.yml +++ b/.github/workflows/elixir.yml @@ -14,8 +14,19 @@ jobs: with: path: | _build + .cargo deps - key: ${{ runner.os }}-build-deps-${{ hashFiles('mix.lock') }} + key: ${{ runner.os }}-deps-2-${{ hashFiles('mix.lock') }} + + - name: Enable caching + run: | + # Disable volumes so caching can take effect + sed -i -Ee 's/- app_[a-z]+_data:.*$//g' docker-compose.yml + + # Make ourselves the owner + echo "RUN addgroup -g $(id -g) -S appgroup && adduser -u $(id -u) -S appuser -G appgroup" >> docker/app/Dockerfile + echo "USER appuser" >> docker/app/Dockerfile + echo "RUN mix local.hex --force && mix local.rebar --force" >> docker/app/Dockerfile - run: docker compose pull - run: docker compose build @@ -27,6 +38,18 @@ jobs: run: | docker compose run app mix sobelow --config docker compose run app mix deps.audit + + - name: Dialyzer + run: | + docker compose run app mix dialyzer + + typos: + name: 'Check for spelling errors' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: crate-ci/typos@master + lint-and-test: name: 'JavaScript Linting and Unit Tests' runs-on: ubuntu-latest diff --git a/.typos.toml b/.typos.toml new file mode 100644 index 00000000..898ad2e4 --- /dev/null +++ b/.typos.toml @@ -0,0 +1,10 @@ +[default] +extend-ignore-re = [ + # Ignore development secret key. Production secret key should + # be in environment files and not checked into source control. + ".*secret_key_base.*", + + # Key constraints with encoded names + "fk_rails_[a-f0-9]+" +] + diff --git a/assets/js/utils/__tests__/local-autocompleter.spec.ts b/assets/js/utils/__tests__/local-autocompleter.spec.ts index bc612a08..182e1308 100644 --- a/assets/js/utils/__tests__/local-autocompleter.spec.ts +++ b/assets/js/utils/__tests__/local-autocompleter.spec.ts @@ -28,12 +28,12 @@ describe('Local Autocompleter', () => { }); describe('instantiation', () => { - it('should be constructable with compatible data', () => { + it('should be constructible with compatible data', () => { const result = new LocalAutocompleter(mockData); expect(result).toBeInstanceOf(LocalAutocompleter); }); - it('should NOT be constructable with incompatible data', () => { + it('should NOT be constructible with incompatible data', () => { const versionDataOffset = 12; const mockIncompatibleDataArray = new Array(versionDataOffset).fill(0); // Set data version to 1 @@ -45,6 +45,8 @@ describe('Local Autocompleter', () => { }); describe('topK', () => { + const termStem = ['f', 'o'].join(''); + let localAc: LocalAutocompleter; beforeAll(() => { @@ -66,7 +68,7 @@ describe('Local Autocompleter', () => { }); it('should return suggestions sorted by image count', () => { - const result = localAc.topK('fo', defaultK); + const result = localAc.topK(termStem, defaultK); expect(result).toEqual([ expect.objectContaining({ name: 'forest', imageCount: 3 }), expect.objectContaining({ name: 'fog', imageCount: 1 }), @@ -82,13 +84,13 @@ describe('Local Autocompleter', () => { }); it('should return only the required number of suggestions', () => { - const result = localAc.topK('fo', 1); + const result = localAc.topK(termStem, 1); expect(result).toEqual([expect.objectContaining({ name: 'forest', imageCount: 3 })]); }); it('should NOT return suggestions associated with hidden tags', () => { window.booru.hiddenTagList = [1]; - const result = localAc.topK('fo', defaultK); + const result = localAc.topK(termStem, defaultK); expect(result).toEqual([]); }); diff --git a/lib/philomena/tags.ex b/lib/philomena/tags.ex index 1f6e80c6..de7a0171 100644 --- a/lib/philomena/tags.ex +++ b/lib/philomena/tags.ex @@ -251,7 +251,7 @@ defmodule Philomena.Tags do |> where(tag_id: ^tag.id) |> Repo.delete_all() - # Update other assocations + # Update other associations ArtistLink |> where(tag_id: ^tag.id) |> Repo.update_all(set: [tag_id: target_tag.id]) diff --git a/lib/philomena/users/user_notifier.ex b/lib/philomena/users/user_notifier.ex index 48083321..2cd85d86 100644 --- a/lib/philomena/users/user_notifier.ex +++ b/lib/philomena/users/user_notifier.ex @@ -88,7 +88,7 @@ defmodule Philomena.Users.UserNotifier do Your account has been automatically locked due to too many attempts to sign in. - You can unlock your account by visting the URL below: + You can unlock your account by visiting the URL below: #{url} diff --git a/lib/philomena_web/controllers/admin/site_notice_controller.ex b/lib/philomena_web/controllers/admin/site_notice_controller.ex index 7612422e..ff284a75 100644 --- a/lib/philomena_web/controllers/admin/site_notice_controller.ex +++ b/lib/philomena_web/controllers/admin/site_notice_controller.ex @@ -44,7 +44,7 @@ defmodule PhilomenaWeb.Admin.SiteNoticeController do case SiteNotices.update_site_notice(conn.assigns.site_notice, site_notice_params) do {:ok, _site_notice} -> conn - |> put_flash(:info, "Succesfully updated site notice.") + |> put_flash(:info, "Successfully updated site notice.") |> redirect(to: ~p"/admin/site_notices") {:error, changeset} -> @@ -56,7 +56,7 @@ defmodule PhilomenaWeb.Admin.SiteNoticeController do {:ok, _site_notice} = SiteNotices.delete_site_notice(conn.assigns.site_notice) conn - |> put_flash(:info, "Sucessfully deleted site notice.") + |> put_flash(:info, "Successfully deleted site notice.") |> redirect(to: ~p"/admin/site_notices") end diff --git a/lib/philomena_web/templates/conversation/show.html.slime b/lib/philomena_web/templates/conversation/show.html.slime index 5af5ead9..85bf0299 100644 --- a/lib/philomena_web/templates/conversation/show.html.slime +++ b/lib/philomena_web/templates/conversation/show.html.slime @@ -59,5 +59,5 @@ h1 = @conversation.title p You've managed to send over 1,000 messages in this conversation! p We'd like to ask you to make a new conversation. Don't worry, this one won't go anywhere if you need to refer back to it. p - => link "Click here", to: ~p"/conversations/new?#{[receipient: other.name]}" + => link "Click here", to: ~p"/conversations/new?#{[recipient: other.name]}" ' to make a new conversation with this user. diff --git a/lib/philomena_web/templates/filter/_form.html.slime b/lib/philomena_web/templates/filter/_form.html.slime index 77965906..e46cda9a 100644 --- a/lib/philomena_web/templates/filter/_form.html.slime +++ b/lib/philomena_web/templates/filter/_form.html.slime @@ -73,7 +73,7 @@ .fieldlabel strong You probably do not want to check this unless you know what you are doing - it cannot be changed later - | . Pulic filters can be shared with other users and used by them; if you make changes to a filter, it will update all users of that filter. + | . Public filters can be shared with other users and used by them; if you make changes to a filter, it will update all users of that filter. - input_value(f, :public) == true -> .fieldlabel diff --git a/lib/philomena_web/templates/topic/poll/_form.html.slime b/lib/philomena_web/templates/topic/poll/_form.html.slime index c1ba66cf..f5d960b0 100644 --- a/lib/philomena_web/templates/topic/poll/_form.html.slime +++ b/lib/philomena_web/templates/topic/poll/_form.html.slime @@ -29,10 +29,10 @@ p.fieldlabel = select @f, :vote_method, ["-": "", "Single option": :single, "Multiple options": :multiple], class: "input" = error_tag @f, :vote_method -= inputs_for @f, :options, fn fo -> += inputs_for @f, :options, fn opt -> .field.js-poll-option.field--inline.flex--no-wrap.flex--centered - = text_input fo, :label, class: "input flex__grow js-option-label", placeholder: "Option" - = error_tag fo, :label + = text_input opt, :label, class: "input flex__grow js-option-label", placeholder: "Option" + = error_tag opt, :label label.input--separate-left.flex__fixed.flex--centered a.js-option-remove href="#"