1.3 KiB · text History b868907
defmodule GitGud.Advisories.Workers.Scan do
  @moduledoc """
  Scan one repository's lockfiles (`GitGud.Advisories.scan/2`).

  On its own queue, one at a time: a scan loads OSV's dump for each
  ecosystem its lockfiles need, and npm's alone is ~600 MB in memory
  while it runs. Unique per repository for a minute, so a burst of
  pushes is one scan.
  """
  use Oban.Worker,
    queue: :advisories,
    max_attempts: 3,
    unique: [period: 60, keys: [:repository_id], states: [:available, :scheduled, :retryable]]

  require Logger

  alias GitGud.Advisories
  alias GitGud.Repositories.Repository

  @impl Oban.Worker
  def perform(%Oban.Job{args: %{"repository_id" => id} = args}) do
    case GitGud.Repo.get(Repository, id) do
      nil ->
        :ok

      repo ->
        repo = GitGud.Repo.preload(repo, :organization)

        if Advisories.enabled?(repo) do
          case Advisories.scan(repo, force: args["force"] == true) do
            {:ok, _} ->
              :ok

            # Nothing to scan with, or nothing to scan: not worth retrying.
            {:error, reason} when reason in [:off, :no_scanner, :no_default_branch] ->
              Logger.info("advisories: #{repo.name} not scanned: #{reason}")
              :ok

            {:error, reason} ->
              {:error, reason}
          end
        else
          :ok
        end
    end
  end
end