├── .gitignore ├── testdata ├── devbox.json └── devbox.lock ├── .github ├── dependabot.yml └── workflows │ └── test.yaml ├── README.md └── action.yml /.gitignore: -------------------------------------------------------------------------------- 1 | # MacOS filesystem 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /testdata/devbox.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "go@latest" 4 | ], 5 | "shell": { 6 | "init_hook": [] 7 | } 8 | } -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | day: monday 8 | -------------------------------------------------------------------------------- /testdata/devbox.lock: -------------------------------------------------------------------------------- 1 | { 2 | "lockfile_version": "1", 3 | "packages": { 4 | "go@latest": { 5 | "last_modified": "2023-09-17T10:54:49Z", 6 | "resolved": "github:NixOS/nixpkgs/5148520bfab61f99fd25fb9ff7bfbb50dad3c9db#go_1_21", 7 | "source": "devbox-search", 8 | "version": "1.21.1" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # devbox-install-action 2 | 3 | This action downloads the devbox CLI and installs the Nix packages defined in your `devbox.json`. 4 | 5 | [![version](https://img.shields.io/github/v/release/jetify-com/devbox-install-action?color=green&label=version&sort=semver)](https://github.com/jetify-com/devbox-install-action/releases) [![tests](https://github.com/jetify-com/devbox-install-action/actions/workflows/test.yaml/badge.svg)](https://github.com/jetify-com/devbox-install-action/actions/workflows/test.yaml?branch=main) 6 | 7 | ## Example Workflow 8 | 9 | ``` 10 | name: Testing with devbox 11 | 12 | on: push 13 | 14 | jobs: 15 | test: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v3 19 | 20 | - name: Install devbox 21 | uses: jetify-com/devbox-install-action@v0.12.0 22 | 23 | - name: Run arbitrary commands 24 | run: devbox run -- echo "done!" 25 | 26 | - name: Run a script called test 27 | run: devbox run test 28 | ``` 29 | 30 | ## Configure Action 31 | 32 | ### Action Inputs 33 | 34 | | Input argument | description | default | 35 | | ------------------------ | ------------------------------------------------------------------------------------- | --------------------- | 36 | | project-path | Path to the folder that contains a valid `devbox.json` | repo's root directory | 37 | | enable-cache | Cache the entire Nix store in github based on your `devbox.json` | false | 38 | | refresh-cli | Specify whether the CLI should be redownloaded | false | 39 | | devbox-version | Specify devbox CLI version you want to pin to. Only supports >0.2.2 | latest | 40 | | sha256-checksum | Specify an explicit checksum for the devbox binary | | 41 | | disable-nix-access-token | Disable configuration of nix access-tokens with the GitHub token used in the workflow | false | 42 | | skip-nix-installation | Skip the installation of nix | false | 43 | | extra-nix-config | Gets appended to `nix.conf` if passed | | 44 | 45 | ### Example Configurations 46 | 47 | Here's an example job with most inputs: 48 | 49 | ``` 50 | - name: Install devbox 51 | uses: jetify-com/devbox-install-action@v0.12.0 52 | with: 53 | project-path: 'path-to-folder' 54 | enable-cache: 'true' 55 | refresh-cli: 'false' 56 | devbox-version: 0.13.4 57 | disable-nix-access-token: 'false' 58 | sha256-checksum: 59 | ``` 60 | 61 | #### Usage on a GitHub Enterprise Server 62 | 63 | On a privately hosted GitHub Enterprise Server, the `github.token` available in the context is not valid for accessing `api.github.com`, 64 | which can lead to failures due to the rate-limit for unauthenticated requests. To work around this, you can provide a personal access token 65 | for `api.github.com` in the `extra-nix-config` input. 66 | Additionally, it might be necessary to provide a token for your GitHub Enterprise Server, if you are using Nix packages from there. 67 | 68 | ``` 69 | - name: Install devbox 70 | uses: jetify-com/devbox-install-action@v0.12.0 71 | with: 72 | extra-nix-config: access-tokens = my-github-enterprise-server.example.com=${{ github.token }} github.com=${{ secrets.MY_GITHUB_COM_TOKEN }} 73 | ``` 74 | -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: test 2 | # Runs the Devbox installer tests 3 | 4 | concurrency: 5 | group: ${{ github.ref }} 6 | cancel-in-progress: true 7 | 8 | on: 9 | pull_request: 10 | push: 11 | branches: 12 | - main 13 | paths-ignore: 14 | - '**.md' 15 | 16 | workflow_call: 17 | workflow_dispatch: 18 | 19 | permissions: 20 | contents: read 21 | pull-requests: read 22 | 23 | jobs: 24 | test-action: 25 | strategy: 26 | matrix: 27 | os: [macos-13, macos-14, macos-latest, ubuntu-latest] 28 | enable-cache: ['true', 'false'] 29 | runs-on: ${{ matrix.os }} 30 | steps: 31 | - uses: actions/checkout@v4 32 | - name: Install devbox 33 | uses: ./ 34 | with: 35 | project-path: 'testdata' 36 | enable-cache: ${{ matrix.enable-cache }} 37 | disable-nix-access-token: "${{ github.ref != 'refs/heads/main' }}" 38 | 39 | test-action-with-devbox-version: 40 | runs-on: ubuntu-latest 41 | strategy: 42 | matrix: 43 | enable-cache: ['true', 'false'] 44 | steps: 45 | - uses: actions/checkout@v4 46 | - name: Install devbox 47 | uses: ./ 48 | with: 49 | devbox-version: 0.13.6 50 | project-path: 'testdata' 51 | enable-cache: ${{ matrix.enable-cache }} 52 | disable-nix-access-token: "${{ github.ref != 'refs/heads/main' }}" 53 | 54 | test-action-with-sha256-checksum: 55 | runs-on: ubuntu-latest 56 | steps: 57 | - uses: actions/checkout@v4 58 | - name: Install devbox 59 | uses: ./ 60 | with: 61 | devbox-version: 0.13.6 62 | refresh-cli: true 63 | project-path: 'testdata' 64 | sha256-checksum: '22a31081df183aab7b8f88a794505c7c0ae217d6314e61b3e0bfe6972b992199' 65 | disable-nix-access-token: "${{ github.ref != 'refs/heads/main' }}" 66 | 67 | test-action-with-sha256-checksum-failure: 68 | runs-on: ubuntu-latest 69 | steps: 70 | - uses: actions/checkout@v4 71 | - name: Install devbox 72 | id: install-devbox 73 | uses: ./ 74 | continue-on-error: true 75 | with: 76 | devbox-version: 0.13.6 77 | refresh-cli: true 78 | sha256-checksum: 'bad-sha' 79 | project-path: 'testdata' 80 | disable-nix-access-token: "${{ github.ref != 'refs/heads/main' }}" 81 | - name: Fail on success 82 | if: steps.install-devbox.outcome == 'success' 83 | run: echo "The SHA check should have failed!" && exit 1 84 | 85 | test-action-with-sha256-checksum-on-mac: 86 | runs-on: macos-latest 87 | steps: 88 | - uses: actions/checkout@v4 89 | - name: Install devbox 90 | uses: ./ 91 | with: 92 | devbox-version: 0.13.6 93 | refresh-cli: true 94 | sha256-checksum: '169836de22c41a1c68ac5a43e0514d4021137647c7c08ee8bd921faa430ee286' 95 | project-path: 'testdata' 96 | disable-nix-access-token: "${{ github.ref != 'refs/heads/main' }}" 97 | 98 | test-action-with-extra-nix-config: 99 | runs-on: ubuntu-latest 100 | steps: 101 | - uses: actions/checkout@v4 102 | - name: Install devbox with extra nix config "user-agent-suffix = test-suffix" 103 | uses: ./ 104 | with: 105 | devbox-version: 0.13.6 106 | project-path: 'testdata' 107 | extra-nix-config: user-agent-suffix = test-suffix 108 | - name: Check nix user-agent-suffix config 109 | run: | 110 | [[ "$(nix config show user-agent-suffix)" == "test-suffix" ]] 111 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'devbox installer' 2 | description: 'Install Devbox in your CICD workflow' 3 | branding: 4 | icon: 'box' 5 | color: 'purple' 6 | 7 | inputs: 8 | project-path: # path to folder 9 | description: 'Project path to devbox.json. Default to the root directory of the repository.' 10 | default: '.' 11 | enable-cache: # 'true' or 'false' 12 | description: 'Caching the entire Nix store in github based on your devbox.json' 13 | default: 'false' 14 | refresh-cli: # 'true' or 'false' 15 | description: 'Specify whether the CLI should be redownloaded' 16 | default: 'false' 17 | devbox-version: # version of the devbox cli 18 | description: 'Specify devbox CLI version you want to pin to. Default to latest' 19 | default: '' 20 | sha256-checksum: # the expected SHA256 checksum of the devbox binary. 21 | description: 'Specify an explicit checksum for the devbox binary. For extra security on top of the existing checks in the devbox launch script' 22 | disable-nix-access-token: # 'true' or 'false' 23 | description: 'Disable configuration of nix access-tokens with the GitHub token used in the workflow' 24 | default: 'false' 25 | skip-nix-installation: # 'true' or 'false' 26 | description: 'Skip the installation of nix' 27 | default: 'false' 28 | extra-nix-config: 29 | description: 'Gets appended to `nix.conf` if passed' 30 | default: '' 31 | 32 | runs: 33 | using: "composite" 34 | steps: 35 | - name: Get devbox version 36 | shell: bash 37 | env: 38 | DEVBOX_USE_VERSION: ${{ inputs.devbox-version }} 39 | run: | 40 | if [[ -n $DEVBOX_USE_VERSION ]]; then 41 | echo "latest_version=$DEVBOX_USE_VERSION" >> $GITHUB_ENV 42 | else 43 | tmp_file=$(mktemp) 44 | latest_url="https://releases.jetify.com/devbox/stable/version" 45 | curl --fail --silent --location --output "${tmp_file}" "${latest_url}" 46 | latest_version=$(cat "${tmp_file}") 47 | if [[ -n ${latest_version} ]]; then 48 | echo "Found devbox latest version ${latest_version}." 49 | echo "latest_version=$latest_version" >> $GITHUB_ENV 50 | else 51 | echo "ERROR: unable to find the latest devbox version." 52 | exit 1 53 | fi 54 | fi 55 | 56 | - name: Mount devbox cli cache 57 | if: inputs.refresh-cli == 'false' 58 | id: cache-devbox-cli 59 | uses: actions/cache/restore@v4 60 | with: 61 | path: ~/.local/bin/devbox 62 | key: ${{ runner.os }}-${{ runner.arch }}-devbox-cli-${{ env.latest_version }} 63 | 64 | - name: Install devbox cli 65 | if: steps.cache-devbox-cli.outputs.cache-hit != 'true' 66 | shell: bash 67 | env: 68 | DEVBOX_SHA256: ${{ inputs.sha256-checksum }} 69 | run: | 70 | export DEVBOX_USE_VERSION="${{ env.latest_version }}" 71 | curl -fsSL https://get.jetify.com/devbox | FORCE=1 bash 72 | 73 | version=$(devbox version) 74 | if [[ ! "$version" = "$DEVBOX_USE_VERSION" ]]; then 75 | echo "ERROR: mismatch devbox version downloaded. Expected $DEVBOX_USE_VERSION, got $version." 76 | exit 1 77 | fi 78 | DEVBOX_BINARY="$(find "${HOME}/.cache/devbox/bin" -name devbox)" 79 | if [ -n "$DEVBOX_SHA256" ]; then 80 | if command -v "sha256sum" 1>/dev/null 2>&1; then 81 | # Linux distributions will likely have this. 82 | DEVBOX_CHECKSUM="$(sha256sum "$DEVBOX_BINARY" | cut -f1 -d' ')" 83 | elif command -v "shasum" 1>/dev/null 2>&1; then 84 | # MacOS comes with this. 85 | DEVBOX_CHECKSUM="$(shasum -a 256 "$DEVBOX_BINARY" | cut -f1 -d' ')" 86 | fi 87 | 88 | if [ -z "$DEVBOX_CHECKSUM" ]; then 89 | echo "ERROR: unable to get devbox checksum. Please ensure sha256sum or shasum is installed." 90 | exit 2 91 | fi 92 | 93 | if [[ ! "$DEVBOX_CHECKSUM" = "$DEVBOX_SHA256" ]]; then 94 | echo "ERROR: checksums do not match. Expected $DEVBOX_SHA256, got $DEVBOX_CHECKSUM." 95 | exit 3 96 | fi 97 | fi 98 | mkdir -p ~/.local/bin 99 | mv "$DEVBOX_BINARY" ~/.local/bin/devbox 100 | 101 | - name: Add devbox binary to path 102 | shell: bash 103 | run: | 104 | echo "$HOME/.local/bin" >> $GITHUB_PATH 105 | 106 | - name: Save devbox cli cache 107 | if: inputs.refresh-cli == 'false' && steps.cache-devbox-cli.outputs.cache-hit != 'true' 108 | uses: actions/cache/save@v4 109 | with: 110 | path: ~/.local/bin/devbox 111 | key: ${{ runner.os }}-${{ runner.arch }}-devbox-cli-${{ env.latest_version }} 112 | 113 | - name: Workaround nix store cache permission issue 114 | if: inputs.enable-cache == 'true' 115 | shell: bash 116 | run: | 117 | if [ "$RUNNER_OS" == "macOS" ]; then 118 | gtar_path=$(which gtar) 119 | sudo mv $gtar_path $gtar_path.orig 120 | echo "#!/bin/sh" >> $gtar_path 121 | echo "exec sudo $gtar_path.orig \"\$@\"" >> $gtar_path 122 | sudo chmod +x $gtar_path 123 | elif [ "$RUNNER_OS" == "Linux" ]; then 124 | mkdir -p ~/.cache 125 | mkdir -p ~/.local/bin 126 | echo "#!/bin/sh" >> ~/.local/bin/tar 127 | echo 'exec sudo /usr/bin/tar "$@"' >> ~/.local/bin/tar 128 | sudo chmod +x ~/.local/bin/tar 129 | fi 130 | 131 | - name: Configure nix access-tokens 132 | if: inputs.disable-nix-access-token == 'false' && github.server_url == 'https://github.com' 133 | shell: bash 134 | run: | 135 | mkdir -p ~/.config/nix 136 | echo "access-tokens = github.com=${{ github.token }}" >> ~/.config/nix/nix.conf 137 | 138 | - name: Configure nix extra config 139 | if: inputs.extra-nix-config != '' 140 | shell: bash 141 | run: | 142 | mkdir -p ~/.config/nix 143 | echo "${{ inputs.extra-nix-config }}" >> ~/.config/nix/nix.conf 144 | 145 | - name: Install nix 146 | if: inputs.skip-nix-installation == 'false' 147 | uses: DeterminateSystems/nix-installer-action@786fff0690178f1234e4e1fe9b536e94f5433196 # v20 148 | with: 149 | logger: pretty 150 | extra-conf: experimental-features = ca-derivations fetch-closure 151 | 152 | - name: Get nix version 153 | shell: bash 154 | run: | 155 | NIX_VERSION_OUTPUT=$(nix --version) 156 | NIX_VERSION=$(echo "${NIX_VERSION_OUTPUT}" | awk '{print $NF}') 157 | echo "nix_version=$NIX_VERSION" >> $GITHUB_ENV 158 | 159 | - name: Mount nix store cache 160 | id: cache-devbox-nix-store 161 | if: inputs.enable-cache == 'true' 162 | uses: actions/cache/restore@v4 163 | with: 164 | path: | 165 | ~/.cache/devbox 166 | ~/.cache/nix 167 | ~/.local/state/nix 168 | ~/.nix-defexpr 169 | ~/.nix-profile 170 | /nix/store 171 | /nix/var/nix 172 | key: ${{ runner.os }}-${{ runner.arch }}-devbox-nix-store-${{ env.nix_version }}-${{ hashFiles(format('{0}/devbox.lock', inputs.project-path)) }} 173 | 174 | - name: Install devbox packages 175 | shell: bash 176 | run: | 177 | devbox run --config=${{ inputs.project-path }} -- echo "Packages installed!" 178 | 179 | - name: List nix store cache on failure 180 | shell: bash 181 | if: failure() 182 | env: 183 | GH_TOKEN: ${{ github.token }} 184 | run: | 185 | echo "It is likely that nix has shipped a backwards incompatible change. Proceed to the actions tab and manually delete the following cache objects:" 186 | gh cache list --key ${{ runner.os }}-${{ runner.arch }}-devbox --json key 187 | 188 | - name: Save nix store cache 189 | if: inputs.enable-cache == 'true' && steps.cache-devbox-nix-store.outputs.cache-hit != 'true' 190 | uses: actions/cache/save@v4 191 | with: 192 | path: | 193 | ~/.cache/devbox 194 | ~/.cache/nix 195 | ~/.local/state/nix 196 | ~/.nix-defexpr 197 | ~/.nix-profile 198 | /nix/store 199 | /nix/var/nix 200 | key: ${{ runner.os }}-${{ runner.arch }}-devbox-nix-store-${{ env.nix_version }}-${{ hashFiles(format('{0}/devbox.lock', inputs.project-path)) }} 201 | 202 | - name: Restore tar command 203 | if: inputs.enable-cache == 'true' 204 | shell: bash 205 | run: | 206 | if [ "$RUNNER_OS" == "macOS" ]; then 207 | gtar_path=$(which gtar) 208 | sudo mv $gtar_path.orig $gtar_path 209 | elif [ "$RUNNER_OS" == "Linux" ]; then 210 | rm ~/.local/bin/tar 211 | fi 212 | --------------------------------------------------------------------------------