[
  {
    "path": ".github/CODEOWNERS",
    "content": "* @conda-forge/miniforge\n"
  },
  {
    "path": ".github/actions/autoupdate/environment.yml",
    "content": "name: miniconda-autoupdate\nchannels:\n  - conda-forge\n  - nodefaults\ndependencies:\n  - packaging\n  - requests\n"
  },
  {
    "path": ".github/actions/autoupdate/update.py",
    "content": "#!/usr/bin/env python\n\nimport re\nimport requests\nfrom packaging import version\n\ndef get_most_recent_version(name):\n    request = requests.get(\n        \"https://api.anaconda.org/package/conda-forge/\" + name\n    )\n    request.raise_for_status()\n\n    pkg = max(\n        request.json()[\"files\"], key=lambda x: version.parse(x[\"version\"])\n    )\n    return pkg[\"version\"]\n\nmamba_version = get_most_recent_version(\"mamba\")\n\nwith open(\"Miniforge3/construct.yaml\", \"r\") as f:\n    content = f.read()\n\n# Replace mamba version\ncontent = re.sub(r\"mamba [\\d.]+$\", f\"mamba {mamba_version}\", content, flags=re.M)\n\nwith open(\"Miniforge3/construct.yaml\", \"w\") as f:\n    f.write(content)\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"monthly\"\n    groups:\n      github-actions:\n        patterns:\n          - '*'\n"
  },
  {
    "path": ".github/shellcheck-matcher.json",
    "content": "{\n  \"problemMatcher\": [\n    {\n      \"owner\": \"shellcheck\",\n      \"pattern\": [\n        {\n          \"regexp\": \"^(.+):(\\\\d+):(\\\\d+):\\\\s(note|warning|error):\\\\s(.*)\\\\s\\\\[(SC\\\\d+)\\\\]$\",\n          \"file\": 1,\n          \"line\": 2,\n          \"column\": 3,\n          \"message\": 5,\n          \"code\": 6\n        }\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": ".github/workflows/autoupdate.yml",
    "content": "name: Auto-update mamba\non:\n  schedule:\n    - cron: \"0 */6 * * *\"\njobs:\n  createPullRequest:\n    runs-on: ubuntu-slim\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          ssh-key: ${{ secrets.MINIFORGE_AUTOUPDATE_SSH_PRIVATE_KEY }}\n      - uses: conda-incubator/setup-miniconda@fc2d68f6413eb2d87b895e92f8584b5b94a10167 # v3.3.0\n        with:\n          miniforge-version: latest\n          environment-file: .github/actions/autoupdate/environment.yml\n      - run: python .github/actions/autoupdate/update.py\n      - name: Create Pull Request\n        id: cpr\n        # This is the v3 tag but for security purposes we pin to the exact commit.\n        uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0\n        with:\n          commit-message: \"Update mamba version\"\n          title: \"Update mamba version\"\n          body: |\n            This PR was created by the autoupdate action as it detected that\n            the mamba version has changed and thus should be updated\n            in the configuration.\n\n            Due to limitations of Github Actions, you will need to close/reopen\n            the PR to get the actions running.\n          branch: autoupdate-action\n          delete-branch: true\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: Build miniforge\non: [ push, pull_request ]\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    name: Miniforge3-${{ matrix.OS_NAME }}-${{ matrix.ARCH }}\n    runs-on: ${{ matrix.os }}\n    strategy:\n      fail-fast: false\n      matrix:\n        include:\n          - os: windows-latest\n            ARCH: x86_64\n            TARGET_PLATFORM: win-64\n            OS_NAME: \"Windows\"\n\n          - os: macos-latest\n            ARCH: arm64\n            TARGET_PLATFORM: osx-arm64\n            OS_NAME: \"MacOSX\"\n\n          - os: macos-latest\n            ARCH: x86_64\n            TARGET_PLATFORM: osx-64\n            OS_NAME: \"MacOSX\"\n\n          - os: ubuntu-latest\n            ARCH: aarch64\n            TARGET_PLATFORM: linux-aarch64\n            DOCKER_ARCH: arm64/v8\n            DOCKERIMAGE: condaforge/linux-anvil-aarch64\n            OS_NAME: \"Linux\"\n            # Reduce the test matrix because the builds timeouts on emulated architectures\n            # The time consuming operation is an attempt a full solve of conda/mamba/boa\n            # for as a compatibility\n            # xref https://github.com/conda-forge/miniforge/pull/361\n            TEST_IMAGE_NAMES: \"ubuntu:24.04\"\n\n          - os: ubuntu-latest\n            ARCH: x86_64\n            TARGET_PLATFORM: linux-64\n            DOCKER_ARCH: amd64\n            DOCKERIMAGE: condaforge/linux-anvil-cos7-x86_64\n            OS_NAME: \"Linux\"\n\n          - os: ubuntu-latest\n            ARCH: ppc64le\n            TARGET_PLATFORM: linux-ppc64le\n            DOCKER_ARCH: ppc64le\n            DOCKERIMAGE: condaforge/linux-anvil-ppc64le\n            OS_NAME: \"Linux\"\n            # Reduce the test matrix because the builds timeouts on emulated architectures\n            # The time consuming operation is an attempt a full solve of conda/mamba/boa\n            # for as a compatibility\n            # xref https://github.com/conda-forge/miniforge/pull/361\n            TEST_IMAGE_NAMES: \"ubuntu:24.04\"\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - uses: conda-incubator/setup-miniconda@fc2d68f6413eb2d87b895e92f8584b5b94a10167 # v3.3.0\n        with:\n          miniforge-version: \"latest\"\n          use-mamba: true\n        if: ${{ ! contains(matrix.OS_NAME, 'Linux') }}\n\n      - name: Prepare certificates (macOS)\n        if: startsWith(matrix.TARGET_PLATFORM, 'osx-') && github.event_name != 'pull_request'\n        env:\n          APPLE_INSTALLER_CERTIFICATE_BASE64: ${{ secrets.MACOS_CERTIFICATE_INSTALLER_BASE64 }}\n          APPLE_INSTALLER_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_INSTALLER_PASSWORD }}\n          APPLE_APPLICATION_CERTIFICATE_BASE64: ${{ secrets.MACOS_CERTIFICATE_APPLICATION_BASE64 }}\n          APPLE_APPLICATION_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_APPLICATION_PASSWORD }}\n          APPLE_TEMP_KEYCHAIN_PASSWORD: ${{ secrets.MACOS_TEMP_KEYCHAIN_PASSWORD }}\n          APPLE_NOTARIZATION_ISSUER_ID: ${{ secrets.MACOS_NOTARIZATION_ISSUER_ID }}\n          APPLE_NOTARIZATION_KEY_ID: ${{ secrets.MACOS_NOTARIZATION_KEY_ID }}\n          APPLE_NOTARIZATION_AUTHKEY_BASE64: ${{ secrets.MACOS_NOTARIZATION_AUTHKEY_BASE64 }}\n        run: |\n          if [[ \"${APPLE_NOTARIZATION_KEY_ID:-}\" == \"\" ]]; then\n            exit 0  # skip if secrets are not populated\n          fi\n\n          # This script will export APPLE_SIGNING_IDENTITY and APPLE_NOTARIZATION_IDENTITY\n          source scripts/osx_prepare_certificates.sh\n\n          # These will be needed by the build.sh script\n          echo \"APPLE_SIGNING_IDENTITY=$APPLE_SIGNING_IDENTITY\" >> $GITHUB_ENV\n          echo \"APPLE_NOTARIZATION_IDENTITY=$APPLE_NOTARIZATION_IDENTITY\" >> $GITHUB_ENV\n          echo \"APPLE_NOTARIZATION_ISSUER_ID=$APPLE_NOTARIZATION_ISSUER_ID\" >> $GITHUB_ENV\n          echo \"APPLE_NOTARIZATION_KEY_ID=$APPLE_NOTARIZATION_KEY_ID\" >> $GITHUB_ENV\n          echo \"APPLE_NOTARIZATION_AUTHKEY_PATH=$APPLE_NOTARIZATION_AUTHKEY_PATH\" >> $GITHUB_ENV\n\n      - name: Enable PKGs (macOS)\n        if: startsWith(matrix.TARGET_PLATFORM, 'osx-')\n        run: |\n          # This env var is read in construct.yaml; we need 'all' to build both SH and PKG\n          echo \"MINIFORGE_INSTALLER_TYPE=all\" >> $GITHUB_ENV\n\n      - name: Build and test miniforge\n        env:\n          ARCH: ${{ matrix.ARCH }}\n          OS_NAME: ${{ matrix.OS_NAME }}\n          DOCKERIMAGE: ${{ matrix.DOCKERIMAGE }}\n          DOCKER_ARCH: ${{ matrix.DOCKER_ARCH }}\n          TARGET_PLATFORM: ${{ matrix.TARGET_PLATFORM }}\n          TEST_IMAGE_NAMES: ${{ matrix.TEST_IMAGE_NAMES }}\n        run: |\n          if [[ \"$GITHUB_REF\" == refs/tags/* ]]; then\n            export MINIFORGE_VERSION=${GITHUB_REF##*/};\n          fi\n          if [[ \"$OS_NAME\" == \"Linux\" ]]; then\n            export EXT=sh\n            bash build_miniforge.sh;\n          fi\n          if [[ \"$OS_NAME\" == \"MacOSX\" ]]; then\n            export EXT=sh\n            bash build_miniforge_osx.sh;\n          fi\n          if [[ \"$OS_NAME\" == \"Windows\" ]]; then\n            export EXT=exe\n            echo \"WINDIR:$WINDIR\"\n            source \"${CONDA}\"/Scripts/activate;\n            source build_miniforge_win.sh;\n          fi\n          # Copy for latest release\n          cp build/Miniforge3-*-$OS_NAME-$ARCH.$EXT build/Miniforge3-$OS_NAME-$ARCH.$EXT\n          if [[ \"$OS_NAME\" == \"MacOSX\" ]]; then\n            # Copy PKGs too, and alias -MacOSX- to -Darwin-\n            cp build/Miniforge3-*-$OS_NAME-$ARCH.$EXT build/Miniforge3-Darwin-$ARCH.$EXT\n            cp build/Miniforge3-*-$OS_NAME-$ARCH.pkg build/Miniforge3-$OS_NAME-$ARCH.pkg\n            cp build/Miniforge3-*-$OS_NAME-$ARCH.pkg build/Miniforge3-Darwin-$ARCH.pkg\n          fi\n          ls -alh build\n        shell: bash\n\n      - name: Upload miniforge to Github artifact\n        if: always()\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          path: build/Miniforge3-${{ matrix.OS_NAME }}-${{ matrix.ARCH }}*\n          name: Miniforge3-${{ matrix.OS_NAME }}-${{ matrix.ARCH }}\n\n      - name: Upload miniforge to release\n        uses: svenstaro/upload-release-action@b98a3b12e86552593f3e4e577ca8a62aa2f3f22b # v2.11.4\n        with:\n          repo_token: ${{ secrets.GITHUB_TOKEN }}\n          file: build/M*forge*\n          tag: ${{ github.ref }}\n          overwrite: true\n          file_glob: true\n        if: startsWith(github.ref, 'refs/tags/')\n"
  },
  {
    "path": ".github/workflows/conda_release.js",
    "content": "const https = require('https')\nconst options = {\n  hostname: 'api.anaconda.org',\n  port: 443,\n  path: '/package/conda-forge/conda',\n  method: 'GET'\n}\n\nfunction compareVersions(version1, version2) {\n  ver1 = version1.split(\".\").map(Number);\n  ver2 = version2.split(\".\").map(Number);\n\n  const common_length = Math.min(ver1.length, ver2.length);\n  for (var i = 0; i < common_length; ++i) {\n    if (ver1[i] < ver2[i]) {\n      return -1;\n    } else if (ver1[i] > ver2[i]) {\n      return 1;\n    }\n  }\n\n  if (ver1.length > common_length) {\n    return 1;\n  } else if (ver2.length > common_length) {\n    return -1;\n  } else {\n    return 0;\n  }\n}\n\nmodule.exports = ({github, context}) => {\n  const req = https.request(options, res => {\n    var data = '';\n\n    res.on('data', chunk => {\n      data += chunk;\n    });\n\n    res.on('end', function () {\n      versions = JSON.parse(data)[\"files\"].map(x => x[\"version\"]);\n      versions.sort(compareVersions);\n      conda_version = versions.pop();\n\n      github.rest.repos.getLatestRelease({\n        owner: context.repo.owner,\n        repo: context.repo.repo,\n      }).then((release) => {\n        const current_version = release['data']['tag_name'].split(\"-\")[0]\n        if (compareVersions(conda_version, current_version) === 1) {\n          github.rest.issues.listForRepo({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              state: \"open\",\n              labels: \"[bot] conda release\"\n          }).then((issues) => {\n            if (issues.data.length === 0) {\n              github.rest.issues.create({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                title: \"New conda release: please tag a miniforge release\",\n                body: \"A new conda release was found, please tag a new miniforge release with `\" + conda_version + \"-0`\",\n                labels: [\"[bot] conda release\"]\n              })\n            }\n          });\n        }\n      });\n    });\n  })\n\n  req.end();\n}\n"
  },
  {
    "path": ".github/workflows/conda_release.yml",
    "content": "name: Check for new conda releases\non:\n  schedule:\n    - cron: \"0 */6 * * *\"\njobs:\n  check_conda_release:\n    name: \"Check for release and open issue\"\n    runs-on: ubuntu-slim\n    steps:\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n      - name: Run Actions script\n        uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0\n        with:\n          script: |\n            const script = require(`${process.env.GITHUB_WORKSPACE}/.github/workflows/conda_release.js`)\n            console.log(script({github, context}))\n"
  },
  {
    "path": ".github/workflows/docs.yml",
    "content": "name: Build docs\non: [ push, pull_request ]\njobs:\n  docs:\n    runs-on: ubuntu-latest\n    defaults:\n      run:\n        shell: bash -l {0}\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n      - uses: conda-incubator/setup-miniconda@fc2d68f6413eb2d87b895e92f8584b5b94a10167 # v3.3.0\n      - run: python -m pip install -r docs/requirements.txt\n      - run: python docs/releases.py\n      - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          path: build/docs\n          name: docs\n      - uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0\n        with:\n          github_token: ${{ secrets.GITHUB_TOKEN }}\n          publish_dir: build/docs/all-releases\n        if: startsWith(github.ref, 'refs/tags/')\n"
  },
  {
    "path": ".github/workflows/lint.yml",
    "content": "name: Lint\non: [ pull_request ]\njobs:\n  lint:\n    runs-on: ubuntu-slim\n    defaults:\n      run:\n        shell: bash -l {0}\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n      - name: Setup Miniconda\n        uses: conda-incubator/setup-miniconda@fc2d68f6413eb2d87b895e92f8584b5b94a10167 # v3.3.0\n      - name: Install dependencies\n        run: |\n          conda install -c conda-forge shellcheck\n      - name: Shellcheck\n        run: |\n          echo \"::add-matcher::.github/shellcheck-matcher.json\"\n          shellcheck --format=gcc $(find . -iname \"*.sh\")\n          echo \"::remove-matcher owner=shellcheck::\"\n"
  },
  {
    "path": ".gitignore",
    "content": "build/\n"
  },
  {
    "path": "LICENSE",
    "content": "Miniforge installer code uses BSD-3-Clause license as stated below.\n\nBinary packages that come with it have their own licensing terms\nand by installing miniforge you agree to the licensing terms of individual\npackages as well. They include different OSI-approved licenses including\nthe GNU General Public License and can be found in pkgs/<pkg-name>/info/licenses\nfolders.\n\nMiniforge installer comes with a bootstrapping executable that is used\nwhen installing miniforge and is deleted after miniforge is installed.\nThe bootstrapping executable uses micromamba, cli11, cpp-filesystem,\ncurl, c-ares, krb5, libarchive, libev, lz4, nghttp2, openssl, libsolv,\nnlohmann-json, reproc and zstd which are licensed under BSD-3-Clause,\nMIT and OpenSSL licenses. Licenses and copyright notices of these\nprojects can be found at the following URL.\nhttps://github.com/conda-forge/micromamba-feedstock/tree/master/recipe.\n\n=============================================================================\n\nCopyright (c) 2019-2022, conda-forge\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright notice,\nthis list of conditions and the following disclaimer in the documentation\nand/or other materials provided with the distribution.\n\n3. Neither the name of the copyright holder nor the names of its contributors\nmay be used to endorse or promote products derived from this software without\nspecific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "Miniforge3/construct.yaml",
    "content": "{% set version = os.environ.get(\"MINIFORGE_VERSION\", \"26.1.1-2\") %}\n{% set conda_libmamba_solver_version = \"25.11.0\" %}\n# This file is parsed by the scripts to define\n#   - `MICROMAMBA_VERSION` in `scripts/build.sh`\n#   - `MAMBA_VERSION` in `scripts/test.sh`\n{% set mamba_version = \"2.5.0\" %}\n\nname: Miniforge3\nversion: {{ version }}\ncompany: conda-forge\n\nchannels:\n  # specifying the channel with the full URL adds two channels\n  # when the end user adds the channel without the full URL\n  # - https://conda.anaconda.org/conda-forge\n  - conda-forge\n\nmirrored_channels:\n  conda-forge:\n    - \"https://conda.anaconda.org/conda-forge\"\n    - \"https://prefix.dev/conda-forge\"\n\nwrite_condarc: True\n# keep pkgs for space-saving implications for hardlinks when create new environments\n# and keep the same with Miniconda\nkeep_pkgs: True\nlicense_file: {{ os.environ.get(\"MINIFORGE_LICENSE_OVERRIDE\", \"../LICENSE\") }}\n\n# During the interactive installation, these variables are checked.\n# During batch installation, conda is never initialized\ninitialize_conda: True\ninitialize_by_default: False\n\nuser_requested_specs:\n  - python 3.13.*\n  - conda >={{ version.split(\"-\")[0] }}\n  - mamba >={{ mamba_version }}\n  - pip\n  # Omit conda-libmamba-solver so that conda is free to remove it later\n  - miniforge_console_shortcut 1.*  # [win]\n\nspecs:\n  - python 3.13.*\n  - conda {{ version.split(\"-\")[0] }}\n  - mamba {{ mamba_version }}\n  - conda-libmamba-solver {{ conda_libmamba_solver_version }}\n  - pip\n  - miniforge_console_shortcut 1.*  # [win]\n\nvirtual_specs:\n  - __glibc >=2.17 # [linux]\n  - __osx >=10.13 # [osx]\n\ninstaller_type: {{ os.environ.get(\"MINIFORGE_INSTALLER_TYPE\", \"sh\") }}  # [unix]\ninstaller_type: {{ os.environ.get(\"MINIFORGE_INSTALLER_TYPE\", \"exe\") }}  # [win]\n\n# macOS PKG options\nwelcome_image: osx_pkg_background.png  # [osx]\n# Reset everything to system default (no Anaconda stuff)\n# We can customize it if needed\nwelcome_text: \"\"  # [osx]\nreadme_text: \"\"  # [osx]\nconclusion_text: \"\"  # [osx]\n\n# Signing settings will be added by CI\n{%- if os.environ.get(\"APPLE_SIGNING_IDENTITY\") %}\nsigning_identity_name: \"{{ os.environ[\"APPLE_SIGNING_IDENTITY\"] }}\"\n{%- endif %}\n{%- if os.environ.get(\"APPLE_NOTARIZATION_IDENTITY\") %}\nnotarization_identity_name: \"{{ os.environ[\"APPLE_NOTARIZATION_IDENTITY\"] }}\"\n{%- endif %}\n"
  },
  {
    "path": "README.md",
    "content": "# Miniforge\n\n[![Build miniforge](https://github.com/conda-forge/miniforge/actions/workflows/ci.yml/badge.svg)](https://github.com/conda-forge/miniforge/actions/workflows/ci.yml)\n[![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)\n\nThis 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:\n\n* Packages in the base environment are obtained from the [conda-forge channel](https://anaconda.org/conda-forge).\n* The [conda-forge](https://conda-forge.org/) channel is set as the default (and only) channel.\n\nWe put an emphasis on supporting various CPU architectures (x86_64, ppc64le,\nand aarch64 including Apple Silicon) as well as the stability of this\ninstaller.\n\n## Goals\n\nThe goal of this installer is to provide you with an entry point to the\nconda and mamba commands. If these two commands execute correctly, then this\ninstaller has achieved its goal.\n\nIf you have issues with specific packages, please report them to the\nassociated feedstock. You may find the feedstock associated with a package using\nour [website](https://conda-forge.org/packages/)\n\n## Usage\n\nMiniforge provides installers for the commands [`conda`](https://conda.io/) and\n[`mamba`](https://github.com/mamba-org/mamba).  Once the installer for your OS\nand architecture has been executed, you should be able to use these commands in\na terminal.\n\n### conda/mamba usable in any terminals\n\nHowever, with the default choices of the Windows installer, these commands are\nonly available in the \"Miniforge Prompt\". To be able to use these commands in\nother terminals, one needs to initialize conda for your shell by running in\nthe Miniforge Prompt.\n\n```sh\nconda init\n```\n\nNote that one can also just add the `C:\\Users\\myusername\\miniforge3\\condabin\\` folder\nto the path environment variable\n[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)\nso `conda` and `mamba` may be used more conveniently from any command prompt with limited\nchance of software conflicts.\n\nThe same situation arises on Unix if you use the non-interactive install.\nInitialization can be done by calling conda with its full path, with something like\n\n```sh\n~/miniforge3/bin/conda init\n```\n\n### Automatic activation of environments\n\nBy default, once conda has been initialized for your shell, the `base` environment is\nactivated so that the command `python` corresponds to the base Python provided by\nMiniforge and `conda install` installs packages in the `base` environment. This can\nbe convenient for but it is cleaner to deactivate this automatic activation with\n\n```sh\nconda config --set auto_activate_base false\n```\n\nand use `conda` or `mamba` to create and activate other environments, with for example\n(to create an environment called `my_project`)\n\n```sh\nconda create --name my_project jupyterlab numpy pandas\nconda activate my_project\n# Now you can start jupyter lab\njupyter lab\n```\n\nFinally, it is also possible to add to your shell configuration file\n(typically `~/.bashrc` or `~/.zshrc` on Unix;\non Windows, edit with `notepad $PROFILE`) the activation command.\n\n## Requirements and installers\n\nLatest installers with Python 3.12 `(*)` in the base environment:\n\n| OS      | Architecture                  | Minimum Version | File                                |\n| ------- | ----------------------------- | --------------- | ----------------------------------- |\n| Linux   | x86_64 (amd64)                | glibc >= 2.17   | `Miniforge3-Linux-x86_64.sh`        |\n| Linux   | aarch64 (arm64) `(**)`        | glibc >= 2.17   | `Miniforge3-Linux-aarch64.sh`       |\n| Linux   | ppc64le (POWER8/9)            | glibc >= 2.17   | `Miniforge3-Linux-ppc64le.sh`       |\n| macOS   | x86_64                        | macOS >= 10.13  | `Miniforge3-MacOSX-x86_64.{sh,pkg}` |\n| macOS   | arm64 (Apple Silicon) `(***)` | macOS >= 11.0   | `Miniforge3-MacOSX-arm64.{sh,pkg}`  |\n| Windows | x86_64 `(****)`               | Windows >= 10   | `Miniforge3-Windows-x86_64.exe`     |\n\n`(*)` The Python version is specific only to the base environment. Conda can create new environments with different Python versions and implementations.\n\n`(**)` For Raspberry PI that include a 64 bit processor, you must also use\na 64-bit operating system such as\n[Raspberry Pi OS 64-bit](https://www.raspberrypi.com/software/operating-systems/#raspberry-pi-os-64-bit)\nor\n[Ubuntu for Raspberry PI](https://ubuntu.com/raspberry-pi).\nThe versions listed as \"System: 32-bit\" are not compatible with the installers on this website.\n\n`(***)` Apple silicon builds are experimental and haven't had testing like the other platforms.\n\n`(****)` The Windows installer requires Windows 10 or later. However, we are unsure exactly what version of Windows 10.\nWe need [help](https://github.com/conda-forge/miniforge/issues/599) from users to maintain the backlog of windows questions.\n\n## Install\n\n### Windows\n\nWe [need help](https://github.com/conda-forge/miniforge/issues/599) from activate users and willing maintainers!\n\nDownload and execute [the Windows installer](https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Windows-x86_64.exe).\nFollow the prompts, taking note of the option to\n\"Create start menu shortcuts\".\nThe most convenient and tested way to use the installed software\n(such as commands `conda` and `mamba`)\nis via the \"Miniforge Prompt\" installed to the start menu.\n\nIf you require conda to be accessible to other software,\nyou may consider the option to \"Add Miniforge3 to my PATH environment variable\".\nThe latter is not selected by default due to the potential of serious conflicts\nwith other software. See https://github.com/conda-forge/miniforge/issues/520 and\nhttps://github.com/conda-forge/miniforge/issues/453.\n\nThere are known issues with the usage of special characters and spaces in\nthe installation location, see for example\nhttps://github.com/conda-forge/miniforge/issues/484 and\nhttps://github.com/conda-forge/miniforge/issues/593.\nWe recommend users install in a directory without any such characters in the name.\n\nFor non-interactive usage one can use the batch install option:\n\n```sh\nstart /wait \"\" Miniforge3-Windows-x86_64.exe /InstallationType=JustMe /RegisterPython=0 /S /D=%UserProfile%\\Miniforge3\n```\n### Windows Subsystem for Linux (WSL)\nThe Windows Subsystem for Linux (WSL) lets developers use both Windows and Linux at the same time on a Windows machine.\nWSL 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.\n\n### Unix-like platforms (macOS, Linux, & WSL)\nFrom a terminal window, download the installer appropriate for your computer's architecture using curl or wget or your favorite program.\n\nFor example:\n\n```sh\ncurl -L -O \"https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh\"\n```\n\nor\n\n```sh\nwget \"https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh\"\n```\n\nRun the script with:\n\n```sh\nbash Miniforge3-$(uname)-$(uname -m).sh\n```\n\nThe interactive installation will prompt you to initialize conda with your shell.\nThis is typically with recommended workflow.\n\nFor non-interactive install (for example on a CI), the following command can be used\n(call with `-h` to list the extra options):\n\n```sh\nbash Miniforge3-$(uname)-$(uname -m).sh -b\n```\n\nIn non-interactive installations, the conda initialization commands will not be run by default.\n\n\nNote that Miniforge has been repacked by other package managers such as [Homebrew](https://brew.sh/)(https://formulae.brew.sh/cask/miniforge).\nHowever this can lead to many incompatibilities that we do not test for. As such, we do not recommend using Homebrew to install Miniforge.\n\n### macOS (PKG installers)\n\nPKG installers are available for macOS as of 2026. They are signed and notarized with NumFOCUS certificates.\nDownload and execute [the PKG installer for Apple Silicon](https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-arm64.pkg).\nor [Intel](https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-x86_64.pkg),\nand follow the steps on screen by pressing Continue.\n\nBy the 4th screen, you can choose a different installation path by clicking on \"Change Install Location\".\nOther options may be available behind the \"Customise\" button.\n\nOnce ready, click on Install. If everything went according to plan, the Summary page will report success.\n\nFor unattended installs, please use the SH installers mentioned in the section above.\n\n### As part of a CI pipeline\n\nIf you wish to download the appropriate installer through the command line in a\nmore automated fashion, you may wish to a command similar to\n\nFor Linux, any architecture, use the following command\n\n```sh\nwget -O Miniforge3.sh \"https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh\"\n```\n\nFor macOS, any architecture, use the following command\n\n```sh\ncurl -fsSLo Miniforge3.sh \"https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-$(uname -m).sh\"\n```\n\nThis will download the appropriate installer for the present architecture with\nthe filename `Miniforge3.sh`. Run the shell script with the command in batch\nmode with the `-b` flag:\n\n```sh\nbash Miniforge3.sh -b -p \"${HOME}/conda\"\n```\n\n`-p` is prefix option. A directory will be created on `\"${HOME}/conda\"`.\n\nThen you should create the path to conda and activate conda.\nRun this command:\n\n```sh\nsource \"${HOME}/conda/etc/profile.d/conda.sh\"\n# For mamba support also run the following command\nsource \"${HOME}/conda/etc/profile.d/mamba.sh\"\n```\n\nFinally, you can run the command to activate the base environment\n\n```sh\nconda activate\n```\n\n\n## Uninstall\n\n### Unix-like platforms (macOS & Linux)\n\nUninstalling Miniforge means removing the files that were created during the installation process.\nYou will typically want to remove:\n\n1. Any modifications to your shell rc files that were made by Miniforge:\n\n```sh\n# Use this first command to see what rc files will be updated\nconda init --reverse --dry-run\n# Use this next command to take action on the rc files listed above\nconda init --reverse\n# Temporarily IGNORE the shell message\n#       'For changes to take effect, close and re-open your current shell.',\n# and CLOSE THE SHELL ONLY AFTER the 3rd step below is completed.\n```\n\n2. Remove the folder and all subfolders where the base environment for Miniforge was installed:\n\n```sh\nCONDA_BASE_ENVIRONMENT=\"$(conda info --base)\"\necho The next command will delete all files in \"${CONDA_BASE_ENVIRONMENT}\"\n# Warning, the rm command below is irreversible!\n# check the output of the echo command above\n# To make sure you are deleting the correct directory\nrm -rf \"${CONDA_BASE_ENVIRONMENT}\"\n```\n\n3. Any global conda configuration files that are left behind.\n\n```sh\necho ${HOME}/.condarc will be removed if it exists\nrm -f \"${HOME}/.condarc\"\necho ${HOME}/.conda and underlying files will be removed if they exist.\nrm -fr \"${HOME}/.conda\"\n```\n\n\n## Features\n\n- [X] Automatic build of constructor.\n- [X] Automatic upload of constructor results.\n- [X] Automatic testing of constructor.\n- [ ] Integration with conda-forge's developer documentation.\n- [x] Integration with conda-forge's official site.\n\n\n## Testing\n\nAfter 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:\n\n- Centos 7\n- Debian Bullseye (11)\n- Debian Bookworm (12)\n- Debian Trixie (13)\n- Ubuntu 18.04 ([LTS](https://ubuntu.com/about/release-cycle))\n- Ubuntu 20.04 ([LTS](https://ubuntu.com/about/release-cycle))\n- Ubuntu 22.04 ([LTS](https://ubuntu.com/about/release-cycle))\n- Ubuntu 24.04 ([LTS](https://ubuntu.com/about/release-cycle))\n\n## Building a Miniforge Installer\n\nInstallers are built and uploaded via the CI but if you want to construct your own Miniforge installer, here is how:\n\n### With Docker\n```sh\n# Configuration\nexport ARCH=aarch64\nexport DOCKERIMAGE=condaforge/linux-anvil-aarch64\n\nbash build_miniforge.sh\n```\n\n### Without Docker (Linux)\n```sh\n# Configuration\nexport TARGET_PLATFORM=linux-64\n\nbash scripts/build.sh\nbash scripts/test.sh\n```\n_Be sure to delete the installation directory after `build/test.sh` has run. You will get installation errors if you run subsequent tests._\n```\n***** Run the installer *****\n+ chmod +x build/Miniforge3-25.1.1-2-Linux-x86_64.sh\n++ uname\n+ [[ Linux == MINGW* ]]\n+ [[ Miniforge3 == \\M\\i\\n\\i\\f\\o\\r\\g\\e\\3 ]]\n+ sh build/Miniforge3-25.1.1-2-Linux-x86_64.sh -b -p /home/user001/miniforge\nERROR: File or directory already exists: '/home/user001/miniforge'\nIf you want to update an existing installation, use the -u option.\n```\n\n### Without docker (Windows)\nYou must have Git Bash, or some other MINGW64 shell installed on Windows for this to run successfully.\n```sh\nexport TARGET_PLATFORM=win-64\n\nbash scripts/build.sh\nbash scripts/test.sh\n```\n\n## Support for older operating systems\n\n### Support for macOS 10.9-10.12\n\nIf you require support for macOS 10.9 through 10.12 you may download version\n24.3.0-0 of miniforge available at\nhttps://github.com/conda-forge/miniforge/releases/tag/24.3.0-0\n\n### Support for glibc 2.12-2.16\n\nIf you require support for glibc 2.12 through 2.16 you may download version\n24.3.0-0 of miniforge available at\nhttps://github.com/conda-forge/miniforge/releases/tag/24.3.0-0\n\n\n## FAQ\n\n### What's the difference between Mambaforge and Miniforge?\n\nAfter the release of Miniforge 23.3.1 in August 2023, Miniforge and Mambaforge\nare essentially identical. The only difference is the name of the installer and\nsubsequently the default installation path.\n\nBefore that release, Miniforge only shipped conda, while Mambaforge added mamba\non top. Since Miniconda started shipping conda-libmamba-solver in July 2023,\nMiniforge followed suit and started shipping it too in August. At that point,\nsince conda-libmamba-solver depends on libmambapy, the only difference between\nMiniforge and Mambaforge was the presence of the mamba Python package. To\nminimize surprises, we decided to add mamba to Miniforge too.\n\n### Should I choose one or another going forward at the risk of one of them getting deprecated?\n\nAs of June 2024, Mambaforge is deprecated and will be retired in January 2025.\nWe recommend users switch to Miniforge3 immediately. For more details, please\nsee the note above.\n\n\n## Release\n\nTo release a new version of Miniforge:\n\n- Make a new pre-release on GitHub with name `$CONDA_VERSION-$BUILD_NUMBER`\n- Wait until all artifacts are uploaded by CI\n  - For each build, we upload 3 artifacts\n    1. One installer with the version name\n    2. One installer without the version name\n    3. The SHA256\n  - 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.\n- Mark the pre-release as a release\n\nNOTE: using a pre-release is important to make sure the latest links work.\n\n\n## License\n\n[BSD 3-Clause](./LICENSE)\n\n\n## History\n\nRelevant conversations:\n\n- https://github.com/conda-forge/conda-forge.github.io/issues/871#issue-496677528\n- https://github.com/conda-forge/conda-forge.github.io/pull/922\n\n\n<details>\n\n<summary>🚨 PyPy support is deprecated (<b>Deprecated</b> as of August 2024) 🚨</summary>\n\nTL;DR: We are planning to remove PyPy from conda-forge feedstock recipes in a\nfew weeks (and thus to stop building new releases of packages for PyPy), unless\nthere is substantial enough interest to justify the continued maintenance\neffort.\n\nTo help with this transition, the latest installers will:\n\n* The installer will refuse to proceed every two weeks in October\n* The installer will refuse to proceed every ten days in November\n* The installer will refuse to proceed every five days in December\n* The installer will refuse to proceed in 2025+\n\n### Miniforge-pypy3\n\nLatest installers with PyPy 3.9 in the base environment are listed below.\nHowever, the latest installers will cease to work and will stop being made available in 2025.\nYou should therefore pin to 24.7.0 if you require PyPy3.\n\n| OS      | Architecture       | Minimum Version | Miniforge Version                                                          |\n| ------- | ------------------ | --------------- | -------------------------------------------------------------------------- |\n| Linux   | x86_64 (amd64)     | glibc >= 2.17   | [24.9.2-0](https://github.com/conda-forge/miniforge/releases/tag/24.9.2-0) |\n| Linux   | x86_64 (amd64)     | glibc >= 2.12   | [24.3.0-0](https://github.com/conda-forge/miniforge/releases/tag/24.3.0-0) |\n| Linux   | aarch64 (arm64)    | glibc >= 2.17   | [24.9.2-0](https://github.com/conda-forge/miniforge/releases/tag/24.9.2-0) |\n| Linux   | aarch64 (arm64)    | glibc >= 2.12   | [24.3.0-0](https://github.com/conda-forge/miniforge/releases/tag/24.3.0-0) |\n| Linux   | ppc64le (POWER8/9) | glibc >= 2.17   | [24.9.2-0](https://github.com/conda-forge/miniforge/releases/tag/24.9.2-0) |\n| Linux   | ppc64le (POWER8/9) | glibc >= 2.12   | [24.3.0-0](https://github.com/conda-forge/miniforge/releases/tag/24.3.0-0) |\n| macOS   | x86_64             | macOS >= 10.13  | [24.9.2-0](https://github.com/conda-forge/miniforge/releases/tag/24.9.2-0) |\n| macOS   | x86_64             | macOS >= 10.9   | [24.3.0-0](https://github.com/conda-forge/miniforge/releases/tag/24.3.0-0) |\n| Windows | x86_64             | Windows >= 7    | [24.9.2-0](https://github.com/conda-forge/miniforge/releases/tag/24.9.2-0) |\n\n</details>\n\n<details>\n\n<summary>🚨 Mambaforge (<b>Deprecated</b> as of July 2024) 🚨</summary>\n\nUpdate for July 2024:\n\nAs of July 2024, `Mambaforge` is deprecated. We suggest users switch to\n`Miniforge3` immediately. These installers will be retired from new releases\nafter January 2025. To assist in the migration, we will be introducing rollowing\nbrownouts to the latest Mambaforge installer. Installers up to version 24.5.0-1\nwill not have any brownouts. 24.5.0-1 will include a warning message.\nInstallers 2024.5.0-2 and later will have the following brownout schedule:\n\n* The installer will refuse to proceed every two weeks in October\n* The installer will refuse to proceed every ten days in November\n* The installer will refuse to proceed every five days in December\n* The installer will refuse to proceed in 2025+\n\nPrevious information:\n\nWith the [release](https://github.com/conda-forge/miniforge/releases/tag/23.3.1-0) of\n`Miniforge3-23.3.1-0`, that incorporated the changes in\n[#277](https://github.com/conda-forge/miniforge/pull/277), the packages and\nconfiguration of `Mambaforge` and `Miniforge3` are now **identical**. The\nonly difference between the two is the name of the installer and, subsequently,\nthe default installation directory.\n\nWe recommend switching to `Miniforge3` immediately. These installers will be\nretired in January 2025. To assist in the migration to Miniforge3 for CI users, we've stopped\nthe latest Mambaforge (24.5+) installer from proceeding with following schedule\n\n* Every two weeks in October\n* Every ten days in November\n* Every five days in December\n* Never in 2025\n\nYou can still find the latest installers in the [24.9.2 release](https://github.com/conda-forge/miniforge/releases/tag/24.9.2-0).\n\n</details>\n"
  },
  {
    "path": "build_miniforge.sh",
    "content": "#!/usr/bin/env bash\n# Build miniforge installers for Linux\n# on various architectures (aarch64, x86_64, ppc64le)\n# Notes:\n# It uses the qemu emulator (see [1] or [2]) to enable\n# the use of containers images with different architectures than the host\n# [1]: https://github.com/multiarch/qemu-user-static/\n# [2]: https://github.com/tonistiigi/binfmt\n# See also: [setup-qemu-action](https://github.com/docker/setup-qemu-action)\nset -ex\n\n# Check parameters\nARCH=${ARCH:-aarch64}\nexport TARGET_PLATFORM=${TARGET_PLATFORM:-linux-aarch64}\nDOCKER_ARCH=${DOCKER_ARCH:-arm64/v8}\nDOCKERIMAGE=${DOCKERIMAGE:-condaforge/linux-anvil-aarch64}\nOS_NAME=${OS_NAME:-Linux}\nEXT=${EXT:-sh}\nTEST_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}\nexport CONSTRUCT_ROOT=/construct\n\necho \"============= Create build directory =============\"\nmkdir -p build/\nchmod 777 build/\n\necho \"============= Enable QEMU =============\"\n# Enable qemu in persistent mode\ndocker run --privileged --rm tonistiigi/binfmt --install all\n\necho \"============= Build the installer =============\"\ndocker run --rm -v \"$(pwd):/construct\" \\\n  -e CONSTRUCT_ROOT -e MINIFORGE_VERSION -e TARGET_PLATFORM -e MINIFORGE_LICENSE_OVERRIDE \\\n  \"${DOCKERIMAGE}\" /construct/scripts/build.sh\n\necho \"============= Test the installer =============\"\nfor TEST_IMAGE_NAME in ${TEST_IMAGE_NAMES}; do\n  echo \"============= Test installer on ${TEST_IMAGE_NAME} =============\"\n  docker run --rm \\\n    -v \"$(pwd):${CONSTRUCT_ROOT}\" -e CONSTRUCT_ROOT \\\n     --platform \"linux/${DOCKER_ARCH}\" \"${DOCKER_ARCH/\\//}/${TEST_IMAGE_NAME}\" /construct/scripts/test.sh\ndone\n"
  },
  {
    "path": "build_miniforge_osx.sh",
    "content": "#!/bin/bash\n\nset -eux\n\neval \"$(PS1=\"${PS1-}\" conda shell.posix activate)\"\n\nbash scripts/build.sh\n# shellcheck disable=SC2154\nif [[ \"${ARCH}\" == \"$(uname -m)\" ]]; then\n  bash scripts/test.sh\nfi\n"
  },
  {
    "path": "build_miniforge_win.sh",
    "content": "#!/usr/bin/env bash\n\nset -ex\n\nconda install posix --yes\nsource scripts/build.sh\nsource scripts/test.sh\n"
  },
  {
    "path": "docs/releases.py",
    "content": "\"\"\"render a miniforge releases page\"\"\"\nimport jinja2\nfrom pathlib import Path\nimport datetime\nimport sys\nimport requests_cache\n\nHERE = Path(__file__).parent\nBUILD = HERE.parent / \"build\"\nDOCS = BUILD / \"docs\"\n\nif not DOCS.exists():\n    DOCS.mkdir(parents=True)\n\n# TODO: handle pagination\nBASE_URL = \"https://api.github.com/repos/conda-forge/miniforge/releases?per_page=100\"\nENV = jinja2.Environment(loader=jinja2.FileSystemLoader([HERE / \"templates\"]))\n\n\ndef get_releases():\n    \"\"\"use the GitHub API to fetch release information\"\"\"\n    s = requests_cache.CachedSession(str(BUILD / \"cache\"))\n    releases = s.get(BASE_URL).json()\n\n    new_releases = []\n\n    for release in releases:\n        if release[\"draft\"] or release[\"prerelease\"]:\n            continue\n        new_assets = []\n        for asset in release[\"assets\"]:\n            name = asset[\"name\"]\n            if \"sha256\" in name:\n                continue\n            if release[\"tag_name\"] not in name:\n                continue\n            if release[\"tag_name\"] in asset[\"name\"]:\n                asset[\"_variant\"], os_plat = asset[\"name\"].split(\n                    f\"\"\"-{release[\"tag_name\"]}-\"\"\"\n                )\n                asset[\"_os\"], asset[\"_arch\"] = os_plat.split(\".\")[0].split(\"-\")\n            else:\n                raise ValueError(f\"Couldn't variant for {name}\")\n            asset[\"_sha256\"] = s.get(\n                f\"\"\"{asset[\"browser_download_url\"]}.sha256\"\"\"\n            ).text.split(\" \")[0]\n            new_assets += [asset]\n        release[\"assets\"] = new_assets\n        new_releases += [release]\n    releases = new_releases\n    return releases\n\n\ndef render(releases):\n    \"\"\"render the release page HTML\"\"\"\n    context = dict(\n        title=\"Miniforge Releases\", releases=releases, year=datetime.datetime.now().year\n    )\n    html = ENV.get_template(\"all-releases.html\").render(**context)\n\n    release_html = DOCS / \"all-releases\" / \"index.html\"\n\n    if not release_html.parent.exists():\n        release_html.parent.mkdir(parents=True)\n\n    release_html.write_text(html, encoding=\"utf-8\")\n\n\ndef main():\n    \"\"\"main entrypoint\"\"\"\n    releases = get_releases()\n    render(releases)\n    return 0\n\n\nif __name__ == \"__main__\":\n    sys.exit(main())\n"
  },
  {
    "path": "docs/requirements.txt",
    "content": "requests_cache\njinja2\n"
  },
  {
    "path": "docs/templates/all-releases.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <title>{{ title }}</title>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <meta name=\"Description\" content=\"Download page for latest and historical Miniforge releases\">\n  </head>\n  <style>\n    :root {\n      --cf-border-color: solid 1px rgba(255,255,255,0.25);\n      --cf-link-color: rgb(66, 220, 163);\n      --cf-anvil-img: url('data:image/svg+xml;base64,CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjQgMjQiPgo8cGF0aCBmaWxsPSIjZmZmIiBkPSJNOC4yMDYgNS44NjZsLjAwNS4zOTZINi43NTRsLjAwNi42NTV2LjAwNWwtNi43NTguMDAydi4yMTFMMCA3Ljk3M2wuMDIuMDQxYy4yMTIuNDY3LjY2My45MDEgMS4yNTcgMS4zMTMuNTk0LjQxMSAxLjMzNS43OTYgMi4xNDUgMS4xMyAxLjYyLjY2NCAzLjUwMiAxLjEyIDUuMDA2IDEuMS43NDYtLjAxIDEuMjY1LjIyOCAxLjYyLjY3Mi4zNDEuNDI2LjUxIDEuMDkyLjUyNCAxLjkyTDcuOTQgMTYuMjM5bC4wMDggMS44OTZIMjAuMjlsLS4wMDQtMS43Ni0yLjYzLTIuMjJjLjA1NS0yLjAxMy43MDgtMy40NDMgMS43NzctNC40MDUgMS4wODctLjk3OSAyLjYxLTEuNDkgNC4zNy0xLjYxNmwuMTk1LS4wMTVMMjQgNS44NzJ6bS40MjUuNDIybDE0Ljk0Ni4wMDYtLjAwNCAxLjQ1N2MtMS43MzcuMTU1LTMuMjkuNjY2LTQuNDI0IDEuNjg1LS45MTIuODIyLTEuNDMzIDIuMDYyLTEuNjkxIDMuNTM0bC0xLjYxNy4wMDQuMDAyLjQyMiAxLjUzNS0uMDA0Yy0uMDI3LjIyNi0uMTEzLjQtLjEyMy42NGwtLjg5My0uMDAzLS4wMDIuNDIyLjk5NS4wMDQgMi4xMzggMS44MDItMi45NDEuMDAyYy0uNzI0LS42NzUtMS41NTItMS4xMTYtMi40MTYtMS4xNTgtLjgxNy0uMDQtMS42MzguMzI0LTIuMzg3IDEuMDRsLTIuOTc4LS4wMjQgMi4yNDgtMS43ODF2LS4xMDJjLjAwMi0uOTQzLS4yLTEuNzItLjY0LTIuMjY5LS4zOTYtLjQ5Ni0xLjAwNy0uNzQ5LTEuNzQxLS43OWwtLjAwOC00LjQ5aC4wMDh6bS0xLjQ1LjM5NmgxLjAyNmwuMDA4IDQuNDA0Yy0xLjM4Ny0uMDItMy4xMjUtLjQwNC00LjYzMS0xLjAyMy0uNzg3LS4zMjQtMS41MDctLjY5OC0yLjA2Ni0xLjA4NkMuOTY4IDguNi41ODcgOC4yMDMuNDI0IDcuODZ2LS41MTRsNi4zMzYtLjAwMnYyLjE2aC40MjJ2LTIuMTZoLjAwNGwtLjAwNC0uNDM1di0uMjI2em02LjkzNSA4LjgzOWMuNzUuMDM3IDEuNTAzLjQzNiAyLjE4IDEuMDc4bC0uMDAyIDEuMTEyaC00LjM0NWwtLjAwNi0xLjJjLjcwNi0uNzE3IDEuNDQzLTEuMDI2IDIuMTczLS45OXpNOC4zNiAxNi41MzdsMy4xNi4wMjMuMDA2IDEuMTUzaC0zLjE2em0xMS41LjE0MmwuMDAyIDEuMDM0aC0zLjE0OFYxNi42OHoiLz4KPC9zdmc+Cg==');\n      --cf-padding: 2em;\n    }\n    body {\n      font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n      padding: 0;\n      margin: 0;\n      font-size: 15px;\n      line-height: 1.5;\n      box-sizing: border-box;\n      color: #fff;\n      background-color: #000;\n    }\n    header {\n      background-color: #000;\n      padding: 0 var(--cf-padding);\n      color: #fff;\n      z-index: 1;\n      border-bottom: solid 1px var(--cf-link-color);\n      display: flex;\n      align-items: center;\n      position: sticky;\n      top: 0;\n    }\n    article, h2 {\n      scroll-margin-top: 6rem;\n    }\n    footer {\n      border-top: solid 1px var(--cf-link-color);\n      background-color: #000;\n      padding: var(--cf-padding);\n      text-align: center;\n    }\n    h1 {\n      background-image: var(--cf-anvil-img);\n      background-repeat: no-repeat;\n      padding-left: 2em;\n    }\n    nav {\n      flex: 1;\n      display: flex;\n      flex-wrap: wrap;\n    }\n    nav ul {\n      flex: 1;\n      display: flex;\n    }\n    nav ul:last-child {\n      flex: 0;\n    }\n    nav ul li {\n      flex: 0;\n      list-style: none;\n    }\n    nav ul li a {\n      padding: 0.5em var(--cf-padding);\n      font-size: 150%;\n    }\n    main {\n      padding: var(--cf-padding);\n      background-color: rgba(255,255,255,0.05);\n    }\n    a, a code {\n      text-decoration: none;\n      color: var(--cf-link-color);\n    }\n    a:hover {\n      text-decoration: underline;\n    }\n    table {\n      border-collapse: collapse;\n      margin: auto;\n    }\n    td, th {\n      padding: 0.1em 0.5em;\n      vertical-align: center;\n    }\n    tbody tr:nth-child(odd) {\n      background-color: rgba(255,255,255,.05);\n    }\n    table pre {\n      white-space: nowrap;\n      overflow: hidden;\n      text-overflow: ellipsis;\n      display: inline-block;\n      max-width: 6em;\n      margin: 0;\n    }\n    label {\n      font-style: italic;\n    }\n    tr.variant-row {\n      border-top: var(--cf-border-color);\n    }\n    tr td, tr th {\n      border-bottom: var(--cf-border-color);\n    }\n\n    tr:hover td {\n      border-bottom: solid 1px var(--cf-link-color);\n    }\n    td:nth-last-child(2) {\n      text-align: right;\n    }\n  </style>\n  <body>\n    <header>\n      <h1>{{ title }}</h1>\n      <nav>\n        <ul>\n          <li><a href=\"#latest-release\">Latest</a></li>\n          <li><a href=\"#history\">History</a></li>\n        </ul>\n        <ul>\n          <li><a href=\"https://github.com/conda-forge/miniforge\">Source</a></li>\n        </ul>\n      </nav>\n    </header>\n    <main>\n      {%- for release in releases %}\n      {% if loop.index0 == 0 %}\n      <h2 id=\"latest-release\">Latest</h2>\n      {% elif loop.index0 == 1 %}\n      <h2 id=\"history\">History</h2>\n      {% endif %}\n      <article id=\"{{ release.tag_name }}\">\n        <h3>\n          Miniforge {{ release.tag_name }}\n          <a title=\"Link to {{ release.tag_name }}\" href=\"#{{ release.tag_name }}\">#</a>\n        </h3>\n        {%- if loop.index0 %}<details><summary>{% endif -%}\n        <label>\n          {{ release.assets | count }} artifact{% if release.assets | count > 1 %}s{% endif %}\n          <a href=\"{{ release.html_url }}\">released</a>\n          <span title=\"{{ release.published_at }}\">{{ release.published_at.split(\"T\")[0] }}</span>\n        </label>\n        {%- if loop.index0 %}</summary>{% endif %}\n        <table>\n          <thead>\n            <tr>\n              <th>Variant</th>\n              <th>OS</th>\n              <th>Arch</th>\n              <th>Artifact</th>\n              <th>Size</th>\n              <th>SHA256<th>\n            </tr>\n          </thead>\n          <tbody>\n            {%- for variant, vassets in release.assets | groupby(\"_variant\") %}\n            {%- set vloop = loop -%}\n            {%- for os, oassets in vassets | groupby(\"_os\") -%}\n            {%- set oloop = loop -%}\n            {%- for arch, aassets in oassets | groupby(\"_arch\") -%}\n            {%- set aloop = loop -%}\n            {% for asset in aassets %}\n              {%- if oloop.index0 + aloop.index0 == 0 %}\n            <tr class=\"variant-row\">\n              <th rowspan=\"{{ vassets | count }}\">{{ variant }}</th>\n              {%- else -%}\n            <tr>\n              {%- endif -%}\n              {%- if aloop.index0 == 0%}\n              <th rowspan=\"{{ oassets | count }}\">{{ os }}</th>\n              {% endif -%}\n              <th>\n                <code>{{ arch }}</code>\n              </th>\n              <td>\n                <a href=\"{{ asset.browser_download_url }}\"\n                   title=\"Download {{ variant }} {{ release.tag_name }} for {{ os }} on {{ arch }}\">\n                  {{ asset.name }}\n                </a>\n              </td>\n              <td>{{ asset.size | filesizeformat }}</td>\n              <td>\n                <pre><code>{{ asset._sha256 }}</code></pre>\n              </td>\n            </tr>\n            {% endfor -%}\n            {% endfor -%}\n            {% endfor -%}\n            {% endfor -%}\n          </tbody>\n        </table>\n        {% if loop.index0 %}</summary>{% endif -%}\n      </article>\n      {% endfor -%}\n    </main>\n    <footer>\n      &copy; {{ year }} Miniforge Contributors\n    </footer>\n</html>\n"
  },
  {
    "path": "scripts/build.sh",
    "content": "#!/usr/bin/env bash\n\nset -xe\n\nenv | sort\n\necho \"***** Start: Building Miniforge installer(s) *****\"\nCONSTRUCT_ROOT=\"${CONSTRUCT_ROOT:-${PWD}}\"\nSCRIPT_DIR=$( cd -- \"$( dirname -- \"${BASH_SOURCE[0]}\" )\" &> /dev/null && pwd )\n\ncd \"${CONSTRUCT_ROOT}\"\n\necho \"***** Install constructor *****\"\n\nMINIFORGE_CHANNEL_NAME=\"${MINIFORGE_CHANNEL_NAME:-conda-forge}\"\nmamba install --yes \\\n    --channel \"${MINIFORGE_CHANNEL_NAME}\" --override-channels \\\n    jinja2 curl libarchive \\\n    \"constructor>=3.14.0\"\n\nif [[ \"$(uname)\" == \"Darwin\" ]]; then\n    mamba install --yes \\\n        --channel \"${MINIFORGE_CHANNEL_NAME}\" --override-channels \\\n        coreutils\nfi\n\nmamba list\n\necho \"***** Make temp directory *****\"\nif [[ \"$(uname)\" == MINGW* ]]; then\n   # LOCALAPPDATA is a reference variable to the user's AppData\\Local directory\n   TEMP_DIR=$(mktemp -d --tmpdir=\"$LOCALAPPDATA/Temp/\");\nelse\n   TEMP_DIR=$(mktemp -d);\nfi\n\necho \"***** Copy file for installer construction *****\"\ncp -R Miniforge3 \"${TEMP_DIR}/\"\ncp LICENSE \"${TEMP_DIR}/\"\n\nls -al \"${TEMP_DIR}\"\n\nif [[ \"${TARGET_PLATFORM}\" != win-* ]]; then\n    # Assumes specific structure in construct.yaml\n    MICROMAMBA_VERSION=$(grep \"set mamba_version\" Miniforge3/construct.yaml | cut -d '=' -f 2 | cut -d '\"' -f 2)\n    MICROMAMBA_BUILD=1\n    mkdir \"${TEMP_DIR}/micromamba\"\n    pushd \"${TEMP_DIR}/micromamba\"\n    MICROMAMBA_SOURCE_URL=\"${MICROMAMBA_SOURCE_URL:-https://anaconda.org/conda-forge/micromamba/${MICROMAMBA_VERSION}/download/${TARGET_PLATFORM}/micromamba-${MICROMAMBA_VERSION}-${MICROMAMBA_BUILD}.tar.bz2}\"\n    curl -L -O \"${MICROMAMBA_SOURCE_URL}\"\n    $(which bsdtar || which tar) -xf \"micromamba-${MICROMAMBA_VERSION}-${MICROMAMBA_BUILD}.tar.bz2\"\n    if [[ \"${TARGET_PLATFORM}\" == win-* ]]; then\n      MICROMAMBA_FILE=\"${PWD}/Library/bin/micromamba.exe\"\n    else\n      MICROMAMBA_FILE=\"${PWD}/bin/micromamba\"\n    fi\n    popd\n    EXTRA_CONSTRUCTOR_ARGS=\"${EXTRA_CONSTRUCTOR_ARGS} --conda-exe ${MICROMAMBA_FILE} --platform ${TARGET_PLATFORM}\"\nfi\n\necho \"***** Set virtual package versions *****\"\nif [[ \"${TARGET_PLATFORM}\" == linux-* ]]; then\n    export CONDA_OVERRIDE_GLIBC=2.17\nelif [[ \"${TARGET_PLATFORM}\" == osx-64 ]]; then\n    export CONDA_OVERRIDE_OSX=10.13\nelif [[ \"${TARGET_PLATFORM}\" == osx-arm64 ]]; then\n    export CONDA_OVERRIDE_OSX=11.0\nfi\n\necho \"***** Construct the installer(s) *****\"\n# Transmutation requires the current directory is writable\ncd \"${TEMP_DIR}\"\n# shellcheck disable=SC2086\nconstructor \"${TEMP_DIR}/Miniforge3/\" --output-dir \"${TEMP_DIR}\" ${EXTRA_CONSTRUCTOR_ARGS}\ncd -\n\necho \"***** Generate installer hash *****\"\ncd \"${TEMP_DIR}\"\nls -alh\nif [[ \"$(uname)\" == MINGW* ]]; then\n   EXTS=(\"exe\");\nelif [[ \"$(uname)\" == Darwin ]]; then\n   if [[ \"$MINIFORGE_INSTALLER_TYPE\" == \"all\" ]]; then\n      EXTS=(\"sh\" \"pkg\");\n   else\n      EXTS=(\"${MINIFORGE_INSTALLER_TYPE:-sh}\")\n   fi\nelse\n   EXTS=(\"sh\");\nfi\n\nfor EXT in \"${EXTS[@]}\"; do\n   # This line will break if there is more than one installer with extension $EXT in the folder.\n   INSTALLER_PATH=$(find . -name \"M*forge*.${EXT}\" | head -n 1)\n\n   if [[ \"${EXT}\" == \"pkg\" && -n \"${APPLE_NOTARIZATION_KEY_ID:-}\" ]]; then\n      # notarize the PKG installer\n      echo \"***** Notarizing the PKG installer *****\"\n      bash \"$SCRIPT_DIR/notarize_osx_pkg.sh\" \"${INSTALLER_PATH}\"\n   fi\n   \n   HASH_PATH=\"${INSTALLER_PATH}.sha256\"\n   sha256sum \"${INSTALLER_PATH}\" > \"${HASH_PATH}\"\n\n   echo \"***** Move .$EXT installer and hash to build folder *****\"\n   mkdir -p \"${CONSTRUCT_ROOT}/build\"\n   mv \"${INSTALLER_PATH}\" \"${CONSTRUCT_ROOT}/build/\"\n   mv \"${HASH_PATH}\" \"${CONSTRUCT_ROOT}/build/\"\n\n   # copy the installer for latest\n   if [[ \"${MINIFORGE_NAME:-}\" != \"\" && \"${OS_NAME:-}\" != \"\" && \"${ARCH:-}\" != \"\" ]]; then\n      cp \"${CONSTRUCT_ROOT}/build/${MINIFORGE_NAME}-\"*\"-${OS_NAME}-${ARCH}.${EXT}\" \"${CONSTRUCT_ROOT}/build/${MINIFORGE_NAME}-${OS_NAME}-${ARCH}.${EXT}\"\n   fi\ndone\n\ncd \"${CONSTRUCT_ROOT}\"\n\necho \"***** Done: Building Miniforge installer(s) *****\"\n"
  },
  {
    "path": "scripts/notarize_osx_pkg.sh",
    "content": "#!/usr/bin/env bash\n\n# This script takes a macOS installer package (.pkg) and notarizes + staples it.\n# It expects the following environment variables to be set:\n# APPLE_NOTARIZATION_ISSUER_ID: Apple App Store Connect team identifier\n# APPLE_NOTARIZATION_KEY_ID: Apple App Store Connect API key identifier\n# APPLE_NOTARIZATION_AUTHKEY_PATH: Apple App Store Connect API AuthKey .p8 file path\n# These can be obtained in https://appstoreconnect.apple.com/access/users > Integrations\n\nset -euxo pipefail\n\nif [ -z \"${1:-}\" ]; then\n    echo \"Usage: $0 <installer.pkg>\"\n    exit 1\nelse\n    INSTALLER_PATH=\"$1\"\nfi\n\nif [ ! -f \"$INSTALLER_PATH\" ]; then\n    echo \"Error: $INSTALLER_PATH does not exist\"\n    exit 1\nfi\n\nif [[ \"$(basename \"$INSTALLER_PATH\")\" != *.pkg ]]; then\n    echo \"Error: $INSTALLER_PATH is not a .pkg file\"\n    exit 1\nfi\n\nif [ \"$(uname)\" != \"Darwin\" ]; then\n    echo \"Error: $0 can only be run on macOS\"\n    exit 1\nfi\n\nif ! command -v xcrun >/dev/null; then\n    echo \"Error: xcrun is not installed\"\n    exit 1\nfi\n\nif ! command -v stapler >/dev/null; then\n    echo \"Error: stapler is not installed\"\n    exit 1\nfi\n\nif [ -z \"${APPLE_NOTARIZATION_AUTHKEY_PATH:-}\" ]; then\n    echo \"Error: APPLE_NOTARIZATION_AUTHKEY_PATH is not set\"\n    exit 1\nfi\n\nif [ -z \"${APPLE_NOTARIZATION_KEY_ID:-}\" ]; then\n    echo \"Error: APPLE_NOTARIZATION_KEY_ID is not set\"\n    exit 1\nfi\n\nif [ -z \"${APPLE_NOTARIZATION_ISSUER_ID:-}\" ]; then\n    echo \"Error: APPLE_NOTARIZATION_ISSUER_ID is not set\"\n    exit 1\nfi\n\n# Check signatures. If this fails, there's no point in attempting notarization.\npkgutil --check-signature \"$INSTALLER_PATH\"\n\n# Submit for notarization to Apple servers\ntmp_output_dir=$(mktemp -d)\njson_output_file=\"${tmp_output_dir}/$(basename \"$INSTALLER_PATH\").notarization.json\"\nset +e\nxcrun notarytool submit \"$INSTALLER_PATH\" \\\n    --key \"$APPLE_NOTARIZATION_AUTHKEY_PATH\" \\\n    --key-id \"$APPLE_NOTARIZATION_KEY_ID\" \\\n    --issuer \"$APPLE_NOTARIZATION_ISSUER_ID\" \\\n    --output-format json \\\n    --wait \\\n    --timeout 30m \\\n    | tee \"$json_output_file\"\nnotary_exit_code=$?\nset -e\nif [[ $notary_exit_code != 0 ]]; then\n    submission_id=$(jq -r '.id' \"$json_output_file\")\n    xcrun notarytool log \"$submission_id\" \\\n        --key \"$APPLE_NOTARIZATION_AUTHKEY_PATH\" \\\n        --key-id \"$APPLE_NOTARIZATION_KEY_ID\" \\\n        --issuer \"$APPLE_NOTARIZATION_ISSUER_ID\"\n    exit $notary_exit_code\nfi\n\n# Staple\nxcrun stapler staple --verbose \"$INSTALLER_PATH\"\n\n# Check notarization status\nspctl --assess -vv --type install \"$INSTALLER_PATH\" 2>&1 | tee /dev/stderr | grep accepted\n"
  },
  {
    "path": "scripts/osx_pkg_background.py",
    "content": "\"\"\"\nRun this to generate a macOS PKG background with\nthe conda-forge anvil logo in the bottom left corner\n\"\"\"\n# needs 'pillow' package\nfrom PIL import Image, ImageOps\n\n# logo taken from https://github.com/conda-forge/marketing/084d589/main/logo/just_anvil_black.png\nlogo = Image.open(\"just_anvil_black.png\")  \nbackground = Image.new(\"RGBA\", (1227, 600), (0, 0, 0, 0))\nbackground.paste(ImageOps.contain(logo, (290, 290)), (30, 460))\nbackground.save(\"osx_pkg_background.png\", format=\"png\")\n"
  },
  {
    "path": "scripts/osx_prepare_certificates.sh",
    "content": "#!/usr/bin/env bash\n\nset -euxo pipefail\n\n# Import AppleID certificates on macOS\n# This script is used to import the AppleID certificates into the keychain\n# It expects the following environment variables to be set:\n# - APPLE_INSTALLER_CERTIFICATE_BASE64: base64 encoded certificate\n# - APPLE_INSTALLER_CERTIFICATE_PASSWORD: password for the certificate\n# - APPLE_APPLICATION_CERTIFICATE_BASE64: base64 encoded certificate\n# - APPLE_APPLICATION_CERTIFICATE_PASSWORD: password for the certificate\n# - APPLE_NOTARIZATION_AUTHKEY_BASE64: base64 encoded AppStore Connect API authkey (.p8)\n# - APPLE_TEMP_KEYCHAIN_PASSWORD: user-generated password for the temporary keychain\n# Certificates can be generated at https://developer.apple.com/account/resources/certificates/list\n\n# create variables\nTEMP_DIR=\"$(mktemp -d)\"\nINSTALLER_CERTIFICATE_PATH=\"$TEMP_DIR/installer_developer_cert.p12\"\nAPPLICATION_CERTIFICATE_PATH=\"$TEMP_DIR/application_developer_cert.p12\"\nNOTARIZATION_AUTHKEY_PATH=\"$TEMP_DIR/notarization_authkey.p8\"\nKEYCHAIN_PATH=\"$TEMP_DIR/installer-signing.keychain-db\"\n\n# import certificate and provisioning profile from secrets\necho -n \"${APPLE_INSTALLER_CERTIFICATE_BASE64}\" | base64 --decode --output \"$INSTALLER_CERTIFICATE_PATH\"\necho -n \"${APPLE_APPLICATION_CERTIFICATE_BASE64}\" | base64 --decode --output \"$APPLICATION_CERTIFICATE_PATH\"\necho -n \"${APPLE_NOTARIZATION_AUTHKEY_BASE64}\" | base64 --decode --output \"$NOTARIZATION_AUTHKEY_PATH\"\n\n# create temporary keychain\nsecurity create-keychain -p \"${APPLE_TEMP_KEYCHAIN_PASSWORD}\" \"$KEYCHAIN_PATH\"\nsecurity set-keychain-settings -lut 21600 \"$KEYCHAIN_PATH\"\nsecurity unlock-keychain -p \"${APPLE_TEMP_KEYCHAIN_PASSWORD}\" \"$KEYCHAIN_PATH\"\n\n# import certificate to keychain\nsecurity import \"$INSTALLER_CERTIFICATE_PATH\" -P \"${APPLE_INSTALLER_CERTIFICATE_PASSWORD}\" -A -t cert -f pkcs12 -k \"$KEYCHAIN_PATH\"\nsecurity import \"$APPLICATION_CERTIFICATE_PATH\" -P \"${APPLE_APPLICATION_CERTIFICATE_PASSWORD}\" -A -t cert -f pkcs12 -k \"$KEYCHAIN_PATH\"\nsecurity list-keychain -d user -s \"$KEYCHAIN_PATH\"\n\n# export identity name to construct.yaml\nAPPLE_SIGNING_IDENTITY=$(security find-identity \"$KEYCHAIN_PATH\" | grep -m 1 -o '\"Developer ID Installer.*\"' | tr -d '\"')\nAPPLE_NOTARIZATION_IDENTITY=$(security find-identity \"$KEYCHAIN_PATH\" | grep -m 1 -o '\"Developer ID Application.*\"' | tr -d '\"')\n\nexport APPLE_SIGNING_IDENTITY\nexport APPLE_NOTARIZATION_IDENTITY\nexport APPLE_NOTARIZATION_AUTHKEY_PATH=\"$NOTARIZATION_AUTHKEY_PATH\"\n"
  },
  {
    "path": "scripts/test.sh",
    "content": "#!/usr/bin/env bash\n\nset -ex\n\necho \"***** Start: Testing Miniforge installer *****\"\n\nCONSTRUCT_ROOT=\"${CONSTRUCT_ROOT:-${PWD}}\"\ncd \"${CONSTRUCT_ROOT}\"\n\nexport CONDA_PATH=\"${HOME}/miniforge\"\nMAMBA_VERSION=$(grep \"set mamba_version\" Miniforge3/construct.yaml | cut -d '=' -f 2 | cut -d '\"' -f 2)\nexport MAMBA_VERSION\n\necho \"***** Get the installer *****\"\nls build/\nif [[ \"$(uname)\" == MINGW* ]]; then\n   EXT=\"exe\";\nelse\n   EXT=\"sh\";\nfi\nINSTALLER_PATH=$(find build/ -name \"*forge*.${EXT}\" | head -n 1)\nINSTALLER_NAME=$(basename \"${INSTALLER_PATH}\" | cut -d \"-\" -f 1)\n\necho \"***** Run the installer *****\"\nchmod +x \"${INSTALLER_PATH}\"\nif [[ \"$(uname)\" == MINGW* ]]; then\n  echo \"start /wait \\\"\\\" ${INSTALLER_PATH} /InstallationType=JustMe /RegisterPython=0 /S /D=$(cygpath -w \"${CONDA_PATH}\")\" > install.bat\n  cmd.exe //c install.bat\n\n  echo \"***** Setup conda *****\"\n  # Workaround a conda bug where it uses Unix style separators, but MinGW doesn't understand them\n  export PATH=$CONDA_PATH/Library/bin:$PATH\n  # shellcheck disable=SC1091\n  source \"${CONDA_PATH}/Scripts/activate\"\n  conda.exe config --set show_channel_urls true\n\n  echo \"***** Print conda info *****\"\n  conda.exe info\n  conda.exe list\n\n  echo \"***** Check if we are bundling packages from msys2 or defaults *****\"\n  conda.exe list | grep defaults && exit 1\n  conda.exe list | grep msys2 && exit 1\n\n  echo \"***** Check if we can install a package which requires msys2 *****\"\n  conda.exe install r-base --yes --quiet\n  conda.exe list\nelse\n  # Test one of our installers in batch mode\n  if [[ \"${INSTALLER_NAME}\" == \"Miniforge3\" ]]; then\n    sh \"${INSTALLER_PATH}\" -b -p \"${CONDA_PATH}\"\n  # And the other in interactive mode\n  else\n    # Test interactive install. The install will ask the user to\n    # - newline -- read the EULA\n    # - yes -- then accept\n    # - ${CONDA_PATH} -- Then specify the path\n    # - no -- Then whether or not they want to initialize conda\n    cat <<EOF | sh \"${INSTALLER_PATH}\"\n\nyes\n${CONDA_PATH}\nno\nEOF\n  fi\n\n  echo \"***** Setup conda *****\"\n  # shellcheck disable=SC1091\n  source \"${CONDA_PATH}/bin/activate\"\n\n  echo \"***** Print conda info *****\"\n  conda info\n  conda list\nfi\n\necho \"+ Mamba does not warn (check that there is no warning on stderr) and returns exit code 0\"\nmamba --help 2> stderr.log || cat stderr.log\ntest ! -s stderr.log\nrm -f stderr.log\n\necho \"+ mamba info\"\nmamba info\n\necho \"+ mamba config sources\"\nmamba config sources\n\necho \"+ mamba config list\"\nmamba config list\n\necho \"+ Testing mamba version (i.e. ${MAMBA_VERSION})\"\nmamba info --json | python -c \"import sys, json; info = json.loads(sys.stdin.read()); assert info['mamba version'] == '${MAMBA_VERSION}', info\"\necho \"  OK\"\n\nMINIFORGE_CHANNEL_NAME=\"${MINIFORGE_CHANNEL_NAME:-conda-forge}\"\necho \"+ Testing mamba channels\"\nmamba 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\"\necho \"  OK\"\n\necho \"+ Testing mirrored channels\"\nmamba 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']\"\n\necho \"***** Python path *****\"\npython -c \"import sys; print(sys.executable)\"\npython -c \"import sys; assert 'miniforge' in sys.executable\"\n\necho \"***** Print system informations from Python *****\"\npython -c \"print('Hello Miniforge !')\"\npython -c \"import platform; print(platform.architecture())\"\npython -c \"import platform; print(platform.system())\"\npython -c \"import platform; print(platform.machine())\"\npython -c \"import platform; print(platform.release())\"\n\necho \"***** Done: Testing installer *****\"\n\necho \"***** Testing the usage of mamba main commands *****\"\n\necho \"***** Initialize the current session for mamba *****\"\neval \"$(mamba shell hook --shell bash)\"\n\necho \"***** Create a new environment *****\"\nENV_PREFIX=\"/tmp/testenv\"\n\nmamba create -p $ENV_PREFIX numpy --yes -vvv\n\necho \"***** Activate the environment with mamba *****\"\nmamba activate $ENV_PREFIX\n\necho \"***** Check that numpy is installed with mamba list *****\"\nmamba list | grep numpy\n\necho \"***** Deactivate the environment *****\"\nmamba deactivate\n\necho \"***** Activate the environment with conda *****\"\nconda activate $ENV_PREFIX\n\necho \"***** Check that numpy is installed with python *****\"\npython -c \"import numpy; print(numpy.__version__)\"\n\necho \"***** Remove numpy *****\"\nmamba remove numpy --yes\n\necho \"***** Check that numpy is not installed with mamba list *****\"\nmamba list | grep -v numpy\n\necho \"***** Deactivate the environment with conda *****\"\nconda deactivate\n\necho \"***** Remove the environment *****\"\nmamba env remove -p $ENV_PREFIX --yes\n\necho \"***** Done: Testing mamba main commands *****\"\n\n"
  }
]