Current section

Files

Jump to
chimeway mix.exs
Raw

mix.exs

defmodule Chimeway.MixProject do
  use Mix.Project

  @version "1.2.1"

  def project do
    [
      app: :chimeway,
      version: @version,
      elixir: "~> 1.17",
      elixirc_paths: elixirc_paths(Mix.env()),
      test_load_filters: [~r{^(?!test/fixtures/).*_test\.exs$}],
      test_ignore_filters: [~r{^test/fixtures/}],
      start_permanent: Mix.env() == :prod,
      deps: deps(),
      aliases: aliases(),
      description: "Explainable, durable notification library for Elixir.",
      package: package(),
      docs: docs()
    ]
  end

  defp elixirc_paths(:test), do: ["lib", "test/support"]
  defp elixirc_paths(_), do: ["lib"]

  # Run "mix help compile.app" to learn about applications.
  def application do
    [
      extra_applications: [:logger],
      mod: {Chimeway.Application, []}
    ]
  end

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
      {:ecto_sql, "~> 3.11"},
      {:postgrex, ">= 0.0.0"},
      {:nimble_options, "~> 1.1"},
      {:jason, "~> 1.4"},
      {:tzdata, "~> 1.1"},
      {:oban, "~> 2.17", optional: true},
      {:ex_doc, "~> 0.31", only: :dev, runtime: false},
      {:credo, "~> 1.7", only: [:dev, :test], runtime: false},
      {:mix_audit, "~> 2.1", only: [:dev, :test], runtime: false}
    ] ++ mailglass_deps() ++ accrue_deps() ++ threadline_deps() ++ sigra_deps()
  end

  defp mailglass_deps do
    if System.get_env("CHIMEWAY_SKIP_MAILGLASS_DEP") in ["1", "true"] do
      []
    else
      [{:mailglass, "~> 1.3", optional: true}]
    end
  end

  defp accrue_deps do
    if System.get_env("CHIMEWAY_SKIP_ACCRUE_DEP") in ["1", "true"] do
      []
    else
      [accrue_dep()]
    end
  end

  defp aliases do
    [
      # Full local gate: run before pushing
      ci: ["ci.lint", "ci.test"],

      # Lint lane
      "ci.lint": [
        "format --check-formatted",
        "cmd --shell cd chimeway_admin && mix format --check-formatted",
        "cmd --shell cd chimeway_inbox && mix format --check-formatted",
        "cmd --shell cd examples/chimeway_demo_host && mix deps.get && mix format --check-formatted",
        "compile --warnings-as-errors",
        "credo --strict"
      ],

      # Core test lane; partner integrations run through their dedicated mix verify.* aliases.
      "ci.test": [
        # Keep the paths explicit for Elixir 1.17, which predates
        # :test_load_filters/:test_ignore_filters and would otherwise recurse
        # into the standalone Mix projects under test/fixtures.
        "cmd scripts/test-db env CHIMEWAY_SKIP_PARTNER_TEST_REPOS=1 MIX_ENV=test mix test test/chimeway_test.exs test/chimeway --exclude mailglass --exclude accrue --exclude accrue_artifact_proof --exclude accrue_packaged_cli --exclude threadline --exclude sigra --exclude adoption_paths_e2e --warnings-as-errors"
      ],

      # Docs gate: fails on undocumented public functions
      "ci.docs": ["docs --warnings-as-errors"],

      # Dependency audit
      "ci.audit": ["hex.audit", "deps.audit"],

      # Post-publish verify trio (run locally by maintainer, not in pre-merge CI)
      "verify.clean": ["cmd bash scripts/ci/verify-clean.sh"],
      # Local artifact proof: build and unpack the default root package under
      # MIX_ENV=prod (so the override is absent and Hex accepts the build), with no
      # Sigra skip envs, and fail unless the unpacked root carries every package
      # whitelist entry. No live Hex API calls (release-time/manual evidence only).
      "verify.parity": [
        "cmd --shell rm -rf /tmp/chimeway_verify && env MIX_ENV=prod mix hex.build --unpack --output /tmp/chimeway_verify && root=/tmp/chimeway_verify && if [ ! -f \"$root/mix.exs\" ]; then root=$(dirname \"$(find /tmp/chimeway_verify -maxdepth 2 -name mix.exs | head -1)\"); fi && for f in mix.exs lib priv guides README.md CHANGELOG.md LICENSE.md .formatter.exs; do test -e \"$root/$f\" || { echo \"verify.parity: missing package whitelist entry $f under $root\" >&2; exit 1; }; done && echo \"verify.parity OK: unpacked package root $root contains all whitelist entries\""
      ],
      # verify.published: invoked as `mix verify.published <version>` (Mix task)
      # Canonical host-mount E2E and operator-admin smoke proof.
      # Run separately from ci.test to preserve fast feedback on core library tests.
      "verify.example": [
        # Exclude :journey here — those run in verify.journeys (--only journey).
        # `mix demo.up --check` commits seed data outside the SQL sandbox
        # into the shared CI DB; running it alongside these sandboxed tests leaks
        # rows into unscoped queries (DeliveryAttempt counts, mailglass idempotency,
        # inbox badge). Keeping it out of this lane removes the cross-test pollution
        # with no coverage loss.
        "cmd --shell cd examples/chimeway_demo_host && mix deps.get && mix test --exclude journey",
        "cmd --shell cd chimeway_admin && mix deps.get && mix test",
        "cmd --shell cd chimeway_inbox && mix deps.get && mix test --warnings-as-errors"
      ],

      # Installer golden-diff, idempotency, prefix, and DB migration contract (path-gated in CI, not default ci)
      "verify.install_golden": [
        "cmd env CHIMEWAY_SKIP_OBAN=1 MIX_ENV=test mix test test/chimeway/install/golden_diff_test.exs test/chimeway/install/idempotency_test.exs test/chimeway/install/prefix_contract_test.exs test/chimeway/migration_contract_test.exs --warnings-as-errors"
      ],
      "verify.runtime_prefix": [
        "cmd env MIX_ENV=test mix test test/chimeway/repo_prefix_test.exs test/chimeway/runtime_prefix_integration_test.exs test/chimeway/generated_prefixed_runtime_proof_test.exs --warnings-as-errors"
      ],
      "verify.apns": [
        "cmd scripts/test-db env CHIMEWAY_SKIP_PARTNER_TEST_REPOS=1 MIX_ENV=test mix test test/chimeway/apns/api_coverage_test.exs test/chimeway/apns/request_test.exs test/chimeway/apns/result_test.exs test/chimeway/adapters/apns_test.exs test/chimeway/safe_evidence_test.exs test/chimeway/migration_contract_test.exs --warnings-as-errors",
        "cmd bash scripts/verify-apns.sh"
      ],
      "ci.install_golden": ["verify.install_golden"],

      # Documentation-contract and version-alignment gates. Keep the packaged
      # Accrue clean-consumer proof independently runnable so CI can give it a
      # dedicated timeout while the canonical release alias still runs both.
      "ci.verify_contracts": [
        "cmd scripts/test-db env CHIMEWAY_SKIP_PARTNER_TEST_REPOS=1 MIX_ENV=test mix test test/chimeway/doc_contract_test.exs test/chimeway/release_gate_contract_test.exs --exclude adoption_paths_e2e --exclude accrue_packaged_cli --warnings-as-errors"
      ],
      "ci.verify_accrue_package": [
        "cmd scripts/test-db env CHIMEWAY_SKIP_PARTNER_TEST_REPOS=1 MIX_ENV=test mix test test/chimeway/release_gate_contract_test.exs --only accrue_packaged_cli --warnings-as-errors"
      ],
      "ci.crosswake_provider_feedback_docs": ["verify.crosswake_provider_feedback_docs"],
      "ci.verify_gates": [
        "ci.verify_contracts",
        "ci.verify_accrue_package",
        "ci.crosswake_provider_feedback_docs"
      ],
      "ci.alpha_twin": ["verify.alpha_twin", "verify.physical_proof_contract"],

      # TeamPulse consumer journey proof.
      "verify.journeys": [
        "cmd --shell cd examples/chimeway_demo_host && mix deps.get && mix test --only journey"
      ],

      # Mailglass adapter, webhook pipeline, and demo-host proof.
      "verify.mailglass": [
        "cmd env MIX_ENV=test mix test --only mailglass --warnings-as-errors",
        "cmd --shell cd examples/chimeway_demo_host && mix deps.get && mix test --only mailglass --warnings-as-errors"
      ],

      # Accrue dunning integration harness (root and demo-host :accrue lane).
      "verify.accrue": [
        "deps.compile",
        "cmd env MIX_ENV=test mix test --only accrue --warnings-as-errors",
        "cmd --shell cd examples/chimeway_demo_host && env CHIMEWAY_SKIP_ACCRUE_DEP=1 ACCRUE_PATH=../../accrue/accrue/accrue CHIMEWAY_PATH=../.. mix deps.get && env CHIMEWAY_SKIP_ACCRUE_DEP=1 ACCRUE_PATH=../../accrue/accrue/accrue CHIMEWAY_PATH=../.. mix deps.compile && env CHIMEWAY_SKIP_ACCRUE_DEP=1 ACCRUE_PATH=../../accrue/accrue/accrue CHIMEWAY_PATH=../.. mix test --only accrue --warnings-as-errors"
      ],

      # Inbox integration proof: core, package, admin, contracts, and demo journey.
      "verify.inbox": [
        "cmd scripts/test-db env CHIMEWAY_SKIP_PARTNER_TEST_REPOS=1 MIX_ENV=test mix test test/chimeway/inbox_state_transition_test.exs test/chimeway/inbox_change_publisher_test.exs test/chimeway/trigger_inbox_change_test.exs test/chimeway/traces_test.exs test/chimeway/safe_evidence_test.exs --warnings-as-errors",
        "cmd --shell cd chimeway_inbox && mix deps.get && mix test --warnings-as-errors",
        "cmd --shell cd chimeway_admin && mix deps.get && mix test test/chimeway_admin/components/timeline_event_test.exs test/chimeway_admin/redaction_test.exs --warnings-as-errors",
        "cmd scripts/test-db env CHIMEWAY_SKIP_PARTNER_TEST_REPOS=1 MIX_ENV=test mix test test/chimeway/doc_contract_test.exs test/chimeway/release_gate_contract_test.exs --only inbox_gate_parity --warnings-as-errors",
        "cmd --shell cd examples/chimeway_demo_host && mix deps.get && mix test --only inbox --warnings-as-errors"
      ],

      # Threadline telemetry reporter proof (root and demo-host :threadline lane).
      "verify.threadline": [
        "cmd env MIX_ENV=test mix test --only threadline --warnings-as-errors",
        "cmd --shell threadline_path=${THREADLINE_PATH:-../threadline/threadline}; threadline_path=$(cd \"$threadline_path\" && pwd); cd examples/chimeway_demo_host && env CHIMEWAY_SKIP_SIGRA_DEP=1 THREADLINE_PATH=\"$threadline_path\" CHIMEWAY_PATH=../.. mix deps.get && env CHIMEWAY_SKIP_SIGRA_DEP=1 THREADLINE_PATH=\"$threadline_path\" CHIMEWAY_PATH=../.. mix deps.compile && env CHIMEWAY_SKIP_SIGRA_DEP=1 THREADLINE_PATH=\"$threadline_path\" CHIMEWAY_PATH=../.. mix test --only threadline --warnings-as-errors"
      ],

      # Sigra auth notification proof (root and demo-host :sigra lane).
      "verify.sigra": [
        "cmd env MIX_ENV=test mix test --only sigra --warnings-as-errors",
        "cmd --shell sigra_path=${SIGRA_PATH:-../sigra/sigra}; sigra_path=$(cd \"$sigra_path\" && pwd); cd examples/chimeway_demo_host && env CHIMEWAY_SKIP_THREADLINE_DEP=1 CHIMEWAY_SKIP_MAILGLASS_DEP=1 CHIMEWAY_SKIP_SIGRA_TRANSITIVE_DEP=1 SIGRA_PATH=\"$sigra_path\" CHIMEWAY_PATH=../.. mix deps.get && env CHIMEWAY_SKIP_THREADLINE_DEP=1 CHIMEWAY_SKIP_MAILGLASS_DEP=1 CHIMEWAY_SKIP_SIGRA_TRANSITIVE_DEP=1 SIGRA_PATH=\"$sigra_path\" CHIMEWAY_PATH=../.. mix deps.compile && env CHIMEWAY_SKIP_THREADLINE_DEP=1 CHIMEWAY_SKIP_MAILGLASS_DEP=1 CHIMEWAY_SKIP_SIGRA_TRANSITIVE_DEP=1 SIGRA_PATH=\"$sigra_path\" CHIMEWAY_PATH=../.. mix compile && env CHIMEWAY_SKIP_THREADLINE_DEP=1 CHIMEWAY_SKIP_MAILGLASS_DEP=1 CHIMEWAY_SKIP_SIGRA_TRANSITIVE_DEP=1 SIGRA_PATH=\"$sigra_path\" CHIMEWAY_PATH=../.. mix test --only sigra --warnings-as-errors"
      ],

      # Mounted admin package, demo-host, and browser smoke proof.
      "verify.admin": [
        "cmd env MIX_ENV=test mix test test/chimeway/admin_test.exs --warnings-as-errors",
        "cmd --shell cd chimeway_admin && mix deps.get && mix test --warnings-as-errors",
        "cmd --shell cd examples/chimeway_demo_host && env CHIMEWAY_SKIP_THREADLINE_DEP=1 CHIMEWAY_SKIP_SIGRA_DEP=1 MIX_ENV=test mix deps.get && env CHIMEWAY_SKIP_THREADLINE_DEP=1 CHIMEWAY_SKIP_SIGRA_DEP=1 MIX_ENV=test mix test test/demo_host_web/admin_trace_live_test.exs --warnings-as-errors",
        "cmd npm ci",
        "cmd npx playwright install --with-deps chromium",
        "cmd npx playwright test test/browser/admin_smoke.spec.ts"
      ]
    ]
  end

  defp accrue_dep do
    # Local dev: ACCRUE_PATH=../accrue/accrue mix deps.get
    case System.get_env("ACCRUE_PATH") do
      nil -> {:accrue, "~> 1.3", optional: true, runtime: false}
      path -> {:accrue, path: path, optional: true, runtime: false}
    end
  end

  defp threadline_deps do
    if System.get_env("CHIMEWAY_SKIP_THREADLINE_DEP") in ["1", "true"] do
      []
    else
      [threadline_dep()]
    end
  end

  defp threadline_dep do
    # Local dev: THREADLINE_PATH=../threadline mix deps.get
    case System.get_env("THREADLINE_PATH") do
      nil -> {:threadline, "~> 0.7", optional: true, runtime: false}
      path -> {:threadline, path: path, optional: true, runtime: false}
    end
  end

  defp sigra_deps do
    if System.get_env("CHIMEWAY_SKIP_SIGRA_DEP") in ["1", "true"] or
         System.get_env("CHIMEWAY_SKIP_SIGRA_TRANSITIVE_DEP") in ["1", "true"] do
      []
    else
      [sigra_dep()]
    end
  end

  defp sigra_dep do
    # Local dev: SIGRA_PATH=../sigra mix deps.get
    #
    # chimeway's own lib/ never references Sigra; this optional, runtime:false dep
    # only exists so the Sigra integration (Sigra.Integrations.Chimeway, exercised by
    # `mix verify.sigra` via SIGRA_PATH) resolves. Pinned `~> 1.0` to match mailglass's
    # `sigra ~> 1.0`, so the plain hex requirement needs no override — which keeps the
    # Hex package build override-free (Hex rejects overridden deps) and lets
    # `mix hex.publish` run in :dev, where ex_doc lives to build docs.
    base = [optional: true, runtime: false]

    case System.get_env("SIGRA_PATH") do
      # No SIGRA_PATH: `sigra ~> 1.0` matches mailglass's requirement — no override.
      nil ->
        {:sigra, "~> 1.0", base}

      # SIGRA_PATH set (verify.sigra): the local path dep must override chimeway's hex
      # `sigra ~> 1.0` requirement so the checkout is used. This branch never runs in a
      # Hex publish (which sets no SIGRA_PATH), so the override never reaches the package.
      path ->
        {:sigra, [{:path, path}, {:override, true} | base]}
    end
  end

  defp package do
    [
      files:
        ~w(lib priv guides scripts/prove-accrue-consumer.exs scripts/prove-adoption-paths.exs CHANGELOG.md LICENSE.md README.md mix.exs .formatter.exs),
      licenses: ["MIT"],
      links: %{"GitHub" => "https://github.com/szTheory/chimeway"}
    ]
  end

  defp docs do
    [
      main: "Chimeway",
      logo: "brandbook/assets/logo/chimeway-mark.svg",
      favicon: "brandbook/assets/favicon/favicon.svg",
      source_ref: "v#{@version}",
      source_url: "https://github.com/szTheory/chimeway",
      extras: [
        "guides/introduction/adoption-paths.md",
        "guides/introduction/mobile-adoption-operations.md",
        "guides/introduction/getting-started.md",
        "guides/introduction/installation.md",
        "guides/introduction/golden-path.md",
        "guides/introduction/storage-prefix-upgrade.md",
        "guides/introduction/mailglass-integration.md",
        "guides/introduction/accrue-dunning-integration.md",
        "guides/introduction/admin-console-integration.md",
        "guides/introduction/inbox-integration.md",
        "guides/introduction/threadline-integration.md",
        "guides/introduction/sigra-auth-integration.md",
        "guides/flows/multi-step-journeys.md",
        "guides/recipes/oban-integration.md",
        "guides/recipes/custom-adapter.md",
        "guides/recipes/accrue-dunning-blueprint.md",
        "guides/recipes/mailglass-integration-blueprint.md",
        "guides/recipes/sigra-auth-blueprint.md",
        "guides/recipes/tracing-a-notification.md",
        "guides/recipes/password-reset-support-trace.md",
        "guides/recipes/feedback-escalation-workflow.md",
        "guides/recipes/mention-escalation.md",
        "guides/reference/apns-api-coverage.md",
        "guides/cheatsheet.cheatmd"
      ],
      groups_extras: [
        Introduction: ~r/guides\/introduction\//,
        Flows: ~r/guides\/flows\//,
        Recipes: ~r/guides\/recipes\//,
        Reference: ~r/guides\/reference\//
      ]
    ]
  end
end