diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f6e6b62ed..a286a0a9c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,32 +12,8 @@ stages: stage: build_and_deploy_website image: node:8 before_script: - - cd gitlab-pages/website - - npm install - script: - - npm run version next - - npm run build - after_script: - - cp -r gitlab-pages/website/build/ligo public - artifacts: - paths: - - public - -.docker: &docker - image: docker:1.11 - services: - - docker:dind - -.docker_build: &docker_build - script: - - docker build -t $LIGO_REGISTRY_IMAGE:next -f ./docker/Dockerfile . - -.before_script: &before_script - before_script: - # Install dependencies - # rsync is needed by opam to sync a package installed from a local directory with the copy in ~/.opam - - apt-get update -qq - - apt-get -y -qq install rsync libhidapi-dev libcap-dev libev-dev bubblewrap + - scripts/install_native_dependencies.sh + # TODO: these things are moved to scripts in other branches. - wget https://github.com/ocaml/opam/releases/download/2.0.1/opam-2.0.1-x86_64-linux -O opam-2.0.1-x86_64-linux - cp opam-2.0.1-x86_64-linux /usr/local/bin/opam - chmod +x /usr/local/bin/opam @@ -57,12 +33,68 @@ stages: - printf '' | ocaml - opam switch + # install deps for internal documentation + - opam install -y odoc + - vendors/opam-repository-tools/rewrite-local-opam-repository.sh + - opam repository add localrepo "file://$PWD/vendors/ligo-opam-repository-local-generated/" + - opam install -y --build-test --deps-only ./src/ + - dune build -p ligo + # TODO: also try instead from time to time: + #- (cd ./src/; dune build -p ligo) + + # build with odoc + - dune build @doc + + # npm + - cd gitlab-pages/website + - npm install + script: + - npm run version next + - npm run build + # move internal odoc documentation to the website folder + - mkdir -p gitlab-pages/website/build/ligo/ + - mv ../../_build/default/_doc/_html/ gitlab-pages/website/build/ligo/odoc + - ls gitlab-pages/website/build/ligo/ # for debug + after_script: + - cp -r gitlab-pages/website/build/ligo public + artifacts: + paths: + - public + +.docker: &docker + image: docker:1.11 + services: + - docker:dind + +.docker_build: &docker_build + script: + - docker build -t $LIGO_REGISTRY_IMAGE:next -f ./docker/Dockerfile . + +.before_script: &before_script + before_script: + # Install dependencies + # rsync is needed by opam to sync a package installed from a local directory with the copy in ~/.opam + - apt-get update -qq + - scripts/install_native_dependencies.sh + - scripts/install_opam.sh + - export PATH="/usr/local/bin${PATH:+:}${PATH:-}" + + # Initialise opam, create switch, load opam environment variables + - printf '' | opam init --bare + - printf '' | opam switch create ligo-switch ocaml-base-compiler.4.06.1 + - eval $(opam config env) + + # Show versions and current switch + - echo "$PATH" + - opam --version + - printf '' | ocaml + - opam switch + local-dune-job: <<: *before_script stage: test script: - - vendors/opam-repository-tools/rewrite-local-opam-repository.sh - - opam repository add localrepo "file://$PWD/vendors/ligo-opam-repository-local-generated/" + - scripts/setup_ligo_opam_repository.sh - opam install -y --build-test --deps-only ./src/ - dune build -p ligo # TODO: also try instead from time to time: @@ -126,4 +158,4 @@ pages: only: - master - dev - + - feature/#3-add-odoc-to-website diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..f70b9412a --- /dev/null +++ b/Makefile @@ -0,0 +1,3 @@ +build-deps: + scripts/install_native_dependencies.sh + scripts/install_opam.sh diff --git a/docker/Dockerfile b/docker/Dockerfile index 5cedfcd58..dbc051aee 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -16,12 +16,12 @@ ADD . /ligo # the upcoming scripts WORKDIR /ligo -# Setup a custom opam repository where ligo is published -RUN sh scripts/setup_ligo_opam_repository.sh - # Install required native dependencies RUN sh scripts/install_native_dependencies.sh +# Setup a custom opam repository where ligo is published +RUN sh scripts/setup_ligo_opam_repository.sh + RUN opam update # Install ligo diff --git a/gitlab-pages/website/core/Footer.js b/gitlab-pages/website/core/Footer.js index ad6c1cfe5..1233b5ab1 100644 --- a/gitlab-pages/website/core/Footer.js +++ b/gitlab-pages/website/core/Footer.js @@ -37,6 +37,9 @@ class Footer extends React.Component { Contribute + + Api Documentation +
Community
diff --git a/gitlab-pages/website/siteConfig.js b/gitlab-pages/website/siteConfig.js index c265c4286..34a273ecc 100644 --- a/gitlab-pages/website/siteConfig.js +++ b/gitlab-pages/website/siteConfig.js @@ -100,6 +100,7 @@ const siteConfig = { {doc: 'setup/installation', label: 'Docs'}, {doc: 'tutorials/get-started/tezos-taco-shop-smart-contract', label: 'Tutorials'}, { blog: true, label: 'Blog' }, + // TODO: { href: "/odoc", label: "Api" }, {doc: 'contributors/origin', label: 'Contribute'}, {href: 'https://discord.gg/9rhYaEt', label: ''}, { search: true }, diff --git a/scripts/build_docker_image.sh b/scripts/build_docker_image.sh index eb2bdb611..273fa92c6 100755 --- a/scripts/build_docker_image.sh +++ b/scripts/build_docker_image.sh @@ -1 +1,4 @@ -docker build -t ligolang/ligo -f docker/Dockerfile . \ No newline at end of file +#!/bin/sh +set -e + +docker build -t ligolang/ligo -f docker/Dockerfile . diff --git a/scripts/install_ligo_with_dependencies.sh b/scripts/install_ligo_with_dependencies.sh index 9ad969f3f..78e5d8b62 100755 --- a/scripts/install_ligo_with_dependencies.sh +++ b/scripts/install_ligo_with_dependencies.sh @@ -1 +1,5 @@ -cd src && opam install . --yes \ No newline at end of file +#!/bin/sh +set -e + +cd src +opam install . --yes diff --git a/scripts/install_native_dependencies.sh b/scripts/install_native_dependencies.sh index 04d4ce17f..6b06f51ad 100755 --- a/scripts/install_native_dependencies.sh +++ b/scripts/install_native_dependencies.sh @@ -1,7 +1,14 @@ -apt-get -y install \ +#!/bin/sh +set -e + +apt-get update -qq +apt-get -y -qq install \ libev-dev \ perl \ pkg-config \ libgmp-dev \ libhidapi-dev \ - m4 \ No newline at end of file + m4 \ + libcap-dev \ + bubblewrap \ + rsync diff --git a/scripts/install_opam.sh b/scripts/install_opam.sh new file mode 100755 index 000000000..1a89f6a9b --- /dev/null +++ b/scripts/install_opam.sh @@ -0,0 +1,10 @@ +#!/bin/sh +set -e + +# TODO: this has many different modes of failure (file temp.opam-2.0.1-x86_64-linux.download-in-progress already exists, /usr/local/bin/opam already exists and is a directory or hard link, …) +# Try to improve these aspects. + +wget https://github.com/ocaml/opam/releases/download/2.0.1/opam-2.0.1-x86_64-linux -O temp.opam-2.0.1-x86_64-linux.download-in-progress +cp -i temp.opam-2.0.1-x86_64-linux.download-in-progress /usr/local/bin/opam +chmod +x /usr/local/bin/opam +rm temp.opam-2.0.1-x86_64-linux.download-in-progress diff --git a/scripts/installer.sh b/scripts/installer.sh index 7486f5a0f..c8623c6a7 100755 --- a/scripts/installer.sh +++ b/scripts/installer.sh @@ -1,31 +1,96 @@ -#!/bin/bash +#!/bin/sh +set -e + # You can run this installer like this: # curl https://gitlab.com/ligolang/ligo/blob/master/scripts/installer.sh | bash -# Make sure the marigold/ligo image is published at docker hub first -set -euET -o pipefail -version=$1 -printf "\nInstalling LIGO ($version)\n\n" +# Make sure the marigold/ligo image is published at docker hub first -if [ $version = "next" ] - then - # Install the ligo.sh from master - wget https://gitlab.com/ligolang/ligo/raw/dev/scripts/ligo.sh - else - # Install the ligo.sh from master - wget https://gitlab.com/ligolang/ligo/raw/master/scripts/ligo.sh +if test $# -ne 1; then + printf 'Usage: installer.sh VERSION'\\n + printf \\n + printf ' where VERSION can be "next" or a version number like 1.0.0'\\n + exit 1 +else + version=$1 + printf \\n'Installing LIGO (%s)'\\n\\n "$version" + + if [ $version = "next" ] + then + # Install the ligo.sh from master + url=https://gitlab.com/ligolang/ligo/raw/dev/scripts/ligo.sh + else + # Install the ligo.sh from master + url=https://gitlab.com/ligolang/ligo/raw/master/scripts/ligo.sh + fi + + # Pull the docker image used by ligo.sh + docker pull "ligolang/ligo:$version" + + # Install ligo.sh + # Rationale behind this part of the script: + # * mv is one of the few commands which is atomic + # * therefore we will create a file with the desired contents, and if that works, atomically mv it. + # If something goes wrong it will attempt to remove the temporary file + # (if removing the temporary file fails it's not a big deal due to the fairly explicit file name, + # the fact that it is hidden, and its small size) + # * most utilities (e.g. touch) don't explicitly state that they support umask in their man page + # * therefore we try to set the mode for the temporary file with an umask + do a chmod just to be sure + # * this leaves open a race condition where: + # 0) umask isn't applied by touch (e.g. the file already exists) + # 1) for some reason touch creates an executable file (e.g. the file already exists) + # 2) a user grabs the file while it is executable, and triggers its execution (the process is created but execution of the script doesn't start yet) + # 3) chmod makes it non-executable + # 4) the file is partially written + # 5) the execution actually starts, and executes a prefix of the desired command, and that prefix is usable for adverse effects + # To mitigate this, we wrap the command in the script with + # if true; then the_command; fi + # That way, the shell will raise an error due to a missing "fi" if the script executed while it is partially written + # * This still leaves open the same race condition where a propper prefix of #!/bin/sh\nif can be used to adverse effect, but there's not much we can do about this. + # * after the file is completely written, we make it executable + # * we then check for the cases where `mv` misbehaves + # * we then atomically move it to (hopefully) its destination + # * the main risks here are if /usr/local/bin/ is writable by hostile users on the same machine (then there are bigger problems than what is our concern) + # or if root itself tries to create a race condition (then there are bigger problems than what is our concern) + + # It's hard to place comments inside a sequence of commands, so here are the comments for the following code: + # wget download to stdout + # | sudo become root (sudo) for the rest of the commands + # ( subshell (to clean up temporary file if anything goes wrong) + # remove temporary file in case it already exists + # && create temporary file with (hopefully) the right permissions + # && fix permisisons in case the creation didn't take umask into account + # && redirect the output of the wget download to the temporary file + # ) || clean up temporary file if any command in the previous block failed + + wget "$url" -O - \ + | sed -e "s/next/$version/g" \ + | sudo sh -c ' \ + ( \ + rm -f /usr/local/bin/.temp.ligo.before-atomic-move \ + && (umask 0600 > /dev/null 2>&1; UMASK=0600 touch /usr/local/bin/.temp.ligo.before-atomic-move) \ + && chmod 0600 /usr/local/bin/.temp.ligo.before-atomic-move \ + && cat > /usr/local/bin/.temp.ligo.before-atomic-move \ + ) || (rm /usr/local/bin/.temp.ligo.before-atomic-move; exit 1)' + + # sudo become root (sudo) for the rest of the commands + # ( subshell (to clean up temporary file if anything goes wrong) + # && check that the download seems complete (one can't rely on sigpipe & failures to correctly stop the sudo session in case the download fails) + # && overwite LIGO version in the executable + # && now that the temporary file is complete, make it executable + # && if check for some corner cases: destination exists and is a directory + # elif check for some corner cases: destination exists and is symbolic link + # else atomically (hopefully) move temporary file to its destination + # ) || clean up temporary file if any command in the previous block failed + + sudo sh -c ' \ + ( \ + grep "END OF DOWNLOADED FILE" /usr/local/bin/.temp.ligo.before-atomic-move \ + && chmod 0755 /usr/local/bin/.temp.ligo.before-atomic-move \ + && if test -d /usr/local/bin/ligo; then printf "/usr/local/bin/ligo already exists and is a directory, cancelling installation"'\\\\'n; rm /usr/local/bin/.temp.ligo.before-atomic-move; \ + elif test -L /usr/local/bin/ligo; then printf "/usr/local/bin/ligo already exists and is a symbolic link, cancelling installation"'\\\\'n; rm /usr/local/bin/.temp.ligo.before-atomic-move; \ + else mv -i /usr/local/bin/.temp.ligo.before-atomic-move /usr/local/bin/ligo; fi \ + ) || (rm /usr/local/bin/.temp.ligo.before-atomic-move; exit 1)' + + # Installation finished, try running 'ligo' from your CLI + printf \\n'Installation successful, try to run '\''ligo --help'\'' now.'\\n fi - - -# Overwrite LIGO version in the executable -sed -i '' "s/latest/$version/g" ligo.sh - -# Copy the exucutable to the appropriate directory -sudo cp ligo.sh /usr/local/bin/ligo -sudo chmod +x /usr/local/bin/ligo -rm ligo.sh - -# Pull the docker image used by ligo.sh -docker pull "ligolang/ligo:$version" - -# Installation finished, try running 'ligo' from your CLI -printf "\nInstallation successful, try to run 'ligo --help' now.\n" \ No newline at end of file diff --git a/scripts/ligo.sh b/scripts/ligo.sh index 8ccadad8e..d0f9725d1 100755 --- a/scripts/ligo.sh +++ b/scripts/ligo.sh @@ -1,2 +1,10 @@ -#!/bin/bash -docker run -it -v "$PWD":"$PWD" -w "$PWD" ligolang/ligo:latest "$@" \ No newline at end of file +#!/bin/sh +set -e +if [ test "x$PWD" = "x" ]; then + echo "Cannot detect the current directory, the environment variable PWD is empty." + exit 1 +else + docker run -it -v "$PWD":"$PWD" -w "$PWD" ligolang/ligo:next "$@" +fi +# Do not remove the next line. It is used as an approximate witness that the download of this file was complete. This string should not appear anywhere else in the file. +# END OF DOWNLOADED FILE diff --git a/scripts/setup_ligo_opam_repository.sh b/scripts/setup_ligo_opam_repository.sh index e07eac487..444aee6d5 100755 --- a/scripts/setup_ligo_opam_repository.sh +++ b/scripts/setup_ligo_opam_repository.sh @@ -1,3 +1,6 @@ +#!/bin/sh +set -e + vendors/opam-repository-tools/rewrite-local-opam-repository.sh opam repo add ligo-opam-repository ./vendors/ligo-opam-repository-local-generated -opam update ligo-opam-repository \ No newline at end of file +opam update ligo-opam-repository diff --git a/vendors/opam-repository-tools/rewrite-local-opam-repository.sh b/vendors/opam-repository-tools/rewrite-local-opam-repository.sh index 01b196df9..8771aa7bd 100755 --- a/vendors/opam-repository-tools/rewrite-local-opam-repository.sh +++ b/vendors/opam-repository-tools/rewrite-local-opam-repository.sh @@ -1,13 +1,55 @@ -#!/bin/bash -set -euET -o pipefail -main(){ - root_dir="$(pwd | sed -e 's/\\/\\\\/' | sed -e 's/&/\\\&/' | sed -e 's/~/\\~/')" - rm -fr vendors/ligo-opam-repository-local-generated - mkdir vendors/ligo-opam-repository-local-generated - cp -a index.tar.gz packages repo urls.txt vendors/ligo-opam-repository-local-generated - cd vendors/ligo-opam-repository-local-generated - grep -r --null -l src: | grep -z 'opam$' | xargs -0 \ - sed -i -e 's~src: *"https://gitlab.com/ligolang/ligo/-/archive/master/ligo\.tar\.gz"~src: "file://'"$root_dir"'"~' - # TODO: run the update.sh script adequately to regenerate the index.tar.gz etc. in the local repo -} -if main; then exit 0; else exit $?; fi +#!/bin/sh + +# Stop on error. +set -e + +# Defensive checks. We're going to remove an entire folder so this script is somewhat dangerous. Better check in advance what can go wrong in the entire execution of the script. +if test -e index.tar.gz && test -e packages && test -e repo && test -e urls.txt; then + if test -d vendors/; then + if test -d "$PWD"; then + if command -v sed >/dev/null 2>&1 \ + && command -v rm >/dev/null 2>&1 \ + && command -v mkdir >/dev/null 2>&1 \ + && command -v cp >/dev/null 2>&1 \ + && command -v find >/dev/null 2>&1 \ + && command -v xargs >/dev/null 2>&1 \ + && command -v opam >/dev/null 2>&1; then + + # Escape the current directory, to be used as the replacement part of the sed regular expression + escaped_project_root="$(printf %s "$PWD" | sed -e 's/\\/\\\\/' | sed -e 's/&/\\\&/' | sed -e 's/~/\\~/')" + + # Recreate vendors/ligo-opam-repository-local-generated which contains a copy of the files related to the opam repository + rm -fr vendors/ligo-opam-repository-local-generated + mkdir vendors/ligo-opam-repository-local-generated + cp -pR index.tar.gz packages repo urls.txt vendors/ligo-opam-repository-local-generated + + # Rewrite the URLs in the opam repository to point to the project root + ( + cd vendors/ligo-opam-repository-local-generated + find . -type f -name opam -print0 | xargs -0 sed -i -e 's~src: *"https://gitlab.com/ligolang/ligo/-/archive/master/ligo\.tar\.gz"~src: "file://'"$escaped_project_root"'"~' + ) + + # Regenerate the index.tar.gz etc. in the local repo + ( + cd vendors/ligo-opam-repository-local-generated + opam admin index + opam admin cache + ) + else + echo "One of the following commands is unavailable: sed rm mkdir cp find xargs opam." + exit 1 + fi + else + echo "Unable to access the current directory as indicated by PWD. Was the CWD of the current shell removed?" + exit 1 + fi + + else + echo "Cannot find the directory vendors/ in the current directory" + exit 1 + fi +else + echo "Cannot find some of the following files in the current directory" + echo "index.tar.gz packages repo urls.txt" + exit 1 +fi