Download and run Elm tooling from elm-tooling.json.
MIT License
Use elm-tooling instead.
Download and run Elm tooling from elm-tooling.json.
Proof-of-concept. Hacky JSON parsing. But it works! No Windows support.
example-project
├── elm-tooling.json
├── elm.json
└── src
└── Main.elm
Run cd example-project && elm-version download
to get the versions of elm
and elm-format
used in the project. Done! Now running elm
and elm-format
will automatically use the version needed for the project you’re in.
There’s no magic – elm-version
simply replaces your global elm
and elm-format
with wrappers that look up the directory tree for an elm-tooling.json and uses the versions specified there (or the latest version if no elm-tooling.json is found.) The actual binaries are stored in ~/.elm
.
Copy and paste into your terminal:
sh -c '
# Exit on errors:
set -e
# Where to install elm-version:
path="/usr/local/bin/elm-version"
# Where to download elm-version from:
url="https://raw.githubusercontent.com/lydell/elm-version/master/elm-version"
# Download elm-version using curl if available, and wget otherwise.
if command -v curl > /dev/null; then curl -#fLo "$path" "$url"; else wget -nv -O "$path" "$url"; fi
# Make elm-version executable:
chmod +x "$path"
# Create wrappers for elm and elm-format, next to elm-version:
elm-version setup "$(dirname "$path")"
'
Permission denied? Try adding
sudo
at the start:sudo sh -c '...'
You can also install using npm
if you prefer:
sh -c 'npm install --global elm-version && elm-version setup "$(dirname "$(which elm-version)")"'
elm-version
shell script from this repo.$PATH
.elm-version setup SOME_DIR_IN_PATH
to create wrappers for elm
and elm-format
.Want to use elm-version
in CI and build systems? There are two ways to do it:
npm install --save-dev elm-version
To upgrade, edit the version number for "elm-version"
in package.json
.
You could copy installation command into your CI setup and build scripts, but:
elm-version
in CI vs your build scripts.By instead committing a copy of elm-version
:
sh elm-version ...
elm-version
installed can run sh elm-version setup /usr/bin/local
to get it. They might not get the absolutely latest version, but they’ll at least get something that works with your project.elm-version
is a couple of hundred lines of shell script so it shouldn’t be too bad to commit.Once you’ve installed elm-version
on your computer, you could run the following to copy it to your project:
cd your-project
sh -c 'cp "$(which elm-version)" elm-version'
# Install npm packages in a separate image, for maximum Docker caching.
# Otherwise you’d lose the cached downloads of Elm binaries every time
# package.json changes (which is much more frequent).
FROM node:12 AS npm
WORKDIR app
COPY package.json package-lock.json ./
RUN npm ci
# Start a new image.
FROM node:12
WORKDIR app
# Copy elm-version from the previous image, then setup and install.
COPY --from=npm /app/node_modules/elm-version/elm-version elm-version
COPY elm-tooling.json ./
RUN sh elm-version setup /usr/local/bin && elm-version download
# Copy the full node_modules folder for the rest of your build.
COPY --from=npm /app/node_modules node_modules
# Then do whatever you need to.
# Put this early in your Dockerfile, to take advantage of Docker caching.
COPY elm-version elm-tooling.json ./
RUN sh elm-version setup /usr/local/bin && elm-version download
Note: curl
or wget
is required – you might need to install one of them depending on what Docker image you use.
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: "12"
- name: Cache node_modules
uses: actions/cache@v1
with:
path: node_modules
key: node_modules-${{ hashFiles('package-lock.json') }}
- name: Cache elm packages and binaries
uses: actions/cache@v1
with:
path: ~/.elm
key: elm-${{ hashFiles('elm*.json') }}
- name: Run workflow
run: |
test -d node_modules || npm ci
sudo npx elm-version setup /usr/local/bin
elm-version download
npm run build # Or whatever you do in your build
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Cache elm packages and binaries
uses: actions/cache@v1
with:
path: ~/.elm
key: elm-${{ hashFiles('elm*.json') }}
- name: Run workflow
run: |
sudo sh elm-version setup /usr/local/bin
elm-version download
elm make src/Main.elm # Or whatever you do in your build
To upgrade elm-version
itself, re-run the installation instructions. It overwrites the previous installation.
To upgrade elm
or elm-format
, edit elm-tooling.json and run elm-version download
. Note: This might requiring updating elm-version
as well. elm-version
hardcodes the versions of binaries it supports (see the next section for why). This shouldn’t be a problem since elm
and elm-format
releases aren’t frequent.
Run elm-version uninstall
and follow the instructions. Basically, you need to remove a couple of files.
If you installed using npm
you need to run either npm uninstall elm-version
or npm uninstall --global elm-version
afterwards.
elm-version
includes sha256 checksums for all binary versions it supports. If there’s a checksum mismatch on a downloaded file, elm-version
removes the bad file and errors. Only known versions can be installed.
Notes:
npm
.elm-version
could help installing such binaries globally in the future?elm
and elm-format
using npm
? Because npm
doesn’t really support platform-specific binaries, which means that the binaries aren’t cached and often re-downloaded unnecessarily when you run npm install
. Also, you’ll get a copy of the binaries in each project, making them take around 45 MB* more space than they’d need to.(*) After running npm install elm elm-format
in a new folder on macOS, node_modules
is 45 MB. That’s including the size of the binaries as well as all 70 dependencies the elm
and elm-format
npm packages use to get the binaries to your computer.
Run elm-version init
to create an elm-tooling.json with the latest versions, that matches the elm.json
created by running elm init
.
mkdir my-project
cd my-project
elm-version init
elm-version download
elm init
mkdir src
touch src/Main.elm
Then start working on your project!
You can use elm-version init
for existing projects as well, but you might need to tweak elm-tooling.json a little.
cd my-project
elm-version init
elm
and elm-format
using npm
, copy their versions from package.json
to elm-tooling.json. Then you can remove them from package.json
. You also need to edit "entrypoints"
in elm-tooling.json to match your project.elm-version download
elm
, not ./node_modules/.bin/elm
.sh -c 'cp "$(which elm-version)" elm-version'
sh elm-version setup /usr/local/bin && elm-version download
rather than npm install
(see the CI/Build installation section).If you use for example Elm 0.19.0 very often, you could put a symlink to ~/.elm/elm-tooling/elm/0.19.0/elm
in your $PATH
. For example:
sh -c 'ln -s "${ELM_HOME:-$HOME/.elm}/elm-tooling/elm/0.19.0/elm" /usr/local/bin/elm0.19.0'
If you want to check if you and someone else are running the same version of elm-version
, you could both run sh -c 'cksum "$(which elm-version)"'
and compare outputs.
The goal is to make it easy and fast to have project-specific versions of Elm and Elm tooling. It should be easy for developers, as well as for CI and build scripts.
The dream is that editors will start to support elm-tooling.json so they don’t even need to rely on elm-version
’s wrappers of elm
and elm-format
. That would mean 0 overhead – editors could just execute binaries directly.