├── .github
├── CODEOWNERS
├── dependabot.yml
├── release.yml
├── scripts
│ └── release.sh
└── workflows
│ ├── bump-versions.yml
│ ├── release.yml
│ └── test.yml
├── LICENSE
├── README.md
├── action.yml
├── project.toml
└── test
├── polarify
└── recipe.yaml
└── test-package
└── recipe.yaml
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @pavelzw
2 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: github-actions
4 | directory: /
5 | schedule:
6 | interval: daily
7 | groups:
8 | dependencies:
9 | patterns:
10 | - "*"
11 |
--------------------------------------------------------------------------------
/.github/release.yml:
--------------------------------------------------------------------------------
1 | changelog:
2 | exclude:
3 | labels:
4 | - ignore for release
5 | categories:
6 | - title: 💥 Breaking changes
7 | labels:
8 | - breaking
9 | - title: ✨ New features
10 | labels:
11 | - enhancement
12 | - title: 👷🏻 CI
13 | labels:
14 | - ci
15 | - title: 🐛 Bug fixes
16 | labels:
17 | - bug
18 | - title: 📝 Documentation
19 | labels:
20 | - documentation
21 | - title: ⬆️ Dependency updates
22 | labels:
23 | - dependencies
24 | - title: 🤷🏻 Other changes
25 | labels:
26 | - "*"
27 |
--------------------------------------------------------------------------------
/.github/scripts/release.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | version="${TAG_NAME}"
4 | major="${version%%.*}" # see https://linuxjournal.com/article/8919 for an explanation of this bash magic
5 |
6 | git tag -d "${major}"
7 | local_delete=$?
8 | if [ $local_delete -eq 0 ]; then
9 | echo "Deleted local tag ${major}."
10 | echo "Deleted local tag \`${major}\`." >> "$GITHUB_STEP_SUMMARY"
11 | else
12 | echo "No local tag ${major} to delete."
13 | echo "No local tag \`${major}\` to delete." >> "$GITHUB_STEP_SUMMARY"
14 | fi
15 | git tag "${major}"
16 |
17 | git push -d origin "${major}"
18 | remote_delete=$?
19 | if [ $remote_delete -eq 0 ]; then
20 | echo "Deleted remote tag ${major}."
21 | echo "Deleted remote tag \`${major}\`." >> "$GITHUB_STEP_SUMMARY"
22 | else
23 | echo "No remote tag ${major} to delete."
24 | echo "No remote tag \`${major}\` to delete." >> "$GITHUB_STEP_SUMMARY"
25 | fi
26 | git push origin "${major}"
27 | push_worked=$?
28 | if [ $push_worked -ne 0 ]; then
29 | echo "Failed to push ${major} tag to remote."
30 | echo "Failed to push \`${major}\` tag to remote." >> "$GITHUB_STEP_SUMMARY"
31 | exit 1
32 | fi
33 |
34 | if [ $remote_delete -eq 0 ]; then
35 | echo "Result: moved ${major} -> ${version} tag on remote."
36 | echo "Result: moved \`${major}\` -> \`${version}\` tag on remote." >> "$GITHUB_STEP_SUMMARY"
37 | else
38 | echo "Result: created ${major} -> ${version} tag on remote."
39 | echo "Result: created \`${major}\` -> \`${version}\` tag on remote." >> "$GITHUB_STEP_SUMMARY"
40 | fi
41 |
--------------------------------------------------------------------------------
/.github/workflows/bump-versions.yml:
--------------------------------------------------------------------------------
1 | name: Bump versions
2 | on:
3 | workflow_dispatch:
4 | schedule:
5 | - cron: 0 6 * * *
6 |
7 | jobs:
8 | bump:
9 | name: Bump ${{ matrix.tool }}
10 | runs-on: ubuntu-latest
11 | strategy:
12 | matrix:
13 | include:
14 | - tool: rattler-build
15 | repo: prefix-dev/rattler-build
16 | steps:
17 | - uses: actions/checkout@v4
18 | - name: Bump versions
19 | id: bump
20 | run: |
21 | set -exuo pipefail
22 | new_version="$(gh repo view --json latestRelease ${{ matrix.repo }} | jq -r '.latestRelease.tagName')"
23 | echo "new-version=$new_version" >> "$GITHUB_OUTPUT"
24 | yq -i ".inputs.${{ matrix.tool }}-version.default = \"$new_version\"" action.yml
25 | env:
26 | GH_TOKEN: ${{ github.token }}
27 | - name: Create Pull Request
28 | uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e
29 | with:
30 | title: Bump ${{ matrix.tool }} to ${{ steps.bump.outputs.new-version }}
31 | delete-branch: true
32 | commit-message: Bump ${{ matrix.tool }} version to ${{ steps.bump.outputs.new-version }}
33 | branch: bump-${{ matrix.tool }}-${{ steps.bump.outputs.new-version }}
34 | labels: dependencies,enhancement
35 | body: |
36 | - [ ] Update version in [project.toml](https://github.com/prefix-dev/rattler-build-action/blob/bump-${{ matrix.tool }}-${{ steps.bump.outputs.new-version }}/project.toml)
37 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | branches: main
6 | permissions:
7 | contents: write
8 |
9 | # To release a new version, update the version in `project.toml` and push to main.
10 | # This will create a draft release with the changelog and push a 'vx' tag that points to the new release as well as 'vx.y.z'.
11 |
12 | jobs:
13 | release:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v4
17 | - uses: quantco/ui-actions/version-metadata@v1
18 | id: version-metadata
19 | with:
20 | file: ./project.toml
21 | token: ${{ secrets.GITHUB_TOKEN }}
22 | version-extraction-override: 'regex:version = "(.*)"'
23 | - run: .github/scripts/release.sh
24 | if: steps.version-metadata.outputs.changed == 'true'
25 | env:
26 | TAG_NAME: v${{ steps.version-metadata.outputs.newVersion }}
27 | - name: Create release
28 | if: steps.version-metadata.outputs.changed == 'true'
29 | uses: softprops/action-gh-release@v2
30 | with:
31 | generate_release_notes: true
32 | tag_name: v${{ steps.version-metadata.outputs.newVersion }}
33 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Test
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | branches:
9 | - main
10 |
11 | jobs:
12 | bump:
13 | name: Test action
14 | runs-on: ${{ matrix.os }}
15 | timeout-minutes: 10
16 | strategy:
17 | fail-fast: false
18 | matrix:
19 | recipe:
20 | - polarify
21 | - test-package
22 | os:
23 | - ubuntu-latest
24 | - macos-13
25 | - macos-latest
26 | - windows-latest
27 | - ubuntu-24.04-arm
28 | rattler-build-version:
29 | - '' # default
30 | - latest
31 | steps:
32 | - uses: actions/checkout@v4
33 | - uses: ./
34 | with:
35 | recipe-path: test/${{ matrix.recipe }}/recipe.yaml
36 | artifact-name: package-${{ matrix.recipe }}-${{ matrix.os }}-${{ matrix.rattler-build-version }}
37 |
38 | check-readme:
39 | name: Check versions in README.md
40 | runs-on: ubuntu-latest
41 | steps:
42 | - uses: actions/checkout@v4
43 | - name: Check rattler-build-action version mentions
44 | run: |
45 | project_version="$(yq '.version' project.toml)"
46 | count_expected=6
47 | count_actual="$(grep -c "prefix-dev/rattler-build-action@v${project_version}" README.md || true)"
48 | if [ "$count_actual" -ne "$count_expected" ]; then
49 | echo "::error file=README.md::Expected $count_expected mentions of \`rattler-build-action@v$project_version\` in README.md, but found $count_actual."
50 | exit 1
51 | fi
52 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2024, Pavel Zwerschke
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice,
12 | this list of conditions and the following disclaimer in the documentation
13 | and/or other materials provided with the distribution.
14 |
15 | 3. Neither the name of the copyright holder nor the names of its
16 | contributors may be used to endorse or promote products derived from
17 | this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | [![License][license-badge]][license]
4 | [![CI][test-badge]][test]
5 | [![Latest release][latest-release-badge]][releases]
6 | [![Project Chat][chat-badge]][chat-url]
7 |
8 | [license-badge]: https://img.shields.io/github/license/prefix-dev/rattler-build-action?style=flat-square
9 | [license]: ./LICENSE
10 | [test-badge]: https://img.shields.io/github/actions/workflow/status/prefix-dev/rattler-build-action/test.yml?style=flat-square
11 | [test]: https://github.com/prefix-dev/rattler-build-action/actions/
12 | [latest-release-badge]: https://img.shields.io/github/v/tag/prefix-dev/rattler-build-action?style=flat-square&label=latest&sort=semver
13 | [releases]: https://github.com/prefix-dev/rattler-build-action/releases
14 | [chat-badge]: https://img.shields.io/discord/1082332781146800168.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2&style=flat-square
15 | [chat-url]: https://discord.gg/kKV8ZxyzY4
16 |
17 |
18 |
19 | # rattler-build-action 📦🐍
20 |
21 | `rattler-build-action` is a GitHub Action for building conda packages using [rattler-build](https://github.com/prefix-dev/rattler-build).
22 |
23 | ## Usage
24 |
25 | Create `.github/workflows/package.yml` in your repository. Here's a quick template:
26 |
27 | ```yml
28 | name: Package
29 |
30 | on: [push]
31 |
32 | jobs:
33 | build:
34 | name: Build package
35 | runs-on: ubuntu-latest
36 | steps:
37 | - uses: actions/checkout@v4
38 | - name: Build conda package
39 | uses: prefix-dev/rattler-build-action@v0.2.33
40 | ```
41 |
42 | > [!WARNING]
43 | > Since rattler-build is still experimental and the API can change in minor versions, please pin this action to its minor version, i.e., `prefix-dev/rattler-build-action@v0.2.33`.
44 |
45 | > [!TIP]
46 | > You can use dependabot to automatically update the version of `rattler-build-action`. Add the following to your `.github/dependabot.yml`:
47 | >
48 | > ```yml
49 | > version: 2
50 | > updates:
51 | > - package-ecosystem: github-actions
52 | > directory: /
53 | > schedule:
54 | > interval: monthly
55 | > groups:
56 | > gh-actions:
57 | > patterns:
58 | > - "*"
59 | > ```
60 |
61 | This action will build the conda recipe in `conda.recipe/recipe.yaml` and upload the built packages as a build artifact.
62 |
63 | ## Customizations
64 |
65 | - `rattler-build-version`: Define the version of rattler-build. Pins to the latest version that is available when releasing.
66 | - `recipe-path`: Path to the rattler recipe. Defaults to `conda.recipe/recipe.yaml`.
67 | - `upload-artifact`: Decide whether to upload the built packages as a build artifact.
68 | - `build-args`: Additional arguments to pass to `rattler-build build`.
69 | - `artifact-name`: Name of the artifact that is uploaded after build. If running `rattler-build-action` multiple times in a matrix, you need a distinct name for each workflow.
70 |
71 | ### `rattler-build-version`
72 |
73 | `rattler-build-version` is strictly pinned to the latest version of `rattler-build` that is available when releasing a new version of `rattler-build-action`.
74 | This is to ensure that no breakages occur if a new version of `rattler-build` is released.
75 |
76 | You can use dependabot to automatically update the version of `prefix-dev/rattler-build-action` which will also update the version of `rattler-build` to the latest version.
77 |
78 | ## Examples
79 |
80 | ### Build for multiple targets using matrix
81 |
82 | ```yml
83 | jobs:
84 | build:
85 | name: Build package
86 | runs-on: ${{ matrix.os }}
87 | strategy:
88 | matrix:
89 | include:
90 | - os: ubuntu-latest
91 | target-platform: linux-64
92 | - os: ubuntu-latest
93 | target-platform: linux-aarch64
94 | - os: windows-latest
95 | target-platform: win-64
96 | - os: macos-latest
97 | target-platform: osx-64
98 | - os: macos-14
99 | target-platform: osx-arm64
100 | steps:
101 | - uses: actions/checkout@v4
102 | - name: Build conda package
103 | uses: prefix-dev/rattler-build-action@v0.2.33
104 | with:
105 | # needs to be unique for each matrix entry
106 | artifact-name: package-${{ matrix.target-platform }}
107 | build-args: --target-platform ${{ matrix.target-platform }}${{ matrix.target-platform == 'linux-aarch64' && ' --no-test' || '' }}
108 | ```
109 |
110 | ### Upload to quetz
111 |
112 | ```yml
113 | jobs:
114 | build:
115 | name: Build package
116 | runs-on: ubuntu-latest
117 | steps:
118 | - uses: actions/checkout@v4
119 | - name: Build conda package
120 | uses: prefix-dev/rattler-build-action@v0.2.33
121 | - run: |
122 | for pkg in $(find output -type f \( -name "*.conda" -o -name "*.tar.bz2" \) ); do
123 | echo "Uploading ${pkg}"
124 | rattler-build upload quetz "${pkg}"
125 | done
126 | env:
127 | QUETZ_SERVER_URL: https://my.quetz.server
128 | QUETZ_API_KEY: ${{ secrets.QUETZ_API_KEY }}
129 | QUETZ_CHANNEL: my-channel
130 | ```
131 |
132 | ### Upload to prefix.dev via OIDC from GitHub Actions
133 |
134 | This requires you to configure the workflow as a trusted publisher for your target channel (see [Trusted Publishing to Conda Channels](https://prefix.dev/blog/trusted_publishing_to_conda_channels)).
135 |
136 | ```yml
137 | jobs:
138 | build:
139 | name: Build package
140 | runs-on: ubuntu-latest
141 |
142 | permissions:
143 | id-token: write
144 | contents: read
145 |
146 | steps:
147 | - uses: actions/checkout@v4
148 | - name: Build conda package
149 | uses: prefix-dev/rattler-build-action@v0.2.33
150 | - run: |
151 | for pkg in $(find output -type f \( -name "*.conda" -o -name "*.tar.bz2" \) ); do
152 | echo "Uploading ${pkg}"
153 | rattler-build upload prefix -c my-channel "${pkg}"
154 | done
155 | ```
156 |
157 | ### Use private channel
158 |
159 | You can use a private channel while building your conda package by setting the `RATTLER_AUTH_FILE` environment variable.
160 | As of now, `rattler-build` does not support a `login` command [prefix-dev/rattler-build#334](https://github.com/prefix-dev/rattler-build/issues/334), so you need to create the `RATTLER_AUTH_FILE` manually.
161 |
162 | ```yml
163 | jobs:
164 | build:
165 | name: Build package
166 | runs-on: ubuntu-latest
167 | steps:
168 | - uses: actions/checkout@v4
169 | - name: Authenticate with private channel
170 | run: |
171 | RATTLER_AUTH_FILE=${{ runner.temp }}/credentials.json
172 | echo '{"my.quetz.server": {"CondaToken": "${{ secrets.QUETZ_API_KEY }}"}}' > "$RATTLER_AUTH_FILE"
173 | echo "RATTLER_AUTH_FILE=$RATTLER_AUTH_FILE" >> "$GITHUB_ENV"
174 | - name: Build conda package
175 | uses: prefix-dev/rattler-build-action@v0.2.33
176 | with:
177 | build-args: -c conda-forge -c https://my.quetz.server/get/my-channel
178 | ```
179 |
--------------------------------------------------------------------------------
/action.yml:
--------------------------------------------------------------------------------
1 | name: rattler-build-action
2 | description: GitHub action to build conda packages using rattler-build
3 | author: Pavel Zwerschke
4 | branding:
5 | icon: package
6 | color: yellow
7 | inputs:
8 | rattler-build-version:
9 | description: Version of rattler-build to use
10 | required: false
11 | default: 'v0.39.0'
12 | recipe-path:
13 | description: Path to the recipe.yaml file
14 | required: true
15 | default: conda.recipe/recipe.yaml
16 | upload-artifact:
17 | description: whether to upload the built packages as a build artifact
18 | required: false
19 | default: 'true'
20 | artifact-name:
21 | description: Package name of the uploaded artifact
22 | required: false
23 | default: 'package'
24 | build-args:
25 | description: arguments to pass to rattler-build
26 | required: false
27 | default: ''
28 | runs:
29 | using: composite
30 | steps:
31 | - name: Generate rattler-build URL
32 | shell: bash
33 | id: url
34 | run: |
35 | arch=$(uname -m)
36 | if [ "$arch" = "arm64" ]; then
37 | arch="aarch64"
38 | fi
39 | platform=${{ runner.os == 'macOS' && 'apple-darwin' || '' }}${{ runner.os == 'Linux' && 'unknown-linux-musl' || '' }}${{ runner.os == 'Windows' && 'pc-windows-msvc' || '' }}
40 | if [ ${{ inputs.rattler-build-version }} = "latest" ]; then
41 | url="https://github.com/prefix-dev/rattler-build/releases/latest/download/rattler-build-$arch-$platform${{ runner.os == 'Windows' && '.exe' || '' }}"
42 | else
43 | url="https://github.com/prefix-dev/rattler-build/releases/download/${{ inputs.rattler-build-version }}/rattler-build-$arch-$platform${{ runner.os == 'Windows' && '.exe' || '' }}"
44 | fi
45 | echo "url=$url" >> $GITHUB_OUTPUT
46 | - name: Install rattler-build (Unix)
47 | shell: bash
48 | if: ${{ runner.os != 'Windows' }}
49 | run: |
50 | mkdir -p ${{ runner.temp }}/rattler-build
51 | curl -Ls \
52 | ${{ steps.url.outputs.url }} \
53 | -o ${{ runner.temp }}/rattler-build/rattler-build
54 | chmod +x ${{ runner.temp }}/rattler-build/rattler-build
55 | echo ${{ runner.temp }}/rattler-build >> $GITHUB_PATH
56 | - name: Install rattler-build (Windows)
57 | shell: powershell
58 | if: ${{ runner.os == 'Windows' }}
59 | run: |
60 | New-Item -ItemType Directory -Path "${{ runner.temp }}\rattler-build" -Force
61 | Invoke-WebRequest -Uri "${{ steps.url.outputs.url }}" -OutFile "${{ runner.temp }}\rattler-build\rattler-build.exe"
62 | Add-Content -Path $env:GITHUB_PATH -Value "${{ runner.temp }}\rattler-build"
63 | - name: Build conda package (non-Windows)
64 | shell: bash
65 | if: ${{ runner.os != 'Windows' }}
66 | run: |
67 | rattler-build build --recipe "${{ inputs.recipe-path }}" ${{ inputs.build-args }}
68 | env:
69 | RATTLER_BUILD_ENABLE_GITHUB_INTEGRATION: 'true'
70 | RATTLER_BUILD_COLOR: 'always'
71 | - name: Build conda package (Windows)
72 | shell: powershell
73 | if: ${{ runner.os == 'Windows' }}
74 | run: |
75 | rattler-build build --recipe "${{ inputs.recipe-path }}" ${{ inputs.build-args }}
76 | env:
77 | RATTLER_BUILD_ENABLE_GITHUB_INTEGRATION: 'true'
78 | RATTLER_BUILD_COLOR: 'always'
79 | - name: Upload build artifacts
80 | uses: actions/upload-artifact@v4
81 | if: ${{ inputs.upload-artifact == 'true' }}
82 | with:
83 | name: ${{ inputs.artifact-name }}
84 | path: |
85 | output/**/*.tar.bz2
86 | output/**/*.conda
87 |
--------------------------------------------------------------------------------
/project.toml:
--------------------------------------------------------------------------------
1 | version = "0.2.33"
2 |
--------------------------------------------------------------------------------
/test/polarify/recipe.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/prefix-dev/recipe-format/main/schema.json
2 | context:
3 | name: polarify
4 | version: 0.1.3
5 |
6 | source:
7 | - url: https://github.com/quantco/polarify/archive/refs/tags/v${{ version }}.tar.gz
8 | sha256: 93441164c23b764d72c8a66d14b11d5bbd353ed6112ccf3b35efda2a98f9df02
9 |
10 | outputs:
11 | - package:
12 | name: ${{ name }}
13 | version: ${{ version }}
14 | build:
15 | noarch: python
16 | script:
17 | - python -m pip install . --no-deps --ignore-installed -vv --no-build-isolation --disable-pip-version-check
18 | requirements:
19 | host:
20 | - python >=3.9
21 | - pip
22 | - hatchling
23 | run:
24 | - python >=3.9
25 | - polars >=0.14.24,<0.20
26 | tests:
27 | - python:
28 | imports:
29 | - polarify
30 | pip_check: true
31 |
32 | about:
33 | homepage: https://github.com/quantco/polarify
34 | license: BSD-3-Clause
35 |
--------------------------------------------------------------------------------
/test/test-package/recipe.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/prefix-dev/recipe-format/main/schema.json
2 |
3 | context:
4 | name: test-package
5 | version: 0.1.0
6 |
7 | outputs:
8 | - package:
9 | name: ${{ name }}
10 | version: ${{ version }}
11 | build:
12 | noarch: python
13 | script:
14 | - echo "Hello, world!"
15 | requirements:
16 | host:
17 | - python >=3.9
18 | run:
19 | - python >=3.9
20 |
--------------------------------------------------------------------------------