Repository: conda-forge/miniforge Branch: main Commit: 4a9571bf21eb Files: 26 Total size: 62.0 KB Directory structure: gitextract_93bddb5h/ ├── .github/ │ ├── CODEOWNERS │ ├── actions/ │ │ └── autoupdate/ │ │ ├── environment.yml │ │ └── update.py │ ├── dependabot.yml │ ├── shellcheck-matcher.json │ └── workflows/ │ ├── autoupdate.yml │ ├── ci.yml │ ├── conda_release.js │ ├── conda_release.yml │ ├── docs.yml │ └── lint.yml ├── .gitignore ├── LICENSE ├── Miniforge3/ │ └── construct.yaml ├── README.md ├── build_miniforge.sh ├── build_miniforge_osx.sh ├── build_miniforge_win.sh ├── docs/ │ ├── releases.py │ ├── requirements.txt │ └── templates/ │ └── all-releases.html └── scripts/ ├── build.sh ├── notarize_osx_pkg.sh ├── osx_pkg_background.py ├── osx_prepare_certificates.sh └── test.sh ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/CODEOWNERS ================================================ * @conda-forge/miniforge ================================================ FILE: .github/actions/autoupdate/environment.yml ================================================ name: miniconda-autoupdate channels: - conda-forge - nodefaults dependencies: - packaging - requests ================================================ FILE: .github/actions/autoupdate/update.py ================================================ #!/usr/bin/env python import re import requests from packaging import version def get_most_recent_version(name): request = requests.get( "https://api.anaconda.org/package/conda-forge/" + name ) request.raise_for_status() pkg = max( request.json()["files"], key=lambda x: version.parse(x["version"]) ) return pkg["version"] mamba_version = get_most_recent_version("mamba") with open("Miniforge3/construct.yaml", "r") as f: content = f.read() # Replace mamba version content = re.sub(r"mamba [\d.]+$", f"mamba {mamba_version}", content, flags=re.M) with open("Miniforge3/construct.yaml", "w") as f: f.write(content) ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "monthly" groups: github-actions: patterns: - '*' ================================================ FILE: .github/shellcheck-matcher.json ================================================ { "problemMatcher": [ { "owner": "shellcheck", "pattern": [ { "regexp": "^(.+):(\\d+):(\\d+):\\s(note|warning|error):\\s(.*)\\s\\[(SC\\d+)\\]$", "file": 1, "line": 2, "column": 3, "message": 5, "code": 6 } ] } ] } ================================================ FILE: .github/workflows/autoupdate.yml ================================================ name: Auto-update mamba on: schedule: - cron: "0 */6 * * *" jobs: createPullRequest: runs-on: ubuntu-slim steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ssh-key: ${{ secrets.MINIFORGE_AUTOUPDATE_SSH_PRIVATE_KEY }} - uses: conda-incubator/setup-miniconda@fc2d68f6413eb2d87b895e92f8584b5b94a10167 # v3.3.0 with: miniforge-version: latest environment-file: .github/actions/autoupdate/environment.yml - run: python .github/actions/autoupdate/update.py - name: Create Pull Request id: cpr # This is the v3 tag but for security purposes we pin to the exact commit. uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 with: commit-message: "Update mamba version" title: "Update mamba version" body: | This PR was created by the autoupdate action as it detected that the mamba version has changed and thus should be updated in the configuration. Due to limitations of Github Actions, you will need to close/reopen the PR to get the actions running. branch: autoupdate-action delete-branch: true ================================================ FILE: .github/workflows/ci.yml ================================================ name: Build miniforge on: [ push, pull_request ] concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} cancel-in-progress: true jobs: build: name: Miniforge3-${{ matrix.OS_NAME }}-${{ matrix.ARCH }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: include: - os: windows-latest ARCH: x86_64 TARGET_PLATFORM: win-64 OS_NAME: "Windows" - os: macos-latest ARCH: arm64 TARGET_PLATFORM: osx-arm64 OS_NAME: "MacOSX" - os: macos-latest ARCH: x86_64 TARGET_PLATFORM: osx-64 OS_NAME: "MacOSX" - os: ubuntu-latest ARCH: aarch64 TARGET_PLATFORM: linux-aarch64 DOCKER_ARCH: arm64/v8 DOCKERIMAGE: condaforge/linux-anvil-aarch64 OS_NAME: "Linux" # Reduce the test matrix because the builds timeouts on emulated architectures # The time consuming operation is an attempt a full solve of conda/mamba/boa # for as a compatibility # xref https://github.com/conda-forge/miniforge/pull/361 TEST_IMAGE_NAMES: "ubuntu:24.04" - os: ubuntu-latest ARCH: x86_64 TARGET_PLATFORM: linux-64 DOCKER_ARCH: amd64 DOCKERIMAGE: condaforge/linux-anvil-cos7-x86_64 OS_NAME: "Linux" - os: ubuntu-latest ARCH: ppc64le TARGET_PLATFORM: linux-ppc64le DOCKER_ARCH: ppc64le DOCKERIMAGE: condaforge/linux-anvil-ppc64le OS_NAME: "Linux" # Reduce the test matrix because the builds timeouts on emulated architectures # The time consuming operation is an attempt a full solve of conda/mamba/boa # for as a compatibility # xref https://github.com/conda-forge/miniforge/pull/361 TEST_IMAGE_NAMES: "ubuntu:24.04" steps: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: conda-incubator/setup-miniconda@fc2d68f6413eb2d87b895e92f8584b5b94a10167 # v3.3.0 with: miniforge-version: "latest" use-mamba: true if: ${{ ! contains(matrix.OS_NAME, 'Linux') }} - name: Prepare certificates (macOS) if: startsWith(matrix.TARGET_PLATFORM, 'osx-') && github.event_name != 'pull_request' env: APPLE_INSTALLER_CERTIFICATE_BASE64: ${{ secrets.MACOS_CERTIFICATE_INSTALLER_BASE64 }} APPLE_INSTALLER_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_INSTALLER_PASSWORD }} APPLE_APPLICATION_CERTIFICATE_BASE64: ${{ secrets.MACOS_CERTIFICATE_APPLICATION_BASE64 }} APPLE_APPLICATION_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_APPLICATION_PASSWORD }} APPLE_TEMP_KEYCHAIN_PASSWORD: ${{ secrets.MACOS_TEMP_KEYCHAIN_PASSWORD }} APPLE_NOTARIZATION_ISSUER_ID: ${{ secrets.MACOS_NOTARIZATION_ISSUER_ID }} APPLE_NOTARIZATION_KEY_ID: ${{ secrets.MACOS_NOTARIZATION_KEY_ID }} APPLE_NOTARIZATION_AUTHKEY_BASE64: ${{ secrets.MACOS_NOTARIZATION_AUTHKEY_BASE64 }} run: | if [[ "${APPLE_NOTARIZATION_KEY_ID:-}" == "" ]]; then exit 0 # skip if secrets are not populated fi # This script will export APPLE_SIGNING_IDENTITY and APPLE_NOTARIZATION_IDENTITY source scripts/osx_prepare_certificates.sh # These will be needed by the build.sh script echo "APPLE_SIGNING_IDENTITY=$APPLE_SIGNING_IDENTITY" >> $GITHUB_ENV echo "APPLE_NOTARIZATION_IDENTITY=$APPLE_NOTARIZATION_IDENTITY" >> $GITHUB_ENV echo "APPLE_NOTARIZATION_ISSUER_ID=$APPLE_NOTARIZATION_ISSUER_ID" >> $GITHUB_ENV echo "APPLE_NOTARIZATION_KEY_ID=$APPLE_NOTARIZATION_KEY_ID" >> $GITHUB_ENV echo "APPLE_NOTARIZATION_AUTHKEY_PATH=$APPLE_NOTARIZATION_AUTHKEY_PATH" >> $GITHUB_ENV - name: Enable PKGs (macOS) if: startsWith(matrix.TARGET_PLATFORM, 'osx-') run: | # This env var is read in construct.yaml; we need 'all' to build both SH and PKG echo "MINIFORGE_INSTALLER_TYPE=all" >> $GITHUB_ENV - name: Build and test miniforge env: ARCH: ${{ matrix.ARCH }} OS_NAME: ${{ matrix.OS_NAME }} DOCKERIMAGE: ${{ matrix.DOCKERIMAGE }} DOCKER_ARCH: ${{ matrix.DOCKER_ARCH }} TARGET_PLATFORM: ${{ matrix.TARGET_PLATFORM }} TEST_IMAGE_NAMES: ${{ matrix.TEST_IMAGE_NAMES }} run: | if [[ "$GITHUB_REF" == refs/tags/* ]]; then export MINIFORGE_VERSION=${GITHUB_REF##*/}; fi if [[ "$OS_NAME" == "Linux" ]]; then export EXT=sh bash build_miniforge.sh; fi if [[ "$OS_NAME" == "MacOSX" ]]; then export EXT=sh bash build_miniforge_osx.sh; fi if [[ "$OS_NAME" == "Windows" ]]; then export EXT=exe echo "WINDIR:$WINDIR" source "${CONDA}"/Scripts/activate; source build_miniforge_win.sh; fi # Copy for latest release cp build/Miniforge3-*-$OS_NAME-$ARCH.$EXT build/Miniforge3-$OS_NAME-$ARCH.$EXT if [[ "$OS_NAME" == "MacOSX" ]]; then # Copy PKGs too, and alias -MacOSX- to -Darwin- cp build/Miniforge3-*-$OS_NAME-$ARCH.$EXT build/Miniforge3-Darwin-$ARCH.$EXT cp build/Miniforge3-*-$OS_NAME-$ARCH.pkg build/Miniforge3-$OS_NAME-$ARCH.pkg cp build/Miniforge3-*-$OS_NAME-$ARCH.pkg build/Miniforge3-Darwin-$ARCH.pkg fi ls -alh build shell: bash - name: Upload miniforge to Github artifact if: always() uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: path: build/Miniforge3-${{ matrix.OS_NAME }}-${{ matrix.ARCH }}* name: Miniforge3-${{ matrix.OS_NAME }}-${{ matrix.ARCH }} - name: Upload miniforge to release uses: svenstaro/upload-release-action@b98a3b12e86552593f3e4e577ca8a62aa2f3f22b # v2.11.4 with: repo_token: ${{ secrets.GITHUB_TOKEN }} file: build/M*forge* tag: ${{ github.ref }} overwrite: true file_glob: true if: startsWith(github.ref, 'refs/tags/') ================================================ FILE: .github/workflows/conda_release.js ================================================ const https = require('https') const options = { hostname: 'api.anaconda.org', port: 443, path: '/package/conda-forge/conda', method: 'GET' } function compareVersions(version1, version2) { ver1 = version1.split(".").map(Number); ver2 = version2.split(".").map(Number); const common_length = Math.min(ver1.length, ver2.length); for (var i = 0; i < common_length; ++i) { if (ver1[i] < ver2[i]) { return -1; } else if (ver1[i] > ver2[i]) { return 1; } } if (ver1.length > common_length) { return 1; } else if (ver2.length > common_length) { return -1; } else { return 0; } } module.exports = ({github, context}) => { const req = https.request(options, res => { var data = ''; res.on('data', chunk => { data += chunk; }); res.on('end', function () { versions = JSON.parse(data)["files"].map(x => x["version"]); versions.sort(compareVersions); conda_version = versions.pop(); github.rest.repos.getLatestRelease({ owner: context.repo.owner, repo: context.repo.repo, }).then((release) => { const current_version = release['data']['tag_name'].split("-")[0] if (compareVersions(conda_version, current_version) === 1) { github.rest.issues.listForRepo({ owner: context.repo.owner, repo: context.repo.repo, state: "open", labels: "[bot] conda release" }).then((issues) => { if (issues.data.length === 0) { github.rest.issues.create({ owner: context.repo.owner, repo: context.repo.repo, title: "New conda release: please tag a miniforge release", body: "A new conda release was found, please tag a new miniforge release with `" + conda_version + "-0`", labels: ["[bot] conda release"] }) } }); } }); }); }) req.end(); } ================================================ FILE: .github/workflows/conda_release.yml ================================================ name: Check for new conda releases on: schedule: - cron: "0 */6 * * *" jobs: check_conda_release: name: "Check for release and open issue" runs-on: ubuntu-slim steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Run Actions script uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: | const script = require(`${process.env.GITHUB_WORKSPACE}/.github/workflows/conda_release.js`) console.log(script({github, context})) ================================================ FILE: .github/workflows/docs.yml ================================================ name: Build docs on: [ push, pull_request ] jobs: docs: runs-on: ubuntu-latest defaults: run: shell: bash -l {0} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: conda-incubator/setup-miniconda@fc2d68f6413eb2d87b895e92f8584b5b94a10167 # v3.3.0 - run: python -m pip install -r docs/requirements.txt - run: python docs/releases.py - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: path: build/docs name: docs - uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: build/docs/all-releases if: startsWith(github.ref, 'refs/tags/') ================================================ FILE: .github/workflows/lint.yml ================================================ name: Lint on: [ pull_request ] jobs: lint: runs-on: ubuntu-slim defaults: run: shell: bash -l {0} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup Miniconda uses: conda-incubator/setup-miniconda@fc2d68f6413eb2d87b895e92f8584b5b94a10167 # v3.3.0 - name: Install dependencies run: | conda install -c conda-forge shellcheck - name: Shellcheck run: | echo "::add-matcher::.github/shellcheck-matcher.json" shellcheck --format=gcc $(find . -iname "*.sh") echo "::remove-matcher owner=shellcheck::" ================================================ FILE: .gitignore ================================================ build/ ================================================ FILE: LICENSE ================================================ Miniforge installer code uses BSD-3-Clause license as stated below. Binary packages that come with it have their own licensing terms and by installing miniforge you agree to the licensing terms of individual packages as well. They include different OSI-approved licenses including the GNU General Public License and can be found in pkgs//info/licenses folders. Miniforge installer comes with a bootstrapping executable that is used when installing miniforge and is deleted after miniforge is installed. The bootstrapping executable uses micromamba, cli11, cpp-filesystem, curl, c-ares, krb5, libarchive, libev, lz4, nghttp2, openssl, libsolv, nlohmann-json, reproc and zstd which are licensed under BSD-3-Clause, MIT and OpenSSL licenses. Licenses and copyright notices of these projects can be found at the following URL. https://github.com/conda-forge/micromamba-feedstock/tree/master/recipe. ============================================================================= Copyright (c) 2019-2022, conda-forge All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: Miniforge3/construct.yaml ================================================ {% set version = os.environ.get("MINIFORGE_VERSION", "26.1.1-2") %} {% set conda_libmamba_solver_version = "25.11.0" %} # This file is parsed by the scripts to define # - `MICROMAMBA_VERSION` in `scripts/build.sh` # - `MAMBA_VERSION` in `scripts/test.sh` {% set mamba_version = "2.5.0" %} name: Miniforge3 version: {{ version }} company: conda-forge channels: # specifying the channel with the full URL adds two channels # when the end user adds the channel without the full URL # - https://conda.anaconda.org/conda-forge - conda-forge mirrored_channels: conda-forge: - "https://conda.anaconda.org/conda-forge" - "https://prefix.dev/conda-forge" write_condarc: True # keep pkgs for space-saving implications for hardlinks when create new environments # and keep the same with Miniconda keep_pkgs: True license_file: {{ os.environ.get("MINIFORGE_LICENSE_OVERRIDE", "../LICENSE") }} # During the interactive installation, these variables are checked. # During batch installation, conda is never initialized initialize_conda: True initialize_by_default: False user_requested_specs: - python 3.13.* - conda >={{ version.split("-")[0] }} - mamba >={{ mamba_version }} - pip # Omit conda-libmamba-solver so that conda is free to remove it later - miniforge_console_shortcut 1.* # [win] specs: - python 3.13.* - conda {{ version.split("-")[0] }} - mamba {{ mamba_version }} - conda-libmamba-solver {{ conda_libmamba_solver_version }} - pip - miniforge_console_shortcut 1.* # [win] virtual_specs: - __glibc >=2.17 # [linux] - __osx >=10.13 # [osx] installer_type: {{ os.environ.get("MINIFORGE_INSTALLER_TYPE", "sh") }} # [unix] installer_type: {{ os.environ.get("MINIFORGE_INSTALLER_TYPE", "exe") }} # [win] # macOS PKG options welcome_image: osx_pkg_background.png # [osx] # Reset everything to system default (no Anaconda stuff) # We can customize it if needed welcome_text: "" # [osx] readme_text: "" # [osx] conclusion_text: "" # [osx] # Signing settings will be added by CI {%- if os.environ.get("APPLE_SIGNING_IDENTITY") %} signing_identity_name: "{{ os.environ["APPLE_SIGNING_IDENTITY"] }}" {%- endif %} {%- if os.environ.get("APPLE_NOTARIZATION_IDENTITY") %} notarization_identity_name: "{{ os.environ["APPLE_NOTARIZATION_IDENTITY"] }}" {%- endif %} ================================================ FILE: README.md ================================================ # Miniforge [![Build miniforge](https://github.com/conda-forge/miniforge/actions/workflows/ci.yml/badge.svg)](https://github.com/conda-forge/miniforge/actions/workflows/ci.yml) [![GitHub downloads](https://img.shields.io/github/downloads/conda-forge/miniforge/total.svg)](https://tooomm.github.io/github-release-stats/?username=conda-forge&repository=miniforge) This repository holds the minimal installers for [Conda](https://conda.io/) and [Mamba](https://github.com/mamba-org/mamba) specific to [conda-forge](https://conda-forge.org/), with the following features pre-configured: * Packages in the base environment are obtained from the [conda-forge channel](https://anaconda.org/conda-forge). * The [conda-forge](https://conda-forge.org/) channel is set as the default (and only) channel. We put an emphasis on supporting various CPU architectures (x86_64, ppc64le, and aarch64 including Apple Silicon) as well as the stability of this installer. ## Goals The goal of this installer is to provide you with an entry point to the conda and mamba commands. If these two commands execute correctly, then this installer has achieved its goal. If you have issues with specific packages, please report them to the associated feedstock. You may find the feedstock associated with a package using our [website](https://conda-forge.org/packages/) ## Usage Miniforge provides installers for the commands [`conda`](https://conda.io/) and [`mamba`](https://github.com/mamba-org/mamba). Once the installer for your OS and architecture has been executed, you should be able to use these commands in a terminal. ### conda/mamba usable in any terminals However, with the default choices of the Windows installer, these commands are only available in the "Miniforge Prompt". To be able to use these commands in other terminals, one needs to initialize conda for your shell by running in the Miniforge Prompt. ```sh conda init ``` Note that one can also just add the `C:\Users\myusername\miniforge3\condabin\` folder to the path environment variable [manually](https://learn.microsoft.com/en-us/previous-versions/office/developer/sharepoint-2010/ee537574(v=office.14)#to-add-a-path-to-the-path-environment-variable) so `conda` and `mamba` may be used more conveniently from any command prompt with limited chance of software conflicts. The same situation arises on Unix if you use the non-interactive install. Initialization can be done by calling conda with its full path, with something like ```sh ~/miniforge3/bin/conda init ``` ### Automatic activation of environments By default, once conda has been initialized for your shell, the `base` environment is activated so that the command `python` corresponds to the base Python provided by Miniforge and `conda install` installs packages in the `base` environment. This can be convenient for but it is cleaner to deactivate this automatic activation with ```sh conda config --set auto_activate_base false ``` and use `conda` or `mamba` to create and activate other environments, with for example (to create an environment called `my_project`) ```sh conda create --name my_project jupyterlab numpy pandas conda activate my_project # Now you can start jupyter lab jupyter lab ``` Finally, it is also possible to add to your shell configuration file (typically `~/.bashrc` or `~/.zshrc` on Unix; on Windows, edit with `notepad $PROFILE`) the activation command. ## Requirements and installers Latest installers with Python 3.12 `(*)` in the base environment: | OS | Architecture | Minimum Version | File | | ------- | ----------------------------- | --------------- | ----------------------------------- | | Linux | x86_64 (amd64) | glibc >= 2.17 | `Miniforge3-Linux-x86_64.sh` | | Linux | aarch64 (arm64) `(**)` | glibc >= 2.17 | `Miniforge3-Linux-aarch64.sh` | | Linux | ppc64le (POWER8/9) | glibc >= 2.17 | `Miniforge3-Linux-ppc64le.sh` | | macOS | x86_64 | macOS >= 10.13 | `Miniforge3-MacOSX-x86_64.{sh,pkg}` | | macOS | arm64 (Apple Silicon) `(***)` | macOS >= 11.0 | `Miniforge3-MacOSX-arm64.{sh,pkg}` | | Windows | x86_64 `(****)` | Windows >= 10 | `Miniforge3-Windows-x86_64.exe` | `(*)` The Python version is specific only to the base environment. Conda can create new environments with different Python versions and implementations. `(**)` For Raspberry PI that include a 64 bit processor, you must also use a 64-bit operating system such as [Raspberry Pi OS 64-bit](https://www.raspberrypi.com/software/operating-systems/#raspberry-pi-os-64-bit) or [Ubuntu for Raspberry PI](https://ubuntu.com/raspberry-pi). The versions listed as "System: 32-bit" are not compatible with the installers on this website. `(***)` Apple silicon builds are experimental and haven't had testing like the other platforms. `(****)` The Windows installer requires Windows 10 or later. However, we are unsure exactly what version of Windows 10. We need [help](https://github.com/conda-forge/miniforge/issues/599) from users to maintain the backlog of windows questions. ## Install ### Windows We [need help](https://github.com/conda-forge/miniforge/issues/599) from activate users and willing maintainers! Download and execute [the Windows installer](https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Windows-x86_64.exe). Follow the prompts, taking note of the option to "Create start menu shortcuts". The most convenient and tested way to use the installed software (such as commands `conda` and `mamba`) is via the "Miniforge Prompt" installed to the start menu. If you require conda to be accessible to other software, you may consider the option to "Add Miniforge3 to my PATH environment variable". The latter is not selected by default due to the potential of serious conflicts with other software. See https://github.com/conda-forge/miniforge/issues/520 and https://github.com/conda-forge/miniforge/issues/453. There are known issues with the usage of special characters and spaces in the installation location, see for example https://github.com/conda-forge/miniforge/issues/484 and https://github.com/conda-forge/miniforge/issues/593. We recommend users install in a directory without any such characters in the name. For non-interactive usage one can use the batch install option: ```sh start /wait "" Miniforge3-Windows-x86_64.exe /InstallationType=JustMe /RegisterPython=0 /S /D=%UserProfile%\Miniforge3 ``` ### Windows Subsystem for Linux (WSL) The Windows Subsystem for Linux (WSL) lets developers use both Windows and Linux at the same time on a Windows machine. WSL users should make sure they are in a Linux terminal window (not Powershell) and use the Linux installer appropriate for the computer's architecture as described in the instructions in the next section. ### Unix-like platforms (macOS, Linux, & WSL) From a terminal window, download the installer appropriate for your computer's architecture using curl or wget or your favorite program. For example: ```sh curl -L -O "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh" ``` or ```sh wget "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh" ``` Run the script with: ```sh bash Miniforge3-$(uname)-$(uname -m).sh ``` The interactive installation will prompt you to initialize conda with your shell. This is typically with recommended workflow. For non-interactive install (for example on a CI), the following command can be used (call with `-h` to list the extra options): ```sh bash Miniforge3-$(uname)-$(uname -m).sh -b ``` In non-interactive installations, the conda initialization commands will not be run by default. Note that Miniforge has been repacked by other package managers such as [Homebrew](https://brew.sh/)(https://formulae.brew.sh/cask/miniforge). However this can lead to many incompatibilities that we do not test for. As such, we do not recommend using Homebrew to install Miniforge. ### macOS (PKG installers) PKG installers are available for macOS as of 2026. They are signed and notarized with NumFOCUS certificates. Download and execute [the PKG installer for Apple Silicon](https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-arm64.pkg). or [Intel](https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-x86_64.pkg), and follow the steps on screen by pressing Continue. By the 4th screen, you can choose a different installation path by clicking on "Change Install Location". Other options may be available behind the "Customise" button. Once ready, click on Install. If everything went according to plan, the Summary page will report success. For unattended installs, please use the SH installers mentioned in the section above. ### As part of a CI pipeline If you wish to download the appropriate installer through the command line in a more automated fashion, you may wish to a command similar to For Linux, any architecture, use the following command ```sh wget -O Miniforge3.sh "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh" ``` For macOS, any architecture, use the following command ```sh curl -fsSLo Miniforge3.sh "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-$(uname -m).sh" ``` This will download the appropriate installer for the present architecture with the filename `Miniforge3.sh`. Run the shell script with the command in batch mode with the `-b` flag: ```sh bash Miniforge3.sh -b -p "${HOME}/conda" ``` `-p` is prefix option. A directory will be created on `"${HOME}/conda"`. Then you should create the path to conda and activate conda. Run this command: ```sh source "${HOME}/conda/etc/profile.d/conda.sh" # For mamba support also run the following command source "${HOME}/conda/etc/profile.d/mamba.sh" ``` Finally, you can run the command to activate the base environment ```sh conda activate ``` ## Uninstall ### Unix-like platforms (macOS & Linux) Uninstalling Miniforge means removing the files that were created during the installation process. You will typically want to remove: 1. Any modifications to your shell rc files that were made by Miniforge: ```sh # Use this first command to see what rc files will be updated conda init --reverse --dry-run # Use this next command to take action on the rc files listed above conda init --reverse # Temporarily IGNORE the shell message # 'For changes to take effect, close and re-open your current shell.', # and CLOSE THE SHELL ONLY AFTER the 3rd step below is completed. ``` 2. Remove the folder and all subfolders where the base environment for Miniforge was installed: ```sh CONDA_BASE_ENVIRONMENT="$(conda info --base)" echo The next command will delete all files in "${CONDA_BASE_ENVIRONMENT}" # Warning, the rm command below is irreversible! # check the output of the echo command above # To make sure you are deleting the correct directory rm -rf "${CONDA_BASE_ENVIRONMENT}" ``` 3. Any global conda configuration files that are left behind. ```sh echo ${HOME}/.condarc will be removed if it exists rm -f "${HOME}/.condarc" echo ${HOME}/.conda and underlying files will be removed if they exist. rm -fr "${HOME}/.conda" ``` ## Features - [X] Automatic build of constructor. - [X] Automatic upload of constructor results. - [X] Automatic testing of constructor. - [ ] Integration with conda-forge's developer documentation. - [x] Integration with conda-forge's official site. ## Testing After construction on the CI, the installer is tested against a range of distribution that match the installer architecture (`$ARCH`). For example when architecture is `aarch64`, the constructed installer is tested against: - Centos 7 - Debian Bullseye (11) - Debian Bookworm (12) - Debian Trixie (13) - Ubuntu 18.04 ([LTS](https://ubuntu.com/about/release-cycle)) - Ubuntu 20.04 ([LTS](https://ubuntu.com/about/release-cycle)) - Ubuntu 22.04 ([LTS](https://ubuntu.com/about/release-cycle)) - Ubuntu 24.04 ([LTS](https://ubuntu.com/about/release-cycle)) ## Building a Miniforge Installer Installers are built and uploaded via the CI but if you want to construct your own Miniforge installer, here is how: ### With Docker ```sh # Configuration export ARCH=aarch64 export DOCKERIMAGE=condaforge/linux-anvil-aarch64 bash build_miniforge.sh ``` ### Without Docker (Linux) ```sh # Configuration export TARGET_PLATFORM=linux-64 bash scripts/build.sh bash scripts/test.sh ``` _Be sure to delete the installation directory after `build/test.sh` has run. You will get installation errors if you run subsequent tests._ ``` ***** Run the installer ***** + chmod +x build/Miniforge3-25.1.1-2-Linux-x86_64.sh ++ uname + [[ Linux == MINGW* ]] + [[ Miniforge3 == \M\i\n\i\f\o\r\g\e\3 ]] + sh build/Miniforge3-25.1.1-2-Linux-x86_64.sh -b -p /home/user001/miniforge ERROR: File or directory already exists: '/home/user001/miniforge' If you want to update an existing installation, use the -u option. ``` ### Without docker (Windows) You must have Git Bash, or some other MINGW64 shell installed on Windows for this to run successfully. ```sh export TARGET_PLATFORM=win-64 bash scripts/build.sh bash scripts/test.sh ``` ## Support for older operating systems ### Support for macOS 10.9-10.12 If you require support for macOS 10.9 through 10.12 you may download version 24.3.0-0 of miniforge available at https://github.com/conda-forge/miniforge/releases/tag/24.3.0-0 ### Support for glibc 2.12-2.16 If you require support for glibc 2.12 through 2.16 you may download version 24.3.0-0 of miniforge available at https://github.com/conda-forge/miniforge/releases/tag/24.3.0-0 ## FAQ ### What's the difference between Mambaforge and Miniforge? After the release of Miniforge 23.3.1 in August 2023, Miniforge and Mambaforge are essentially identical. The only difference is the name of the installer and subsequently the default installation path. Before that release, Miniforge only shipped conda, while Mambaforge added mamba on top. Since Miniconda started shipping conda-libmamba-solver in July 2023, Miniforge followed suit and started shipping it too in August. At that point, since conda-libmamba-solver depends on libmambapy, the only difference between Miniforge and Mambaforge was the presence of the mamba Python package. To minimize surprises, we decided to add mamba to Miniforge too. ### Should I choose one or another going forward at the risk of one of them getting deprecated? As of June 2024, Mambaforge is deprecated and will be retired in January 2025. We recommend users switch to Miniforge3 immediately. For more details, please see the note above. ## Release To release a new version of Miniforge: - Make a new pre-release on GitHub with name `$CONDA_VERSION-$BUILD_NUMBER` - Wait until all artifacts are uploaded by CI - For each build, we upload 3 artifacts 1. One installer with the version name 2. One installer without the version name 3. The SHA256 - At the time of writing, the is a sum of 72 artifacts, and with the two sources, we expect a grand total of 74 artifacts. - Mark the pre-release as a release NOTE: using a pre-release is important to make sure the latest links work. ## License [BSD 3-Clause](./LICENSE) ## History Relevant conversations: - https://github.com/conda-forge/conda-forge.github.io/issues/871#issue-496677528 - https://github.com/conda-forge/conda-forge.github.io/pull/922
🚨 PyPy support is deprecated (Deprecated as of August 2024) 🚨 TL;DR: We are planning to remove PyPy from conda-forge feedstock recipes in a few weeks (and thus to stop building new releases of packages for PyPy), unless there is substantial enough interest to justify the continued maintenance effort. To help with this transition, the latest installers will: * The installer will refuse to proceed every two weeks in October * The installer will refuse to proceed every ten days in November * The installer will refuse to proceed every five days in December * The installer will refuse to proceed in 2025+ ### Miniforge-pypy3 Latest installers with PyPy 3.9 in the base environment are listed below. However, the latest installers will cease to work and will stop being made available in 2025. You should therefore pin to 24.7.0 if you require PyPy3. | OS | Architecture | Minimum Version | Miniforge Version | | ------- | ------------------ | --------------- | -------------------------------------------------------------------------- | | Linux | x86_64 (amd64) | glibc >= 2.17 | [24.9.2-0](https://github.com/conda-forge/miniforge/releases/tag/24.9.2-0) | | Linux | x86_64 (amd64) | glibc >= 2.12 | [24.3.0-0](https://github.com/conda-forge/miniforge/releases/tag/24.3.0-0) | | Linux | aarch64 (arm64) | glibc >= 2.17 | [24.9.2-0](https://github.com/conda-forge/miniforge/releases/tag/24.9.2-0) | | Linux | aarch64 (arm64) | glibc >= 2.12 | [24.3.0-0](https://github.com/conda-forge/miniforge/releases/tag/24.3.0-0) | | Linux | ppc64le (POWER8/9) | glibc >= 2.17 | [24.9.2-0](https://github.com/conda-forge/miniforge/releases/tag/24.9.2-0) | | Linux | ppc64le (POWER8/9) | glibc >= 2.12 | [24.3.0-0](https://github.com/conda-forge/miniforge/releases/tag/24.3.0-0) | | macOS | x86_64 | macOS >= 10.13 | [24.9.2-0](https://github.com/conda-forge/miniforge/releases/tag/24.9.2-0) | | macOS | x86_64 | macOS >= 10.9 | [24.3.0-0](https://github.com/conda-forge/miniforge/releases/tag/24.3.0-0) | | Windows | x86_64 | Windows >= 7 | [24.9.2-0](https://github.com/conda-forge/miniforge/releases/tag/24.9.2-0) |
🚨 Mambaforge (Deprecated as of July 2024) 🚨 Update for July 2024: As of July 2024, `Mambaforge` is deprecated. We suggest users switch to `Miniforge3` immediately. These installers will be retired from new releases after January 2025. To assist in the migration, we will be introducing rollowing brownouts to the latest Mambaforge installer. Installers up to version 24.5.0-1 will not have any brownouts. 24.5.0-1 will include a warning message. Installers 2024.5.0-2 and later will have the following brownout schedule: * The installer will refuse to proceed every two weeks in October * The installer will refuse to proceed every ten days in November * The installer will refuse to proceed every five days in December * The installer will refuse to proceed in 2025+ Previous information: With the [release](https://github.com/conda-forge/miniforge/releases/tag/23.3.1-0) of `Miniforge3-23.3.1-0`, that incorporated the changes in [#277](https://github.com/conda-forge/miniforge/pull/277), the packages and configuration of `Mambaforge` and `Miniforge3` are now **identical**. The only difference between the two is the name of the installer and, subsequently, the default installation directory. We recommend switching to `Miniforge3` immediately. These installers will be retired in January 2025. To assist in the migration to Miniforge3 for CI users, we've stopped the latest Mambaforge (24.5+) installer from proceeding with following schedule * Every two weeks in October * Every ten days in November * Every five days in December * Never in 2025 You can still find the latest installers in the [24.9.2 release](https://github.com/conda-forge/miniforge/releases/tag/24.9.2-0).
================================================ FILE: build_miniforge.sh ================================================ #!/usr/bin/env bash # Build miniforge installers for Linux # on various architectures (aarch64, x86_64, ppc64le) # Notes: # It uses the qemu emulator (see [1] or [2]) to enable # the use of containers images with different architectures than the host # [1]: https://github.com/multiarch/qemu-user-static/ # [2]: https://github.com/tonistiigi/binfmt # See also: [setup-qemu-action](https://github.com/docker/setup-qemu-action) set -ex # Check parameters ARCH=${ARCH:-aarch64} export TARGET_PLATFORM=${TARGET_PLATFORM:-linux-aarch64} DOCKER_ARCH=${DOCKER_ARCH:-arm64/v8} DOCKERIMAGE=${DOCKERIMAGE:-condaforge/linux-anvil-aarch64} OS_NAME=${OS_NAME:-Linux} EXT=${EXT:-sh} TEST_IMAGE_NAMES=${TEST_IMAGE_NAMES:-ubuntu:24.04 ubuntu:22.04 ubuntu:20.04 ubuntu:18.04 centos:7 debian:trixie debian:bookworm debian:bullseye} export CONSTRUCT_ROOT=/construct echo "============= Create build directory =============" mkdir -p build/ chmod 777 build/ echo "============= Enable QEMU =============" # Enable qemu in persistent mode docker run --privileged --rm tonistiigi/binfmt --install all echo "============= Build the installer =============" docker run --rm -v "$(pwd):/construct" \ -e CONSTRUCT_ROOT -e MINIFORGE_VERSION -e TARGET_PLATFORM -e MINIFORGE_LICENSE_OVERRIDE \ "${DOCKERIMAGE}" /construct/scripts/build.sh echo "============= Test the installer =============" for TEST_IMAGE_NAME in ${TEST_IMAGE_NAMES}; do echo "============= Test installer on ${TEST_IMAGE_NAME} =============" docker run --rm \ -v "$(pwd):${CONSTRUCT_ROOT}" -e CONSTRUCT_ROOT \ --platform "linux/${DOCKER_ARCH}" "${DOCKER_ARCH/\//}/${TEST_IMAGE_NAME}" /construct/scripts/test.sh done ================================================ FILE: build_miniforge_osx.sh ================================================ #!/bin/bash set -eux eval "$(PS1="${PS1-}" conda shell.posix activate)" bash scripts/build.sh # shellcheck disable=SC2154 if [[ "${ARCH}" == "$(uname -m)" ]]; then bash scripts/test.sh fi ================================================ FILE: build_miniforge_win.sh ================================================ #!/usr/bin/env bash set -ex conda install posix --yes source scripts/build.sh source scripts/test.sh ================================================ FILE: docs/releases.py ================================================ """render a miniforge releases page""" import jinja2 from pathlib import Path import datetime import sys import requests_cache HERE = Path(__file__).parent BUILD = HERE.parent / "build" DOCS = BUILD / "docs" if not DOCS.exists(): DOCS.mkdir(parents=True) # TODO: handle pagination BASE_URL = "https://api.github.com/repos/conda-forge/miniforge/releases?per_page=100" ENV = jinja2.Environment(loader=jinja2.FileSystemLoader([HERE / "templates"])) def get_releases(): """use the GitHub API to fetch release information""" s = requests_cache.CachedSession(str(BUILD / "cache")) releases = s.get(BASE_URL).json() new_releases = [] for release in releases: if release["draft"] or release["prerelease"]: continue new_assets = [] for asset in release["assets"]: name = asset["name"] if "sha256" in name: continue if release["tag_name"] not in name: continue if release["tag_name"] in asset["name"]: asset["_variant"], os_plat = asset["name"].split( f"""-{release["tag_name"]}-""" ) asset["_os"], asset["_arch"] = os_plat.split(".")[0].split("-") else: raise ValueError(f"Couldn't variant for {name}") asset["_sha256"] = s.get( f"""{asset["browser_download_url"]}.sha256""" ).text.split(" ")[0] new_assets += [asset] release["assets"] = new_assets new_releases += [release] releases = new_releases return releases def render(releases): """render the release page HTML""" context = dict( title="Miniforge Releases", releases=releases, year=datetime.datetime.now().year ) html = ENV.get_template("all-releases.html").render(**context) release_html = DOCS / "all-releases" / "index.html" if not release_html.parent.exists(): release_html.parent.mkdir(parents=True) release_html.write_text(html, encoding="utf-8") def main(): """main entrypoint""" releases = get_releases() render(releases) return 0 if __name__ == "__main__": sys.exit(main()) ================================================ FILE: docs/requirements.txt ================================================ requests_cache jinja2 ================================================ FILE: docs/templates/all-releases.html ================================================ {{ title }}

{{ title }}

{%- for release in releases %} {% if loop.index0 == 0 %}

Latest

{% elif loop.index0 == 1 %}

History

{% endif %}

Miniforge {{ release.tag_name }} #

{%- if loop.index0 %}
{% endif -%} {%- if loop.index0 %}{% endif %} {%- for variant, vassets in release.assets | groupby("_variant") %} {%- set vloop = loop -%} {%- for os, oassets in vassets | groupby("_os") -%} {%- set oloop = loop -%} {%- for arch, aassets in oassets | groupby("_arch") -%} {%- set aloop = loop -%} {% for asset in aassets %} {%- if oloop.index0 + aloop.index0 == 0 %} {%- else -%} {%- endif -%} {%- if aloop.index0 == 0%} {% endif -%} {% endfor -%} {% endfor -%} {% endfor -%} {% endfor -%}
Variant OS Arch Artifact Size SHA256
{{ variant }}
{{ os }} {{ arch }} {{ asset.name }} {{ asset.size | filesizeformat }}
{{ asset._sha256 }}
{% if loop.index0 %}{% endif -%}
{% endfor -%}
================================================ FILE: scripts/build.sh ================================================ #!/usr/bin/env bash set -xe env | sort echo "***** Start: Building Miniforge installer(s) *****" CONSTRUCT_ROOT="${CONSTRUCT_ROOT:-${PWD}}" SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) cd "${CONSTRUCT_ROOT}" echo "***** Install constructor *****" MINIFORGE_CHANNEL_NAME="${MINIFORGE_CHANNEL_NAME:-conda-forge}" mamba install --yes \ --channel "${MINIFORGE_CHANNEL_NAME}" --override-channels \ jinja2 curl libarchive \ "constructor>=3.14.0" if [[ "$(uname)" == "Darwin" ]]; then mamba install --yes \ --channel "${MINIFORGE_CHANNEL_NAME}" --override-channels \ coreutils fi mamba list echo "***** Make temp directory *****" if [[ "$(uname)" == MINGW* ]]; then # LOCALAPPDATA is a reference variable to the user's AppData\Local directory TEMP_DIR=$(mktemp -d --tmpdir="$LOCALAPPDATA/Temp/"); else TEMP_DIR=$(mktemp -d); fi echo "***** Copy file for installer construction *****" cp -R Miniforge3 "${TEMP_DIR}/" cp LICENSE "${TEMP_DIR}/" ls -al "${TEMP_DIR}" if [[ "${TARGET_PLATFORM}" != win-* ]]; then # Assumes specific structure in construct.yaml MICROMAMBA_VERSION=$(grep "set mamba_version" Miniforge3/construct.yaml | cut -d '=' -f 2 | cut -d '"' -f 2) MICROMAMBA_BUILD=1 mkdir "${TEMP_DIR}/micromamba" pushd "${TEMP_DIR}/micromamba" MICROMAMBA_SOURCE_URL="${MICROMAMBA_SOURCE_URL:-https://anaconda.org/conda-forge/micromamba/${MICROMAMBA_VERSION}/download/${TARGET_PLATFORM}/micromamba-${MICROMAMBA_VERSION}-${MICROMAMBA_BUILD}.tar.bz2}" curl -L -O "${MICROMAMBA_SOURCE_URL}" $(which bsdtar || which tar) -xf "micromamba-${MICROMAMBA_VERSION}-${MICROMAMBA_BUILD}.tar.bz2" if [[ "${TARGET_PLATFORM}" == win-* ]]; then MICROMAMBA_FILE="${PWD}/Library/bin/micromamba.exe" else MICROMAMBA_FILE="${PWD}/bin/micromamba" fi popd EXTRA_CONSTRUCTOR_ARGS="${EXTRA_CONSTRUCTOR_ARGS} --conda-exe ${MICROMAMBA_FILE} --platform ${TARGET_PLATFORM}" fi echo "***** Set virtual package versions *****" if [[ "${TARGET_PLATFORM}" == linux-* ]]; then export CONDA_OVERRIDE_GLIBC=2.17 elif [[ "${TARGET_PLATFORM}" == osx-64 ]]; then export CONDA_OVERRIDE_OSX=10.13 elif [[ "${TARGET_PLATFORM}" == osx-arm64 ]]; then export CONDA_OVERRIDE_OSX=11.0 fi echo "***** Construct the installer(s) *****" # Transmutation requires the current directory is writable cd "${TEMP_DIR}" # shellcheck disable=SC2086 constructor "${TEMP_DIR}/Miniforge3/" --output-dir "${TEMP_DIR}" ${EXTRA_CONSTRUCTOR_ARGS} cd - echo "***** Generate installer hash *****" cd "${TEMP_DIR}" ls -alh if [[ "$(uname)" == MINGW* ]]; then EXTS=("exe"); elif [[ "$(uname)" == Darwin ]]; then if [[ "$MINIFORGE_INSTALLER_TYPE" == "all" ]]; then EXTS=("sh" "pkg"); else EXTS=("${MINIFORGE_INSTALLER_TYPE:-sh}") fi else EXTS=("sh"); fi for EXT in "${EXTS[@]}"; do # This line will break if there is more than one installer with extension $EXT in the folder. INSTALLER_PATH=$(find . -name "M*forge*.${EXT}" | head -n 1) if [[ "${EXT}" == "pkg" && -n "${APPLE_NOTARIZATION_KEY_ID:-}" ]]; then # notarize the PKG installer echo "***** Notarizing the PKG installer *****" bash "$SCRIPT_DIR/notarize_osx_pkg.sh" "${INSTALLER_PATH}" fi HASH_PATH="${INSTALLER_PATH}.sha256" sha256sum "${INSTALLER_PATH}" > "${HASH_PATH}" echo "***** Move .$EXT installer and hash to build folder *****" mkdir -p "${CONSTRUCT_ROOT}/build" mv "${INSTALLER_PATH}" "${CONSTRUCT_ROOT}/build/" mv "${HASH_PATH}" "${CONSTRUCT_ROOT}/build/" # copy the installer for latest if [[ "${MINIFORGE_NAME:-}" != "" && "${OS_NAME:-}" != "" && "${ARCH:-}" != "" ]]; then cp "${CONSTRUCT_ROOT}/build/${MINIFORGE_NAME}-"*"-${OS_NAME}-${ARCH}.${EXT}" "${CONSTRUCT_ROOT}/build/${MINIFORGE_NAME}-${OS_NAME}-${ARCH}.${EXT}" fi done cd "${CONSTRUCT_ROOT}" echo "***** Done: Building Miniforge installer(s) *****" ================================================ FILE: scripts/notarize_osx_pkg.sh ================================================ #!/usr/bin/env bash # This script takes a macOS installer package (.pkg) and notarizes + staples it. # It expects the following environment variables to be set: # APPLE_NOTARIZATION_ISSUER_ID: Apple App Store Connect team identifier # APPLE_NOTARIZATION_KEY_ID: Apple App Store Connect API key identifier # APPLE_NOTARIZATION_AUTHKEY_PATH: Apple App Store Connect API AuthKey .p8 file path # These can be obtained in https://appstoreconnect.apple.com/access/users > Integrations set -euxo pipefail if [ -z "${1:-}" ]; then echo "Usage: $0 " exit 1 else INSTALLER_PATH="$1" fi if [ ! -f "$INSTALLER_PATH" ]; then echo "Error: $INSTALLER_PATH does not exist" exit 1 fi if [[ "$(basename "$INSTALLER_PATH")" != *.pkg ]]; then echo "Error: $INSTALLER_PATH is not a .pkg file" exit 1 fi if [ "$(uname)" != "Darwin" ]; then echo "Error: $0 can only be run on macOS" exit 1 fi if ! command -v xcrun >/dev/null; then echo "Error: xcrun is not installed" exit 1 fi if ! command -v stapler >/dev/null; then echo "Error: stapler is not installed" exit 1 fi if [ -z "${APPLE_NOTARIZATION_AUTHKEY_PATH:-}" ]; then echo "Error: APPLE_NOTARIZATION_AUTHKEY_PATH is not set" exit 1 fi if [ -z "${APPLE_NOTARIZATION_KEY_ID:-}" ]; then echo "Error: APPLE_NOTARIZATION_KEY_ID is not set" exit 1 fi if [ -z "${APPLE_NOTARIZATION_ISSUER_ID:-}" ]; then echo "Error: APPLE_NOTARIZATION_ISSUER_ID is not set" exit 1 fi # Check signatures. If this fails, there's no point in attempting notarization. pkgutil --check-signature "$INSTALLER_PATH" # Submit for notarization to Apple servers tmp_output_dir=$(mktemp -d) json_output_file="${tmp_output_dir}/$(basename "$INSTALLER_PATH").notarization.json" set +e xcrun notarytool submit "$INSTALLER_PATH" \ --key "$APPLE_NOTARIZATION_AUTHKEY_PATH" \ --key-id "$APPLE_NOTARIZATION_KEY_ID" \ --issuer "$APPLE_NOTARIZATION_ISSUER_ID" \ --output-format json \ --wait \ --timeout 30m \ | tee "$json_output_file" notary_exit_code=$? set -e if [[ $notary_exit_code != 0 ]]; then submission_id=$(jq -r '.id' "$json_output_file") xcrun notarytool log "$submission_id" \ --key "$APPLE_NOTARIZATION_AUTHKEY_PATH" \ --key-id "$APPLE_NOTARIZATION_KEY_ID" \ --issuer "$APPLE_NOTARIZATION_ISSUER_ID" exit $notary_exit_code fi # Staple xcrun stapler staple --verbose "$INSTALLER_PATH" # Check notarization status spctl --assess -vv --type install "$INSTALLER_PATH" 2>&1 | tee /dev/stderr | grep accepted ================================================ FILE: scripts/osx_pkg_background.py ================================================ """ Run this to generate a macOS PKG background with the conda-forge anvil logo in the bottom left corner """ # needs 'pillow' package from PIL import Image, ImageOps # logo taken from https://github.com/conda-forge/marketing/084d589/main/logo/just_anvil_black.png logo = Image.open("just_anvil_black.png") background = Image.new("RGBA", (1227, 600), (0, 0, 0, 0)) background.paste(ImageOps.contain(logo, (290, 290)), (30, 460)) background.save("osx_pkg_background.png", format="png") ================================================ FILE: scripts/osx_prepare_certificates.sh ================================================ #!/usr/bin/env bash set -euxo pipefail # Import AppleID certificates on macOS # This script is used to import the AppleID certificates into the keychain # It expects the following environment variables to be set: # - APPLE_INSTALLER_CERTIFICATE_BASE64: base64 encoded certificate # - APPLE_INSTALLER_CERTIFICATE_PASSWORD: password for the certificate # - APPLE_APPLICATION_CERTIFICATE_BASE64: base64 encoded certificate # - APPLE_APPLICATION_CERTIFICATE_PASSWORD: password for the certificate # - APPLE_NOTARIZATION_AUTHKEY_BASE64: base64 encoded AppStore Connect API authkey (.p8) # - APPLE_TEMP_KEYCHAIN_PASSWORD: user-generated password for the temporary keychain # Certificates can be generated at https://developer.apple.com/account/resources/certificates/list # create variables TEMP_DIR="$(mktemp -d)" INSTALLER_CERTIFICATE_PATH="$TEMP_DIR/installer_developer_cert.p12" APPLICATION_CERTIFICATE_PATH="$TEMP_DIR/application_developer_cert.p12" NOTARIZATION_AUTHKEY_PATH="$TEMP_DIR/notarization_authkey.p8" KEYCHAIN_PATH="$TEMP_DIR/installer-signing.keychain-db" # import certificate and provisioning profile from secrets echo -n "${APPLE_INSTALLER_CERTIFICATE_BASE64}" | base64 --decode --output "$INSTALLER_CERTIFICATE_PATH" echo -n "${APPLE_APPLICATION_CERTIFICATE_BASE64}" | base64 --decode --output "$APPLICATION_CERTIFICATE_PATH" echo -n "${APPLE_NOTARIZATION_AUTHKEY_BASE64}" | base64 --decode --output "$NOTARIZATION_AUTHKEY_PATH" # create temporary keychain security create-keychain -p "${APPLE_TEMP_KEYCHAIN_PASSWORD}" "$KEYCHAIN_PATH" security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" security unlock-keychain -p "${APPLE_TEMP_KEYCHAIN_PASSWORD}" "$KEYCHAIN_PATH" # import certificate to keychain security import "$INSTALLER_CERTIFICATE_PATH" -P "${APPLE_INSTALLER_CERTIFICATE_PASSWORD}" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH" security import "$APPLICATION_CERTIFICATE_PATH" -P "${APPLE_APPLICATION_CERTIFICATE_PASSWORD}" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH" security list-keychain -d user -s "$KEYCHAIN_PATH" # export identity name to construct.yaml APPLE_SIGNING_IDENTITY=$(security find-identity "$KEYCHAIN_PATH" | grep -m 1 -o '"Developer ID Installer.*"' | tr -d '"') APPLE_NOTARIZATION_IDENTITY=$(security find-identity "$KEYCHAIN_PATH" | grep -m 1 -o '"Developer ID Application.*"' | tr -d '"') export APPLE_SIGNING_IDENTITY export APPLE_NOTARIZATION_IDENTITY export APPLE_NOTARIZATION_AUTHKEY_PATH="$NOTARIZATION_AUTHKEY_PATH" ================================================ FILE: scripts/test.sh ================================================ #!/usr/bin/env bash set -ex echo "***** Start: Testing Miniforge installer *****" CONSTRUCT_ROOT="${CONSTRUCT_ROOT:-${PWD}}" cd "${CONSTRUCT_ROOT}" export CONDA_PATH="${HOME}/miniforge" MAMBA_VERSION=$(grep "set mamba_version" Miniforge3/construct.yaml | cut -d '=' -f 2 | cut -d '"' -f 2) export MAMBA_VERSION echo "***** Get the installer *****" ls build/ if [[ "$(uname)" == MINGW* ]]; then EXT="exe"; else EXT="sh"; fi INSTALLER_PATH=$(find build/ -name "*forge*.${EXT}" | head -n 1) INSTALLER_NAME=$(basename "${INSTALLER_PATH}" | cut -d "-" -f 1) echo "***** Run the installer *****" chmod +x "${INSTALLER_PATH}" if [[ "$(uname)" == MINGW* ]]; then echo "start /wait \"\" ${INSTALLER_PATH} /InstallationType=JustMe /RegisterPython=0 /S /D=$(cygpath -w "${CONDA_PATH}")" > install.bat cmd.exe //c install.bat echo "***** Setup conda *****" # Workaround a conda bug where it uses Unix style separators, but MinGW doesn't understand them export PATH=$CONDA_PATH/Library/bin:$PATH # shellcheck disable=SC1091 source "${CONDA_PATH}/Scripts/activate" conda.exe config --set show_channel_urls true echo "***** Print conda info *****" conda.exe info conda.exe list echo "***** Check if we are bundling packages from msys2 or defaults *****" conda.exe list | grep defaults && exit 1 conda.exe list | grep msys2 && exit 1 echo "***** Check if we can install a package which requires msys2 *****" conda.exe install r-base --yes --quiet conda.exe list else # Test one of our installers in batch mode if [[ "${INSTALLER_NAME}" == "Miniforge3" ]]; then sh "${INSTALLER_PATH}" -b -p "${CONDA_PATH}" # And the other in interactive mode else # Test interactive install. The install will ask the user to # - newline -- read the EULA # - yes -- then accept # - ${CONDA_PATH} -- Then specify the path # - no -- Then whether or not they want to initialize conda cat < stderr.log || cat stderr.log test ! -s stderr.log rm -f stderr.log echo "+ mamba info" mamba info echo "+ mamba config sources" mamba config sources echo "+ mamba config list" mamba config list echo "+ Testing mamba version (i.e. ${MAMBA_VERSION})" mamba info --json | python -c "import sys, json; info = json.loads(sys.stdin.read()); assert info['mamba version'] == '${MAMBA_VERSION}', info" echo " OK" MINIFORGE_CHANNEL_NAME="${MINIFORGE_CHANNEL_NAME:-conda-forge}" echo "+ Testing mamba channels" mamba info --json | python -c "import sys, json; info = json.loads(sys.stdin.read()); assert any('${MINIFORGE_CHANNEL_NAME}' in c for c in info['channels']), info" echo " OK" echo "+ Testing mirrored channels" mamba config list --json | python -c "import sys, json; info = json.loads(sys.stdin.read()); assert info['mirrored_channels']['conda-forge'] == ['https://conda.anaconda.org/conda-forge','https://prefix.dev/conda-forge']" echo "***** Python path *****" python -c "import sys; print(sys.executable)" python -c "import sys; assert 'miniforge' in sys.executable" echo "***** Print system informations from Python *****" python -c "print('Hello Miniforge !')" python -c "import platform; print(platform.architecture())" python -c "import platform; print(platform.system())" python -c "import platform; print(platform.machine())" python -c "import platform; print(platform.release())" echo "***** Done: Testing installer *****" echo "***** Testing the usage of mamba main commands *****" echo "***** Initialize the current session for mamba *****" eval "$(mamba shell hook --shell bash)" echo "***** Create a new environment *****" ENV_PREFIX="/tmp/testenv" mamba create -p $ENV_PREFIX numpy --yes -vvv echo "***** Activate the environment with mamba *****" mamba activate $ENV_PREFIX echo "***** Check that numpy is installed with mamba list *****" mamba list | grep numpy echo "***** Deactivate the environment *****" mamba deactivate echo "***** Activate the environment with conda *****" conda activate $ENV_PREFIX echo "***** Check that numpy is installed with python *****" python -c "import numpy; print(numpy.__version__)" echo "***** Remove numpy *****" mamba remove numpy --yes echo "***** Check that numpy is not installed with mamba list *****" mamba list | grep -v numpy echo "***** Deactivate the environment with conda *****" conda deactivate echo "***** Remove the environment *****" mamba env remove -p $ENV_PREFIX --yes echo "***** Done: Testing mamba main commands *****"