diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100755 index 0000000..99928c4 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# Lines starting with '#' are comments. +# Each line is a file pattern followed by one or more owners. + +# These owners will be the default owners for everything in the repo. +* @probably-not diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..02e2a11 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,32 @@ +version: 2 + +updates: + - package-ecosystem: "mix" + directory: "/" + schedule: + interval: "daily" + reviewers: + - "@probably-not" + open-pull-requests-limit: 10 + - package-ecosystem: "mix" + directory: "/demo" + schedule: + interval: "weekly" + day: "sunday" + reviewers: + - "@probably-not" + open-pull-requests-limit: 10 + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + day: "sunday" + reviewers: + - "@probably-not" + - package-ecosystem: docker + directory: "/" + schedule: + interval: "weekly" + day: "sunday" + reviewers: + - "@probably-not" diff --git a/.github/workflows/pipeline.yaml b/.github/workflows/pipeline.yaml new file mode 100644 index 0000000..127e88b --- /dev/null +++ b/.github/workflows/pipeline.yaml @@ -0,0 +1,113 @@ +name: "CI Pipeline" + +on: + push: + branches: + - main + pull_request: + branches: + - main + types: + - opened + - synchronize + - reopened + - ready_for_review + +concurrency: + group: pipeline-${{ github.event.repository.name }}-${{ github.ref }} + cancel-in-progress: false + +jobs: + pipeline: + if: github.event.pull_request.draft == false + runs-on: ubuntu-latest + strategy: + matrix: + otp: ["26.2"] + elixir: ["1.18.1", "1.17.3", "1.16.3"] + steps: + - name: Git clone the repository + uses: actions/checkout@v4 + - name: Set up Elixir + uses: erlef/setup-beam@v1 + id: beam + with: + otp-version: ${{matrix.otp}} + elixir-version: ${{matrix.elixir}} + - name: Cache deps + id: cache-deps + uses: actions/cache@v4 + env: + cache-name: cache-elixir-deps + with: + path: deps + key: ${{ runner.os }}-mix-${{ env.cache-name }}-${{ hashFiles('**/mix.lock') }} + restore-keys: | + ${{ runner.os }}-mix-${{ env.cache-name }}- + # Step: Define how to cache the `_build` directory. After the first run, + # this speeds up tests runs a lot. This includes not re-compiling our + # project's downloaded deps every run. + - name: Cache compiled build + id: cache-build + uses: actions/cache@v4 + env: + cache-name: cache-compiled-build + with: + path: _build + key: ${{ runner.os }}-mix-${{ env.cache-name }}-${{ hashFiles('**/mix.lock') }} + restore-keys: | + ${{ runner.os }}-mix-${{ env.cache-name }}- + ${{ runner.os }}-mix- + # Step: Conditionally bust the cache when job is re-run. + # Sometimes, we may have issues with incremental builds that are fixed by + # doing a full recompile. In order to not waste dev time on such trivial + # issues (while also reaping the time savings of incremental builds for + # *most* day-to-day development), force a full recompile only on builds + # that are retried. + - name: Clean to rule out incremental build as a source of flakiness + if: github.run_attempt != '1' + run: | + mix deps.clean --all + mix clean + shell: sh + - name: Install dependencies + run: mix deps.get + - name: Check for unused deps + run: mix deps.unlock --check-unused + - name: Compiles without warnings + run: mix compile --warnings-as-errors + - name: Check Formatting + run: mix format --check-formatted + - name: Lint with Credo + run: mix credo + - name: Restore PLT cache + id: plt_cache + uses: actions/cache/restore@v4 + with: + key: | + plt-${{ runner.os }}-${{ steps.beam.outputs.otp-version }}-${{ steps.beam.outputs.elixir-version }}-${{ hashFiles('**/mix.lock') }} + restore-keys: | + plt-${{ runner.os }}-${{ steps.beam.outputs.otp-version }}-${{ steps.beam.outputs.elixir-version }}- + path: | + priv/plts + # Create PLTs if no cache was found + - name: Create PLTs + if: steps.plt_cache.outputs.cache-hit != 'true' + run: mix dialyzer --plt + # By default, the GitHub Cache action will only save the cache if all steps in the job succeed, + # so we separate the cache restore and save steps in case running dialyzer fails. + - name: Save PLT cache + id: plt_cache_save + uses: actions/cache/save@v4 + if: steps.plt_cache.outputs.cache-hit != 'true' + with: + key: | + plt-${{ runner.os }}-${{ steps.beam.outputs.otp-version }}-${{ steps.beam.outputs.elixir-version }}-${{ hashFiles('**/mix.lock') }} + path: | + priv/plts + - name: Run Dialyzer + run: mix dialyzer --format github + - name: Start EPMD for tests + run: epmd -daemon + - name: Run tests + run: mix test diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..5e5a97a --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,40 @@ +name: "Release To Hex" + +on: + push: + branches-ignore: + - "**" + tags: + - v* + +concurrency: + group: release-${{ github.event.repository.name }}-${{ github.ref }} + cancel-in-progress: false + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Git clone the repository + uses: actions/checkout@v4 + - name: Set up Elixir + uses: erlef/setup-beam@v1 + with: + version-file: .tool-versions + version-type: strict + - name: Install dependencies + run: mix deps.get + - name: Release to Hex.PM + env: + HEX_API_KEY: ${{ secrets.HEX_API_KEY }} + run: mix hex.publish --yes + deploy: + needs: [release] + name: Deploy to Fly.io + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: superfly/flyctl-actions/setup-flyctl@master + - run: flyctl deploy --remote-only + env: + FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}