# Developing packages with rix

## Why bring `{rix}` into your package workflow?

This vignette walks through a recommended development loop for package authors:

1. Declare the package dependencies with `{rix}`.
2. Commit the resulting `default.nix` to the repository.
3. Use the same definition locally and in CI/CD (for example GitHub Actions).
4. Refresh the snapshot frequently so that you notice upstream changes early.

## Declaring your package environment

Start by calling `rix()` from your package root. List the R packages and system tools that your package requires for development, testing, or vignette builds:

    rix(
      r_ver = "bleeding-edge",
      r_pkgs = c(
        "devtools", "rcmdcheck", "roxygen2", # package development helpers
        "jsonlite", "httr"                    # package runtime deps
      ),
      system_pkgs = c("pandoc"), # or anything else
      ide = "none",
      path = "default.nix",
      overwrite = TRUE
    )

A few tips when shaping the environment:

- Prefer `r_ver = "bleeding-edge"` (or at least a very recent date). This aligns your local setup with what users will experience soon and surfaces compatibility problems early. See `vignette("bleeding-edge")` for more details on using `"bleeding-edge"`.
- If you use a fixed date, then keep `date` current. Updating it every few weeks lets you track CRAN, nixpkgs, and system toolchain updates. If the new snapshot fails you can fix issues right away instead of facing a large backlog later, or you could always revert to an earlier working date.

## Committing the environment to your repository

Place the `default.nix` file at the root of the package repository so that contributors can run:

    nix-shell

This drops them into a shell with the right environment for contributing.

To simplify onboarding, document in `README.md` (or a contributing guide) that contributors should run `nix-shell` before working on the package.

Because the environment is pinned, collaborators and CI jobs execute the same versions of your dependencies, eliminating “works on my machine” bugs.

## Keeping the snapshot fresh

You could setp up a CI action to update the environment frequently, which would then trigger unit tests on CI as well. If the tests fail you can immediately address incompatibilities introduced by recent CRAN changes.

## Using `{rix}` in GitHub Actions

Because `default.nix` captures the entire toolchain, you should use it as the basis for your CI workflow. Below is a minimal GitHub Actions configuration thatruns your package’s unit tests:

    on:
      push:
        branches: [main, master]
      pull_request:
        branches: [main, master]

    name: devtools-tests-via-r-nix

    permissions:
      contents: read

    jobs:
      devtools_test:
        runs-on: ${{ matrix.os }}
        strategy:
          matrix:
            os: [macos-latest, ubuntu-latest]
        env:
          GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}

        steps:
          - uses: actions/checkout@v4

          - name: Create this folder to silence warning
            run: mkdir -p ~/.nix-defexpr/channels

          - name: Create .Renviron
            run: |
              echo "GITHUB_PAT=${{ secrets.GITHUB_TOKEN }}" >> ~/.Renviron
            shell: bash

          - uses: cachix/install-nix-action@v31
            with:
              nix_path: nixpkgs=https://github.com/rstats-on-nix/nixpkgs/archive/refs/heads/r-daily.tar.gz

          - uses: cachix/cachix-action@v14
            with:
              name: rstats-on-nix

          - name: devtools::test() via nix-shell
            run: nix-shell --run "Rscript -e \"devtools::test(stop_on_failure = TRUE)\""

The workflow builds the same shell you use locally and uses our `rstats-on-nix` binary cache for fast, reproducible builds. Any failure signals that newly published CRAN may be incompatible. Having the tests run on a schedule is a safe way to catch them very early and avoid the dreaded 2 weeks notice from CRAN to fix your package!

## Summary

By defining your package environment with `{rix}`, committing the `default.nix`, and reusing it across local development and CI/CD, you build confidence that your package remains compatible with the evolving R ecosystem. Regularly updating the snapshot keeps you close to the latest CRAN state while still benefiting from the reproducibility that Nix provides.