mirror of
https://github.com/enso-org/enso.git
synced 2024-09-11 21:27:15 +03:00
Better component handling in the project manager (#1399)
This commit is contained in:
parent
197190ceeb
commit
10bccf6b56
194
.github/workflows/release.yml
vendored
194
.github/workflows/release.yml
vendored
@ -31,7 +31,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: repo
|
path: repo
|
||||||
- name: Enable Developer Command Prompt (Windows)
|
- name: Enable Developer Command Prompt (Windows)
|
||||||
uses: ilammy/msvc-dev-cmd@v1.4.1
|
uses: ilammy/msvc-dev-cmd@v1.5.0
|
||||||
- name: Disable TCP/UDP Offloading (macOS)
|
- name: Disable TCP/UDP Offloading (macOS)
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -147,19 +147,19 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sleep 1
|
sleep 1
|
||||||
sbt 'set launcherDistributionRoot := file("${{ env.LAUNCHER_DIST_DIR }}"); buildLauncherDistribution'
|
sbt buildLauncherDistribution
|
||||||
- name: Prepare Engine Distribution
|
- name: Prepare Engine Distribution
|
||||||
working-directory: repo
|
working-directory: repo
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sleep 1
|
sleep 1
|
||||||
sbt 'set engineDistributionRoot := file("${{ env.ENGINE_DIST_DIR }}"); buildEngineDistribution'
|
sbt buildEngineDistribution
|
||||||
- name: Prepare Project Manager Distribution
|
- name: Prepare Project Manager Distribution
|
||||||
working-directory: repo
|
working-directory: repo
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sleep 1
|
sleep 1
|
||||||
sbt 'set projectManagerDistributionRoot := file("${{ env.PROJECTMANAGER_DIST_DIR }}"); buildProjectManagerDistribution'
|
sbt buildProjectManagerDistribution
|
||||||
|
|
||||||
# Ensure that the versions encoded in the binary and in the release match
|
# Ensure that the versions encoded in the binary and in the release match
|
||||||
- name: Check Versions (Unix)
|
- name: Check Versions (Unix)
|
||||||
@ -202,17 +202,17 @@ jobs:
|
|||||||
- name: Upload the Engine Artifact
|
- name: Upload the Engine Artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: ${{ env.ENGINE_DIST_ROOT }}
|
name: ${{ env.ENGINE_DIST_NAME }}
|
||||||
path: repo/${{ env.ENGINE_DIST_ROOT }}
|
path: repo/${{ env.ENGINE_DIST_ROOT }}
|
||||||
- name: Upload the Launcher Artifact
|
- name: Upload the Launcher Artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: ${{ env.LAUNCHER_DIST_ROOT }}
|
name: ${{ env.LAUNCHER_DIST_NAME }}
|
||||||
path: repo/${{ env.LAUNCHER_DIST_ROOT }}
|
path: repo/${{ env.LAUNCHER_DIST_ROOT }}
|
||||||
- name: Upload the Project Manager Artifact
|
- name: Upload the Project Manager Artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: ${{ env.PROJECTMANAGER_DIST_ROOT }}
|
name: ${{ env.PROJECTMANAGER_DIST_NAME }}
|
||||||
path: repo/${{ env.PROJECTMANAGER_DIST_ROOT }}
|
path: repo/${{ env.PROJECTMANAGER_DIST_ROOT }}
|
||||||
- name: Upload the Manifest Artifact
|
- name: Upload the Manifest Artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
@ -237,12 +237,36 @@ jobs:
|
|||||||
# Without specifying options, it downloads all artifacts
|
# Without specifying options, it downloads all artifacts
|
||||||
- uses: actions/download-artifact@v2
|
- uses: actions/download-artifact@v2
|
||||||
with:
|
with:
|
||||||
path: artifacts
|
path: repo/built-distribution
|
||||||
|
|
||||||
# This jobs can be used to debug errors, it may be removed
|
# This jobs can be used to debug errors, it may be removed
|
||||||
- name: Display Structure of Downloaded Files
|
- name: Display Structure of Downloaded Files
|
||||||
run: ls -R
|
run: ls -R
|
||||||
working-directory: artifacts
|
working-directory: repo/built-distribution
|
||||||
|
|
||||||
|
- name: Setup GraalVM Environment
|
||||||
|
uses: ayltai/setup-graalvm@v1
|
||||||
|
with:
|
||||||
|
graalvm-version: ${{ env.graalVersion }}
|
||||||
|
java-version: ${{ env.javaVersion }}
|
||||||
|
native-image: true
|
||||||
|
- name: Set Up SBT
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
curl -fsSL -o sbt.tgz https://github.com/sbt/sbt/releases/download/v${{env.sbtVersion}}/sbt-${{env.sbtVersion}}.tgz
|
||||||
|
tar -xzf sbt.tgz
|
||||||
|
echo $GITHUB_WORKSPACE/sbt/bin/ >> $GITHUB_PATH
|
||||||
|
|
||||||
|
# Caches
|
||||||
|
- name: Cache SBT
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.sbt
|
||||||
|
~/.ivy2/cache
|
||||||
|
~/.cache
|
||||||
|
key: ${{ runner.os }}-sbt-${{ hashFiles('**build.sbt') }}
|
||||||
|
restore-keys: ${{ runner.os }}-sbt-
|
||||||
|
|
||||||
- name: Save Version to Environment
|
- name: Save Version to Environment
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -252,87 +276,19 @@ jobs:
|
|||||||
echo "Preparing release for $DIST_VERSION"
|
echo "Preparing release for $DIST_VERSION"
|
||||||
echo "DIST_VERSION=$DIST_VERSION" >> $GITHUB_ENV
|
echo "DIST_VERSION=$DIST_VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Download GraalVM for Bundles
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
curl -fsSL -o graalvm-linux.tar.gz "https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-${{ env.graalVersion }}/graalvm-ce-java${{ env.javaVersion }}-linux-amd64-${{ env.graalVersion }}.tar.gz"
|
|
||||||
echo "Linux JVM downloaded"
|
|
||||||
curl -fsSL -o graalvm-macos.tar.gz "https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-${{ env.graalVersion }}/graalvm-ce-java${{ env.javaVersion }}-darwin-amd64-${{ env.graalVersion }}.tar.gz"
|
|
||||||
echo "MacOS JVM downloaded"
|
|
||||||
curl -fsSL -o graalvm-windows.zip "https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-${{ env.graalVersion }}/graalvm-ce-java${{ env.javaVersion }}-windows-amd64-${{ env.graalVersion }}.zip"
|
|
||||||
echo "Windows JVM downloaded"
|
|
||||||
mkdir graalvm-linux
|
|
||||||
mkdir graalvm-macos
|
|
||||||
mkdir graalvm-windows
|
|
||||||
(cd graalvm-linux && tar xf ../graalvm-linux.tar.gz)
|
|
||||||
echo "Linux JVM extracted"
|
|
||||||
(cd graalvm-macos && tar xf ../graalvm-macos.tar.gz)
|
|
||||||
echo "MacOS JVM extracted"
|
|
||||||
(cd graalvm-windows && unzip -q ../graalvm-windows.zip)
|
|
||||||
echo "Windows JVM extracted"
|
|
||||||
|
|
||||||
# As the download-artifact action does not preserve the executable bits,
|
|
||||||
# we fix them here, so that the release assets are easy to use.
|
|
||||||
- name: Fix Package Structure
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
chmod +x artifacts/enso-engine-${{ env.DIST_VERSION }}-linux-amd64/enso-${{ env.DIST_VERSION }}/bin/enso
|
|
||||||
chmod +x artifacts/enso-engine-${{ env.DIST_VERSION }}-macos-amd64/enso-${{ env.DIST_VERSION }}/bin/enso
|
|
||||||
chmod +x artifacts/enso-launcher-${{ env.DIST_VERSION }}-linux-amd64/enso/bin/enso
|
|
||||||
chmod +x artifacts/enso-launcher-${{ env.DIST_VERSION }}-macos-amd64/enso/bin/enso
|
|
||||||
chmod +x artifacts/enso-project-manager-${{ env.DIST_VERSION }}-linux-amd64/enso/bin/project-manager
|
|
||||||
chmod +x artifacts/enso-project-manager-${{ env.DIST_VERSION }}-macos-amd64/enso/bin/project-manager
|
|
||||||
mkdir artifacts/enso-launcher-${{ env.DIST_VERSION }}-linux-amd64/enso/config
|
|
||||||
mkdir artifacts/enso-launcher-${{ env.DIST_VERSION }}-linux-amd64/enso/dist
|
|
||||||
mkdir artifacts/enso-launcher-${{ env.DIST_VERSION }}-linux-amd64/enso/runtime
|
|
||||||
mkdir artifacts/enso-launcher-${{ env.DIST_VERSION }}-macos-amd64/enso/config
|
|
||||||
mkdir artifacts/enso-launcher-${{ env.DIST_VERSION }}-macos-amd64/enso/dist
|
|
||||||
mkdir artifacts/enso-launcher-${{ env.DIST_VERSION }}-macos-amd64/enso/runtime
|
|
||||||
mkdir artifacts/enso-launcher-${{ env.DIST_VERSION }}-windows-amd64/enso/config
|
|
||||||
mkdir artifacts/enso-launcher-${{ env.DIST_VERSION }}-windows-amd64/enso/dist
|
|
||||||
mkdir artifacts/enso-launcher-${{ env.DIST_VERSION }}-windows-amd64/enso/runtime
|
|
||||||
|
|
||||||
- name: Prepare Packages
|
- name: Prepare Packages
|
||||||
shell: bash
|
shell: bash
|
||||||
|
working-directory: repo
|
||||||
run: |
|
run: |
|
||||||
(cd artifacts/enso-engine-${{ env.DIST_VERSION }}-linux-amd64/ && tar -czf ../../enso-engine-${{ env.DIST_VERSION }}-linux-amd64.tar.gz enso-${{ env.DIST_VERSION }} )
|
sleep 1
|
||||||
echo "Linux Engine packaged"
|
sbt makePackages
|
||||||
(cd artifacts/enso-engine-${{ env.DIST_VERSION }}-macos-amd64/ && tar -czf ../../enso-engine-${{ env.DIST_VERSION }}-macos-amd64.tar.gz enso-${{ env.DIST_VERSION }} )
|
|
||||||
echo "MacOS Engine packaged"
|
|
||||||
(cd artifacts/enso-engine-${{ env.DIST_VERSION }}-windows-amd64/ && zip -q -r ../../enso-engine-${{ env.DIST_VERSION }}-windows-amd64.zip enso-${{ env.DIST_VERSION }} )
|
|
||||||
echo "Windows Engine packaged"
|
|
||||||
|
|
||||||
(cd artifacts/enso-launcher-${{ env.DIST_VERSION }}-linux-amd64/ && tar -czf ../../enso-launcher-${{ env.DIST_VERSION }}-linux-amd64.tar.gz enso )
|
|
||||||
echo "Linux Launcher packaged"
|
|
||||||
(cd artifacts/enso-launcher-${{ env.DIST_VERSION }}-macos-amd64/ && tar -czf ../../enso-launcher-${{ env.DIST_VERSION }}-macos-amd64.tar.gz enso )
|
|
||||||
echo "MacOS Launcher packaged"
|
|
||||||
(cd artifacts/enso-launcher-${{ env.DIST_VERSION }}-windows-amd64/ && zip -q -r ../../enso-launcher-${{ env.DIST_VERSION }}-windows-amd64.zip enso )
|
|
||||||
echo "Windows Launcher packaged"
|
|
||||||
|
|
||||||
(cd artifacts/enso-project-manager-${{ env.DIST_VERSION }}-linux-amd64/ && tar -czf ../../enso-project-manager-${{ env.DIST_VERSION }}-linux-amd64.tar.gz enso )
|
|
||||||
echo "Linux Project Manager packaged"
|
|
||||||
(cd artifacts/enso-project-manager-${{ env.DIST_VERSION }}-macos-amd64/ && tar -czf ../../enso-project-manager-${{ env.DIST_VERSION }}-macos-amd64.tar.gz enso )
|
|
||||||
echo "MacOS Project Manager packaged"
|
|
||||||
(cd artifacts/enso-project-manager-${{ env.DIST_VERSION }}-windows-amd64/ && zip -q -r ../../enso-project-manager-${{ env.DIST_VERSION }}-windows-amd64.zip enso )
|
|
||||||
echo "Windows Project Manager packaged"
|
|
||||||
|
|
||||||
- name: Prepare Bundles
|
- name: Prepare Bundles
|
||||||
shell: bash
|
shell: bash
|
||||||
|
working-directory: repo
|
||||||
run: |
|
run: |
|
||||||
cp -r artifacts/enso-engine-${{ env.DIST_VERSION }}-linux-amd64/enso-${{ env.DIST_VERSION }} artifacts/enso-launcher-${{ env.DIST_VERSION }}-linux-amd64/enso/dist/${{ env.DIST_VERSION }}
|
sleep 1
|
||||||
cp -r artifacts/enso-engine-${{ env.DIST_VERSION }}-macos-amd64/enso-${{ env.DIST_VERSION }} artifacts/enso-launcher-${{ env.DIST_VERSION }}-macos-amd64/enso/dist/${{ env.DIST_VERSION }}
|
sbt makeBundles
|
||||||
cp -r artifacts/enso-engine-${{ env.DIST_VERSION }}-windows-amd64/enso-${{ env.DIST_VERSION }} artifacts/enso-launcher-${{ env.DIST_VERSION }}-windows-amd64/enso/dist/${{ env.DIST_VERSION }}
|
|
||||||
mv graalvm-linux/graalvm-ce-java${{ env.javaVersion }}-${{ env.graalVersion }} artifacts/enso-launcher-${{ env.DIST_VERSION }}-linux-amd64/enso/runtime
|
|
||||||
mv graalvm-macos/graalvm-ce-java${{ env.javaVersion }}-${{ env.graalVersion }} artifacts/enso-launcher-${{ env.DIST_VERSION }}-macos-amd64/enso/runtime
|
|
||||||
mv graalvm-windows/graalvm-ce-java${{ env.javaVersion }}-${{ env.graalVersion }} artifacts/enso-launcher-${{ env.DIST_VERSION }}-windows-amd64/enso/runtime
|
|
||||||
|
|
||||||
echo "Bundles prepared"
|
|
||||||
(cd artifacts/enso-launcher-${{ env.DIST_VERSION }}-linux-amd64/ && tar -czf ../../enso-bundle-${{ env.DIST_VERSION }}-linux-amd64.tar.gz enso )
|
|
||||||
echo "Linux Bundle packaged"
|
|
||||||
(cd artifacts/enso-launcher-${{ env.DIST_VERSION }}-macos-amd64/ && tar -czf ../../enso-bundle-${{ env.DIST_VERSION }}-macos-amd64.tar.gz enso )
|
|
||||||
echo "MacOS Bundle packaged"
|
|
||||||
(cd artifacts/enso-launcher-${{ env.DIST_VERSION }}-windows-amd64/ && zip -q -r ../../enso-bundle-${{ env.DIST_VERSION }}-windows-amd64.zip enso )
|
|
||||||
echo "Windows Bundle packaged"
|
|
||||||
|
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
id: create_release
|
id: create_release
|
||||||
@ -357,7 +313,7 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sleep 1
|
sleep 1
|
||||||
docker build -t ensosharedwus2acr.azurecr.io/runtime:${{ env.DIST_VERSION }} -f ./repo/tools/ci/docker/Dockerfile ./artifacts/enso-engine-${{ env.DIST_VERSION }}-linux-amd64/enso-${{ env.DIST_VERSION }}/component
|
docker build -t ensosharedwus2acr.azurecr.io/runtime:${{ env.DIST_VERSION }} -f ./repo/tools/ci/docker/Dockerfile ./repo/built-distribution/enso-engine-${{ env.DIST_VERSION }}-linux-amd64/enso-${{ env.DIST_VERSION }}/component
|
||||||
docker push ensosharedwus2acr.azurecr.io/runtime:${{ env.DIST_VERSION }}
|
docker push ensosharedwus2acr.azurecr.io/runtime:${{ env.DIST_VERSION }}
|
||||||
|
|
||||||
# Publish the launcher packages to the backup/fallback S3 bucket
|
# Publish the launcher packages to the backup/fallback S3 bucket
|
||||||
@ -373,25 +329,26 @@ jobs:
|
|||||||
- name: Upload the Linux Launcher Package to S3
|
- name: Upload the Linux Launcher Package to S3
|
||||||
shell: bash
|
shell: bash
|
||||||
run: >
|
run: >
|
||||||
aws s3 cp enso-launcher-${{ env.DIST_VERSION }}-linux-amd64.tar.gz
|
aws s3 cp repo/built-distribution/enso-launcher-${{ env.DIST_VERSION
|
||||||
s3://launcherfallback/launcher/enso-${{ env.DIST_VERSION }}/ --profile
|
}}-linux-amd64.tar.gz s3://launcherfallback/launcher/enso-${{
|
||||||
s3-upload --acl public-read
|
env.DIST_VERSION }}/ --profile s3-upload --acl public-read
|
||||||
- name: Upload the macOS Launcher Package to S3
|
- name: Upload the macOS Launcher Package to S3
|
||||||
shell: bash
|
shell: bash
|
||||||
run: >
|
run: >
|
||||||
aws s3 cp enso-launcher-${{ env.DIST_VERSION }}-macos-amd64.tar.gz
|
aws s3 cp repo/built-distribution/enso-launcher-${{ env.DIST_VERSION
|
||||||
s3://launcherfallback/launcher/enso-${{ env.DIST_VERSION }}/ --profile
|
}}-macos-amd64.tar.gz s3://launcherfallback/launcher/enso-${{
|
||||||
s3-upload --acl public-read
|
env.DIST_VERSION }}/ --profile s3-upload --acl public-read
|
||||||
- name: Upload the Windows Launcher Package to S3
|
- name: Upload the Windows Launcher Package to S3
|
||||||
shell: bash
|
shell: bash
|
||||||
run: >
|
run: >
|
||||||
aws s3 cp enso-launcher-${{ env.DIST_VERSION }}-windows-amd64.zip
|
aws s3 cp repo/built-distribution/enso-launcher-${{ env.DIST_VERSION
|
||||||
s3://launcherfallback/launcher/enso-${{ env.DIST_VERSION }}/ --profile
|
}}-windows-amd64.zip s3://launcherfallback/launcher/enso-${{
|
||||||
s3-upload --acl public-read
|
env.DIST_VERSION }}/ --profile s3-upload --acl public-read
|
||||||
- name: Upload the Launcher Manifest to S3
|
- name: Upload the Launcher Manifest to S3
|
||||||
shell: bash
|
shell: bash
|
||||||
run: >
|
run: >
|
||||||
aws s3 cp artifacts/launcher-manifest/launcher-manifest.yaml
|
aws s3 cp
|
||||||
|
repo/built-distribution/launcher-manifest/launcher-manifest.yaml
|
||||||
s3://launcherfallback/launcher/enso-${{ env.DIST_VERSION
|
s3://launcherfallback/launcher/enso-${{ env.DIST_VERSION
|
||||||
}}/launcher-manifest.yaml --profile s3-upload --acl public-read
|
}}/launcher-manifest.yaml --profile s3-upload --acl public-read
|
||||||
- name: Update the Release List in S3
|
- name: Update the Release List in S3
|
||||||
@ -422,7 +379,9 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path: enso-engine-${{ env.DIST_VERSION }}-linux-amd64.tar.gz
|
asset_path:
|
||||||
|
repo/built-distribution/enso-engine-${{ env.DIST_VERSION
|
||||||
|
}}-linux-amd64.tar.gz
|
||||||
asset_name: enso-engine-${{ env.DIST_VERSION }}-linux-amd64.tar.gz
|
asset_name: enso-engine-${{ env.DIST_VERSION }}-linux-amd64.tar.gz
|
||||||
asset_content_type: application/x-tar
|
asset_content_type: application/x-tar
|
||||||
- name: Publish the Engine (MacOS)
|
- name: Publish the Engine (MacOS)
|
||||||
@ -431,7 +390,9 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path: enso-engine-${{ env.DIST_VERSION }}-macos-amd64.tar.gz
|
asset_path:
|
||||||
|
repo/built-distribution/enso-engine-${{ env.DIST_VERSION
|
||||||
|
}}-macos-amd64.tar.gz
|
||||||
asset_name: enso-engine-${{ env.DIST_VERSION }}-macos-amd64.tar.gz
|
asset_name: enso-engine-${{ env.DIST_VERSION }}-macos-amd64.tar.gz
|
||||||
asset_content_type: application/x-tar
|
asset_content_type: application/x-tar
|
||||||
- name: Publish the Engine (Windows)
|
- name: Publish the Engine (Windows)
|
||||||
@ -440,7 +401,9 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path: enso-engine-${{ env.DIST_VERSION }}-windows-amd64.zip
|
asset_path:
|
||||||
|
repo/built-distribution/enso-engine-${{ env.DIST_VERSION
|
||||||
|
}}-windows-amd64.zip
|
||||||
asset_name: enso-engine-${{ env.DIST_VERSION }}-windows-amd64.zip
|
asset_name: enso-engine-${{ env.DIST_VERSION }}-windows-amd64.zip
|
||||||
asset_content_type: application/zip
|
asset_content_type: application/zip
|
||||||
|
|
||||||
@ -450,7 +413,9 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path: enso-launcher-${{ env.DIST_VERSION }}-linux-amd64.tar.gz
|
asset_path:
|
||||||
|
repo/built-distribution/enso-launcher-${{ env.DIST_VERSION
|
||||||
|
}}-linux-amd64.tar.gz
|
||||||
asset_name: enso-launcher-${{ env.DIST_VERSION }}-linux-amd64.tar.gz
|
asset_name: enso-launcher-${{ env.DIST_VERSION }}-linux-amd64.tar.gz
|
||||||
asset_content_type: application/x-tar
|
asset_content_type: application/x-tar
|
||||||
- name: Publish the Launcher (MacOS)
|
- name: Publish the Launcher (MacOS)
|
||||||
@ -459,7 +424,9 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path: enso-launcher-${{ env.DIST_VERSION }}-macos-amd64.tar.gz
|
asset_path:
|
||||||
|
repo/built-distribution/enso-launcher-${{ env.DIST_VERSION
|
||||||
|
}}-macos-amd64.tar.gz
|
||||||
asset_name: enso-launcher-${{ env.DIST_VERSION }}-macos-amd64.tar.gz
|
asset_name: enso-launcher-${{ env.DIST_VERSION }}-macos-amd64.tar.gz
|
||||||
asset_content_type: application/x-tar
|
asset_content_type: application/x-tar
|
||||||
- name: Publish the Launcher (Windows)
|
- name: Publish the Launcher (Windows)
|
||||||
@ -468,7 +435,9 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path: enso-launcher-${{ env.DIST_VERSION }}-windows-amd64.zip
|
asset_path:
|
||||||
|
repo/built-distribution/enso-launcher-${{ env.DIST_VERSION
|
||||||
|
}}-windows-amd64.zip
|
||||||
asset_name: enso-launcher-${{ env.DIST_VERSION }}-windows-amd64.zip
|
asset_name: enso-launcher-${{ env.DIST_VERSION }}-windows-amd64.zip
|
||||||
asset_content_type: application/zip
|
asset_content_type: application/zip
|
||||||
|
|
||||||
@ -479,7 +448,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path:
|
asset_path:
|
||||||
enso-project-manager-${{ env.DIST_VERSION }}-linux-amd64.tar.gz
|
repo/built-distribution/enso-project-manager-${{ env.DIST_VERSION
|
||||||
|
}}-linux-amd64.tar.gz
|
||||||
asset_name:
|
asset_name:
|
||||||
enso-project-manager-${{ env.DIST_VERSION }}-linux-amd64.tar.gz
|
enso-project-manager-${{ env.DIST_VERSION }}-linux-amd64.tar.gz
|
||||||
asset_content_type: application/x-tar
|
asset_content_type: application/x-tar
|
||||||
@ -490,7 +460,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path:
|
asset_path:
|
||||||
enso-project-manager-${{ env.DIST_VERSION }}-macos-amd64.tar.gz
|
repo/built-distribution/enso-project-manager-${{ env.DIST_VERSION
|
||||||
|
}}-macos-amd64.tar.gz
|
||||||
asset_name:
|
asset_name:
|
||||||
enso-project-manager-${{ env.DIST_VERSION }}-macos-amd64.tar.gz
|
enso-project-manager-${{ env.DIST_VERSION }}-macos-amd64.tar.gz
|
||||||
asset_content_type: application/x-tar
|
asset_content_type: application/x-tar
|
||||||
@ -501,7 +472,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path:
|
asset_path:
|
||||||
enso-project-manager-${{ env.DIST_VERSION }}-windows-amd64.zip
|
repo/built-distribution/enso-project-manager-${{ env.DIST_VERSION
|
||||||
|
}}-windows-amd64.zip
|
||||||
asset_name:
|
asset_name:
|
||||||
enso-project-manager-${{ env.DIST_VERSION }}-windows-amd64.zip
|
enso-project-manager-${{ env.DIST_VERSION }}-windows-amd64.zip
|
||||||
asset_content_type: application/zip
|
asset_content_type: application/zip
|
||||||
@ -512,7 +484,9 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path: enso-bundle-${{ env.DIST_VERSION }}-linux-amd64.tar.gz
|
asset_path:
|
||||||
|
repo/built-distribution/enso-bundle-${{ env.DIST_VERSION
|
||||||
|
}}-linux-amd64.tar.gz
|
||||||
asset_name: enso-bundle-${{ env.DIST_VERSION }}-linux-amd64.tar.gz
|
asset_name: enso-bundle-${{ env.DIST_VERSION }}-linux-amd64.tar.gz
|
||||||
asset_content_type: application/x-tar
|
asset_content_type: application/x-tar
|
||||||
- name: Publish the Bundle (MacOS)
|
- name: Publish the Bundle (MacOS)
|
||||||
@ -521,7 +495,9 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path: enso-bundle-${{ env.DIST_VERSION }}-macos-amd64.tar.gz
|
asset_path:
|
||||||
|
repo/built-distribution/enso-bundle-${{ env.DIST_VERSION
|
||||||
|
}}-macos-amd64.tar.gz
|
||||||
asset_name: enso-bundle-${{ env.DIST_VERSION }}-macos-amd64.tar.gz
|
asset_name: enso-bundle-${{ env.DIST_VERSION }}-macos-amd64.tar.gz
|
||||||
asset_content_type: application/x-tar
|
asset_content_type: application/x-tar
|
||||||
- name: Publish the Bundle (Windows)
|
- name: Publish the Bundle (Windows)
|
||||||
@ -530,7 +506,9 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path: enso-bundle-${{ env.DIST_VERSION }}-windows-amd64.zip
|
asset_path:
|
||||||
|
repo/built-distribution/enso-bundle-${{ env.DIST_VERSION
|
||||||
|
}}-windows-amd64.zip
|
||||||
asset_name: enso-bundle-${{ env.DIST_VERSION }}-windows-amd64.zip
|
asset_name: enso-bundle-${{ env.DIST_VERSION }}-windows-amd64.zip
|
||||||
asset_content_type: application/zip
|
asset_content_type: application/zip
|
||||||
|
|
||||||
@ -540,7 +518,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path: artifacts/manifest/manifest.yaml
|
asset_path: repo/built-distribution/manifest/manifest.yaml
|
||||||
asset_name: manifest.yaml
|
asset_name: manifest.yaml
|
||||||
asset_content_type: application/yaml
|
asset_content_type: application/yaml
|
||||||
- name: Publish the Launcher Manifest
|
- name: Publish the Launcher Manifest
|
||||||
@ -549,6 +527,6 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path: artifacts/launcher-manifest/launcher-manifest.yaml
|
asset_path: repo/built-distribution/launcher-manifest/launcher-manifest.yaml
|
||||||
asset_name: launcher-manifest.yaml
|
asset_name: launcher-manifest.yaml
|
||||||
asset_content_type: application/yaml
|
asset_content_type: application/yaml
|
||||||
|
14
.github/workflows/scala.yml
vendored
14
.github/workflows/scala.yml
vendored
@ -39,7 +39,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Enable Developer Command Prompt (Windows)
|
- name: Enable Developer Command Prompt (Windows)
|
||||||
uses: ilammy/msvc-dev-cmd@v1.4.1
|
uses: ilammy/msvc-dev-cmd@v1.5.0
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
- name: Disable TCP/UDP Offloading (macOS)
|
- name: Disable TCP/UDP Offloading (macOS)
|
||||||
@ -188,7 +188,7 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sleep 1
|
sleep 1
|
||||||
sbt 'set launcherDistributionRoot := file("${{ env.LAUNCHER_DIST_DIR }}"); buildLauncherDistribution'
|
sbt buildLauncherDistribution
|
||||||
|
|
||||||
# The way artifacts are uploaded currently does not preserve the
|
# The way artifacts are uploaded currently does not preserve the
|
||||||
# executable bits for Unix. However putting artifacts into a ZIP would
|
# executable bits for Unix. However putting artifacts into a ZIP would
|
||||||
@ -201,13 +201,13 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sleep 1
|
sleep 1
|
||||||
sbt 'set engineDistributionRoot := file("${{ env.ENGINE_DIST_DIR }}"); buildEngineDistribution'
|
sbt buildEngineDistribution
|
||||||
|
|
||||||
- name: Prepare Project Manager Distribution
|
- name: Prepare Project Manager Distribution
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sleep 1
|
sleep 1
|
||||||
sbt 'set projectManagerDistributionRoot := file("${{ env.PROJECTMANAGER_DIST_DIR }}"); buildProjectManagerDistribution'
|
sbt buildProjectManagerDistribution
|
||||||
|
|
||||||
# Test Distribution
|
# Test Distribution
|
||||||
- name: Prepare Engine Test Environment
|
- name: Prepare Engine Test Environment
|
||||||
@ -243,17 +243,17 @@ jobs:
|
|||||||
- name: Publish the Engine Distribution Artifact
|
- name: Publish the Engine Distribution Artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: ${{ env.ENGINE_DIST_ROOT }}
|
name: ${{ env.ENGINE_DIST_NAME }}
|
||||||
path: ${{ env.ENGINE_DIST_ROOT }}
|
path: ${{ env.ENGINE_DIST_ROOT }}
|
||||||
- name: Publish the Launcher
|
- name: Publish the Launcher
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: ${{ env.LAUNCHER_DIST_ROOT }}
|
name: ${{ env.LAUNCHER_DIST_NAME }}
|
||||||
path: ${{ env.LAUNCHER_DIST_ROOT }}
|
path: ${{ env.LAUNCHER_DIST_ROOT }}
|
||||||
- name: Publish the Project Manager
|
- name: Publish the Project Manager
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: ${{ env.PROJECTMANAGER_DIST_ROOT }}
|
name: ${{ env.PROJECTMANAGER_DIST_NAME }}
|
||||||
path: ${{ env.PROJECTMANAGER_DIST_ROOT }}
|
path: ${{ env.PROJECTMANAGER_DIST_ROOT }}
|
||||||
|
|
||||||
- name: Prepare the FlatBuffers Schemas for Upload
|
- name: Prepare the FlatBuffers Schemas for Upload
|
||||||
|
18
build.sbt
18
build.sbt
@ -93,6 +93,13 @@ openLegalReviewReport := {
|
|||||||
lazy val analyzeDependency = inputKey[Unit]("...")
|
lazy val analyzeDependency = inputKey[Unit]("...")
|
||||||
analyzeDependency := GatherLicenses.analyzeDependency.evaluated
|
analyzeDependency := GatherLicenses.analyzeDependency.evaluated
|
||||||
|
|
||||||
|
val packageBuilder = new DistributionPackage.Builder(
|
||||||
|
ensoVersion = ensoVersion,
|
||||||
|
graalVersion = graalVersion,
|
||||||
|
graalJavaVersion = javaVersion,
|
||||||
|
artifactRoot = file("built-distribution")
|
||||||
|
)
|
||||||
|
|
||||||
Global / onChangedBuildSource := ReloadOnSourceChanges
|
Global / onChangedBuildSource := ReloadOnSourceChanges
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@ -201,6 +208,9 @@ lazy val enso = (project in file("."))
|
|||||||
testkit
|
testkit
|
||||||
)
|
)
|
||||||
.settings(Global / concurrentRestrictions += Tags.exclusive(Exclusive))
|
.settings(Global / concurrentRestrictions += Tags.exclusive(Exclusive))
|
||||||
|
.settings(
|
||||||
|
commands ++= Seq(packageBuilder.makePackages, packageBuilder.makeBundles)
|
||||||
|
)
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// === Dependency Versions ====================================================
|
// === Dependency Versions ====================================================
|
||||||
@ -1338,9 +1348,11 @@ lazy val launcherDistributionRoot =
|
|||||||
lazy val projectManagerDistributionRoot =
|
lazy val projectManagerDistributionRoot =
|
||||||
settingKey[File]("Root of built project manager distribution")
|
settingKey[File]("Root of built project manager distribution")
|
||||||
|
|
||||||
engineDistributionRoot := file("built-distribution/engine")
|
engineDistributionRoot :=
|
||||||
launcherDistributionRoot := file("built-distribution/launcher")
|
packageBuilder.localArtifact("engine") / s"enso-$ensoVersion"
|
||||||
projectManagerDistributionRoot := file("built-distribution/project-manager")
|
launcherDistributionRoot := packageBuilder.localArtifact("launcher") / "enso"
|
||||||
|
projectManagerDistributionRoot :=
|
||||||
|
packageBuilder.localArtifact("project-manager") / "enso"
|
||||||
|
|
||||||
lazy val buildEngineDistribution =
|
lazy val buildEngineDistribution =
|
||||||
taskKey[Unit]("Builds the engine distribution")
|
taskKey[Unit]("Builds the engine distribution")
|
||||||
|
1
distribution/enso.bundle.template
Normal file
1
distribution/enso.bundle.template
Normal file
@ -0,0 +1 @@
|
|||||||
|
Enso Bundle Marker
|
@ -27,7 +27,7 @@ dependencies, and Enso projects for use by our users.
|
|||||||
Explanation of the fallback infrastructure that can be enabled to keep
|
Explanation of the fallback infrastructure that can be enabled to keep
|
||||||
launcher updates functioning even if the primary release provider stops
|
launcher updates functioning even if the primary release provider stops
|
||||||
working.
|
working.
|
||||||
- [**Local Repository:**](local-repository.md) Explanation of local repository
|
|
||||||
structure that is used for bundling engine with project manager distributions.
|
|
||||||
- [**Standard Libraries:**](standard-libraries.md) A brief explanation of the
|
- [**Standard Libraries:**](standard-libraries.md) A brief explanation of the
|
||||||
standard libraries for Enso.
|
standard libraries for Enso.
|
||||||
|
- [**Bundles**](bundles.md) An explanation of distributed bundles that contain
|
||||||
|
all components necessary to run Enso out of the box.
|
||||||
|
71
docs/distribution/bundles.md
Normal file
71
docs/distribution/bundles.md
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
---
|
||||||
|
layout: developer-doc
|
||||||
|
title: Distribution Bundles
|
||||||
|
category: distribution
|
||||||
|
tags: [distribution, layout, bundles]
|
||||||
|
order: 9
|
||||||
|
---
|
||||||
|
|
||||||
|
# Bundles
|
||||||
|
|
||||||
|
This document describes how the distributions are bundled to provide releases
|
||||||
|
that work out-of-the box, allowing to use the latest engine without downloading
|
||||||
|
any additional dependencies.
|
||||||
|
|
||||||
|
<!-- MarkdownTOC levels="2,3" autolink="true" -->
|
||||||
|
|
||||||
|
- [Project Manager Bundle](#project-manager-bundle)
|
||||||
|
- [Launcher Bundles](#launcher-bundles)
|
||||||
|
|
||||||
|
<!-- /MarkdownTOC -->
|
||||||
|
|
||||||
|
## Project Manager Bundle
|
||||||
|
|
||||||
|
The Project Manager is distributed with latest engine version and its
|
||||||
|
corresponding Graal runtime to avoid having to download them at first startup.
|
||||||
|
|
||||||
|
The bundled components are placed in their respective subdirectories (not as
|
||||||
|
packages, but extracted and ready to use) and a bundle marker file called
|
||||||
|
`.enso.bundle` must be placed next to these directories so that the Project
|
||||||
|
Manager can detect the bundle.
|
||||||
|
|
||||||
|
The `project-manager` executable looks for the `.enso.bundle` marker in the
|
||||||
|
parent directory of the directory that it is, itself, located in. So overall,
|
||||||
|
the bundle should have the following structure (the actual engine and Graal
|
||||||
|
versions may of course differ):
|
||||||
|
|
||||||
|
```
|
||||||
|
enso
|
||||||
|
├── bin
|
||||||
|
│ └── project-manager
|
||||||
|
├── dist
|
||||||
|
│ └── 0.2.1-SNAPSHOT
|
||||||
|
├── other-project-manager-files
|
||||||
|
└── runtime
|
||||||
|
└── graalvm-ce-java11-20.2.0
|
||||||
|
```
|
||||||
|
|
||||||
|
If the bundle is detected, the additional `dist` and `runtime` directories are
|
||||||
|
added as secondary search paths for components. Thus, the `project-manager` can
|
||||||
|
use both components present in the default
|
||||||
|
[installed location](distribution.md#installed-enso-distribution-layout) or
|
||||||
|
those from the bundle. In a situation that the same component were to be
|
||||||
|
available both in the installed location and the bundle, the installed location
|
||||||
|
is preferred. New components are installed in the installed location, never next
|
||||||
|
to the bundles.
|
||||||
|
|
||||||
|
In fact, it is possible for the bundle directory to be read-only (which may be
|
||||||
|
the case for example if the Project Manager bundle is packaged as part of IDE's
|
||||||
|
AppImage package). In such situation, it will be impossible to uninstall the
|
||||||
|
bundled components and a relevant error message will be returned.
|
||||||
|
|
||||||
|
## Launcher Bundles
|
||||||
|
|
||||||
|
Bundles are also distributed for the launcher, but these are implemented using a
|
||||||
|
different mechanism.
|
||||||
|
|
||||||
|
Since the launcher can run in
|
||||||
|
[portable mode](distribution.md#portable-enso-distribution-layout), the bundled
|
||||||
|
engine and runtime are simply included within its portable package. They can
|
||||||
|
then be used from within this portable package or
|
||||||
|
[installed](distribution.md#installing-from-a-portable-distribution).
|
@ -3,7 +3,7 @@ layout: developer-doc
|
|||||||
title: Fallback Launcher Release Infrastructure
|
title: Fallback Launcher Release Infrastructure
|
||||||
category: distribution
|
category: distribution
|
||||||
tags: [distribution, launcher, fallback]
|
tags: [distribution, launcher, fallback]
|
||||||
order: 6
|
order: 7
|
||||||
---
|
---
|
||||||
|
|
||||||
# Fallback Launcher Release Infrastructure
|
# Fallback Launcher Release Infrastructure
|
||||||
|
@ -1,107 +0,0 @@
|
|||||||
---
|
|
||||||
layout: developer-doc
|
|
||||||
title: Local Repository
|
|
||||||
category: distribution
|
|
||||||
tags: [distribution, project-manager, offline, local]
|
|
||||||
order: 7
|
|
||||||
---
|
|
||||||
|
|
||||||
# Local Repository
|
|
||||||
|
|
||||||
A `LocalReleaseProvider` is implemented that allows to install components from
|
|
||||||
local (offline) repositories. This functionality can be used to allow installing
|
|
||||||
bundled components.
|
|
||||||
|
|
||||||
<!-- MarkdownTOC levels="2,3" autolink="true" -->
|
|
||||||
|
|
||||||
- [Local Repository Structure](#local-repository-structure)
|
|
||||||
- [General Repository Structure](#general-repository-structure)
|
|
||||||
- [Engine Repository Structure](#engine-repository-structure)
|
|
||||||
- [GraalVM Repository Structure](#graalvm-repository-structure)
|
|
||||||
- [Usage in Project Manager](#usage-in-project-manager)
|
|
||||||
|
|
||||||
<!-- /MarkdownTOC -->
|
|
||||||
|
|
||||||
## Local Repository Structure
|
|
||||||
|
|
||||||
This section explains how a local repository has to be structured in order to
|
|
||||||
work with `LocalReleaseProvider`.
|
|
||||||
|
|
||||||
### General Repository Structure
|
|
||||||
|
|
||||||
In general a local repository should be a separate directory that contains only
|
|
||||||
directories corresponding to releases of a single component. Repositories for
|
|
||||||
separate components should be kept separately. For each provided release it
|
|
||||||
should contain a directory called after the release's tag. That directory of
|
|
||||||
each release should just contain assets associated with that release.
|
|
||||||
|
|
||||||
### Engine Repository Structure
|
|
||||||
|
|
||||||
The engine repository contains a directory `enso-<VERSION>` for each release
|
|
||||||
that resembles the GitHub release structure. The directory for each release
|
|
||||||
should contain a `manifest.yaml` file and the package. As separate bundles are
|
|
||||||
created for each operating system, only the package for the desired operating
|
|
||||||
system is required (normally releases contain packages for all supported
|
|
||||||
systems). It's naming scheme is the same as in GitHub releases, that is
|
|
||||||
`enso-engine-<VERSION>-<OS>-<ARCH>.{zip|tar.gz}`. The extension is `zip` for
|
|
||||||
Windows and `tar.gz` for other platforms. Currently, the only supported `ARCH`
|
|
||||||
is `amd64`. The `OS` can be one of `windows`, `linux`, `macos`.
|
|
||||||
|
|
||||||
For example, a local engine repository could look like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
localengine
|
|
||||||
└── enso-0.1.2-rc.9
|
|
||||||
├── enso-engine-0.1.2-rc.9-linux-amd64.tar.gz
|
|
||||||
└── manifest.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
### GraalVM Repository Structure
|
|
||||||
|
|
||||||
The GraalVM repository contains a directory `vm-<VERSION>` for each release.
|
|
||||||
Inside of that directory, a package should be included (again as in case of the
|
|
||||||
engine, only the package for the current operating system is required). The
|
|
||||||
package name should be
|
|
||||||
`graalvm-ce-java<JAVA_VERSION>-<OS>-<ARCH>-<VERSION>.{zip|tar.gz}`. The
|
|
||||||
extension is `zip` on Windows and `tar.gz` on other platforms. The `ARCH` should
|
|
||||||
be the same as for the engine. The `OS` can be one of `windows`, `linux`,
|
|
||||||
`darwin`. **Note that the MacOS package has different naming scheme for GraalVM
|
|
||||||
than it has for the engine**.
|
|
||||||
|
|
||||||
For example, a local GraalVM repository can look like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
localruntime
|
|
||||||
└── vm-20.2.0
|
|
||||||
└── graalvm-ce-java11-linux-amd64-20.2.0.tar.gz
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage in Project Manager
|
|
||||||
|
|
||||||
Command line options can be used to enable the local repositories in the project
|
|
||||||
manager. `--local-engine-repository` sets the path to the engine repository and
|
|
||||||
`--local-graal-repository` sets the path to the GraalVM repository. The provided
|
|
||||||
paths should be absolute to be sure that they are resolved correctly.
|
|
||||||
|
|
||||||
For example, starting the project manager as written below will first look for
|
|
||||||
engines and GraalVM runtimes in the provided local repositories (but if they are
|
|
||||||
not found, online repository will be used as fallback, if it is available).
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./project-manager --local-engine-repository /a/b/bundle/engines --local-graal-repository /a/b/bundle/graalvm
|
|
||||||
```
|
|
||||||
|
|
||||||
For the above command to work properly, the directory `/a/b/bundle/` may have
|
|
||||||
the following structure:
|
|
||||||
|
|
||||||
```
|
|
||||||
bundle
|
|
||||||
├── other files (project-manager binary etc.)
|
|
||||||
├── engines
|
|
||||||
│ └── enso-0.1.2-rc.9
|
|
||||||
│ ├── enso-engine-0.1.2-rc.9-linux-amd64.tar.gz
|
|
||||||
│ └── manifest.yaml
|
|
||||||
└── graalvm
|
|
||||||
└── vm-20.2.0
|
|
||||||
└── graalvm-ce-java11-linux-amd64-20.2.0.tar.gz
|
|
||||||
```
|
|
@ -3,7 +3,7 @@ layout: developer-doc
|
|||||||
title: Standard Libraries
|
title: Standard Libraries
|
||||||
category: distribution
|
category: distribution
|
||||||
tags: [distribution, stdlib]
|
tags: [distribution, stdlib]
|
||||||
order: 9
|
order: 8
|
||||||
---
|
---
|
||||||
|
|
||||||
# Standard Libraries
|
# Standard Libraries
|
||||||
|
@ -7,12 +7,10 @@ import scala.util.Try
|
|||||||
|
|
||||||
object Cli {
|
object Cli {
|
||||||
|
|
||||||
val JSON_OPTION = "json"
|
val JSON_OPTION = "json"
|
||||||
val HELP_OPTION = "help"
|
val HELP_OPTION = "help"
|
||||||
val VERBOSE_OPTION = "verbose"
|
val VERBOSE_OPTION = "verbose"
|
||||||
val VERSION_OPTION = "version"
|
val VERSION_OPTION = "version"
|
||||||
val LOCAL_ENGINE_REPOSITORY = "local-engine-repository"
|
|
||||||
val LOCAL_GRAAL_REPOSITORY = "local-graal-repository"
|
|
||||||
|
|
||||||
object option {
|
object option {
|
||||||
|
|
||||||
@ -37,28 +35,6 @@ object Cli {
|
|||||||
.longOpt(JSON_OPTION)
|
.longOpt(JSON_OPTION)
|
||||||
.desc("Switches the --version option to JSON output.")
|
.desc("Switches the --version option to JSON output.")
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
val localEngineRepository: cli.Option = cli.Option.builder
|
|
||||||
.longOpt(LOCAL_ENGINE_REPOSITORY)
|
|
||||||
.hasArg
|
|
||||||
.numberOfArgs(1)
|
|
||||||
.argName("path")
|
|
||||||
.desc(
|
|
||||||
"Allows the Project Manager to install engine versions from an " +
|
|
||||||
"offline repository."
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val localGraalRepository: cli.Option = cli.Option.builder
|
|
||||||
.longOpt(LOCAL_GRAAL_REPOSITORY)
|
|
||||||
.hasArg
|
|
||||||
.numberOfArgs(1)
|
|
||||||
.argName("path")
|
|
||||||
.desc(
|
|
||||||
"Allows the Project Manager to install GraalVM versions from an " +
|
|
||||||
"offline repository."
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val options: cli.Options =
|
val options: cli.Options =
|
||||||
@ -67,8 +43,6 @@ object Cli {
|
|||||||
.addOption(option.verbose)
|
.addOption(option.verbose)
|
||||||
.addOption(option.version)
|
.addOption(option.version)
|
||||||
.addOption(option.json)
|
.addOption(option.json)
|
||||||
.addOption(option.localEngineRepository)
|
|
||||||
.addOption(option.localGraalRepository)
|
|
||||||
|
|
||||||
/** Parse the command line options. */
|
/** Parse the command line options. */
|
||||||
def parse(args: Array[String]): Either[String, cli.CommandLine] = {
|
def parse(args: Array[String]): Either[String, cli.CommandLine] = {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package org.enso.projectmanager.boot
|
package org.enso.projectmanager.boot
|
||||||
|
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.nio.file.{InvalidPathException, Path}
|
|
||||||
import java.util.concurrent.ScheduledThreadPoolExecutor
|
import java.util.concurrent.ScheduledThreadPoolExecutor
|
||||||
|
|
||||||
import akka.http.scaladsl.Http
|
import akka.http.scaladsl.Http
|
||||||
@ -15,7 +14,6 @@ import org.enso.projectmanager.boot.Globals.{
|
|||||||
SuccessExitCode
|
SuccessExitCode
|
||||||
}
|
}
|
||||||
import org.enso.projectmanager.boot.configuration.ProjectManagerConfig
|
import org.enso.projectmanager.boot.configuration.ProjectManagerConfig
|
||||||
import org.enso.projectmanager.versionmanagement.DefaultDistributionConfiguration
|
|
||||||
import org.enso.version.VersionDescription
|
import org.enso.version.VersionDescription
|
||||||
import pureconfig.ConfigSource
|
import pureconfig.ConfigSource
|
||||||
import pureconfig.generic.auto._
|
import pureconfig.generic.auto._
|
||||||
@ -120,44 +118,7 @@ object ProjectManager extends App with LazyLogging {
|
|||||||
} else {
|
} else {
|
||||||
val verbosity = options.getOptions.count(_ == Cli.option.verbose)
|
val verbosity = options.getOptions.count(_ == Cli.option.verbose)
|
||||||
logger.info("Starting Project Manager...")
|
logger.info("Starting Project Manager...")
|
||||||
|
setupLogging(verbosity) *>
|
||||||
def parsePath(string: String) = ZIO.effect(Path.of(string))
|
|
||||||
def parseOptionalPath(string: Option[String]) =
|
|
||||||
string.map(parsePath).map(_.map(Some(_))).getOrElse(ZIO.succeed(None))
|
|
||||||
|
|
||||||
val initializeLocalRepositories = for {
|
|
||||||
enginePath <- parseOptionalPath(
|
|
||||||
Option(options.getOptionValue(Cli.LOCAL_ENGINE_REPOSITORY))
|
|
||||||
)
|
|
||||||
graalPath <- parseOptionalPath(
|
|
||||||
Option(options.getOptionValue(Cli.LOCAL_GRAAL_REPOSITORY))
|
|
||||||
)
|
|
||||||
_ <- ZIO.effect(
|
|
||||||
DefaultDistributionConfiguration.setupLocalRepositories(
|
|
||||||
enginePath,
|
|
||||||
graalPath
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} yield ()
|
|
||||||
|
|
||||||
val initializeRepositoryOrLogError = initializeLocalRepositories
|
|
||||||
.catchSome { case error: InvalidPathException =>
|
|
||||||
ZIO.effectTotal(
|
|
||||||
logger
|
|
||||||
.error(s"Could not parse a local repository path: $error", error)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.catchAll { th =>
|
|
||||||
ZIO.effectTotal(
|
|
||||||
logger.error(
|
|
||||||
"Failed to initialize local repositories, " +
|
|
||||||
"default ones will be used.",
|
|
||||||
th
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
setupLogging(verbosity) *> initializeRepositoryOrLogError *>
|
|
||||||
mainProcess.fold(
|
mainProcess.fold(
|
||||||
th => {
|
th => {
|
||||||
logger.error("Main process execution failed.", th)
|
logger.error("Main process execution failed.", th)
|
||||||
|
@ -2,19 +2,8 @@ package org.enso.projectmanager.service.versionmanagement
|
|||||||
|
|
||||||
import org.enso.projectmanager.control.effect.ErrorChannel
|
import org.enso.projectmanager.control.effect.ErrorChannel
|
||||||
import org.enso.projectmanager.service.ProjectServiceFailure
|
import org.enso.projectmanager.service.ProjectServiceFailure
|
||||||
import org.enso.projectmanager.service.ProjectServiceFailure.{
|
import org.enso.projectmanager.service.ProjectServiceFailure._
|
||||||
BrokenComponentFailure,
|
import org.enso.runtimeversionmanager.components._
|
||||||
ComponentInstallationFailure,
|
|
||||||
MissingComponentFailure,
|
|
||||||
ProjectManagerUpgradeRequiredFailure
|
|
||||||
}
|
|
||||||
import org.enso.runtimeversionmanager.components.{
|
|
||||||
BrokenComponentError,
|
|
||||||
ComponentMissingError,
|
|
||||||
ComponentsException,
|
|
||||||
InstallationError,
|
|
||||||
UpgradeRequiredError
|
|
||||||
}
|
|
||||||
|
|
||||||
object RuntimeVersionManagerErrorRecoverySyntax {
|
object RuntimeVersionManagerErrorRecoverySyntax {
|
||||||
implicit class ErrorRecovery[F[+_, +_]: ErrorChannel, A](
|
implicit class ErrorRecovery[F[+_, +_]: ErrorChannel, A](
|
||||||
@ -42,6 +31,8 @@ object RuntimeVersionManagerErrorRecoverySyntax {
|
|||||||
ProjectManagerUpgradeRequiredFailure(
|
ProjectManagerUpgradeRequiredFailure(
|
||||||
upgradeRequired.expectedVersion
|
upgradeRequired.expectedVersion
|
||||||
)
|
)
|
||||||
|
case UninstallationError(message) =>
|
||||||
|
ComponentUninstallationFailure(message)
|
||||||
case _ => mapDefault(componentsException)
|
case _ => mapDefault(componentsException)
|
||||||
}
|
}
|
||||||
case other: Throwable =>
|
case other: Throwable =>
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package org.enso.projectmanager.versionmanagement
|
package org.enso.projectmanager.versionmanagement
|
||||||
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
import com.typesafe.scalalogging.LazyLogging
|
import com.typesafe.scalalogging.LazyLogging
|
||||||
import org.enso.runtimeversionmanager.Environment
|
import org.enso.runtimeversionmanager.Environment
|
||||||
import org.enso.runtimeversionmanager.components.{
|
import org.enso.runtimeversionmanager.components.{
|
||||||
@ -19,10 +17,7 @@ import org.enso.runtimeversionmanager.releases.engine.{
|
|||||||
EngineRelease,
|
EngineRelease,
|
||||||
EngineRepository
|
EngineRepository
|
||||||
}
|
}
|
||||||
import org.enso.runtimeversionmanager.releases.graalvm.{
|
import org.enso.runtimeversionmanager.releases.graalvm.GraalCEReleaseProvider
|
||||||
GraalCEReleaseProvider,
|
|
||||||
GraalVMRuntimeReleaseProvider
|
|
||||||
}
|
|
||||||
import org.enso.runtimeversionmanager.runner.JVMSettings
|
import org.enso.runtimeversionmanager.runner.JVMSettings
|
||||||
|
|
||||||
/** Default distribution configuration to use for the Project Manager in
|
/** Default distribution configuration to use for the Project Manager in
|
||||||
@ -52,15 +47,9 @@ object DefaultDistributionConfiguration
|
|||||||
lazy val temporaryDirectoryManager =
|
lazy val temporaryDirectoryManager =
|
||||||
new TemporaryDirectoryManager(distributionManager, resourceManager)
|
new TemporaryDirectoryManager(distributionManager, resourceManager)
|
||||||
|
|
||||||
private var currentEngineReleaseProvider: ReleaseProvider[EngineRelease] =
|
|
||||||
EngineRepository.defaultEngineReleaseProvider
|
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
def engineReleaseProvider: ReleaseProvider[EngineRelease] =
|
def engineReleaseProvider: ReleaseProvider[EngineRelease] =
|
||||||
currentEngineReleaseProvider
|
EngineRepository.defaultEngineReleaseProvider
|
||||||
|
|
||||||
private var runtimeReleaseProvider: GraalVMRuntimeReleaseProvider =
|
|
||||||
GraalCEReleaseProvider.default
|
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
def makeRuntimeVersionManager(
|
def makeRuntimeVersionManager(
|
||||||
@ -72,7 +61,7 @@ object DefaultDistributionConfiguration
|
|||||||
temporaryDirectoryManager = temporaryDirectoryManager,
|
temporaryDirectoryManager = temporaryDirectoryManager,
|
||||||
resourceManager = resourceManager,
|
resourceManager = resourceManager,
|
||||||
engineReleaseProvider = engineReleaseProvider,
|
engineReleaseProvider = engineReleaseProvider,
|
||||||
runtimeReleaseProvider = runtimeReleaseProvider,
|
runtimeReleaseProvider = GraalCEReleaseProvider.default,
|
||||||
installerKind = InstallerKind.ProjectManager
|
installerKind = InstallerKind.ProjectManager
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -81,35 +70,4 @@ object DefaultDistributionConfiguration
|
|||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def shouldDiscardChildOutput: Boolean = false
|
override def shouldDiscardChildOutput: Boolean = false
|
||||||
|
|
||||||
/** Sets up local repositories if they were requested.
|
|
||||||
* @param engineRepositoryPath the path to a local engine repository if one
|
|
||||||
* should be used
|
|
||||||
* @param graalRepositoryPath the path to a local GraalVM repository if one
|
|
||||||
* should be used
|
|
||||||
*/
|
|
||||||
def setupLocalRepositories(
|
|
||||||
engineRepositoryPath: Option[Path],
|
|
||||||
graalRepositoryPath: Option[Path]
|
|
||||||
): Unit = {
|
|
||||||
val engineProviderOverride =
|
|
||||||
engineRepositoryPath.map(path =>
|
|
||||||
(path, EngineRepository.fromLocalRepository(path))
|
|
||||||
)
|
|
||||||
|
|
||||||
val graalProviderOverride =
|
|
||||||
graalRepositoryPath.map(path =>
|
|
||||||
(path, GraalCEReleaseProvider.fromLocalRepository(path))
|
|
||||||
)
|
|
||||||
|
|
||||||
engineProviderOverride.foreach { case (path, newProvider) =>
|
|
||||||
logger.debug(s"Using a local engine repository from $path.")
|
|
||||||
currentEngineReleaseProvider = newProvider
|
|
||||||
}
|
|
||||||
|
|
||||||
graalProviderOverride.foreach { case (path, newProvider) =>
|
|
||||||
logger.debug(s"Using a local GraalVM repository from $path.")
|
|
||||||
runtimeReleaseProvider = newProvider
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ class TestRuntimeVersionManagementUserInterface(installBroken: Boolean)
|
|||||||
true
|
true
|
||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
override def logInfo(message: => String): Unit = logger.debug(message)
|
override def logInfo(message: => String): Unit = logger.info(message)
|
||||||
|
|
||||||
override def startWaitingForResource(resource: Resource): Unit =
|
override def startWaitingForResource(resource: Resource): Unit =
|
||||||
logger.debug(s"Waiting on ${resource.name}")
|
logger.debug(s"Waiting on ${resource.name}")
|
||||||
|
@ -1,168 +0,0 @@
|
|||||||
package org.enso.runtimeversionmanager.components
|
|
||||||
|
|
||||||
import java.nio.file.Files
|
|
||||||
|
|
||||||
import nl.gn0s1s.bump.SemVer
|
|
||||||
import org.enso.loggingservice.TestLogger
|
|
||||||
import org.enso.runtimeversionmanager.FileSystem
|
|
||||||
import org.enso.runtimeversionmanager.FileSystem.PathSyntax
|
|
||||||
import org.enso.runtimeversionmanager.releases.{
|
|
||||||
EnsoReleaseProvider,
|
|
||||||
Release,
|
|
||||||
SimpleReleaseProvider
|
|
||||||
}
|
|
||||||
import org.enso.runtimeversionmanager.releases.engine.EngineReleaseProvider
|
|
||||||
import org.enso.runtimeversionmanager.releases.graalvm.GraalCEReleaseProvider
|
|
||||||
import org.enso.runtimeversionmanager.releases.local.LocalReleaseProvider
|
|
||||||
import org.enso.runtimeversionmanager.releases.testing.TestArchivePackager
|
|
||||||
import org.enso.runtimeversionmanager.test.{
|
|
||||||
FakeReleases,
|
|
||||||
RuntimeVersionManagerTest
|
|
||||||
}
|
|
||||||
|
|
||||||
import scala.util.{Failure, Try}
|
|
||||||
|
|
||||||
class LocalReleaseProviderSpec extends RuntimeVersionManagerTest {
|
|
||||||
private def localEngines = getTestDirectory / "offline-engine"
|
|
||||||
private def localRuntimes = getTestDirectory / "offline-graal"
|
|
||||||
|
|
||||||
/** Creates a [[RuntimeVersionManager]] that is tied to the local/offline
|
|
||||||
* repository with fallback to default fake release repository.
|
|
||||||
*/
|
|
||||||
private def makeRuntimeManagerWithLocalRepository(): RuntimeVersionManager = {
|
|
||||||
val engineProvider =
|
|
||||||
new LocalReleaseProvider(localEngines, FakeReleases.baseEngineProvider)
|
|
||||||
val runtimeProvider =
|
|
||||||
new LocalReleaseProvider(localRuntimes, FakeReleases.baseRuntimeProvider)
|
|
||||||
makeManagers(
|
|
||||||
engineProvider = new EngineReleaseProvider(engineProvider),
|
|
||||||
runtimeProvider = new GraalCEReleaseProvider(runtimeProvider)
|
|
||||||
)._2
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Creates a local repository with engine 1.2.3-local that uses GraalVM 20.20.20-local.
|
|
||||||
*
|
|
||||||
* It uses the prepared fake-releases and just re-configures them.
|
|
||||||
*/
|
|
||||||
private def prepareLocalRepository(): Unit = {
|
|
||||||
Files.createDirectories(localEngines)
|
|
||||||
Files.createDirectories(localRuntimes)
|
|
||||||
|
|
||||||
{
|
|
||||||
val engineVersion = SemVer(1, 2, 3, Some("local"))
|
|
||||||
val engineName = s"enso-$engineVersion"
|
|
||||||
val destinationRoot = localEngines / engineName
|
|
||||||
Files.createDirectories(destinationRoot)
|
|
||||||
val manifest =
|
|
||||||
"""minimum-launcher-version: 0.0.1
|
|
||||||
|minimum-project-manager-version: 0.0.1
|
|
||||||
|graal-vm-version: 20.20.20-local
|
|
||||||
|graal-java-version: 11
|
|
||||||
|""".stripMargin
|
|
||||||
val sourceArchive =
|
|
||||||
EnsoReleaseProvider.packageNameForComponent("engine", SemVer(0, 0, 0))
|
|
||||||
val tmpArchive = getTestDirectory / sourceArchive
|
|
||||||
FileSystem.copyDirectory(
|
|
||||||
FakeReleases.engineRoot / "enso-0.0.0" / sourceArchive / "enso-0.0.0",
|
|
||||||
tmpArchive / engineName
|
|
||||||
)
|
|
||||||
FileSystem.writeTextFile(
|
|
||||||
tmpArchive / engineName / "manifest.yaml",
|
|
||||||
manifest
|
|
||||||
)
|
|
||||||
FileSystem.writeTextFile(destinationRoot / "manifest.yaml", manifest)
|
|
||||||
val archive =
|
|
||||||
EnsoReleaseProvider.packageNameForComponent("engine", engineVersion)
|
|
||||||
TestArchivePackager.packArchive(
|
|
||||||
tmpArchive,
|
|
||||||
destinationRoot / archive
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
val sourceVersion =
|
|
||||||
GraalVMVersion(SemVer(2, 0, 0), "11")
|
|
||||||
val targetVersion =
|
|
||||||
GraalVMVersion(SemVer(20, 20, 20, Some("local")), "11")
|
|
||||||
val destinationRoot = localRuntimes / s"vm-${targetVersion.graalVersion}"
|
|
||||||
Files.createDirectories(destinationRoot)
|
|
||||||
val sourceRoot =
|
|
||||||
FakeReleases.runtimeRoot / s"vm-${sourceVersion.graalVersion}"
|
|
||||||
TestArchivePackager.packArchive(
|
|
||||||
sourceRoot / GraalCEReleaseProvider.packageFileNameForCurrentOS(
|
|
||||||
sourceVersion
|
|
||||||
),
|
|
||||||
destinationRoot / GraalCEReleaseProvider.packageFileNameForCurrentOS(
|
|
||||||
targetVersion
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
"LocalReleaseProvider" should {
|
|
||||||
"install a release from a local repository" in {
|
|
||||||
prepareLocalRepository()
|
|
||||||
val runtimeVersionManager = makeRuntimeManagerWithLocalRepository()
|
|
||||||
val engineVersion = SemVer(1, 2, 3, Some("local"))
|
|
||||||
val runtimeVersion =
|
|
||||||
GraalVMVersion(SemVer(20, 20, 20, Some("local")), "11")
|
|
||||||
runtimeVersionManager.findOrInstallEngine(engineVersion)
|
|
||||||
runtimeVersionManager
|
|
||||||
.listInstalledEngines()
|
|
||||||
.map(_.version) shouldEqual Seq(engineVersion)
|
|
||||||
runtimeVersionManager
|
|
||||||
.listInstalledGraalRuntimes()
|
|
||||||
.map(_.version) shouldEqual Seq(runtimeVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
"install a release from the fallback repository" in {
|
|
||||||
val runtimeVersionManager = makeRuntimeManagerWithLocalRepository()
|
|
||||||
val engineVersion = SemVer(0, 0, 0)
|
|
||||||
runtimeVersionManager.findOrInstallEngine(engineVersion)
|
|
||||||
runtimeVersionManager
|
|
||||||
.listInstalledEngines()
|
|
||||||
.map(_.version) shouldEqual Seq(engineVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
"include releases from both local and fallback" in {
|
|
||||||
val localVersion = "enso-1.2.3-local"
|
|
||||||
Files.createDirectories(localEngines / localVersion)
|
|
||||||
|
|
||||||
val releaseProvider = new LocalReleaseProvider(
|
|
||||||
localEngines,
|
|
||||||
FakeReleases.baseEngineProvider
|
|
||||||
)
|
|
||||||
|
|
||||||
val tags = releaseProvider.listReleases().get.map(_.tag)
|
|
||||||
tags should contain(localVersion)
|
|
||||||
tags should contain("enso-0.0.0")
|
|
||||||
}
|
|
||||||
|
|
||||||
"work in 'offline-mode' if fallback is unavailable" in {
|
|
||||||
val unavailableProvider = new SimpleReleaseProvider {
|
|
||||||
override def releaseForTag(tag: String): Try[Release] =
|
|
||||||
Failure(new RuntimeException("Repository unavailable."))
|
|
||||||
|
|
||||||
override def listReleases(): Try[Seq[Release]] =
|
|
||||||
Failure(new RuntimeException("Repository unavailable."))
|
|
||||||
}
|
|
||||||
|
|
||||||
val localVersion = "enso-1.2.3-local"
|
|
||||||
Files.createDirectories(localEngines / localVersion)
|
|
||||||
val releaseProvider =
|
|
||||||
new LocalReleaseProvider(localEngines, unavailableProvider)
|
|
||||||
|
|
||||||
val logs = TestLogger.gatherLogs {
|
|
||||||
releaseProvider.listReleases().get.map(_.tag) shouldEqual Seq(
|
|
||||||
localVersion
|
|
||||||
)
|
|
||||||
|
|
||||||
Thread.sleep(500) // making sure the log is processed
|
|
||||||
}
|
|
||||||
val expectedMessage =
|
|
||||||
"The remote release provider failed with java.lang.RuntimeException: " +
|
|
||||||
"Repository unavailable., but locally bundled releases are available."
|
|
||||||
logs.map(_.message) should contain(expectedMessage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +1,18 @@
|
|||||||
package org.enso.runtimeversionmanager.components
|
package org.enso.runtimeversionmanager.components
|
||||||
|
|
||||||
|
import java.nio.file.{Files, Path}
|
||||||
|
|
||||||
import nl.gn0s1s.bump.SemVer
|
import nl.gn0s1s.bump.SemVer
|
||||||
import org.enso.runtimeversionmanager.components
|
import org.enso.runtimeversionmanager.FileSystem.PathSyntax
|
||||||
import org.enso.runtimeversionmanager.config.GlobalConfigurationManager
|
import org.enso.runtimeversionmanager.config.GlobalConfigurationManager
|
||||||
import org.enso.runtimeversionmanager.test.{
|
import org.enso.runtimeversionmanager.test.{
|
||||||
RuntimeVersionManagerTest,
|
RuntimeVersionManagerTest,
|
||||||
TestRuntimeVersionManagementUserInterface
|
TestRuntimeVersionManagementUserInterface
|
||||||
}
|
}
|
||||||
|
import org.enso.runtimeversionmanager.{components, FileSystem, OS}
|
||||||
|
import org.enso.testkit.OsSpec
|
||||||
|
|
||||||
class RuntimeVersionManagerSpec extends RuntimeVersionManagerTest {
|
class RuntimeVersionManagerSpec extends RuntimeVersionManagerTest with OsSpec {
|
||||||
|
|
||||||
"RuntimeVersionManager" should {
|
"RuntimeVersionManager" should {
|
||||||
"find the latest engine version in semver ordering " +
|
"find the latest engine version in semver ordering " +
|
||||||
@ -176,5 +180,139 @@ class RuntimeVersionManagerSpec extends RuntimeVersionManagerTest {
|
|||||||
}
|
}
|
||||||
upgradeException.expectedVersion shouldEqual bigVersion
|
upgradeException.expectedVersion shouldEqual bigVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"support bundled components" in {
|
||||||
|
val engineVersion = SemVer(0, 1, 0)
|
||||||
|
val runtimeVersion = GraalVMVersion(SemVer(1, 0, 0), "11")
|
||||||
|
prepareBundle(
|
||||||
|
engines = Seq(engineVersion),
|
||||||
|
runtimes = Seq(runtimeVersion)
|
||||||
|
)
|
||||||
|
val manager = makeRuntimeVersionManager()
|
||||||
|
|
||||||
|
val engine = manager.findEngine(engineVersion).value
|
||||||
|
engine.version shouldEqual engineVersion
|
||||||
|
engine.isMarkedBroken shouldEqual false
|
||||||
|
engine.ensureValid()
|
||||||
|
|
||||||
|
manager.findGraalRuntime(engine).value.version shouldEqual runtimeVersion
|
||||||
|
manager.findGraalRuntime(runtimeVersion).value.ensureValid()
|
||||||
|
}
|
||||||
|
|
||||||
|
"fail to uninstall a read-only bundled component" taggedAs OsUnix in {
|
||||||
|
val engineVersion = SemVer(0, 1, 0)
|
||||||
|
val runtimeVersion = GraalVMVersion(SemVer(1, 0, 0), "11")
|
||||||
|
prepareBundle(
|
||||||
|
engines = Seq(engineVersion),
|
||||||
|
runtimes = Seq(runtimeVersion)
|
||||||
|
)
|
||||||
|
val manager = makeRuntimeVersionManager()
|
||||||
|
def installedEngines = manager.listInstalledEngines().map(_.version)
|
||||||
|
def installedRuntimes =
|
||||||
|
manager.listInstalledGraalRuntimes().map(_.version)
|
||||||
|
|
||||||
|
val enginePath = getTestDirectory / "dist" / "0.1.0"
|
||||||
|
val runtimePath = getTestDirectory / "runtime" / "graalvm-ce-java11-1.0.0"
|
||||||
|
|
||||||
|
enginePath.toFile.setWritable(false)
|
||||||
|
try {
|
||||||
|
intercept[UninstallationError] {
|
||||||
|
manager.uninstallEngine(engineVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
installedEngines shouldEqual Seq(engineVersion)
|
||||||
|
installedRuntimes shouldEqual Seq(runtimeVersion)
|
||||||
|
} finally {
|
||||||
|
enginePath.toFile.setWritable(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
runtimePath.toFile.setWritable(false)
|
||||||
|
try {
|
||||||
|
manager.uninstallEngine(engineVersion)
|
||||||
|
|
||||||
|
installedEngines shouldEqual Seq()
|
||||||
|
installedRuntimes shouldEqual Seq(runtimeVersion)
|
||||||
|
|
||||||
|
manager.cleanupRuntimes()
|
||||||
|
installedRuntimes shouldEqual Seq(runtimeVersion)
|
||||||
|
} finally {
|
||||||
|
runtimePath.toFile.setWritable(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
manager.cleanupRuntimes()
|
||||||
|
installedRuntimes shouldEqual Seq()
|
||||||
|
}
|
||||||
|
|
||||||
|
"include both bundled and installed components in list" in {
|
||||||
|
prepareBundle(
|
||||||
|
engines = Seq(SemVer(0, 0, 1)),
|
||||||
|
runtimes = Seq(GraalVMVersion(SemVer(1, 0, 0), "11"))
|
||||||
|
)
|
||||||
|
val manager = makeRuntimeVersionManager()
|
||||||
|
manager.findOrInstallEngine(SemVer(0, 1, 0))
|
||||||
|
|
||||||
|
manager
|
||||||
|
.listInstalledEngines()
|
||||||
|
.map(_.version) should contain theSameElementsAs Seq(
|
||||||
|
SemVer(0, 0, 1),
|
||||||
|
SemVer(0, 1, 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
val runtimeVersions = manager.listInstalledGraalRuntimes().map(_.version)
|
||||||
|
runtimeVersions.map(_.graalVersion) should contain theSameElementsAs Seq(
|
||||||
|
SemVer(1, 0, 0),
|
||||||
|
SemVer(2, 0, 0)
|
||||||
|
)
|
||||||
|
runtimeVersions.map(_.java).toSet shouldEqual Set("11")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def prepareBundle(
|
||||||
|
engines: Seq[SemVer],
|
||||||
|
runtimes: Seq[GraalVMVersion]
|
||||||
|
): Unit = {
|
||||||
|
FileSystem.writeTextFile(
|
||||||
|
getTestDirectory / ".enso.bundle",
|
||||||
|
"Enso Bundle Marker"
|
||||||
|
)
|
||||||
|
for (engineVersion <- engines) {
|
||||||
|
fakeInstallEngine(getTestDirectory / "dist", engineVersion)
|
||||||
|
}
|
||||||
|
for (runtimeVersion <- runtimes) {
|
||||||
|
fakeInstallRuntime(getTestDirectory / "runtime", runtimeVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def fakeInstallEngine(searchPath: Path, version: SemVer): Unit = {
|
||||||
|
val manifest = """minimum-launcher-version: 0.0.1
|
||||||
|
|minimum-project-manager-version: 0.0.1
|
||||||
|
|graal-vm-version: 1.0.0
|
||||||
|
|graal-java-version: 11""".stripMargin
|
||||||
|
val root = searchPath / version.toString
|
||||||
|
Files.createDirectories(root)
|
||||||
|
FileSystem.writeTextFile(root / "manifest.yaml", manifest)
|
||||||
|
val components = root / "component"
|
||||||
|
Files.createDirectories(components)
|
||||||
|
makePlaceholder(components / "runner.jar")
|
||||||
|
FileSystem.writeTextFile(components / "runtime.jar", "placeholder")
|
||||||
|
}
|
||||||
|
|
||||||
|
private def fakeInstallRuntime(
|
||||||
|
searchPath: Path,
|
||||||
|
version: GraalVMVersion
|
||||||
|
): Unit = {
|
||||||
|
val root =
|
||||||
|
searchPath / s"graalvm-ce-java${version.java}-${version.graalVersion}"
|
||||||
|
val bin =
|
||||||
|
if (OS.operatingSystem == OS.MacOS) root / "Contents" / "Home" / "bin"
|
||||||
|
else root / "bin"
|
||||||
|
Files.createDirectories(bin)
|
||||||
|
val executable = if (OS.isWindows) "java.exe" else "java"
|
||||||
|
makePlaceholder(bin / executable)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def makePlaceholder(path: Path): Unit = {
|
||||||
|
FileSystem.writeTextFile(path, "placeholder")
|
||||||
|
path.toFile.setExecutable(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package org.enso.runtimeversionmanager.distributuion
|
package org.enso.runtimeversionmanager.distributuion
|
||||||
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.{Files, Path}
|
||||||
|
|
||||||
import org.enso.runtimeversionmanager.Environment
|
import org.enso.runtimeversionmanager.{Environment, FileSystem}
|
||||||
import org.enso.runtimeversionmanager.FileSystem.PathSyntax
|
import org.enso.runtimeversionmanager.FileSystem.PathSyntax
|
||||||
import org.enso.runtimeversionmanager.distribution.{
|
import org.enso.runtimeversionmanager.distribution.{
|
||||||
DistributionManager,
|
DistributionManager,
|
||||||
@ -12,6 +12,7 @@ import org.enso.runtimeversionmanager.test.{
|
|||||||
FakeEnvironment,
|
FakeEnvironment,
|
||||||
WithTemporaryDirectory
|
WithTemporaryDirectory
|
||||||
}
|
}
|
||||||
|
import org.scalatest.OptionValues
|
||||||
import org.scalatest.matchers.should.Matchers
|
import org.scalatest.matchers.should.Matchers
|
||||||
import org.scalatest.wordspec.AnyWordSpec
|
import org.scalatest.wordspec.AnyWordSpec
|
||||||
|
|
||||||
@ -19,7 +20,8 @@ class DistributionManagerSpec
|
|||||||
extends AnyWordSpec
|
extends AnyWordSpec
|
||||||
with Matchers
|
with Matchers
|
||||||
with WithTemporaryDirectory
|
with WithTemporaryDirectory
|
||||||
with FakeEnvironment {
|
with FakeEnvironment
|
||||||
|
with OptionValues {
|
||||||
|
|
||||||
"DistributionManager" should {
|
"DistributionManager" should {
|
||||||
"detect portable distribution" in {
|
"detect portable distribution" in {
|
||||||
@ -35,6 +37,7 @@ class DistributionManagerSpec
|
|||||||
distributionManager.paths.runtimes shouldEqual
|
distributionManager.paths.runtimes shouldEqual
|
||||||
getTestDirectory / "runtime"
|
getTestDirectory / "runtime"
|
||||||
distributionManager.paths.engines shouldEqual getTestDirectory / "dist"
|
distributionManager.paths.engines shouldEqual getTestDirectory / "dist"
|
||||||
|
distributionManager.paths.bundle shouldEqual None
|
||||||
}
|
}
|
||||||
|
|
||||||
"detect installed distribution" in {
|
"detect installed distribution" in {
|
||||||
@ -45,6 +48,21 @@ class DistributionManagerSpec
|
|||||||
|
|
||||||
val distributionManager = new PortableDistributionManager(fakeEnvironment)
|
val distributionManager = new PortableDistributionManager(fakeEnvironment)
|
||||||
distributionManager.isRunningPortable shouldEqual false
|
distributionManager.isRunningPortable shouldEqual false
|
||||||
|
distributionManager.paths.bundle shouldEqual None
|
||||||
|
}
|
||||||
|
|
||||||
|
"detect bundles" in {
|
||||||
|
val executable = fakeExecutablePath()
|
||||||
|
FileSystem.writeTextFile(getTestDirectory / ".enso.bundle", "placeholder")
|
||||||
|
|
||||||
|
val fakeEnvironment = new Environment {
|
||||||
|
override def getPathToRunningExecutable: Path = executable
|
||||||
|
}
|
||||||
|
|
||||||
|
val distributionManager = new PortableDistributionManager(fakeEnvironment)
|
||||||
|
val bundle = distributionManager.paths.bundle.value
|
||||||
|
assert(Files.isSameFile(bundle.engines, getTestDirectory / "dist"))
|
||||||
|
assert(Files.isSameFile(bundle.runtimes, getTestDirectory / "runtime"))
|
||||||
}
|
}
|
||||||
|
|
||||||
"respect environment variable overrides " +
|
"respect environment variable overrides " +
|
||||||
|
@ -65,3 +65,7 @@ case class UpgradeRequiredError(
|
|||||||
s"Minimum version required to use this engine is " +
|
s"Minimum version required to use this engine is " +
|
||||||
s"$expectedVersion."
|
s"$expectedVersion."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/** Indicates uninstallation failure. */
|
||||||
|
case class UninstallationError(message: String)
|
||||||
|
extends ComponentsException(message)
|
||||||
|
@ -48,14 +48,14 @@ case class Engine(version: SemVer, path: Path, manifest: Manifest) {
|
|||||||
Failure(
|
Failure(
|
||||||
CorruptedComponentError(
|
CorruptedComponentError(
|
||||||
s"Engine's runner.jar (expected at " +
|
s"Engine's runner.jar (expected at " +
|
||||||
s"${runnerPath.toAbsolutePath.normalize} is missing."
|
s"`${runnerPath.toAbsolutePath.normalize}`) is missing."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else if (!Files.exists(runtimePath))
|
else if (!Files.exists(runtimePath))
|
||||||
Failure(
|
Failure(
|
||||||
CorruptedComponentError(
|
CorruptedComponentError(
|
||||||
s"Engine's runtime.jar (expected at " +
|
s"`Engine's runtime.jar (expected at " +
|
||||||
s"${runtimePath.toAbsolutePath.normalize} is missing."
|
s"${runtimePath.toAbsolutePath.normalize}`) is missing."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else Success(())
|
else Success(())
|
||||||
|
@ -43,7 +43,7 @@ case class GraalRuntime(version: GraalVMVersion, path: Path) {
|
|||||||
Failure(
|
Failure(
|
||||||
CorruptedComponentError(
|
CorruptedComponentError(
|
||||||
s"Runtime's java executable (expected at " +
|
s"Runtime's java executable (expected at " +
|
||||||
s"${javaExecutable.toAbsolutePath.normalize}) is missing."
|
s"`${javaExecutable.toAbsolutePath.normalize}`) is missing."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else if (!Files.isExecutable(javaExecutable))
|
else if (!Files.isExecutable(javaExecutable))
|
||||||
|
@ -60,13 +60,11 @@ class RuntimeVersionManager(
|
|||||||
*/
|
*/
|
||||||
def findGraalRuntime(version: GraalVMVersion): Option[GraalRuntime] = {
|
def findGraalRuntime(version: GraalVMVersion): Option[GraalRuntime] = {
|
||||||
val name = graalRuntimeNameForVersion(version)
|
val name = graalRuntimeNameForVersion(version)
|
||||||
val path = distributionManager.paths.runtimes / name
|
firstExisting(distributionManager.paths.runtimeSearchPaths.map(_ / name))
|
||||||
if (Files.exists(path)) {
|
.map { path =>
|
||||||
// TODO [RW] for now an exception is thrown if the installation is
|
// TODO [RW] for now an exception is thrown if the installation is
|
||||||
// corrupted, in #1052 offer to repair the broken installation
|
// corrupted, in #1052 offer to repair the broken installation
|
||||||
loadGraalRuntime(path)
|
loadGraalRuntime(path).recoverWith { case e: Exception =>
|
||||||
.map(Some(_))
|
|
||||||
.recoverWith { case e: Exception =>
|
|
||||||
Failure(
|
Failure(
|
||||||
UnrecognizedComponentError(
|
UnrecognizedComponentError(
|
||||||
s"The runtime $version is already installed, but cannot be " +
|
s"The runtime $version is already installed, but cannot be " +
|
||||||
@ -77,9 +75,8 @@ class RuntimeVersionManager(
|
|||||||
e
|
e
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}.get
|
||||||
.get
|
}
|
||||||
} else None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Executes the provided action with a requested engine version.
|
/** Executes the provided action with a requested engine version.
|
||||||
@ -187,16 +184,21 @@ class RuntimeVersionManager(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns the first path from the sequence that exists on the file system,
|
||||||
|
* or None if no path from the sequence exists.
|
||||||
|
*/
|
||||||
|
private def firstExisting(paths: Seq[Path]): Option[Path] =
|
||||||
|
paths.find(Files.exists(_))
|
||||||
|
|
||||||
/** Finds an installed engine with the given `version` and reports any errors.
|
/** Finds an installed engine with the given `version` and reports any errors.
|
||||||
*/
|
*/
|
||||||
private def getEngine(version: SemVer): Try[Engine] = {
|
private def getEngine(version: SemVer): Try[Engine] = {
|
||||||
val name = engineNameForVersion(version)
|
val name = engineNameForVersion(version)
|
||||||
val path = distributionManager.paths.engines / name
|
firstExisting(distributionManager.paths.engineSearchPaths.map(_ / name))
|
||||||
if (Files.exists(path)) {
|
.map(loadEngine)
|
||||||
// TODO [RW] right now we return an exception, in the future (#1052) we
|
.getOrElse {
|
||||||
// will try recovery
|
Failure(ComponentMissingError(s"Engine $version is not installed."))
|
||||||
loadEngine(path)
|
}
|
||||||
} else Failure(ComponentMissingError(s"Engine $version is not installed."))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Finds an engine with the given `version` or returns None if it is not
|
/** Finds an engine with the given `version` or returns None if it is not
|
||||||
@ -224,9 +226,10 @@ class RuntimeVersionManager(
|
|||||||
Failure(
|
Failure(
|
||||||
UnrecognizedComponentError(
|
UnrecognizedComponentError(
|
||||||
s"The engine $version is already installed, but cannot be " +
|
s"The engine $version is already installed, but cannot be " +
|
||||||
s"loaded due to $e. Until the launcher gets an auto-repair " +
|
s"loaded due to $e " +
|
||||||
s"feature, please try running `enso uninstall engine $version` " +
|
s"Please try reinstalling by running " +
|
||||||
s"followed by `enso install engine $version`.",
|
s"`enso uninstall engine $version` followed by " +
|
||||||
|
s"`enso install engine $version`.",
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -270,21 +273,38 @@ class RuntimeVersionManager(
|
|||||||
|
|
||||||
/** Lists all installed GrallVM runtimes. */
|
/** Lists all installed GrallVM runtimes. */
|
||||||
def listInstalledGraalRuntimes(): Seq[GraalRuntime] =
|
def listInstalledGraalRuntimes(): Seq[GraalRuntime] =
|
||||||
FileSystem
|
findComponents(distributionManager.paths.runtimeSearchPaths)
|
||||||
.listDirectory(distributionManager.paths.runtimes)
|
|
||||||
.filter(isNotIgnoredDirectory)
|
|
||||||
.map(path => (path, loadGraalRuntime(path)))
|
.map(path => (path, loadGraalRuntime(path)))
|
||||||
.flatMap(handleErrorsAsWarnings[GraalRuntime]("A runtime"))
|
.flatMap(handleErrorsAsWarnings[GraalRuntime]("A runtime"))
|
||||||
|
|
||||||
/** Lists all installed engines. */
|
/** Lists all installed engines. */
|
||||||
def listInstalledEngines(): Seq[Engine] = {
|
def listInstalledEngines(): Seq[Engine] = {
|
||||||
FileSystem
|
findComponents(distributionManager.paths.engineSearchPaths)
|
||||||
.listDirectory(distributionManager.paths.engines)
|
|
||||||
.filter(isNotIgnoredDirectory)
|
|
||||||
.map(path => (path, loadEngine(path)))
|
.map(path => (path, loadEngine(path)))
|
||||||
.flatMap(handleErrorsAsWarnings[Engine]("An engine"))
|
.flatMap(handleErrorsAsWarnings[Engine]("An engine"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns components found in `searchPaths`.
|
||||||
|
*
|
||||||
|
* If there are duplicate components in multiple paths, the one from the
|
||||||
|
* earliest search path is kept.
|
||||||
|
*/
|
||||||
|
private def findComponents(searchPaths: Seq[Path]): Seq[Path] =
|
||||||
|
searchPaths
|
||||||
|
.foldLeft(Map.empty[String, Path]) { case (map, searchPath) =>
|
||||||
|
val componentsHere =
|
||||||
|
FileSystem.listDirectory(searchPath).filter(isNotIgnoredDirectory)
|
||||||
|
componentsHere.foldLeft(map) { case (map, componentPath) =>
|
||||||
|
val componentName = componentPath.getFileName.toString
|
||||||
|
map.updatedWith(componentName) {
|
||||||
|
case Some(alreadyPresent) => Some(alreadyPresent)
|
||||||
|
case None => Some(componentPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.values
|
||||||
|
.toSeq
|
||||||
|
|
||||||
private def isNotIgnoredDirectory(path: Path): Boolean = {
|
private def isNotIgnoredDirectory(path: Path): Boolean = {
|
||||||
val fileName = path.getFileName.toString
|
val fileName = path.getFileName.toString
|
||||||
val isIgnored = FileSystem.ignoredFileNames.contains(fileName)
|
val isIgnored = FileSystem.ignoredFileNames.contains(fileName)
|
||||||
@ -328,11 +348,32 @@ class RuntimeVersionManager(
|
|||||||
throw ComponentMissingError(s"Enso Engine $version is not installed.")
|
throw ComponentMissingError(s"Enso Engine $version is not installed.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Files.isWritable(engine.path)) {
|
||||||
|
val message =
|
||||||
|
s"$engine cannot be uninstalled because it is placed in a " +
|
||||||
|
s"read-only location (bundled versions cannot be uninstalled)."
|
||||||
|
logger.error(message)
|
||||||
|
throw UninstallationError(message)
|
||||||
|
}
|
||||||
safelyRemoveComponent(engine.path)
|
safelyRemoveComponent(engine.path)
|
||||||
userInterface.logInfo(s"Uninstalled $engine.")
|
userInterface.logInfo(s"Uninstalled $engine.")
|
||||||
cleanupGraalRuntimes()
|
internalCleanupGraalRuntimes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Removes runtimes that are not used by any installed engines.
|
||||||
|
*
|
||||||
|
* Runtimes are automatically cleaned after installation, so currently this
|
||||||
|
* function is only useful for tests.
|
||||||
|
*/
|
||||||
|
def cleanupRuntimes(): Unit = {
|
||||||
|
resourceManager.withResources(
|
||||||
|
userInterface,
|
||||||
|
Resource.AddOrRemoveComponents -> LockType.Exclusive
|
||||||
|
) {
|
||||||
|
internalCleanupGraalRuntimes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Checks if the component version specified in the release's manifest is
|
/** Checks if the component version specified in the release's manifest is
|
||||||
* compatible with the current installer version.
|
* compatible with the current installer version.
|
||||||
*/
|
*/
|
||||||
@ -690,14 +731,21 @@ class RuntimeVersionManager(
|
|||||||
*
|
*
|
||||||
* The caller must hold [[Resource.AddOrRemoveComponents]] exclusively.
|
* The caller must hold [[Resource.AddOrRemoveComponents]] exclusively.
|
||||||
*/
|
*/
|
||||||
private def cleanupGraalRuntimes(): Unit = {
|
private def internalCleanupGraalRuntimes(): Unit = {
|
||||||
for (runtime <- listInstalledGraalRuntimes()) {
|
for (runtime <- listInstalledGraalRuntimes()) {
|
||||||
if (findEnginesUsingRuntime(runtime).isEmpty) {
|
if (findEnginesUsingRuntime(runtime).isEmpty) {
|
||||||
userInterface.logInfo(
|
userInterface.logInfo(
|
||||||
s"Removing $runtime, because it is not used by any installed Enso " +
|
s"Removing $runtime, because it is not used by any installed Enso " +
|
||||||
s"versions."
|
s"versions."
|
||||||
)
|
)
|
||||||
safelyRemoveComponent(runtime.path)
|
if (Files.isWritable(runtime.path)) {
|
||||||
|
safelyRemoveComponent(runtime.path)
|
||||||
|
} else {
|
||||||
|
logger.warn(
|
||||||
|
s"$runtime cannot be uninstalled because it is placed in a " +
|
||||||
|
s"read-only location."
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,12 @@ import scala.util.control.NonFatal
|
|||||||
* @param dataRoot the root of the data directory; for a portable distribution
|
* @param dataRoot the root of the data directory; for a portable distribution
|
||||||
* this is the root of the distribution, for a locally
|
* this is the root of the distribution, for a locally
|
||||||
* installed distribution, it corresponds to `ENSO_DATA_DIR`
|
* installed distribution, it corresponds to `ENSO_DATA_DIR`
|
||||||
* @param runtimes location of runtimes, corresponding to `runtime` directory
|
* @param runtimes primary location of runtimes, corresponding to `runtime`
|
||||||
* @param engines location of engine versions, corresponding to `dist`
|
* directory
|
||||||
|
* @param engines primary location of engine versions, corresponding to `dist`
|
||||||
* directory
|
* directory
|
||||||
|
* @param bundle optional bundle description, containing secondary engine and
|
||||||
|
* runtime directories
|
||||||
* @param config location of configuration
|
* @param config location of configuration
|
||||||
* @param locks a directory for storing lockfiles that are used to synchronize
|
* @param locks a directory for storing lockfiles that are used to synchronize
|
||||||
* access to the various components
|
* access to the various components
|
||||||
@ -29,6 +32,7 @@ case class DistributionPaths(
|
|||||||
dataRoot: Path,
|
dataRoot: Path,
|
||||||
runtimes: Path,
|
runtimes: Path,
|
||||||
engines: Path,
|
engines: Path,
|
||||||
|
bundle: Option[Bundle],
|
||||||
config: Path,
|
config: Path,
|
||||||
locks: Path,
|
locks: Path,
|
||||||
logs: Path,
|
logs: Path,
|
||||||
@ -42,12 +46,36 @@ case class DistributionPaths(
|
|||||||
| dataRoot = $dataRoot,
|
| dataRoot = $dataRoot,
|
||||||
| runtimes = $runtimes,
|
| runtimes = $runtimes,
|
||||||
| engines = $engines,
|
| engines = $engines,
|
||||||
|
| bundle = $bundle,
|
||||||
| config = $config,
|
| config = $config,
|
||||||
| locks = $locks,
|
| locks = $locks,
|
||||||
| tmp = $unsafeTemporaryDirectory
|
| tmp = $unsafeTemporaryDirectory
|
||||||
|)""".stripMargin
|
|)""".stripMargin
|
||||||
|
|
||||||
|
/** Sequence of paths to search for engine installations, in order of
|
||||||
|
* precedence.
|
||||||
|
*/
|
||||||
|
def engineSearchPaths: Seq[Path] = Seq(engines) ++ bundle.map(_.engines).toSeq
|
||||||
|
|
||||||
|
/** Sequence of paths to search for runtime installations, in order of
|
||||||
|
* precedence.
|
||||||
|
*/
|
||||||
|
def runtimeSearchPaths: Seq[Path] =
|
||||||
|
Seq(runtimes) ++ bundle.map(_.runtimes).toSeq
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Paths to secondary directories for additionally bundled engine
|
||||||
|
* distributions.
|
||||||
|
*
|
||||||
|
* These paths are only relevant for an installed distribution which may also
|
||||||
|
* use some locally bundled distributions (possibly located on a read-only
|
||||||
|
* filesystem).
|
||||||
|
*
|
||||||
|
* For portable distributions, bundled packages are already included in the
|
||||||
|
* primary directory.
|
||||||
|
*/
|
||||||
|
case class Bundle(engines: Path, runtimes: Path)
|
||||||
|
|
||||||
/** A helper class that encapsulates management of paths to components of the
|
/** A helper class that encapsulates management of paths to components of the
|
||||||
* distribution.
|
* distribution.
|
||||||
*
|
*
|
||||||
@ -82,6 +110,7 @@ class DistributionManager(val env: Environment) {
|
|||||||
dataRoot = dataRoot,
|
dataRoot = dataRoot,
|
||||||
runtimes = dataRoot / RUNTIMES_DIRECTORY,
|
runtimes = dataRoot / RUNTIMES_DIRECTORY,
|
||||||
engines = dataRoot / ENGINES_DIRECTORY,
|
engines = dataRoot / ENGINES_DIRECTORY,
|
||||||
|
bundle = detectBundle(),
|
||||||
config = configRoot,
|
config = configRoot,
|
||||||
locks = runRoot / LOCK_DIRECTORY,
|
locks = runRoot / LOCK_DIRECTORY,
|
||||||
logs = LocallyInstalledDirectories.logDirectory,
|
logs = LocallyInstalledDirectories.logDirectory,
|
||||||
@ -89,6 +118,32 @@ class DistributionManager(val env: Environment) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Name of the file that should be placed in the distribution root to mark it
|
||||||
|
* as running in portable mode.
|
||||||
|
*/
|
||||||
|
private val BUNDLE_MARK_FILENAME = ".enso.bundle"
|
||||||
|
|
||||||
|
/** Root directory of a bundle.
|
||||||
|
*
|
||||||
|
* If the bundle is present, it will be located next to the `bin/` directory
|
||||||
|
* that contains the executable that we are currently running.
|
||||||
|
*/
|
||||||
|
private def possibleBundleRoot =
|
||||||
|
env.getPathToRunningExecutable.getParent.getParent
|
||||||
|
|
||||||
|
/** Checks if [[possibleBundleRoot]] contains the bundle mark file and returns
|
||||||
|
* directories for the bundle if it was found.
|
||||||
|
*/
|
||||||
|
private def detectBundle(): Option[Bundle] =
|
||||||
|
if (Files.exists(possibleBundleRoot / BUNDLE_MARK_FILENAME))
|
||||||
|
Some(
|
||||||
|
Bundle(
|
||||||
|
engines = possibleBundleRoot / ENGINES_DIRECTORY,
|
||||||
|
runtimes = possibleBundleRoot / RUNTIMES_DIRECTORY
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else None
|
||||||
|
|
||||||
/** Removes unused lockfiles.
|
/** Removes unused lockfiles.
|
||||||
*/
|
*/
|
||||||
def tryCleaningUnusedLockfiles(): Unit = {
|
def tryCleaningUnusedLockfiles(): Unit = {
|
||||||
|
@ -59,6 +59,11 @@ class PortableDistributionManager(env: Environment)
|
|||||||
portable
|
portable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Detects paths for the portable distribution.
|
||||||
|
*
|
||||||
|
* A portable distribution does not include bundle paths, because if
|
||||||
|
* anything was bundled with it, it is already part of its primary installation.
|
||||||
|
*/
|
||||||
override protected def detectPaths(): DistributionPaths =
|
override protected def detectPaths(): DistributionPaths =
|
||||||
if (isRunningPortable) {
|
if (isRunningPortable) {
|
||||||
val root = env.getPathToRunningExecutable.getParent.getParent
|
val root = env.getPathToRunningExecutable.getParent.getParent
|
||||||
@ -66,6 +71,7 @@ class PortableDistributionManager(env: Environment)
|
|||||||
dataRoot = root,
|
dataRoot = root,
|
||||||
runtimes = root / RUNTIMES_DIRECTORY,
|
runtimes = root / RUNTIMES_DIRECTORY,
|
||||||
engines = root / ENGINES_DIRECTORY,
|
engines = root / ENGINES_DIRECTORY,
|
||||||
|
bundle = None,
|
||||||
config = root / CONFIG_DIRECTORY,
|
config = root / CONFIG_DIRECTORY,
|
||||||
locks = root / LOCK_DIRECTORY,
|
locks = root / LOCK_DIRECTORY,
|
||||||
logs = root / LOG_DIRECTORY,
|
logs = root / LOG_DIRECTORY,
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
package org.enso.runtimeversionmanager.releases.engine
|
package org.enso.runtimeversionmanager.releases.engine
|
||||||
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
import org.enso.runtimeversionmanager.releases.ReleaseProvider
|
import org.enso.runtimeversionmanager.releases.ReleaseProvider
|
||||||
import org.enso.runtimeversionmanager.releases.github.GithubReleaseProvider
|
import org.enso.runtimeversionmanager.releases.github.GithubReleaseProvider
|
||||||
import org.enso.runtimeversionmanager.releases.local.LocalReleaseProvider
|
|
||||||
|
|
||||||
/** Represents the default Enso repository providing releases of the engine. */
|
/** Represents the default Enso repository providing releases of the engine. */
|
||||||
object EngineRepository {
|
object EngineRepository {
|
||||||
@ -13,15 +10,4 @@ object EngineRepository {
|
|||||||
/** Default provider of engine releases. */
|
/** Default provider of engine releases. */
|
||||||
def defaultEngineReleaseProvider: ReleaseProvider[EngineRelease] =
|
def defaultEngineReleaseProvider: ReleaseProvider[EngineRelease] =
|
||||||
new EngineReleaseProvider(githubRepository)
|
new EngineReleaseProvider(githubRepository)
|
||||||
|
|
||||||
/** Creates an engine provider that uses a local repository first, falling
|
|
||||||
* back to the default one.
|
|
||||||
*/
|
|
||||||
def fromLocalRepository(
|
|
||||||
releaseDirectory: Path
|
|
||||||
): ReleaseProvider[EngineRelease] = {
|
|
||||||
val mergedRepository =
|
|
||||||
new LocalReleaseProvider(releaseDirectory, githubRepository)
|
|
||||||
new EngineReleaseProvider(mergedRepository)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import org.enso.cli.task.TaskProgress
|
|||||||
import org.enso.runtimeversionmanager.OS
|
import org.enso.runtimeversionmanager.OS
|
||||||
import org.enso.runtimeversionmanager.components.GraalVMVersion
|
import org.enso.runtimeversionmanager.components.GraalVMVersion
|
||||||
import org.enso.runtimeversionmanager.releases.github.GithubReleaseProvider
|
import org.enso.runtimeversionmanager.releases.github.GithubReleaseProvider
|
||||||
import org.enso.runtimeversionmanager.releases.local.LocalReleaseProvider
|
|
||||||
import org.enso.runtimeversionmanager.releases.{
|
import org.enso.runtimeversionmanager.releases.{
|
||||||
ReleaseProviderException,
|
ReleaseProviderException,
|
||||||
SimpleReleaseProvider
|
SimpleReleaseProvider
|
||||||
@ -59,17 +58,6 @@ object GraalCEReleaseProvider {
|
|||||||
*/
|
*/
|
||||||
val default = new GraalCEReleaseProvider(githubRepository)
|
val default = new GraalCEReleaseProvider(githubRepository)
|
||||||
|
|
||||||
/** Creates a GraalVM provider that uses a local repository first, falling
|
|
||||||
* back to the default one.
|
|
||||||
*/
|
|
||||||
def fromLocalRepository(
|
|
||||||
releaseDirectory: Path
|
|
||||||
): GraalVMRuntimeReleaseProvider = {
|
|
||||||
val mergedRepository =
|
|
||||||
new LocalReleaseProvider(releaseDirectory, githubRepository)
|
|
||||||
new GraalCEReleaseProvider(mergedRepository)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Generates the name of the package for the currently running OS and a
|
/** Generates the name of the package for the currently running OS and a
|
||||||
* specified release version.
|
* specified release version.
|
||||||
*/
|
*/
|
||||||
|
@ -1,112 +0,0 @@
|
|||||||
package org.enso.runtimeversionmanager.releases.local
|
|
||||||
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
import cats.syntax.traverse._
|
|
||||||
import com.typesafe.scalalogging.Logger
|
|
||||||
import org.enso.cli.task.TaskProgress
|
|
||||||
import org.enso.runtimeversionmanager.FileSystem
|
|
||||||
import org.enso.runtimeversionmanager.releases.{
|
|
||||||
Asset,
|
|
||||||
Release,
|
|
||||||
SimpleReleaseProvider
|
|
||||||
}
|
|
||||||
|
|
||||||
import scala.io.Source
|
|
||||||
import scala.util.{Try, Using}
|
|
||||||
|
|
||||||
/** A [[SimpleReleaseProvider]] that uses a repository located on a local file
|
|
||||||
* system as its primary source and falls back to some other specified
|
|
||||||
* repository in other cases.
|
|
||||||
*
|
|
||||||
* It can be used to implement bundling some versions with an installer - it
|
|
||||||
* can point to this local repository, so that any required bundled versions
|
|
||||||
* are installed from the bundle and any other versions are handled using the
|
|
||||||
* default repository.
|
|
||||||
*
|
|
||||||
* It is given a `releaseDirectory` that should contain separate directories
|
|
||||||
* for each local release. The name of each subdirectory corresponds to its
|
|
||||||
* release tag and every file in that subdirectory is considered as an asset of
|
|
||||||
* that release.
|
|
||||||
*
|
|
||||||
* It loads the list of releases at construction and thus may throw an error if
|
|
||||||
* it cannot access the provided directory.
|
|
||||||
*/
|
|
||||||
class LocalReleaseProvider(
|
|
||||||
releaseDirectory: Path,
|
|
||||||
fallback: SimpleReleaseProvider
|
|
||||||
) extends SimpleReleaseProvider {
|
|
||||||
private val logger = Logger[LocalReleaseProvider]
|
|
||||||
private val localDirectories: Seq[Path] =
|
|
||||||
FileSystem.listDirectory(releaseDirectory).filter { dir =>
|
|
||||||
val isIgnoredFile =
|
|
||||||
FileSystem.ignoredFileNames.contains(dir.getFileName.toString)
|
|
||||||
!isIgnoredFile
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @inheritdoc */
|
|
||||||
override def releaseForTag(tag: String): Try[Release] = {
|
|
||||||
val localPath = localDirectories.find(_.getFileName.toString == tag)
|
|
||||||
localPath
|
|
||||||
.map(wrapLocalDirectory)
|
|
||||||
.getOrElse { fallback.releaseForTag(tag) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @inheritdoc */
|
|
||||||
override def listReleases(): Try[Seq[Release]] = {
|
|
||||||
val remote = fallback
|
|
||||||
.listReleases()
|
|
||||||
.recover { error =>
|
|
||||||
logger.warn(
|
|
||||||
s"The remote release provider failed with $error, but " +
|
|
||||||
s"locally bundled releases are available."
|
|
||||||
)
|
|
||||||
Seq.empty
|
|
||||||
}
|
|
||||||
.get
|
|
||||||
findLocalReleases() map { local =>
|
|
||||||
val localTags = local.map(_.tag).toSet
|
|
||||||
val remoteDeduplicated = remote.filter { remoteRelease =>
|
|
||||||
val hasLocalCorrespondent = localTags.contains(remoteRelease.tag)
|
|
||||||
!hasLocalCorrespondent
|
|
||||||
}
|
|
||||||
local ++ remoteDeduplicated
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** An asset that is on the local filesystem. */
|
|
||||||
private case class LocalAsset(assetPath: Path) extends Asset {
|
|
||||||
|
|
||||||
/** @inheritdoc */
|
|
||||||
override def fileName: String = assetPath.getFileName.toString
|
|
||||||
|
|
||||||
/** @inheritdoc */
|
|
||||||
override def downloadTo(path: Path): TaskProgress[Unit] =
|
|
||||||
TaskProgress.runImmediately {
|
|
||||||
FileSystem.copyFile(assetPath, path)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @inheritdoc */
|
|
||||||
override def fetchAsText(): TaskProgress[String] =
|
|
||||||
TaskProgress.fromTry {
|
|
||||||
Using(Source.fromFile(assetPath.toFile)) { src =>
|
|
||||||
src.getLines().mkString("\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private case class LocalRelease(
|
|
||||||
override val tag: String,
|
|
||||||
override val assets: Seq[LocalAsset]
|
|
||||||
) extends Release
|
|
||||||
|
|
||||||
/** Creates a [[LocalRelease]] defined by a local directory. */
|
|
||||||
private def wrapLocalDirectory(path: Path): Try[Release] = Try {
|
|
||||||
val tag = path.getFileName.toString
|
|
||||||
val assets = FileSystem.listDirectory(path).map(LocalAsset)
|
|
||||||
LocalRelease(tag, assets)
|
|
||||||
}
|
|
||||||
|
|
||||||
private def findLocalReleases(): Try[Seq[Release]] =
|
|
||||||
localDirectories.map(wrapLocalDirectory).toList.sequence[Try, Release]
|
|
||||||
}
|
|
@ -1,7 +1,10 @@
|
|||||||
import sbt.{file, singleFileFinder, File, IO}
|
import sbt.internal.util.ManagedLogger
|
||||||
|
import sbt._
|
||||||
import sbt.io.syntax.fileToRichFile
|
import sbt.io.syntax.fileToRichFile
|
||||||
import sbt.util.{CacheStore, CacheStoreFactory, FileInfo, Tracked}
|
import sbt.util.{CacheStore, CacheStoreFactory, FileInfo, Tracked}
|
||||||
|
|
||||||
|
import scala.sys.process._
|
||||||
|
|
||||||
object DistributionPackage {
|
object DistributionPackage {
|
||||||
def copyDirectoryIncremental(
|
def copyDirectoryIncremental(
|
||||||
source: File,
|
source: File,
|
||||||
@ -144,4 +147,315 @@ object DistributionPackage {
|
|||||||
cacheFactory.make("launcher-rootfiles")
|
cacheFactory.make("launcher-rootfiles")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed trait OS {
|
||||||
|
def name: String
|
||||||
|
def graalName: String = name
|
||||||
|
def executableName(base: String): String = base
|
||||||
|
def archiveExt: String = ".tar.gz"
|
||||||
|
def isUNIX: Boolean = true
|
||||||
|
}
|
||||||
|
object OS {
|
||||||
|
case object Linux extends OS {
|
||||||
|
override def name: String = "linux"
|
||||||
|
}
|
||||||
|
case object MacOS extends OS {
|
||||||
|
override def name: String = "macos"
|
||||||
|
override def graalName: String = "darwin"
|
||||||
|
}
|
||||||
|
case object Windows extends OS {
|
||||||
|
override def name: String = "windows"
|
||||||
|
override def executableName(base: String): String = base + ".exe"
|
||||||
|
override def archiveExt: String = ".zip"
|
||||||
|
override def isUNIX: Boolean = false
|
||||||
|
}
|
||||||
|
|
||||||
|
val platforms = Seq(Linux, MacOS, Windows)
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed trait Architecture {
|
||||||
|
def name: String
|
||||||
|
}
|
||||||
|
object Architecture {
|
||||||
|
case object X64 extends Architecture {
|
||||||
|
override def name: String = "amd64"
|
||||||
|
}
|
||||||
|
|
||||||
|
val archs = Seq(X64)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A helper class that manages building distribution artifacts. */
|
||||||
|
class Builder(
|
||||||
|
ensoVersion: String,
|
||||||
|
graalVersion: String,
|
||||||
|
graalJavaVersion: String,
|
||||||
|
artifactRoot: File
|
||||||
|
) {
|
||||||
|
|
||||||
|
def artifactName(
|
||||||
|
component: String,
|
||||||
|
os: OS,
|
||||||
|
architecture: Architecture
|
||||||
|
): String =
|
||||||
|
s"enso-$component-$ensoVersion-${os.name}-${architecture.name}"
|
||||||
|
|
||||||
|
def graalInPackageName: String =
|
||||||
|
s"graalvm-ce-java$graalJavaVersion-$graalVersion"
|
||||||
|
|
||||||
|
private def extractZip(archive: File, root: File): Unit = {
|
||||||
|
IO.createDirectory(root)
|
||||||
|
val exitCode = Process(
|
||||||
|
Seq("unzip", "-q", archive.toPath.toAbsolutePath.normalize.toString),
|
||||||
|
cwd = Some(root)
|
||||||
|
).!
|
||||||
|
if (exitCode != 0) {
|
||||||
|
throw new RuntimeException(s"Cannot extract $archive.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def extractTarGz(archive: File, root: File): Unit = {
|
||||||
|
IO.createDirectory(root)
|
||||||
|
val exitCode = Process(
|
||||||
|
Seq(
|
||||||
|
"tar",
|
||||||
|
"xf",
|
||||||
|
archive.toPath.toAbsolutePath.toString
|
||||||
|
),
|
||||||
|
cwd = Some(root)
|
||||||
|
).!
|
||||||
|
if (exitCode != 0) {
|
||||||
|
throw new RuntimeException(s"Cannot extract $archive.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def extract(archive: File, root: File): Unit = {
|
||||||
|
if (archive.getName.endsWith("zip")) {
|
||||||
|
extractZip(archive, root)
|
||||||
|
} else {
|
||||||
|
extractTarGz(archive, root)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def copyGraal(
|
||||||
|
log: ManagedLogger,
|
||||||
|
os: OS,
|
||||||
|
architecture: Architecture,
|
||||||
|
runtimeDir: File
|
||||||
|
): Unit = {
|
||||||
|
val packageName = s"graalvm-${os.name}-${architecture.name}-" +
|
||||||
|
s"$graalVersion-$graalJavaVersion"
|
||||||
|
val root = artifactRoot / packageName
|
||||||
|
if (!root.exists()) {
|
||||||
|
log.info(
|
||||||
|
s"Downloading GraalVM $graalVersion Java $graalJavaVersion " +
|
||||||
|
s"for $os $architecture"
|
||||||
|
)
|
||||||
|
val graalUrl =
|
||||||
|
s"https://github.com/graalvm/graalvm-ce-builds/releases/download/" +
|
||||||
|
s"vm-$graalVersion/" +
|
||||||
|
s"graalvm-ce-java$graalJavaVersion-${os.graalName}-" +
|
||||||
|
s"${architecture.name}-$graalVersion${os.archiveExt}"
|
||||||
|
val archive = artifactRoot / (packageName + os.archiveExt)
|
||||||
|
val exitCode = (url(graalUrl) #> archive).!
|
||||||
|
if (exitCode != 0) {
|
||||||
|
throw new RuntimeException(s"Graal download from $graalUrl failed.")
|
||||||
|
}
|
||||||
|
|
||||||
|
extract(archive, root)
|
||||||
|
}
|
||||||
|
|
||||||
|
IO.copyDirectory(
|
||||||
|
root / graalInPackageName,
|
||||||
|
runtimeDir / graalInPackageName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
def copyEngine(os: OS, architecture: Architecture, distDir: File): Unit = {
|
||||||
|
val engine = builtArtifact("engine", os, architecture)
|
||||||
|
if (!engine.exists()) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
s"Cannot create bundle for $os / $architecture because corresponding " +
|
||||||
|
s"engine has not been built."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
IO.copyDirectory(engine / s"enso-$ensoVersion", distDir / ensoVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
def makeExecutable(file: File): Unit = {
|
||||||
|
val ownerOnly = false
|
||||||
|
file.setExecutable(true, ownerOnly)
|
||||||
|
}
|
||||||
|
|
||||||
|
def fixLauncher(root: File, os: OS): Unit = {
|
||||||
|
makeExecutable(root / "enso" / "bin" / os.executableName("enso"))
|
||||||
|
IO.createDirectories(
|
||||||
|
Seq("dist", "config", "runtime").map(root / "enso" / _)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
def makeArchive(root: File, rootDir: String, target: File): Unit = {
|
||||||
|
val exitCode = if (target.getName.endsWith("zip")) {
|
||||||
|
Process(
|
||||||
|
Seq(
|
||||||
|
"zip",
|
||||||
|
"-q",
|
||||||
|
"-r",
|
||||||
|
target.toPath.toAbsolutePath.normalize.toString,
|
||||||
|
rootDir
|
||||||
|
),
|
||||||
|
cwd = Some(root)
|
||||||
|
).!
|
||||||
|
} else {
|
||||||
|
Process(
|
||||||
|
Seq(
|
||||||
|
"tar",
|
||||||
|
"-czf",
|
||||||
|
target.toPath.toAbsolutePath.normalize.toString,
|
||||||
|
rootDir
|
||||||
|
),
|
||||||
|
cwd = Some(root)
|
||||||
|
).!
|
||||||
|
}
|
||||||
|
if (exitCode != 0) {
|
||||||
|
throw new RuntimeException(s"Failed to create archive $target")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Path to an arbitrary built artifact. */
|
||||||
|
def builtArtifact(
|
||||||
|
component: String,
|
||||||
|
os: OS,
|
||||||
|
architecture: Architecture
|
||||||
|
): File = artifactRoot / artifactName(component, os, architecture)
|
||||||
|
|
||||||
|
/** Path to the artifact that is built on this local machine. */
|
||||||
|
def localArtifact(component: String): File = {
|
||||||
|
val architecture = Architecture.X64
|
||||||
|
val os =
|
||||||
|
if (Platform.isWindows) OS.Windows
|
||||||
|
else if (Platform.isLinux) OS.Linux
|
||||||
|
else if (Platform.isMacOS) OS.MacOS
|
||||||
|
else throw new IllegalStateException("Unknown OS")
|
||||||
|
artifactRoot / artifactName(component, os, architecture)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Path to a built archive.
|
||||||
|
*
|
||||||
|
* These archives are built by [[makePackages]] and [[makeBundles]].
|
||||||
|
*/
|
||||||
|
def builtArchive(
|
||||||
|
component: String,
|
||||||
|
os: OS,
|
||||||
|
architecture: Architecture
|
||||||
|
): File =
|
||||||
|
artifactRoot / (artifactName(
|
||||||
|
component,
|
||||||
|
os,
|
||||||
|
architecture
|
||||||
|
) + os.archiveExt)
|
||||||
|
|
||||||
|
/** Creates compressed and ready for release packages for the launcher and
|
||||||
|
* engine.
|
||||||
|
*
|
||||||
|
* A project manager package is not created, as we release only its bundle.
|
||||||
|
* See [[makeBundles]].
|
||||||
|
*
|
||||||
|
* It does not trigger any builds. Instead, it uses available artifacts
|
||||||
|
* placed in `artifactRoot`. These artifacts may be created using the
|
||||||
|
* `enso/build*Distribution` tasks or they may come from other workers (as
|
||||||
|
* is the case in the release CI where the artifacts are downloaded from
|
||||||
|
* other jobs).
|
||||||
|
*/
|
||||||
|
def makePackages = Command.command("makePackages") { state =>
|
||||||
|
val log = state.log
|
||||||
|
for {
|
||||||
|
os <- OS.platforms
|
||||||
|
arch <- Architecture.archs
|
||||||
|
} {
|
||||||
|
val launcher = builtArtifact("launcher", os, arch)
|
||||||
|
if (launcher.exists()) {
|
||||||
|
fixLauncher(launcher, os)
|
||||||
|
val archive = builtArchive("launcher", os, arch)
|
||||||
|
makeArchive(launcher, "enso", archive)
|
||||||
|
log.info(s"Created $archive")
|
||||||
|
}
|
||||||
|
|
||||||
|
val engine = builtArtifact("engine", os, arch)
|
||||||
|
if (engine.exists()) {
|
||||||
|
if (os.isUNIX) {
|
||||||
|
makeExecutable(engine / s"enso-$ensoVersion" / "bin" / "enso")
|
||||||
|
}
|
||||||
|
val archive = builtArchive("engine", os, arch)
|
||||||
|
makeArchive(engine, s"enso-$ensoVersion", archive)
|
||||||
|
log.info(s"Created $archive")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state
|
||||||
|
}
|
||||||
|
|
||||||
|
private def cleanDirectory(dir: File): Unit = {
|
||||||
|
for (f <- IO.listFiles(dir)) {
|
||||||
|
IO.delete(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates launcher and project-manager bundles that include the component
|
||||||
|
* itself, the engine and a Graal runtime.
|
||||||
|
*
|
||||||
|
* It will download the GraalVM runtime and cache it in `artifactRoot` so
|
||||||
|
* further invocations for the same version will not need to download it.
|
||||||
|
*
|
||||||
|
* It does not trigger any builds. Instead, it uses available artifacts
|
||||||
|
* placed in `artifactRoot`. These artifacts may be created using the
|
||||||
|
* `enso/build*Distribution` tasks or they may come from other workers (as
|
||||||
|
* is the case in the release CI where the artifacts are downloaded from
|
||||||
|
* other jobs).
|
||||||
|
*/
|
||||||
|
def makeBundles = Command.command("makeBundles") { state =>
|
||||||
|
val log = state.log
|
||||||
|
for {
|
||||||
|
os <- OS.platforms
|
||||||
|
arch <- Architecture.archs
|
||||||
|
} {
|
||||||
|
val launcher = builtArtifact("launcher", os, arch)
|
||||||
|
if (launcher.exists()) {
|
||||||
|
fixLauncher(launcher, os)
|
||||||
|
copyEngine(os, arch, launcher / "enso" / "dist")
|
||||||
|
copyGraal(log, os, arch, launcher / "enso" / "runtime")
|
||||||
|
|
||||||
|
val archive = builtArchive("bundle", os, arch)
|
||||||
|
makeArchive(launcher, "enso", archive)
|
||||||
|
|
||||||
|
cleanDirectory(launcher / "enso" / "dist")
|
||||||
|
cleanDirectory(launcher / "enso" / "runtime")
|
||||||
|
|
||||||
|
log.info(s"Created $archive")
|
||||||
|
}
|
||||||
|
|
||||||
|
val pm = builtArtifact("project-manager", os, arch)
|
||||||
|
if (pm.exists()) {
|
||||||
|
if (os.isUNIX) {
|
||||||
|
makeExecutable(pm / "enso" / "bin" / "project-manager")
|
||||||
|
}
|
||||||
|
|
||||||
|
copyEngine(os, arch, pm / "enso" / "dist")
|
||||||
|
copyGraal(log, os, arch, pm / "enso" / "runtime")
|
||||||
|
IO.copyFile(
|
||||||
|
file("distribution/enso.bundle.template"),
|
||||||
|
pm / "enso" / ".enso.bundle"
|
||||||
|
)
|
||||||
|
|
||||||
|
val archive = builtArchive("project-manager", os, arch)
|
||||||
|
makeArchive(pm, "enso", archive)
|
||||||
|
|
||||||
|
cleanDirectory(pm / "enso" / "dist")
|
||||||
|
cleanDirectory(pm / "enso" / "runtime")
|
||||||
|
|
||||||
|
log.info(s"Created $archive")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,21 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
DIST_ARCH=amd64
|
DIST_ARCH=amd64
|
||||||
LAUNCHER_DIST_ROOT=enso-launcher-$DIST_VERSION-$DIST_OS-$DIST_ARCH
|
BUILD_ROOT=built-distribution
|
||||||
|
LAUNCHER_DIST_NAME=enso-launcher-$DIST_VERSION-$DIST_OS-$DIST_ARCH
|
||||||
|
LAUNCHER_DIST_ROOT=$BUILD_ROOT/$LAUNCHER_DIST_NAME
|
||||||
LAUNCHER_DIST_DIR=$LAUNCHER_DIST_ROOT/enso
|
LAUNCHER_DIST_DIR=$LAUNCHER_DIST_ROOT/enso
|
||||||
ENGINE_DIST_ROOT=enso-engine-$DIST_VERSION-$DIST_OS-$DIST_ARCH
|
ENGINE_DIST_NAME=enso-engine-$DIST_VERSION-$DIST_OS-$DIST_ARCH
|
||||||
|
ENGINE_DIST_ROOT=$BUILD_ROOT/$ENGINE_DIST_NAME
|
||||||
ENGINE_DIST_DIR=$ENGINE_DIST_ROOT/enso-$DIST_VERSION
|
ENGINE_DIST_DIR=$ENGINE_DIST_ROOT/enso-$DIST_VERSION
|
||||||
PROJECTMANAGER_DIST_ROOT=enso-project-manager-$DIST_VERSION-$DIST_OS-$DIST_ARCH
|
PROJECTMANAGER_DIST_NAME=enso-project-manager-$DIST_VERSION-$DIST_OS-$DIST_ARCH
|
||||||
|
PROJECTMANAGER_DIST_ROOT=$BUILD_ROOT/$PROJECTMANAGER_DIST_NAME
|
||||||
PROJECTMANAGER_DIST_DIR=$PROJECTMANAGER_DIST_ROOT/enso
|
PROJECTMANAGER_DIST_DIR=$PROJECTMANAGER_DIST_ROOT/enso
|
||||||
|
echo "LAUNCHER_DIST_NAME=$LAUNCHER_DIST_NAME" >> $GITHUB_ENV
|
||||||
echo "LAUNCHER_DIST_DIR=$LAUNCHER_DIST_DIR" >> $GITHUB_ENV
|
echo "LAUNCHER_DIST_DIR=$LAUNCHER_DIST_DIR" >> $GITHUB_ENV
|
||||||
echo "LAUNCHER_DIST_ROOT=$LAUNCHER_DIST_ROOT" >> $GITHUB_ENV
|
echo "LAUNCHER_DIST_ROOT=$LAUNCHER_DIST_ROOT" >> $GITHUB_ENV
|
||||||
|
echo "ENGINE_DIST_NAME=$ENGINE_DIST_NAME" >> $GITHUB_ENV
|
||||||
echo "ENGINE_DIST_DIR=$ENGINE_DIST_DIR" >> $GITHUB_ENV
|
echo "ENGINE_DIST_DIR=$ENGINE_DIST_DIR" >> $GITHUB_ENV
|
||||||
echo "ENGINE_DIST_ROOT=$ENGINE_DIST_ROOT" >> $GITHUB_ENV
|
echo "ENGINE_DIST_ROOT=$ENGINE_DIST_ROOT" >> $GITHUB_ENV
|
||||||
|
echo "PROJECTMANAGER_DIST_NAME=$PROJECTMANAGER_DIST_NAME" >> $GITHUB_ENV
|
||||||
echo "PROJECTMANAGER_DIST_DIR=$PROJECTMANAGER_DIST_DIR" >> $GITHUB_ENV
|
echo "PROJECTMANAGER_DIST_DIR=$PROJECTMANAGER_DIST_DIR" >> $GITHUB_ENV
|
||||||
echo "PROJECTMANAGER_DIST_ROOT=$PROJECTMANAGER_DIST_ROOT" >> $GITHUB_ENV
|
echo "PROJECTMANAGER_DIST_ROOT=$PROJECTMANAGER_DIST_ROOT" >> $GITHUB_ENV
|
||||||
|
Loading…
Reference in New Issue
Block a user