├── omnibus ├── pkg │ └── .gitkeep ├── .ruby-version ├── package-scripts │ └── crystal │ │ ├── preinst │ │ ├── postrm │ │ ├── prerm │ │ ├── postinst │ │ └── makeselfinst ├── Gemfile ├── config │ ├── projects │ │ ├── crystal.rb │ │ └── llvm.rb │ ├── software │ │ ├── tgz_package.rb │ │ ├── llvm_bin.rb │ │ ├── bdw-gc.rb │ │ ├── pcre2.rb │ │ ├── libyaml.rb │ │ ├── zlib.rb │ │ ├── libffi.rb │ │ ├── llvm.rb │ │ ├── shards.rb │ │ └── crystal.rb │ └── templates │ │ └── crystal │ │ └── crystal.erb ├── omnibus.rb └── Gemfile.lock ├── linux ├── .gitignore ├── .dockerignore ├── test.sh ├── README.md ├── bundled.dockerfile ├── Dockerfile └── Makefile ├── docker ├── .gitignore ├── alpine-84codes.Dockerfile ├── ubuntu-84codes.Dockerfile ├── smoke.sh ├── alpine.Dockerfile ├── ubuntu.Dockerfile ├── apply-latest-tags.sh └── Makefile ├── docs ├── aws-config.json ├── Dockerfile ├── aws-cloudfront-redirect.js └── Makefile ├── .gitignore ├── packages ├── Makefile ├── test │ ├── mint.bats │ ├── opensuse.bats │ ├── elementary_os.bats │ ├── fedora.bats │ ├── amazon.bats │ ├── ubuntu.bats │ └── debian.bats ├── test-install-on-docker.sh ├── obs-setup.sh ├── support │ └── test-install.sh ├── obs-push.sh ├── obs-new-minor.sh ├── obs-release.sh ├── README.md └── scripts │ └── install.sh ├── .github └── workflows │ └── packages.yml ├── snapcraft ├── Makefile ├── crystal-snap-wrapper ├── local │ └── snapcraft.yaml.tpl └── README.md ├── README.md ├── processes ├── scripts │ ├── functions.sh │ ├── make-shards-release.sh │ ├── make-crystal-release.sh │ ├── prepare-shards-release.sh │ ├── publish-crystal-packages-on-github.sh │ └── prepare-crystal-release.sh ├── crystal-CHANGELOG.md ├── shards-release.md └── crystal-release.md ├── darwin ├── README.md └── Makefile ├── .circleci └── config.yml └── scripts └── update-shards.sh /omnibus/pkg/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /linux/.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | -------------------------------------------------------------------------------- /omnibus/.ruby-version: -------------------------------------------------------------------------------- 1 | 3.4.3 2 | -------------------------------------------------------------------------------- /linux/.dockerignore: -------------------------------------------------------------------------------- 1 | /** 2 | !/files/** 3 | -------------------------------------------------------------------------------- /docker/.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /build-context/ 3 | -------------------------------------------------------------------------------- /docs/aws-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "IndexDocument": { 3 | "Suffix": "index.html" 4 | }, 5 | "ErrorDocument": { 6 | "Key": "api/${CRYSTAL_VERSION}/404.html" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /omnibus/package-scripts/crystal/preinst: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Perform necessary crystal setup steps 4 | # before package is installed. 5 | # 6 | 7 | echo "You're about to install crystal!" 8 | -------------------------------------------------------------------------------- /omnibus/package-scripts/crystal/postrm: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Perform necessary crystal removal steps 4 | # after package is uninstalled. 5 | # 6 | 7 | echo "crystal has been uninstalled!" 8 | 9 | exit 0 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | omnibus/pkg/ 2 | omnibus/.bundle 3 | omnibus/bin 4 | omnibus/crystal-darwin-* 5 | omnibus/vendor 6 | 7 | docs/build/ 8 | 9 | darwin/build/ 10 | 11 | snapcraft/snapcraft.yaml 12 | snapcraft/*.snap 13 | snapcraft/build/ 14 | -------------------------------------------------------------------------------- /packages/Makefile: -------------------------------------------------------------------------------- 1 | # Recipe for validating published distribution packages 2 | # and the installer script 3 | 4 | # Requires 5 | # * docker 6 | # * https://github.com/bats-core/bats-core 7 | 8 | .PHONY: test 9 | test: 10 | bats test 11 | -------------------------------------------------------------------------------- /packages/test/mint.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | @test "Linux Mint 21" { 4 | ./test-install-on-docker.sh linuxmintd/mint21-amd64 5 | } 6 | 7 | @test "Linux Mint 20" { 8 | ./test-install-on-docker.sh linuxmintd/mint20-amd64 9 | } 10 | 11 | -------------------------------------------------------------------------------- /packages/test/opensuse.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | @test "openSUSE Tumbleweed" { 4 | ./test-install-on-docker.sh opensuse/tumbleweed 5 | } 6 | 7 | @test "openSUSE Leap 15.5" { 8 | ./test-install-on-docker.sh opensuse/leap:15.5 9 | } 10 | -------------------------------------------------------------------------------- /omnibus/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | git_source(:github) do |repo_name| 4 | repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?('/') 5 | "https://github.com/#{repo_name}.git" 6 | end 7 | 8 | gem 'omnibus' 9 | gem 'omnibus-software' 10 | -------------------------------------------------------------------------------- /packages/test/elementary_os.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | @test "Elementary OS stable" { 4 | ./test-install-on-docker.sh elementary/docker:stable 5 | } 6 | 7 | @test "Elementary OS unstable" { 8 | ./test-install-on-docker.sh elementary/docker:unstable 9 | } 10 | -------------------------------------------------------------------------------- /packages/test/fedora.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | @test "Fedora Rawhide" { 4 | ./test-install-on-docker.sh fedora:rawhide 5 | } 6 | 7 | @test "Fedora 40" { 8 | ./test-install-on-docker.sh fedora:40 9 | } 10 | 11 | @test "Fedora 39" { 12 | ./test-install-on-docker.sh fedora:39 13 | } 14 | -------------------------------------------------------------------------------- /packages/test-install-on-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | docker_image="${1}" 6 | 7 | docker run --pull=always -e OBS_PROJECT="${OBS_PROJECT:-}" -e CRYSTAL_VERSION="${CRYSTAL_VERSION:-}" --rm -v $(pwd)/scripts:/scripts -v $(pwd)/support:/support -w / --entrypoint /bin/sh $docker_image -c "/support/test-install.sh ${@:2}" 8 | -------------------------------------------------------------------------------- /packages/test/amazon.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | @test "Amazon Linux 2023" { 4 | ./test-install-on-docker.sh amazonlinux:2023 5 | } 6 | 7 | # This image is stripped down and only comes with microdnf 8 | @test "Amazon Linux 2023 Lambda" { 9 | ./test-install-on-docker.sh public.ecr.aws/lambda/provided:al2023 10 | } 11 | -------------------------------------------------------------------------------- /docker/alpine-84codes.Dockerfile: -------------------------------------------------------------------------------- 1 | ARG crystal_version 2 | FROM 84codes/crystal:${crystal_version}-alpine AS build 3 | ARG llvm_version=20 4 | 5 | RUN \ 6 | apk add --update --no-cache --force-overwrite \ 7 | llvm${llvm_version}-dev llvm${llvm_version}-static \ 8 | g++ libffi-dev 9 | 10 | ENTRYPOINT [] 11 | CMD ["/bin/sh"] 12 | -------------------------------------------------------------------------------- /linux/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | @test "bundled tarball" { 4 | docker run -v $(pwd)/build:/build debian /bin/sh -e -c ' 5 | apt update && apt install -y gcc pkg-config 6 | tar -xf /build/crystal*-bundled.tar.gz 7 | crystal-*/bin/crystal env 8 | crystal-*/bin/crystal --version 9 | crystal-*/bin/crystal eval "puts \"Hello World\""' 10 | } 11 | -------------------------------------------------------------------------------- /packages/test/ubuntu.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | @test "Ubuntu 24.04 LTS" { 4 | ./test-install-on-docker.sh ubuntu:24.04 5 | } 6 | 7 | @test "Ubuntu 23.10" { 8 | ./test-install-on-docker.sh ubuntu:23.10 9 | } 10 | 11 | @test "Ubuntu 22.04" { 12 | ./test-install-on-docker.sh ubuntu:22.04 13 | } 14 | 15 | @test "Ubuntu 20.04" { 16 | ./test-install-on-docker.sh ubuntu:20.04 17 | } 18 | -------------------------------------------------------------------------------- /docker/ubuntu-84codes.Dockerfile: -------------------------------------------------------------------------------- 1 | ARG crystal_version 2 | FROM 84codes/crystal:${crystal_version}-ubuntu-24.04 AS build 3 | 4 | RUN \ 5 | apt-get update && \ 6 | apt-get install -y build-essential llvm-18 lld-18 libedit-dev gdb libffi-dev && \ 7 | apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 8 | 9 | RUN ln -sf /usr/bin/ld.lld-18 /usr/bin/ld.lld 10 | 11 | ENTRYPOINT [] 12 | CMD ["/bin/sh"] 13 | -------------------------------------------------------------------------------- /omnibus/config/projects/crystal.rb: -------------------------------------------------------------------------------- 1 | name 'crystal' 2 | maintainer 'Juan Wajnerman' 3 | homepage 'http://crystal-lang.org/' 4 | 5 | install_dir '/opt/crystal' 6 | build_version do 7 | source :version, from_dependency: 'crystal' 8 | end 9 | build_iteration ENV['PACKAGE_ITERATION'] 10 | 11 | dependency 'crystal' 12 | dependency 'shards' 13 | dependency 'tgz_package' 14 | 15 | exclude '\.git*' 16 | exclude 'bundler\/git' 17 | -------------------------------------------------------------------------------- /packages/obs-setup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This script configures OSC credentials for 4 | # https://api.opensuse.org 5 | # 6 | # Environment variables: 7 | # * OBS_USER: username 8 | # * OBS_PASSWORD: password 9 | 10 | set -eu 11 | 12 | # Configure OSC 13 | cat > ~/.oscrc <&2 12 | exit 1 13 | } 14 | 15 | INSTALL_PATH=/usr 16 | if [ `uname` = "Darwin" -a `uname -r|cut -f1 -d.` -ge 15 ]; then 17 | INSTALL_PATH=/usr/local 18 | fi 19 | 20 | rm -f ${INSTALL_PATH}/bin/crystal ${INSTALL_PATH}/bin/shards 21 | 22 | exit 0 23 | -------------------------------------------------------------------------------- /.github/workflows/packages.yml: -------------------------------------------------------------------------------- 1 | name: Test package installation 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "5 4 * * 0" # every sunday at 04:05 7 | 8 | jobs: 9 | test_packages: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Setup BATS 13 | uses: mig4/setup-bats@v1 14 | with: 15 | bats-version: 1.9.0 16 | 17 | - name: Check out code 18 | uses: actions/checkout@v4 19 | 20 | - name: Run test 21 | run: make -C packages test 22 | -------------------------------------------------------------------------------- /snapcraft/Makefile: -------------------------------------------------------------------------------- 1 | CRYSTAL_TARBALL = 2 | ARCH = 3 | GRADE = 4 | CHANNEL = 5 | 6 | .PHONY: all 7 | all: snapcraft.yaml 8 | snapcraft pack --build-for=$(ARCH) 9 | 10 | .PHONY: snapcraft.yaml 11 | snapcraft.yaml: 12 | sed 's/$${CRYSTAL_TARBALL}/$(subst /,\/,$(CRYSTAL_TARBALL))/; s/$${SNAP_GRADE}/$(GRADE)/' local/snapcraft.yaml.tpl > $@ 13 | 14 | .PHONY: push 15 | push: 16 | for SNAPFILE in *.snap; do\ 17 | sudo -E snapcraft upload --quiet --release=$(CHANNEL) $$SNAPFILE;\ 18 | done 19 | 20 | clean: 21 | snapcraft clean 22 | rm -f snapcraft.yaml *.snap 23 | -------------------------------------------------------------------------------- /omnibus/package-scripts/crystal/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Perform necessary crystal setup steps 4 | # after package is installed. 5 | # 6 | 7 | PROGNAME=$(basename $0) 8 | 9 | function error_exit 10 | { 11 | echo "${PROGNAME}: ${1:-"Unknown Error"}" 1>&2 12 | exit 1 13 | } 14 | 15 | INSTALL_PATH=/usr 16 | if [ `uname` = "Darwin" -a `uname -r|cut -f1 -d.` -ge 15 ]; then 17 | INSTALL_PATH=/usr/local 18 | fi 19 | 20 | ln -nfs /opt/crystal/bin/crystal ${INSTALL_PATH}/bin/crystal 21 | ln -nfs /opt/crystal/embedded/bin/shards ${INSTALL_PATH}/bin/shards 22 | 23 | exit 0 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Distribution scripts for Crystal 2 | 3 | This repository contains scripts to build distributions of the crystal compiler 4 | ready for release. It is used for building the tarballs and linux packages - 5 | currently only for `x86_64`, but eventually for every well supported platform. 6 | 7 | These packages contain `crystal`, `shards`, a copy of the standard library, and 8 | anything else required to make use of crystal. 9 | 10 | Each logical platform has it's own sub-directory, containing a `README` with 11 | information on it's own dependencies and it's own information on how to build. 12 | -------------------------------------------------------------------------------- /docker/smoke.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Smoke tests for Crystal docker images 4 | # 5 | # Used by `make smoke-all` 6 | 7 | set -eux 8 | 9 | if [[ "$VERSION" =~ "^[0-9]+(\.[0-9]+)*$" ]]; then 10 | crystal --version | grep -q "${VERSION}" 11 | else 12 | # $VERSION is not a version number on maintenance builds 13 | crystal --version | grep -q "Crystal" 14 | fi 15 | 16 | shards --version | grep -q Shards 17 | 18 | case "$1" in 19 | *-build) 20 | crystal eval 'require "llvm"; puts LLVM.version' | grep -q "$(/usr/bin/llvm-config-* --version)" 21 | ;; 22 | *) 23 | crystal eval 'puts "Hello World"' | grep -q "Hello World" 24 | ;; 25 | esac 26 | -------------------------------------------------------------------------------- /processes/scripts/functions.sh: -------------------------------------------------------------------------------- 1 | START_STEP=${START_STEP:-1} 2 | step_number=1 3 | 4 | step(){ 5 | message="$1" 6 | shift 7 | command="$*" 8 | 9 | echo 10 | echo -e "\033[33m===============================================================================\033[0m" 11 | echo -e "\033[33m$step_number. $message\033[0m" 12 | echo 13 | echo -en "$ $command" 14 | step_number=$(expr $step_number + 1) 15 | if [ $step_number -lt $START_STEP ]; then 16 | echo -e " \033[33m(skipped)\033[0m" 17 | return 18 | fi 19 | 20 | read -r REPLY 21 | 22 | if [ "$REPLY" != "skip" ]; then 23 | eval "$command" 24 | else 25 | echo -e "\033[33m(skipped)\033[0m" 26 | fi 27 | } 28 | -------------------------------------------------------------------------------- /omnibus/config/projects/llvm.rb: -------------------------------------------------------------------------------- 1 | name 'llvm' 2 | maintainer 'Juan Wajnerman' 3 | homepage 'http://llvm.org/' 4 | 5 | install_dir '/opt/llvm' 6 | build_version do 7 | source :version, from_dependency: 'llvm' 8 | end 9 | build_iteration 3 10 | 11 | def valid_cmake_version? 12 | `cmake --version` =~ /cmake version (\d+\.)(\d+\.)(\d)/ 13 | major, minor, patch = $1.to_i, $2.to_i, $3.to_i 14 | (major > 3) || (major == 3 && minor > 4) || (major == 3 && minor == 4 && patch >= 3) 15 | rescue 16 | false 17 | end 18 | 19 | dependency 'cmake' unless valid_cmake_version? 20 | dependency 'llvm' 21 | dependency 'tgz_package' if macos? || mac_os_x? || centos? 22 | 23 | exclude '\.git*' 24 | exclude 'bundler\/git' 25 | -------------------------------------------------------------------------------- /linux/README.md: -------------------------------------------------------------------------------- 1 | # Linux `x86_64` static build 2 | 3 | The `x86_64` crystal build is built inside an alpine linux container as a 4 | statically linked binary using musl libc. `libgc` is built on debian 5 | to make it work on glibc. 6 | The whole process is automated using a `Makefile`. 7 | 8 | # Dependencies 9 | 10 | - `docker` 11 | 12 | # Getting started 13 | 14 | Just run `make help`! 15 | 16 | # Build version variables 17 | 18 | * `CRYSTAL_VERSION`: How the binaries should be branded. 19 | * `CRYSTAL_SHA1`: Git tag/branch/sha1 to checkout and build source 20 | * `PACKAGE_ITERATION`: The package iteration 21 | * `PREVIOUS_CRYSTAL_RELEASE_LINUX64_TARGZ`: Url to crystal-{version}-{package}-linux-x86_64.tar.gz 22 | -------------------------------------------------------------------------------- /docs/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG crystal_docker_image 2 | FROM ${crystal_docker_image} 3 | 4 | RUN crystal --version 5 | 6 | ARG output_docs_base_name 7 | ARG crystal_sha1 8 | ARG crystal_repo=https://github.com/crystal-lang/crystal 9 | RUN git clone "${crystal_repo}" \ 10 | && cd crystal \ 11 | && git checkout ${crystal_sha1} \ 12 | \ 13 | && make docs DOCS_OPTIONS='--json-config-url=/api/versions.json --canonical-base-url="https://crystal-lang.org/api/latest/"'\ 14 | && git describe --tags --long --always 2>/dev/null > ./docs/revision.txt \ 15 | && mv ./docs ./${output_docs_base_name} \ 16 | \ 17 | && mkdir -p /output \ 18 | && tar -zcvf /output/${output_docs_base_name}.tar.gz ./${output_docs_base_name} \ 19 | && scripts/docs-versions.sh > /output/versions.json 20 | -------------------------------------------------------------------------------- /omnibus/config/software/tgz_package.rb: -------------------------------------------------------------------------------- 1 | name "tgz_package" 2 | default_version "0.0.1" 3 | skip_transitive_dependency_licensing true 4 | 5 | build do 6 | block do 7 | destination = File.expand_path('pkg', Omnibus::Config.project_root) 8 | version = "#{project.build_version}-#{project.build_iteration}" 9 | version.gsub!("/", "-") 10 | tgz_name = "#{project.name}-#{version}-#{ohai['os']}-#{ohai['kernel']['machine']}.tar.gz" 11 | if macos? || mac_os_x? 12 | transform = "-s /./#{project.name}-#{version}/" 13 | else 14 | transform = %(--transform="s/./#{project.name}-#{version}/") 15 | end 16 | 17 | command "tar czf #{destination}/#{tgz_name} #{transform} -C #{install_dir} .", 18 | env: {"COPYFILE_DISABLE" => "1"} 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /omnibus/package-scripts/crystal/makeselfinst: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Install a full crystal 4 | # 5 | 6 | PROGNAME=`basename $0` 7 | INSTALLER_DIR=`dirname $0` 8 | DEST_DIR=/opt/crystal 9 | CONFIG_DIR=/etc/crystal 10 | USAGE="usage: $0" 11 | 12 | error_exit() 13 | { 14 | echo "${PROGNAME}: ${1:-"Unknown Error"}" 1>&2 15 | exit 1 16 | } 17 | 18 | # move the actual files into place 19 | rm -rf $DEST_DIR/* || error_exit "Cannot remove contents of $DEST_DIR" 20 | mkdir -p $DEST_DIR || error_exit "Cannot create $DEST_DIR" 21 | cp -R $INSTALLER_DIR $DEST_DIR || error_exit "Cannot install to $DEST_DIR" 22 | rm -f $DEST_DIR/$PROGNAME 23 | 24 | # You may want to symlink your packages bin files into /usr/bin 25 | # ln -sf $DEST_DIR/bin/crystal /usr/bin || error_exit "Cannot link crystal to /usr/bin" 26 | 27 | exit 0 28 | -------------------------------------------------------------------------------- /omnibus/config/software/llvm_bin.rb: -------------------------------------------------------------------------------- 1 | name "llvm_bin" 2 | LLVM_VERSION = (ENV['LLVM_VERSION'] || "15.0.7").strip 3 | default_version "#{LLVM_VERSION}-3" 4 | skip_transitive_dependency_licensing true 5 | 6 | if (macos? || mac_os_x?) && _64_bit? 7 | case LLVM_VERSION 8 | when "10.0.0" 9 | # source_md5 = "edccfa777cba6e160b19bd5b57b12c8f" # 10.0.0-1 10 | # source_md5 = "dc44dbc947b67c76e44df1c9e38df901" # 10.0.0-2 11 | source_md5 = "d32c4d28b8fc50efda3f451e0d8265ea" # 10.0.0-3 (universal darwin) 12 | when "15.0.7" 13 | source_md5 = "0ab0ffe63a0e72346a979d7a0e964b94" # 15.0.7-3 (universal darwin) 14 | else 15 | raise "llvm_bin #{LLVM_VERSION} not supported on osx" 16 | end 17 | else 18 | raise "llvm_bin not supported" 19 | end 20 | 21 | source url: "http://crystal-lang.s3.amazonaws.com/llvm/llvm-#{version}-#{ohai['os']}-x86_64.tar.gz", 22 | md5: source_md5 23 | 24 | relative_path "llvm-#{version}" 25 | -------------------------------------------------------------------------------- /darwin/README.md: -------------------------------------------------------------------------------- 1 | # Darwin `universal` build 2 | 3 | The `universal` crystal darwin build is built natively in an osx host using omnibus. 4 | The whole process is automated using a `Makefile`. 5 | 6 | # Dependencies 7 | 8 | * Ruby 3.2.2 and `bundle install --binstubs` in `./omnibus` 9 | * `pkgconfig`, `libtool` (Can be installed by `$ brew install pkgconfig libtool`) 10 | * Own `/opt/crystal`, `/var/cache`. 11 | 12 | ``` 13 | sudo mkdir -p /opt/crystal 14 | sudo chown $(whoami) /opt/crystal/ 15 | sudo mkdir -p /var/cache 16 | sudo chown $(whoami) /var/cache 17 | ``` 18 | 19 | # Getting started 20 | 21 | Just run `make help`! 22 | 23 | # Build version variables 24 | 25 | * `CRYSTAL_VERSION`: How the binaries should be branded. 26 | * `CRYSTAL_SHA1`: Git tag/branch/sha1 to checkout and build source 27 | * `PACKAGE_ITERATION`: The package iteration 28 | * `PREVIOUS_CRYSTAL_RELEASE_DARWIN_TARGZ`: Url to `crystal-{version}-{package}-darwin-x86_64.tar.gz` 29 | -------------------------------------------------------------------------------- /snapcraft/crystal-snap-wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ ! -f $SNAP_USER_COMMON/env-check-success ]; then 4 | # check if a simple program can be compiled 5 | # if something fails show a banner to the user 6 | 7 | $SNAP/bin/crystal eval 'puts "1"' >/dev/null 2>/dev/null 8 | if [ $? -eq 0 ]; then 9 | touch $SNAP_USER_COMMON/env-check-success 10 | else 11 | cat < 21 | 22 | ### Text 23 | 24 | 25 | ### Collections 26 | 27 | 28 | ### Serialization 29 | 30 | 31 | ### Time 32 | 33 | ### Files 34 | 35 | ### Networking 36 | 37 | 38 | ### Logging 39 | 40 | ### Crypto 41 | 42 | ### Concurrency 43 | 44 | ### System 45 | 46 | ### Runtime 47 | 48 | ### Spec 49 | 50 | ## Compiler 51 | 52 | 53 | ### Language semantics 54 | 55 | 56 | ### Debugger 57 | 58 | ## Tools 59 | 60 | ### Formatter 61 | 62 | ### Doc generator 63 | 64 | ### Playground 65 | 66 | ## Others 67 | -------------------------------------------------------------------------------- /docker/ubuntu.Dockerfile: -------------------------------------------------------------------------------- 1 | ARG base_docker_image=ubuntu:24.04 2 | FROM ${base_docker_image} AS runtime 3 | ARG llvm_version=20 4 | 5 | RUN \ 6 | apt-get update && \ 7 | apt-get install -y apt-transport-https && \ 8 | apt-get update && \ 9 | DEBIAN_FRONTEND=noninteractive \ 10 | apt-get install -y tzdata gcc pkg-config libssl-dev libxml2-dev libyaml-dev libgmp-dev git make \ 11 | libpcre3-dev libpcre2-dev libz-dev libgc-dev && \ 12 | apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 13 | 14 | ARG TARGETARCH 15 | COPY crystal-${TARGETARCH}.tar.gz /tmp/crystal.tar.gz 16 | 17 | RUN \ 18 | tar -xz -C /usr --strip-component=1 -f /tmp/crystal.tar.gz && \ 19 | rm /tmp/crystal.tar.gz 20 | 21 | CMD ["/bin/sh"] 22 | 23 | FROM runtime AS build 24 | 25 | RUN \ 26 | apt-get update && \ 27 | apt-get install -y build-essential llvm-${llvm_version} lld-${llvm_version} libedit-dev libevent-dev gdb libffi-dev && \ 28 | apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 29 | 30 | RUN ln -sf /usr/bin/ld.lld-${llvm_version} /usr/bin/ld.lld 31 | 32 | CMD ["/bin/sh"] 33 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | jobs: 4 | omnibus_osx_llvm: 5 | macos: 6 | xcode: 26.0.1 7 | environment: 8 | LLVM_VERSION: 15.0.7 9 | MACOSX_DEPLOYMENT_TARGET: 10.11 10 | shell: /bin/bash --login -eo pipefail 11 | steps: 12 | - run: 13 | name: Setup environment 14 | command: | 15 | brew update 16 | brew install pkgconfig libtool cmake 17 | 18 | sudo mkdir -p /opt/llvm 19 | sudo chown $(whoami) /opt/llvm/ 20 | sudo mkdir -p /var/cache 21 | sudo chown $(whoami) /var/cache 22 | - checkout 23 | - run: 24 | no_output_timeout: 280m 25 | name: Build LLVM 26 | command: | 27 | cd omnibus 28 | bundle check || bundle install --binstubs 29 | bundle exec omnibus build llvm 30 | - store_artifacts: 31 | path: ./omnibus/pkg 32 | destination: llvm 33 | 34 | workflows: 35 | version: 2 36 | 37 | build_llvm: 38 | jobs: 39 | - omnibus_osx_llvm: 40 | filters: 41 | branches: 42 | only: 43 | - /.*\bbuild-llvm\b.*/ 44 | -------------------------------------------------------------------------------- /scripts/update-shards.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Update shards release. 4 | # 5 | # Usage: 6 | # 7 | # scripts/update-shards.sh [] 8 | # 9 | # This helper script pulls the latest Shards release from GitHub and updates all 10 | # references to the shards release in this repository. 11 | 12 | set -eu 13 | 14 | SHARDS_VERSION=${1:-} 15 | if [ -z "$SHARDS_VERSION" ]; then 16 | # fetch latest release from GitHub 17 | SHARDS_VERSION=$(gh release view --repo crystal-lang/shards --json tagName --jq .tagName | cut -c 2-) 18 | fi 19 | 20 | # Update SHARDS_VERSION in linux/Makefile 21 | sed -i -E "s|SHARDS_VERSION = .*|SHARDS_VERSION = v${SHARDS_VERSION}|" linux/Makefile 22 | 23 | # Add version to omnibus 24 | if ! grep -q -E "version \"${SHARDS_VERSION}\"" omnibus/config/software/shards.rb; then 25 | archive_checksum=$(curl -L -s "https://github.com/crystal-lang/shards/archive/v${SHARDS_VERSION}.tar.gz" | md5sum | cut -d' ' -f1) 26 | sed -i -E "/^source url:/i version \"${SHARDS_VERSION}\" do\n source md5: \"${archive_checksum}\"\nend\n" omnibus/config/software/shards.rb 27 | fi 28 | 29 | sed -i -E "s|SHARDS_VERSION = .*|SHARDS_VERSION = \"${SHARDS_VERSION}\"|" omnibus/config/software/shards.rb 30 | -------------------------------------------------------------------------------- /docker/apply-latest-tags.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | # This helper script promotes the docker images for the specified version 4 | # to "latest" as well as the major and minor release tags. 5 | # 6 | # Usage: 7 | # 8 | # ./apply-latest-tags.sh 9 | 10 | set -eu 11 | 12 | apply_tag() { 13 | base_tag=$1 14 | new_tag=$2 15 | 16 | echo "Publishing ${base_tag} as ${new_tag}" 17 | 18 | docker tag "${base_tag}" "${new_tag}" 19 | docker push "${new_tag}" 20 | } 21 | 22 | version=$1 23 | 24 | docker pull "crystallang/crystal:${version}" 25 | docker pull "crystallang/crystal:${version}-alpine" 26 | 27 | # Tag latest 28 | apply_tag "crystallang/crystal:${version}" "crystallang/crystal:latest" 29 | apply_tag "crystallang/crystal:${version}-alpine" "crystallang/crystal:latest-alpine" 30 | 31 | # Tag minor (x.y) 32 | apply_tag "crystallang/crystal:${version}" "crystallang/crystal:${version%.*}" 33 | apply_tag "crystallang/crystal:${version}-alpine" "crystallang/crystal:${version%.*}-alpine" 34 | 35 | # Tag major (x) 36 | apply_tag "crystallang/crystal:${version}" "crystallang/crystal:${version%%.*}" 37 | apply_tag "crystallang/crystal:${version}-alpine" "crystallang/crystal:${version%%.*}-alpine" 38 | -------------------------------------------------------------------------------- /processes/scripts/make-shards-release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # 3 | # This helper tags a new Shards release and publishes it to GitHub releases. 4 | # 5 | # Usage: 6 | # 7 | # scripts/make-shards-release.sh [VERSION] 8 | # 9 | # Requirements: 10 | # * packages: git gh sed 11 | # * Working directory should be in a checked out work tree of `crystal-lang/shards`. 12 | # 13 | # * The version is read from `src/VERSION`. 14 | # * Tags current commit and pushes tag to GitHub. 15 | # * Creates GitHub release for that tag with content from `CHANGELOG.md`. 16 | 17 | set -eu 18 | 19 | VERSION=$(cat VERSION | tr -d '\n') 20 | 21 | . $(dirname $(realpath $0))/functions.sh 22 | 23 | grep -q "version: $VERSION" shard.yml || abort "Missing version $VERSION in shard.yml" 24 | 25 | tag=v$VERSION 26 | step "Tag master commit as version ${tag}" git tag -s -a -m $tag $tag 27 | 28 | git show 29 | 30 | step "Push tag to GitHub" git push --tags 31 | 32 | sed -E '3,/^## /!d' CHANGELOG.md | sed '$d' | sed -Ez 's/^\n+//; s/\n+$/\n/g' > CHANGELOG.$VERSION.md 33 | 34 | echo "$ more CHANGELOG.$VERSION.md" 35 | more CHANGELOG.$VERSION.md 36 | 37 | step "Create GitHub release" gh release -R crystal-lang/shards create $tag --title $tag --notes-file CHANGELOG.$VERSION.md 38 | 39 | rm CHANGELOG.$VERSION.md 40 | -------------------------------------------------------------------------------- /processes/scripts/make-crystal-release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # 3 | # This helper tags a new Crystal release and publishes it to GitHub releases. 4 | # 5 | # Usage: 6 | # 7 | # scripts/make-crystal-release.sh 8 | # 9 | # Requirements: 10 | # * packages: git gh sed 11 | # * Working directory should be in a checked out work tree of `crystal-lang/crystal`. 12 | # 13 | # * The version is read from `src/VERSION`. 14 | # * Tags current commit and pushes tag to GitHub. 15 | # * Creates GitHub release for that tag with content from `CHANGELOG.md`. 16 | 17 | set -eu 18 | 19 | VERSION=$(cat src/VERSION | tr -d '\n') 20 | START_STEP=${1:-1} 21 | 22 | . $(dirname $(realpath $0))/functions.sh 23 | 24 | step "Tag master commit as version ${VERSION}" git tag -s -a -m $VERSION $VERSION 25 | 26 | git show 27 | 28 | step "Push tag to GitHub" git push upstream --tags 29 | 30 | sed -E '7,/^## /!d' CHANGELOG.md | sed '$d' | sed -E 's/^\n+//; s/\n+$/\n/g' > CHANGELOG.$VERSION.md 31 | 32 | echo "$ more CHANGELOG.$VERSION.md" 33 | more CHANGELOG.$VERSION.md 34 | 35 | step "Create GitHub release" gh release -R crystal-lang/crystal create $VERSION --draft --title $VERSION --notes-file CHANGELOG.$VERSION.md 36 | 37 | rm CHANGELOG.$VERSION.md 38 | 39 | step "Wait for CI workflow to build artifacts ☕" echo 40 | -------------------------------------------------------------------------------- /snapcraft/local/snapcraft.yaml.tpl: -------------------------------------------------------------------------------- 1 | name: crystal 2 | base: core22 3 | summary: A language for humans and computers 4 | description: | 5 | * Have a syntax similar to Ruby (but compatibility with it is not a goal) 6 | * Statically type-checked but without having to specify the type of variables or method arguments. 7 | * Be able to call C code by writing bindings to it in Crystal. 8 | * Have compile-time evaluation and generation of code, to avoid boilerplate code. Compile to efficient native code. 9 | adopt-info: crystal 10 | 11 | architectures: 12 | - build-on: [amd64] 13 | build-for: [amd64] 14 | - build-on: [amd64, arm64] 15 | build-for: [arm64] 16 | 17 | grade: ${SNAP_GRADE} 18 | confinement: classic 19 | 20 | environment: 21 | SHARDS_CACHE_PATH: $SNAP_USER_COMMON/.cache/shards 22 | CRYSTAL_CACHE_DIR: $SNAP_USER_COMMON/.cache/crystal 23 | 24 | apps: 25 | crystal: 26 | command: crystal-snap-wrapper 27 | shards: 28 | command: bin/shards 29 | 30 | parts: 31 | crystal: 32 | plugin: dump 33 | source: ${CRYSTAL_TARBALL} 34 | override-pull: | 35 | craftctl default 36 | craftctl set version="$(cat $CRAFT_PART_SRC/share/crystal/src/VERSION | head -n 1)" 37 | 38 | snap-wrapper: 39 | plugin: dump 40 | source: . 41 | stage: 42 | - crystal-snap-wrapper 43 | -------------------------------------------------------------------------------- /omnibus/config/software/bdw-gc.rb: -------------------------------------------------------------------------------- 1 | name "bdw-gc" 2 | default_version "8.2.0" 3 | skip_transitive_dependency_licensing true 4 | 5 | source :url => "https://github.com/ivmai/bdwgc/releases/download/v#{version}/gc-#{version}.tar.gz" 6 | 7 | version "7.4.10" do 8 | source md5: "6d894c05c218aa380cd13f54f9c715e9" 9 | end 10 | 11 | version "7.6.8" do 12 | source md5: "9ae6251493ead5d0d13b044954cec7d7" 13 | end 14 | 15 | version "7.6.12" do 16 | source md5: "8175e1be00c6cd6eac2e8d67bdf451df" 17 | end 18 | 19 | version "8.0.4" do 20 | source md5: "67a5093e2f9f381bd550aa891d00b54b" 21 | end 22 | 23 | version "8.0.6" do 24 | source md5: "4878e629f482600f2060f30853c7b415" 25 | end 26 | 27 | version "8.2.0" do 28 | source md5: "c3c04af9c1e4209e315eee50efe7b320" 29 | end 30 | 31 | relative_path "gc-#{version}" 32 | 33 | env = with_standard_compiler_flags(with_embedded_path) 34 | env["CFLAGS"] << " -fPIC -arch arm64 -arch x86_64" 35 | env["CPPFLAGS"] = env["CPPFLAGS"].gsub("-arch arm64 -arch x86_64", "") 36 | 37 | build do 38 | command "./configure" \ 39 | " --disable-debug" \ 40 | " --disable-dependency-tracking" \ 41 | " --disable-shared" \ 42 | " --enable-large-config" \ 43 | " --prefix=#{install_dir}/embedded", env: env 44 | 45 | 46 | make "-j #{workers}" 47 | make "install" 48 | end 49 | -------------------------------------------------------------------------------- /packages/obs-push.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # $ ./obs-push.sh PROJECT VERSION SNAPSHOT COMMIT_HASH CRYSTAL_LINUX64_TARGZ CRYSTAL_DOCS_TARGZ 4 | 5 | # This script uses osc to check out PROJECT, update the version information 6 | # (VERSION, SNAPSHOT, COMMIT_HASH) and build artifacts (*_TARGZ arguments), 7 | # and commit the changes to OBS. 8 | # 9 | # Requirements: 10 | # * packages: osc build which 11 | # * configured ~/.oscrc with credentials 12 | 13 | set -eu 14 | 15 | PACKAGE="crystal" 16 | 17 | PROJECT=$1 18 | VERSION=$2 19 | SNAPSHOT=$3 20 | COMMIT_HASH=$4 21 | CRYSTAL_LINUX64_TARGZ=$5 22 | CRYSTAL_DOCS_TARGZ=$6 23 | 24 | # Checkout OBS package 25 | osc checkout "$PROJECT" "$PACKAGE" 26 | 27 | pushd "$PROJECT/$PACKAGE" 28 | 29 | # Copy build artifacts 30 | cp "$CRYSTAL_LINUX64_TARGZ" "$PACKAGE-snapshot-linux-x86_64.tar.gz" 31 | cp "$CRYSTAL_DOCS_TARGZ" "$PACKAGE-snapshot-docs.tar.gz" 32 | 33 | # Update version in *.dsc and *.spec 34 | PACKAGE_VERSION="${VERSION}~${SNAPSHOT}.git.${COMMIT_HASH:0:8}" 35 | sed -i -e "s/^Version: .*/Version: ${PACKAGE_VERSION}-1/" *.dsc 36 | sed -i -e "s/^Version: .*/Version: ${PACKAGE_VERSION}/" *.spec 37 | 38 | # Commit changes to OBS 39 | message="Update $PROJECT to $SNAPSHOT" 40 | osc vc -m "$message" 41 | osc diff 42 | osc commit -m "$message" 43 | 44 | # Remove OSC working dir 45 | popd 46 | rm -r "$PROJECT/$PACKAGE" 47 | -------------------------------------------------------------------------------- /docs/aws-cloudfront-redirect.js: -------------------------------------------------------------------------------- 1 | // Since CloudFront doesn't run functions when the origin returns a statusCode >=400 2 | // this function has to run upon "viewer request", before hitting the origin 3 | 4 | function redirect(path) { 5 | return { 6 | statusCode: 302, 7 | headers: { 8 | 'location': { value: path } 9 | } 10 | } 11 | } 12 | 13 | const LATEST_INDEX_REDIRECTION_PATHS = [ '/api', '/api/', '/api/index.html', '/api/latest'] 14 | 15 | function handler(event) { 16 | var requestPath = event.request.uri 17 | 18 | // well-known paths that should be queried as-is 19 | if( 20 | requestPath == '/api/versions.json' || 21 | requestPath.startsWith('/api/1.') || 22 | requestPath.startsWith('/api/0.') || 23 | requestPath == '/api/master' || 24 | requestPath.startsWith('/api/master/') 25 | ) { 26 | return event.request 27 | } 28 | 29 | // prefixes that go to the current version's index 30 | if(LATEST_INDEX_REDIRECTION_PATHS.includes(requestPath)) { 31 | return redirect('/api/${CRYSTAL_VERSION}/') 32 | } 33 | 34 | // "latest" prefix should be re-written to the current version 35 | if(requestPath.startsWith('/api/latest/')) { 36 | return redirect(requestPath.replace('/api/latest/', '/api/${CRYSTAL_VERSION}/')) 37 | } 38 | 39 | // at this point, we assume the request omited the version - eg, `/api/String.html` 40 | return redirect(requestPath.replace('/api/', '/api/${CRYSTAL_VERSION}/')) 41 | } 42 | -------------------------------------------------------------------------------- /packages/obs-new-minor.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eu 4 | 5 | if ! command -v osc > /dev/null; then 6 | exec docker run --rm -it \ 7 | -e OBS_USER=${OBS_USER:-} \ 8 | -e OBS_PASSWORD=${OBS_PASSWORD:-} \ 9 | -v $(pwd):/workspace -w /workspace \ 10 | crystallang/osc /bin/bash -x /workspace/$0 $@ 11 | fi 12 | 13 | PROJECT=$1 14 | PACKAGE=$2 15 | VERSION=$3 16 | OLD_PACKAGE=${4} 17 | 18 | BASE_PACKAGE=${PACKAGE%%[0-9]*} 19 | 20 | if [ ! -f ~/.oscrc ]; then 21 | ./obs-setup.sh 22 | fi 23 | 24 | # Checkout OBS package 25 | LOCAL_BRANCH_FOLDER="home:$OBS_USER:branches:$PROJECT/$PACKAGE" 26 | 27 | osc copypac "$PROJECT" "$OLD_PACKAGE" "$PROJECT" "$PACKAGE" 28 | 29 | if [ -d "${LOCAL_BRANCH_FOLDER}" ]; then 30 | pushd "${LOCAL_BRANCH_FOLDER}" 31 | osc up 32 | else 33 | sleep 10 34 | 35 | osc branchco "$PROJECT" "$PACKAGE" 36 | pushd "${LOCAL_BRANCH_FOLDER}" 37 | fi 38 | 39 | # Setup for new minor version package 40 | sed -i -e "s/${OLD_PACKAGE}/${PACKAGE}/" *.spec debian.control *.dsc 41 | 42 | osc mv "${OLD_PACKAGE}.dsc" "${PACKAGE}.dsc" 43 | osc mv "${OLD_PACKAGE}-docs.dsc" "${PACKAGE}-docs.dsc" 44 | 45 | # Start a fresh changelog 46 | cat < debian.changelog 47 | ${PACKAGE} (${VERSION}-1) stable; urgency=low 48 | 49 | * Create package for ${BASE_PACKAGE} ${VERSION} 50 | 51 | -- Crystal Team $(LC_ALL=en_US date --utc +'%a, %-d %b %Y %T UTC') 52 | EOF 53 | echo > *.changes 54 | 55 | popd 56 | ./obs-release.sh $PROJECT $PACKAGE $VERSION 57 | -------------------------------------------------------------------------------- /omnibus/config/software/pcre2.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2012-2014 Chef Software, Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | name "pcre2" 18 | default_version "10.42" 19 | skip_transitive_dependency_licensing true 20 | 21 | source url: "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-#{version}/pcre2-#{version}.tar.gz", 22 | md5: "37d2f77cfd411a3ddf1c64e1d72e43f7" 23 | 24 | relative_path "pcre2-#{version}" 25 | 26 | build do 27 | env = with_standard_compiler_flags(with_embedded_path) 28 | env["CFLAGS"] << " -DMAC_OS_X_VERSION_MIN_REQUIRED=110000 -fPIC -arch arm64 -arch x86_64" 29 | env["CPPFLAGS"] = env["CPPFLAGS"].gsub("-arch arm64 -arch x86_64", "") 30 | 31 | command "./configure" \ 32 | " --prefix=#{install_dir}/embedded" \ 33 | " --disable-cpp" \ 34 | " --disable-shared" \ 35 | " --enable-unicode-properties" \ 36 | " --enable-utf" \ 37 | " --enable-jit", env: env 38 | 39 | make "-j #{workers}", env: env 40 | make "install", env: env 41 | end 42 | -------------------------------------------------------------------------------- /omnibus/config/software/libyaml.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2012-2014 Chef Software, Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | name "libyaml" 18 | default_version '0.1.6' 19 | skip_transitive_dependency_licensing true 20 | 21 | # The sources of pyyaml are republished in S3 since pyyaml.org 22 | # seems to be restricting the user agent or the requests from our CI 23 | # http://pyyaml.org/download/libyaml/yaml-#{version}.tar.gz 24 | 25 | source url: "http://crystal-lang.s3.amazonaws.com/libyaml/yaml-#{version}.tar.gz", 26 | md5: '5fe00cda18ca5daeb43762b80c38e06e' 27 | 28 | relative_path "yaml-#{version}" 29 | 30 | build do 31 | env = with_standard_compiler_flags(with_embedded_path) 32 | env["CFLAGS"] << " -fPIC -arch arm64 -arch x86_64" 33 | env["CPPFLAGS"] = env["CPPFLAGS"].gsub("-arch arm64 -arch x86_64", "") 34 | 35 | command "./configure" \ 36 | " --disable-shared" \ 37 | " --prefix=#{install_dir}/embedded", env: env 38 | 39 | make "-j #{workers}", env: env 40 | make "-j #{workers} install", env: env 41 | end 42 | -------------------------------------------------------------------------------- /processes/scripts/prepare-shards-release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # This helper creates a new release issue for Shards 4 | # 5 | # Usage: 6 | # 7 | # scripts/prepare-shards-release.sh VERSION 8 | # 9 | # The content is generated from Shards release checklist (../shards-release.md) 10 | # with filters applied based on the version type (major, minor, or patch). 11 | 12 | set -eu 13 | 14 | if [ $# -lt 1 ]; then 15 | printf "Release version: " 16 | read VERSION 17 | 18 | if [ -z "$VERSION" ]; then 19 | echo "Usage: $0 VERSION" 20 | exit 1 21 | fi 22 | else 23 | VERSION=$1 24 | fi 25 | 26 | . $(dirname $(realpath $0))/functions.sh 27 | 28 | if [[ ! "$VERSION" =~ ^[0-9] ]]; then 29 | echo "Invalid VERSION: ${VERSION}" 30 | exit 1 31 | fi 32 | 33 | case $VERSION in 34 | *.0.0) 35 | TYPE=major 36 | ;; 37 | *.0) 38 | TYPE=minor 39 | ;; 40 | *) 41 | TYPE=patch 42 | ;; 43 | esac 44 | 45 | dist_scripts_root=$(dirname $(dirname $(dirname $(realpath $0)))) 46 | 47 | body=$(sed -E '/^##/,$!d' $dist_scripts_root/processes/shards-release.md) 48 | 49 | case $TYPE in 50 | patch) 51 | body=$(echo "$body" | sed -E "/\(major\)/d;/\(minor\)/d;s/\(patch\)\s*//") 52 | ;; 53 | minor) 54 | body=$(echo "$body" | sed -E "/\(major\)/d;s/\(minor\)\s*//;/\(patch\)/d") 55 | ;; 56 | major) 57 | body=$(echo "$body" | sed -E "s/\(major\)\s*//;s/\(minor\)\s*//;/\(patch\)/d") 58 | ;; 59 | esac 60 | 61 | body=$(echo "$body" | sed -E "s/\\$\{VERSION\}/$VERSION/g") 62 | 63 | body=$(printf "%q" "$body") 64 | step "Create tracking issue in crystal-lang/distribution-scripts" gh issue create -R crystal-lang/distribution-scripts --body "$body" --label "release" --title \"Release Shards $VERSION\" 65 | -------------------------------------------------------------------------------- /omnibus/config/software/zlib.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2012-2014 Chef Software, Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | name "zlib" 18 | default_version "1.2.8" 19 | license "Zlib" 20 | license_file "README" 21 | skip_transitive_dependency_licensing true 22 | 23 | version "1.2.6" do 24 | source sha256: "21235e08552e6feba09ea5e8d750805b3391c62fb81c71a235c0044dc7a8a61b" 25 | end 26 | 27 | version "1.2.8" do 28 | source sha256: "36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d" 29 | end 30 | 31 | source url: "https://zlib.net/fossils/zlib-#{version}.tar.gz" 32 | 33 | relative_path "zlib-#{version}" 34 | 35 | build do 36 | # We omit the omnibus path here because it breaks mac_os_x builds by picking 37 | # up the embedded libtool instead of the system libtool which the zlib 38 | # configure script cannot handle. 39 | env = with_standard_compiler_flags 40 | env["CFLAGS"] << " -fPIC -arch arm64 -arch x86_64" 41 | env["CPPFLAGS"] = env["CPPFLAGS"].gsub("-arch arm64 -arch x86_64", "") 42 | 43 | # For some reason zlib needs this flag on solaris (cargocult warning?) 44 | env['CFLAGS'] << " -DNO_VIZ" if solaris2? 45 | 46 | command "./configure" \ 47 | " --static" \ 48 | " --prefix=#{install_dir}/embedded", env: env 49 | 50 | make "-j #{workers}", env: env 51 | make "-j #{workers} install", env: env 52 | end 53 | -------------------------------------------------------------------------------- /processes/scripts/publish-crystal-packages-on-github.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # 3 | # This helper pulls binary build artifacts from the release workflow and publishes them to the GitHub release. 4 | # 5 | # Usage: 6 | # 7 | # scripts/publish-crystal-packages-on-github.sh CIRCLECI_ARTIFACT_URL 8 | # 9 | # Arguments: 10 | # 11 | # CIRCLECI_ARTIFACT_URL: URL to a binary artifact from the CircleCI release workflow (`dist_artifact` job). 12 | # Any URL suffices as an example, the script just needs that to pull the path prefix 13 | # and will download all artifacts, not just the given URL. 14 | # 15 | # Requirements: 16 | # * packages: gh wget 17 | # 18 | # * The version is read from `$VERSION` or `src/VERSION`. 19 | # * Pulls release artifacts from CI and attaches them to the GitHub release. 20 | 21 | set -eu 22 | 23 | VERSION=${VERSION:-$(cat src/VERSION | tr -d '\n')} 24 | START_STEP=${START_STEP:-1} 25 | 26 | circle_artifact_url=${1} 27 | 28 | . $(dirname $(realpath $0))/functions.sh 29 | 30 | artifacts_dir=/tmp/artifacts-crystal-$VERSION 31 | mkdir -p "$artifacts_dir" 32 | rm -rf "$artifacts_dir/*" 33 | 34 | wget --directory-prefix="$artifacts_dir/" \ 35 | "${circle_artifact_url%/*}/crystal-$VERSION-1-darwin-universal.tar.gz" \ 36 | "${circle_artifact_url%/*}/crystal-$VERSION-1-linux-x86_64-bundled.tar.gz" \ 37 | "${circle_artifact_url%/*}/crystal-$VERSION-1-linux-x86_64.tar.gz" \ 38 | "${circle_artifact_url%/*}/crystal-$VERSION-1-linux-aarch64-bundled.tar.gz" \ 39 | "${circle_artifact_url%/*}/crystal-$VERSION-1-linux-aarch64.tar.gz" \ 40 | "${circle_artifact_url%/*}/crystal-$VERSION-1.universal.pkg" \ 41 | "${circle_artifact_url%/*}/crystal-$VERSION-docs.tar.gz" | more 42 | 43 | ls -lh "$artifacts_dir/" 44 | 45 | step "Upload artifacts to GitHub release $VERSION" gh release -R crystal-lang/crystal upload $VERSION "$artifacts_dir/*" 46 | 47 | rm -rf "$artifacts_dir" 48 | -------------------------------------------------------------------------------- /omnibus/omnibus.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This file is used to configure the crystal project. It contains 3 | # some minimal configuration examples for working with Omnibus. For a full list 4 | # of configurable options, please see the documentation for +omnibus/config.rb+. 5 | # 6 | 7 | build_dmg false 8 | 9 | # Build internally 10 | # ------------------------------ 11 | # By default, Omnibus uses system folders (like +/var+ and +/opt+) to build and 12 | # cache components. If you would to build everything internally, you can 13 | # uncomment the following options. This will prevent the need for root 14 | # permissions in most cases. You will also need to update the crystal 15 | # project configuration to build at +./local/omnibus/build+ instead of 16 | # ++ 17 | # 18 | # Uncomment this line to change the default base directory to "local" 19 | # ------------------------------------------------------------------- 20 | # base_dir './local' 21 | # 22 | # Alternatively you can tune the individual values 23 | # ------------------------------------------------ 24 | # cache_dir './local/omnibus/cache' 25 | # git_cache_dir './local/omnibus/cache/install_path' 26 | # source_dir './local/omnibus/src' 27 | # build_dir './local/omnibus/build' 28 | # package_dir './local/omnibus/pkg' 29 | # package_tmp './local/omnibus/pkg-tmp' 30 | 31 | # Disable git caching 32 | # ------------------------------ 33 | # use_git_caching false 34 | 35 | # Enable S3 asset caching 36 | # ------------------------------ 37 | # use_s3_caching true 38 | # s3_access_key ENV['S3_ACCESS_KEY'] 39 | # s3_secret_key ENV['S3_SECRET_KEY'] 40 | # s3_bucket ENV['S3_BUCKET'] 41 | 42 | # Customize compiler bits 43 | # ------------------------------ 44 | # solaris_compiler 'gcc' 45 | build_retries 0 46 | 47 | # Load additional software 48 | # ------------------------------ 49 | # software_gems ['omnibus-software', 'my-company-software'] 50 | # local_software_dirs ['/path/to/local/software'] 51 | 52 | append_timestamp false 53 | -------------------------------------------------------------------------------- /omnibus/config/software/libffi.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright:: Chef Software, Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | name "libffi" 18 | default_version "3.4.8" 19 | 20 | license "MIT" 21 | license_file "LICENSE" 22 | skip_transitive_dependency_licensing true 23 | 24 | # version_list: url=https://github.com/libffi/libffi/releases filter=*.tar.gz 25 | 26 | version("3.4.8") { source sha256: "bc9842a18898bfacb0ed1252c4febcc7e78fa139fd27fdc7a3e30d9d9356119b" } 27 | 28 | source url: "https://github.com/libffi/libffi/releases/download/v#{version}/libffi-#{version}.tar.gz" 29 | 30 | relative_path "libffi-#{version}" 31 | 32 | build do 33 | env = with_standard_compiler_flags(with_embedded_path) 34 | 35 | env["INSTALL"] = "/opt/freeware/bin/install" if aix? 36 | 37 | # disable option checking as disable-docs is 3.3+ only 38 | configure_command = ["--disable-option-checking", 39 | "--disable-docs", 40 | ] 41 | 42 | # AIX's old version of patch doesn't like the patch here 43 | unless aix? 44 | # disable multi-os-directory via configure flag (don't use /lib64) 45 | # Works on all platforms, and is compatible on 32bit platforms as well 46 | configure_command << "--disable-multi-os-directory" 47 | end 48 | 49 | configure(*configure_command, env: env) 50 | 51 | make "-j #{workers}", env: env 52 | make "-j #{workers} install", env: env 53 | 54 | # libffi's default install location of header files is awful... 55 | mkdir "#{install_dir}/embedded/include" 56 | copy "#{install_dir}/embedded/lib/libffi-#{version}/include/*", "#{install_dir}/embedded/include/" 57 | 58 | end 59 | -------------------------------------------------------------------------------- /processes/scripts/prepare-crystal-release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # This helper creates a new release issue for Crystal 4 | # 5 | # Usage: 6 | # 7 | # scripts/prepare-crystal-release.sh VERSION RELEASE_DATE FREEZE_PERIOD 8 | # 9 | # The content is generated from Crystal release checklist (../crystal-release.md) 10 | # with filters applied based on the version type (major, minor, or patch). 11 | 12 | set -eu 13 | 14 | if [ $# -lt 1 ]; then 15 | printf "Release version: " 16 | read VERSION 17 | 18 | if [ -z "$VERSION" ]; then 19 | echo "Usage: $0 VERSION" 20 | exit 1 21 | fi 22 | else 23 | VERSION=$1 24 | fi 25 | 26 | . $(dirname $(realpath $0))/functions.sh 27 | 28 | case $VERSION in 29 | *.0.0) 30 | TYPE=major 31 | ;; 32 | *.0) 33 | TYPE=minor 34 | ;; 35 | *) 36 | TYPE=patch 37 | ;; 38 | esac 39 | 40 | if [ $# -lt 2 ]; then 41 | printf "Scheduled release date: " 42 | read RELEASE_DATE 43 | else 44 | RELEASE_DATE=$2 45 | fi 46 | 47 | if [ "$TYPE" != "patch" ]; then 48 | if [ $# -lt 3 ]; then 49 | printf "Freeze period begin: " 50 | read FREEZE_PERIOD 51 | else 52 | FREEZE_PERIOD=$3 53 | fi 54 | else 55 | FREEZE_PERIOD="" 56 | fi 57 | 58 | dist_scripts_root=$(dirname $(dirname $(dirname $(realpath $0)))) 59 | 60 | body=$(sed -E '/^##/,$!d' $dist_scripts_root/processes/crystal-release.md) 61 | 62 | case $TYPE in 63 | patch) 64 | body=$(echo "$body" | sed -E "/\(major\)/d;/\(minor\)/d;s/\(patch\)\s*//") 65 | ;; 66 | minor) 67 | body=$(echo "$body" | sed -E "/\(major\)/d;s/\(minor\)\s*//;/\(patch\)/d") 68 | ;; 69 | major) 70 | body=$(echo "$body" | sed -E "s/\(major\)\s*//;s/\(minor\)\s*//;/\(patch\)/d") 71 | ;; 72 | esac 73 | 74 | IFS='.' read -r major minor patch <<< "$VERSION" 75 | ((minor--)) 76 | OLD_VERSION="$major.$minor.$patch" 77 | 78 | body=$(echo "$body" | sed -E "s/\\$\{RELEASE_DATE\}/$RELEASE_DATE/g; s/\\$\{FREEZE_PERIOD\}/$FREEZE_PERIOD/g; s/\\$\{VERSION\}/$VERSION/g; s/\\$\{VERSION%\.\*\}/${VERSION%.*}/g; s/\\$\{OLD_VERSION%\.\*\}/${OLD_VERSION%.*}/g") 79 | 80 | body=$(printf "%q" "$body") 81 | step "Create tracking issue in crystal-lang/distribution-scripts" gh issue create -R crystal-lang/distribution-scripts --body "$body" --label "release" --title \"Release Crystal $VERSION\" 82 | -------------------------------------------------------------------------------- /snapcraft/README.md: -------------------------------------------------------------------------------- 1 | # snap for Crystal 2 | 3 | 4 | 5 | ## Dependencies 6 | 7 | - [`snapcraft`](https://docs.snapcraft.io/snapcraft-overview) 8 | 9 | For example on Ubuntu: 10 | 11 | ```console 12 | $ sudo apt-get install snapd 13 | $ snap install snapcraft --classic 14 | ``` 15 | 16 | ## Build 17 | 18 | Define the configuration variables and use `make` to expand the `./local/snapcraft.yaml.tpl`. 19 | 20 | ```console 21 | $ export SNAPCRAFT_BUILD_ENVIRONMENT=host 22 | $ make GRADE=devel ARCH=amd64 CRYSTAL_TARBALL=../linux/build/crystal-$(CRYSTAL_VERSION)-1-linux-x86_64.tar.gz 23 | $ make GRADE=devel ARCH=arm64 CRYSTAL_TARBALL=../linux/build/crystal-$(CRYSTAL_VERSION)-1-linux-aarch64.tar.gz 24 | ``` 25 | 26 | ## Channels 27 | 28 | | Build | Channel | Version | Comments | 29 | |-------------------|----------------------------|-----------|------------------------------------------------------| 30 | | tagged release | latest/edge | M.m.p | manual set to beta, candidate, stable upon release | 31 | | nighties release | latest/edge | M.m.p-dev | | 32 | | maintenance build | latest/edge/${branch-name} | M.m.p-dev | | 33 | 34 | ### Configuration 35 | 36 | * `CRYSTAL_TARBALL`: path to `crystal-{version}-{package}-linux-{arch}.tar.gz` 37 | * `ARCH`: the architecture to build (`amd64` or `arm64`) 38 | * `GRADE`: Snap grade (`devel` for nightlies, `stable` for tagged releases) 39 | 40 | ## Install the snap 41 | 42 | 1. [Have snapd installed](https://snapcraft.io/docs/core/install) 43 | 44 | 2. 45 | ```console 46 | $ sudo snap install crystal --classic 47 | ``` 48 | 49 | ## Post-Install 50 | 51 | This snap ships the compiler, all required native libraries should be available on the host. 52 | 53 | The following are the suggested packages to be able to use the whole standard library capabilities. 54 | 55 | ``` 56 | $ sudo apt-get install gcc pkg-config git tzdata \ 57 | libpcre2-dev libyaml-dev \ 58 | libgmp-dev libssl-dev libxml2-dev 59 | ``` 60 | 61 | You can find more detailed information in the [Crystal reference](https://crystal-lang.org/reference/installation/on_debian_and_ubuntu.html) and in the [Crystal wiki](https://github.com/crystal-lang/crystal/wiki/All-required-libraries) if you want to be able to build the compiler itself. 62 | 63 | -------------------------------------------------------------------------------- /omnibus/config/software/llvm.rb: -------------------------------------------------------------------------------- 1 | name "llvm" 2 | LLVM_VERSION = (ENV['LLVM_VERSION'] || "15.0.7").strip 3 | default_version LLVM_VERSION 4 | skip_transitive_dependency_licensing true 5 | 6 | version "3.9.1" do 7 | source url: "http://releases.llvm.org/#{version}/llvm-#{version}.src.tar.xz", 8 | md5: "3259018a7437e157f3642df80f1983ea" 9 | end 10 | 11 | version "6.0.1" do 12 | source url: "http://releases.llvm.org/#{version}/llvm-#{version}.src.tar.xz", 13 | md5: "c88c98709300ce2c285391f387fecce0" 14 | end 15 | 16 | version "10.0.0" do 17 | source url: "https://github.com/llvm/llvm-project/releases/download/llvmorg-#{version}/llvm-#{version}.src.tar.xz", 18 | md5: "693cefdc49d618f828144486a18b473f" 19 | end 20 | 21 | version "15.0.7" do 22 | source url: "https://github.com/llvm/llvm-project/releases/download/llvmorg-#{version}/llvm-project-#{version}.src.tar.xz", 23 | md5: "bac436dbd5d37e38d3da75b03629053c" 24 | end 25 | 26 | if version == "15.0.7" 27 | # This is bringing the whole project because flags weren't sufficient to prevent certain parts from being fetched by the build system. 28 | relative_path "llvm-project-#{version}.src/llvm" 29 | else 30 | relative_path "llvm-#{version}.src" 31 | end 32 | 33 | whitelist_file "lib/BugpointPasses.dylib" 34 | whitelist_file "lib/libLTO.dylib" 35 | whitelist_file "lib/LLVMHello.dylib" 36 | whitelist_file "lib/libRemarks.dylib" 37 | 38 | env = with_standard_compiler_flags(with_embedded_path) 39 | 40 | llvm_build_dir = "#{project_dir}/build-llvm" 41 | 42 | build do 43 | mkdir llvm_build_dir 44 | command "cmake" \ 45 | " -DCMAKE_BUILD_TYPE=MinSizeRel" \ 46 | " -DCMAKE_OSX_ARCHITECTURES=\"arm64;x86_64\"" \ 47 | " -DLLVM_TARGETS_TO_BUILD=\"X86;AArch64\"" \ 48 | " -DLLVM_ENABLE_TERMINFO=OFF" \ 49 | " -DLLVM_ENABLE_FFI=OFF" \ 50 | " -DLLVM_ENABLE_ZLIB=OFF" \ 51 | " -DLLVM_BUILD_DOCS=OFF" \ 52 | " -DLLVM_INCLUDE_DOCS=OFF" \ 53 | " -DLLVM_BINARY_DIR=#{install_dir}" \ 54 | " -DBUILD_SHARED_LIBS=OFF" \ 55 | " -DLLVM_OPTIMIZED_TABLEGEN=ON" \ 56 | " -DLLVM_ENABLE_ASSERTIONS=ON" \ 57 | " -DLLVM_INCLUDE_TESTS=OFF" \ 58 | " -DLLVM_ENABLE_Z3_SOLVER=OFF" \ 59 | " -DLLVM_ENABLE_LIBXML2=OFF" \ 60 | " -DLLVM_BUILD_BENCHMARKS=OFF" \ 61 | " -DLLVM_INCLUDE_BENCHMARKS=OFF" \ 62 | " -DLLVM_ENABLE_ZSTD=OFF" \ 63 | "#{' -DPYTHON_EXECUTABLE=$(which python2.7)' if centos? }"\ 64 | " #{project_dir}", env: env, cwd: llvm_build_dir 65 | command "cmake --build . --parallel $(sysctl -n hw.logicalcpu)", env: env, cwd: llvm_build_dir 66 | command "cmake --build . --target preinstall", env: env, cwd: llvm_build_dir 67 | command "cmake -DCMAKE_INSTALL_PREFIX=#{install_dir} -P cmake_install.cmake", env: env, cwd: llvm_build_dir 68 | end 69 | -------------------------------------------------------------------------------- /packages/obs-release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # $ ./obs-release.sh PROJECT PACKAGE VERSION 4 | # 5 | # This script uses osc to create (or check out) a branch of PROJECT in your OBS 6 | # home project, update the release version and commit the changes to OBS. 7 | # 8 | # If `osc` command is not available, the script automatically runs the docker 9 | # image crystallang/osc and executes itself in the container. 10 | # 11 | # Parameters: 12 | # * `PACKAGE`: OBS base package (e.g. `devel:languages:crystal`) 13 | # * `PROJECT`: OBS project in `PACKAGE` (e.g. `crystal`) 14 | # * `VERSION`: Release version (e.g `1.1.1`) 15 | # 16 | # Requirements: 17 | # * packages: osc build which 18 | # * environment variables: 19 | # `OBS_USER`: OBS username 20 | # `OBS_PASSWORD`: OBS password (only necessary if ~/.oscrc is missing) 21 | 22 | set -eu 23 | 24 | if ! command -v osc > /dev/null; then 25 | exec docker run --rm -it \ 26 | -e OBS_USER=${OBS_USER:-} \ 27 | -e OBS_PASSWORD=${OBS_PASSWORD:-} \ 28 | -v $(pwd):/workspace -w /workspace \ 29 | crystallang/osc /workspace/$0 $@ 30 | fi 31 | 32 | PROJECT=$1 33 | PACKAGE=$2 34 | VERSION=$3 35 | 36 | if [ ! -f ~/.oscrc ]; then 37 | ./obs-setup.sh 38 | fi 39 | 40 | # Checkout OBS package 41 | LOCAL_BRANCH_FOLDER="home:$OBS_USER:branches:$PROJECT/$PACKAGE" 42 | 43 | if [ -d "${LOCAL_BRANCH_FOLDER}" ]; then 44 | pushd "${LOCAL_BRANCH_FOLDER}" 45 | osc up 46 | else 47 | osc branchco "$PROJECT" "$PACKAGE" 48 | pushd "${LOCAL_BRANCH_FOLDER}" 49 | fi 50 | 51 | if [ "$PACKAGE" != "crystal" ]; then 52 | sed -i -e "s/^Version:.*/Version: ${VERSION}/" *.spec 53 | fi 54 | 55 | sed -i -e "s/^Version:.*/Version: ${VERSION}-1/" *.dsc 56 | sed -i -e "s/^Version: .*/Version: ${VERSION%.*}/" debian.control 57 | sed -i -e "s/^export VERSION=.*/export VERSION=${VERSION}/" debian.rules 58 | 59 | sed -i -e "s/^export PACKAGE_ITERATION=.*/export PACKAGE_ITERATION=1/" debian.rules 60 | sed -i -e "s/^%global package_iteration .*/%global package_iteration 1/" *.spec 61 | 62 | if [ "$PACKAGE" == "crystal" ]; then 63 | previous_version=$(grep -o -P '(?<=version_current ).*' crystal.spec) 64 | 65 | sed -i -e "s/version_suffix .*/version_suffix ${VERSION%.*}/" *.spec 66 | sed -i -e "s/version_current .*/version_current ${VERSION}/" *.spec 67 | sed -i -e "s/version_previous .*/version_previous ${previous_version}/" *.spec 68 | sed -i -e "/%define obsolete_crystal_versioned/a Obsoletes: %{1}${previous_version%.*}%{?2:-%{2}} \\\\" *.spec 69 | else 70 | sed -i -e "s/^DEBTRANSFORM-TAR: .*/DEBTRANSFORM-TAR: ${VERSION}.tar.gz/" *.dsc 71 | fi 72 | 73 | sed -i -e "s/^Depends: crystal[^-]*/Depends: crystal${VERSION%.*}/" debian.control 74 | 75 | sed -i -r -e "s/((Provides|Conflicts|Replaces): .* \((=|<<)).*\)/\\1 ${VERSION%.*})/" debian.control 76 | 77 | # Commit changes to OBS 78 | message="Release $VERSION" 79 | osc vc -m "$message" 80 | osc diff 81 | 82 | # Commit 83 | osc commit -m "$message" --noservice 84 | 85 | # Remove OSC working dir 86 | popd 87 | rm -r "$LOCAL_BRANCH_FOLDER" 88 | 89 | echo "The OBS release update is now available at https://build.opensuse.org/package/show/${LOCAL_BRANCH_FOLDER}" 90 | -------------------------------------------------------------------------------- /omnibus/config/software/shards.rb: -------------------------------------------------------------------------------- 1 | SHARDS_VERSION = "0.19.1" 2 | 3 | name "shards" 4 | default_version SHARDS_VERSION 5 | skip_transitive_dependency_licensing true 6 | 7 | dependency "crystal" 8 | dependency "libyaml" 9 | 10 | version "0.7.2" do 11 | source md5: "4f1f1e860ed1846fce01581ce9e6e7ad" 12 | end 13 | 14 | version "0.8.0" do 15 | source md5: "f0a52e64537ea6267a2006195e818c4d" 16 | end 17 | 18 | version "0.8.1" do 19 | source md5: "f5b5108d798b1d86d2b9b45c3a2b5293" 20 | end 21 | 22 | version "0.10.0" do 23 | source md5: "f982f2dc0c796763205bd0de68e9f87e" 24 | end 25 | 26 | version "0.11.0" do 27 | source md5: "a16d6580411152956363a766e1517c9d" 28 | end 29 | 30 | version "0.11.1" do 31 | source md5: "6924888dffc158e2e1a10f8ec9c65cb0" 32 | end 33 | 34 | version "0.12.0" do 35 | source md5: "c65327561cfbb0c465ec4bd945423fe9" 36 | end 37 | 38 | version "0.13.0" do 39 | source md5: "a66b767ad9914472c23e1cb76446fead" 40 | end 41 | 42 | version "0.14.1" do 43 | source md5: "d7bdd10bb096b71428b06fc93097b3cc" 44 | end 45 | 46 | version "0.15.0" do 47 | source md5: "696525e924350a1270eee5c221eb6c80" 48 | end 49 | 50 | version "0.16.0" do 51 | source md5: "60bc6791fa94f3068b7580dd8cde5d1a" 52 | end 53 | 54 | version "0.17.0" do 55 | source md5: "04bdf5739ea4a897267502b9f77ec46f" 56 | end 57 | 58 | version "0.17.1" do 59 | source md5: "8bca944b1bbac88223e1bedcbc23eed0" 60 | end 61 | 62 | version "0.17.2" do 63 | source md5: "2f0ae55946c413bbbb4e4dce204a81e7" 64 | end 65 | 66 | version "0.17.3" do 67 | source md5: "1fc2b19765e28a6bbf16291caf9cf62c" 68 | end 69 | 70 | version "0.17.4" do 71 | source md5: "9215e617238ae297bedf639e574d28d5" 72 | end 73 | 74 | version "0.18.0" do 75 | source md5: "dbc0f55af7751e2ab231a9a441ff27d4" 76 | end 77 | 78 | version "0.19.0" do 79 | source md5: "3546c3a716eda641e629441eb38eac43" 80 | end 81 | 82 | version "0.19.1" do 83 | source md5: "a05c0ce48b94ecac78b6cf392acf4596" 84 | end 85 | 86 | source url: "https://github.com/crystal-lang/shards/archive/v#{version}.tar.gz" 87 | 88 | relative_path "shards-#{version}" 89 | env = with_standard_compiler_flags(with_embedded_path( 90 | "LIBRARY_PATH" => "#{install_dir}/embedded/lib", 91 | "CRYSTAL_LIBRARY_PATH" => "#{install_dir}/embedded/lib" 92 | )) 93 | env["CFLAGS"] << " -fPIC -arch arm64 -arch x86_64" 94 | env["CPPFLAGS"] = env["CPPFLAGS"].gsub("-arch arm64 -arch x86_64", "") 95 | 96 | build do 97 | crflags = "--no-debug --release" 98 | 99 | # Build native 100 | make "bin/shards CRYSTAL=#{install_dir}/bin/crystal FLAGS='#{crflags}'", env: env 101 | move "bin/shards", "bin/shards_#{ohai['kernel']['machine']}" 102 | 103 | # Clean 104 | make "clean", env: env 105 | 106 | # Cross-compile for other arch 107 | other_machine = ohai['kernel']['machine'] == "x86_64" ? "arm64" : "x86_64" 108 | other_target = "#{other_machine}-apple-macosx#{ENV["MACOSX_DEPLOYMENT_TARGET"]}" 109 | crflags += " --cross-compile --target #{other_target}" 110 | make "bin/shards CRYSTAL=#{install_dir}/bin/crystal FLAGS='#{crflags}'", env: env 111 | command "clang bin/shards.o -o bin/shards_#{other_machine} -target #{other_target} -L#{install_dir}/embedded/lib -lyaml -lpcre2-8 -lgc -lpthread -liconv -ldl", env: env 112 | 113 | # Lipo them up 114 | command "lipo -create -output bin/shards bin/shards_x86_64 bin/shards_arm64" 115 | 116 | copy "bin/shards", "#{install_dir}/embedded/bin/shards" 117 | end 118 | -------------------------------------------------------------------------------- /linux/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:12 AS bdwgc 2 | 3 | RUN apt-get update \ 4 | && apt-get install -y build-essential automake libtool git clang-16 5 | 6 | ARG release 7 | ENV CFLAGS="-fPIC -pipe ${release:+-O2}" 8 | ENV CC="clang-16" 9 | 10 | # Build libgc 11 | ARG gc_version 12 | 13 | RUN git clone https://github.com/ivmai/bdwgc \ 14 | && cd bdwgc \ 15 | && git checkout ${gc_version} \ 16 | && ./autogen.sh \ 17 | && ./configure --disable-debug --disable-shared --enable-large-config \ 18 | && make -j$(nproc) 19 | 20 | FROM alpine:3.22 21 | ARG llvm_version=20 22 | 23 | # Install dependencies 24 | RUN apk add --no-cache \ 25 | # Statically-compiled llvm 26 | llvm${llvm_version}-dev llvm${llvm_version}-static \ 27 | # Static stdlib dependencies 28 | gc-dev gc-static zlib-static yaml-static libxml2-static pcre2-dev pcre2-static zstd-static \ 29 | # Static compiler dependencies 30 | libffi-dev \ 31 | # Build tools 32 | git gcc g++ make automake libtool autoconf bash coreutils curl asciidoctor 33 | 34 | ARG release 35 | ENV CFLAGS="-fPIC -pipe ${release:+-O2}" 36 | 37 | # This overrides default CRYSTAL_LIBRARY_PATH baked into the binary (starting with 1.2.0) 38 | # or configured via wrapper script (before 1.2.0) because we want to link against 39 | # the regularly installed libraries, not the ones shipped with the bootstrap compiler. 40 | # This particularly affects libgc which was bundled upto Crystal 1.12 41 | ENV CRYSTAL_LIBRARY_PATH="" 42 | 43 | RUN llvm${llvm_version}-config --version 44 | 45 | ARG previous_crystal_release 46 | ADD ${previous_crystal_release} /tmp/crystal.tar.gz 47 | ENV PATH=${PATH}:/tmp/crystal/bin/ 48 | RUN mkdir -p /tmp/crystal \ 49 | && tar xz -f /tmp/crystal.tar.gz -C /tmp/crystal --strip-component=1 \ 50 | && crystal --version \ 51 | && shards --version 52 | 53 | # Build crystal 54 | ARG crystal_repo=https://github.com/crystal-lang/crystal 55 | ARG crystal_version 56 | ARG crystal_sha1 57 | ARG gnu_target 58 | RUN git clone ${crystal_repo} \ 59 | && cd crystal \ 60 | && git checkout ${crystal_sha1} \ 61 | \ 62 | && make crystal stats=true static=true ${release:+release=true} \ 63 | CRYSTAL_CONFIG_TARGET=${gnu_target} \ 64 | && ( (readelf --program-headers .build/crystal | grep -q "Elf file type is EXEC") || { echo 'crystal is not statically linked'; exit 1; }) \ 65 | && .build/crystal --version 66 | 67 | # Build shards 68 | ARG shards_version 69 | ARG musl_target 70 | RUN git clone https://github.com/crystal-lang/shards \ 71 | && cd shards \ 72 | && git checkout ${shards_version} \ 73 | && make CRYSTAL=/crystal/bin/crystal \ 74 | FLAGS="--stats --target ${musl_target} --static ${release:+--release}" \ 75 | \ 76 | && bin/shards --version \ 77 | && ( (readelf --program-headers bin/shards | grep -q "Elf file type is EXEC") || { echo 'shards is not statically linked'; exit 1; }) 78 | 79 | COPY --from=bdwgc /bdwgc/.libs/libgc.a /libgc-debian.a 80 | 81 | ARG package_iteration 82 | 83 | RUN \ 84 | # Copy libgc.a to /lib/crystal/ 85 | mkdir -p /output/lib/crystal/ \ 86 | && cp /libgc-debian.a /output/lib/crystal/libgc.a \ 87 | \ 88 | # Install crystal 89 | && make -C /crystal install DESTDIR=/output PREFIX= \ 90 | \ 91 | # Install shards 92 | && make -C /shards install DESTDIR=/output PREFIX= \ 93 | \ 94 | # Create tarball 95 | && mv /output /crystal-${crystal_version}-${package_iteration} \ 96 | && mkdir /output \ 97 | && tar -cf /output/crystal-${crystal_version}-${package_iteration}.tar /crystal-${crystal_version}-${package_iteration} 98 | -------------------------------------------------------------------------------- /omnibus/config/templates/crystal/crystal.erb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ################## https://github.com/mkropat/sh-realpath ##################### 4 | # 5 | # The MIT License (MIT) 6 | # 7 | # Copyright (c) 2014 Michael Kropat 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy 10 | # of this software and associated documentation files (the "Software"), to deal 11 | # in the Software without restriction, including without limitation the rights 12 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | # copies of the Software, and to permit persons to whom the Software is 14 | # furnished to do so, subject to the following conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included in 17 | # all copies or substantial portions of the Software. 18 | 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | # THE SOFTWARE. 26 | 27 | realpath() { 28 | canonicalize_path "$(resolve_symlinks "$1")" 29 | } 30 | 31 | resolve_symlinks() { 32 | _resolve_symlinks "$1" 33 | } 34 | 35 | _resolve_symlinks() { 36 | _assert_no_path_cycles "$@" || return 37 | 38 | local dir_context path 39 | path=$(readlink -- "$1") 40 | if [ $? -eq 0 ]; then 41 | dir_context=$(dirname -- "$1") 42 | _resolve_symlinks "$(_prepend_dir_context_if_necessary "$dir_context" "$path")" "$@" 43 | else 44 | printf '%s\n' "$1" 45 | fi 46 | } 47 | 48 | _prepend_dir_context_if_necessary() { 49 | if [ "$1" = . ]; then 50 | printf '%s\n' "$2" 51 | else 52 | _prepend_path_if_relative "$1" "$2" 53 | fi 54 | } 55 | 56 | _prepend_path_if_relative() { 57 | case "$2" in 58 | /* ) printf '%s\n' "$2" ;; 59 | * ) printf '%s\n' "$1/$2" ;; 60 | esac 61 | } 62 | 63 | _assert_no_path_cycles() { 64 | local target path 65 | 66 | target=$1 67 | shift 68 | 69 | for path in "$@"; do 70 | if [ "$path" = "$target" ]; then 71 | return 1 72 | fi 73 | done 74 | } 75 | 76 | canonicalize_path() { 77 | if [ -d "$1" ]; then 78 | _canonicalize_dir_path "$1" 79 | else 80 | _canonicalize_file_path "$1" 81 | fi 82 | } 83 | 84 | _canonicalize_dir_path() { 85 | (cd "$1" 2>/dev/null && pwd -P) 86 | } 87 | 88 | _canonicalize_file_path() { 89 | local dir file 90 | dir=$(dirname -- "$1") 91 | file=$(basename -- "$1") 92 | (cd "$dir" 2>/dev/null && printf '%s/%s\n' "$(pwd -P)" "$file") 93 | } 94 | 95 | ############################################################################## 96 | 97 | SCRIPT_PATH="$(dirname "$(realpath "$0" || echo $0)")" 98 | INSTALL_DIR="$(realpath "$SCRIPT_PATH/..")" 99 | EMBEDDED_CRYSTAL_PATH=$("$INSTALL_DIR/embedded/bin/crystal" env CRYSTAL_PATH) 100 | export CRYSTAL_PATH="${CRYSTAL_PATH:-"$EMBEDDED_CRYSTAL_PATH:$INSTALL_DIR/src"}" 101 | export CRYSTAL_LIBRARY_PATH="${CRYSTAL_LIBRARY_PATH:+$CRYSTAL_LIBRARY_PATH:}$INSTALL_DIR/embedded/lib" 102 | "$INSTALL_DIR/embedded/bin/crystal" "$@" 103 | -------------------------------------------------------------------------------- /processes/shards-release.md: -------------------------------------------------------------------------------- 1 | # Shards release process checklist 2 | 3 | Add an issue `Shards release ${VERSION}` in https://github.com/crystal-lang/distribution-scripts/issues with a copy of this document. In this way it's easy to track the progress of the release (*Helper script: [`scripts/prepare-shards-release.sh`](./scripts/prepare-shards-release.sh)*) 4 | 5 | ## Release preparation 6 | 7 | 1. [ ] Prepare the changelog entry: [`crystal-lang/crystal/scripts/github-changelog.cr crystal-lang/shards ${VERSION}`](https://github.com/crystal-lang/crystal/blob/master/scripts/github-changelog.cr) 8 | * Ensure that all merged PRs are added to the milestone (check [`is:pr is:merged sort:updated-desc no:milestone`](https://github.com/crystal-lang/shards/pulls?q=is%3Apr+is%3Amerged+sort%3Aupdated-desc+no%3Amilestone+-label%3Astatus%3Areverted+base%3Amaster+merged%3A%3E%3D2023-01-01)). 9 | * Ensure that all milestoned PRs are properly labelled (check [`is:pr is:merged sort:updated-desc no:label milestone:${VERSION}`](https://github.com/crystal-lang/shards/pulls?q=is%3Apr+is%3Amerged+sort%3Aupdated-desc+milestone%3A${VERSION}+no%3Alabel)).[ ] Start preparing changelog and release notes 10 | 2. [ ] Prepare release notes (typically published with Crystal) 11 | 3. [ ] Publish release PR draft 12 | * It should be populated with updates to `CHANGELOG.md`, `VERSION`, and `shard.yml`. 13 | 14 | ## Release process 15 | 16 | *Steps 4.-6. are automated via [`scripts/make-shards-release.sh`](https://github.com/crystal-lang/distribution-scripts/blob/master/processes/scripts/make-shards-release.sh)* 17 | 18 | 1. [ ] Finalize the release PR 19 | * Make sure all changes are mentioned in the changelog 20 | * Check release date 21 | * Build man files with the release date: `$ make clean docs SOURCE_DATE_EPOCH=$(gdate -ud "YYYY-MM-DD" +"%s")` 22 | * Un-draft the PR 23 | 2. [ ] (minor) Split off release branch (`release/x.y`) 24 | 3. [ ] Smoke test with [test-ecosystem](https://github.com/crystal-lang/test-ecosystem) 25 | * Run [*Test Crystal & Shards Workflow*](https://github.com/crystal-lang/test-ecosystem/actions/workflows/test-crystal-shards.yml) with the release branch as `shards_branch`. 26 | 4. [ ] Merge the release PR 27 | 5. [ ] Tag & annotate the commit with the changelog using v`` pattern as {version} 28 | * `git tag -s -a -m v${VERSION} v${VERSION}` 29 | * `git push --tags` 30 | 6. [ ] Publish Github release (https://github.com/crystal-lang/shards/releases/new) 31 | * Copy the changelog section as description 32 | 7. [ ] Close milestone (https://github.com/crystal-lang/shards/milestones) 33 | 34 | ## Post-release 35 | 36 | 1. [ ] (minor) Increment VERSION file to the next minor and -dev suffix 37 | 2. [ ] Update distribution-scripts (*Helper script: [`scripts/update-shards.sh`](https://github.com/crystal-lang/distribution-scripts/blob/master/scripts/update-shards.sh)*) 38 | * Edit [linux/Makefile](../linux/Makefile) 39 | * Edit [omnibus/config/software/shards.rb](../omnibus/config/software/shards.rb) 40 | 3. [ ] Update https://github.com/crystal-lang/crystal (*Helper script: [`scripts/update-shards.sh`](https://github.com/crystal-lang/crystal/blob/master/scripts/update-shards.sh)*) 41 | * Edit [`.github/workflows/win_build_portable.yml`](https://github.com/crystal-lang/crystal/blob/master/.github/workflows/win_build_portable.yml) 42 | * Edit [`.github/workflows/mingw-w64.yml`](https://github.com/crystal-lang/crystal/blob/master/.github/workflows/mingw-w64.yml) 43 | 3. [ ] Submit a PR to update the homebrew formula in https://github.com/Homebrew/homebrew-core/blob/master/Formula/crystal.rb . Or do it on Crystal release. 44 | 4. [ ] Update default base version in test-ecosystem 45 | 6. [ ] (minor) Perform uncomment/todos left in the repo 46 | -------------------------------------------------------------------------------- /omnibus/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.8.7) 5 | public_suffix (>= 2.0.2, < 7.0) 6 | awesome_print (1.9.2) 7 | aws-eventstream (1.4.0) 8 | aws-partitions (1.1178.0) 9 | aws-sdk-core (3.235.0) 10 | aws-eventstream (~> 1, >= 1.3.0) 11 | aws-partitions (~> 1, >= 1.992.0) 12 | aws-sigv4 (~> 1.9) 13 | base64 14 | bigdecimal 15 | jmespath (~> 1, >= 1.6.1) 16 | logger 17 | aws-sdk-kms (1.115.0) 18 | aws-sdk-core (~> 3, >= 3.234.0) 19 | aws-sigv4 (~> 1.5) 20 | aws-sdk-s3 (1.116.0) 21 | aws-sdk-core (~> 3, >= 3.127.0) 22 | aws-sdk-kms (~> 1) 23 | aws-sigv4 (~> 1.4) 24 | aws-sigv4 (1.12.1) 25 | aws-eventstream (~> 1, >= 1.0.2) 26 | base64 (0.3.0) 27 | bigdecimal (3.3.1) 28 | chef-cleanroom (1.0.5) 29 | chef-config (18.8.46) 30 | addressable 31 | chef-utils (= 18.8.46) 32 | fuzzyurl 33 | mixlib-config (>= 2.2.12, < 4.0) 34 | mixlib-shellout (>= 2.0, < 4.0) 35 | tomlrb (~> 1.2) 36 | chef-utils (18.8.46) 37 | concurrent-ruby 38 | citrus (3.0.2) 39 | concurrent-ruby (1.3.5) 40 | contracts (0.16.1) 41 | ffi (1.16.3) 42 | ffi-yajl (2.6.0) 43 | libyajl2 (>= 1.2) 44 | fuzzyurl (0.9.0) 45 | iostruct (0.5.0) 46 | ipaddress (0.8.3) 47 | jmespath (1.6.2) 48 | json (2.15.2) 49 | libyajl2 (2.1.0) 50 | license_scout (1.4.0) 51 | ffi-yajl (~> 2.2) 52 | mixlib-shellout (>= 2.2, < 4.0) 53 | toml-rb (>= 1, < 3) 54 | logger (1.7.0) 55 | mixlib-cli (2.1.8) 56 | mixlib-config (3.0.27) 57 | tomlrb 58 | mixlib-log (3.2.3) 59 | ffi (>= 1.15.5) 60 | mixlib-shellout (3.3.9) 61 | chef-utils 62 | mixlib-versioning (1.2.12) 63 | multipart-post (2.4.1) 64 | net-scp (4.1.0) 65 | net-ssh (>= 2.6.5, < 8.0.0) 66 | net-ssh (7.3.0) 67 | ohai (18.2.6) 68 | chef-config (>= 14.12, < 19) 69 | chef-utils (>= 16.0, < 19) 70 | ffi (~> 1.9, <= 1.17.0) 71 | ffi-yajl (~> 2.2) 72 | ipaddress 73 | mixlib-cli (>= 1.7.0) 74 | mixlib-config (>= 2.0, < 4.0) 75 | mixlib-log (>= 2.0.1, < 4.0) 76 | mixlib-shellout (~> 3.2, >= 3.2.5) 77 | plist (~> 3.1) 78 | train-core 79 | wmi-lite (~> 1.0) 80 | omnibus (9.0.24) 81 | aws-sdk-s3 (~> 1.116.0) 82 | chef-cleanroom (~> 1.0) 83 | chef-utils (>= 15.4) 84 | contracts (>= 0.16.0, < 0.17.0) 85 | ffi-yajl (~> 2.2) 86 | license_scout (~> 1.0) 87 | mixlib-shellout (>= 2.0, < 4.0) 88 | mixlib-versioning 89 | ohai (>= 16, < 19) 90 | pedump 91 | rexml (~> 3.2) 92 | ruby-progressbar (~> 1.7) 93 | thor (>= 0.18, < 2.0) 94 | omnibus-software (23.7.295) 95 | omnibus (>= 9.0.0) 96 | pedump (0.6.10) 97 | awesome_print 98 | iostruct (>= 0.0.4) 99 | multipart-post (>= 2.0.0) 100 | rainbow 101 | zhexdump (>= 0.0.2) 102 | plist (3.7.2) 103 | public_suffix (6.0.2) 104 | rainbow (3.1.1) 105 | rexml (3.4.4) 106 | ruby-progressbar (1.13.0) 107 | thor (1.4.0) 108 | toml-rb (2.2.0) 109 | citrus (~> 3.0, > 3.0) 110 | tomlrb (1.3.0) 111 | train-core (3.13.4) 112 | addressable (~> 2.5) 113 | ffi (~> 1.16.0) 114 | json (>= 1.8, < 3.0) 115 | mixlib-shellout (>= 2.0, < 4.0) 116 | net-scp (>= 1.2, < 5.0) 117 | net-ssh (>= 2.9, < 8.0) 118 | wmi-lite (1.0.7) 119 | zhexdump (0.3.0) 120 | 121 | PLATFORMS 122 | ruby 123 | 124 | DEPENDENCIES 125 | omnibus 126 | omnibus-software 127 | 128 | BUNDLED WITH 129 | 2.6.9 130 | -------------------------------------------------------------------------------- /darwin/Makefile: -------------------------------------------------------------------------------- 1 | # Recipes for this Makefile 2 | 3 | ## Build everything 4 | ## $ make 5 | 6 | CRYSTAL_REPO ?= https://github.com/crystal-lang/crystal## Allow to override the official repo with fork or local 7 | CRYSTAL_VERSION ?= ## How the binaries should be branded 8 | CRYSTAL_SHA1 ?= $(CRYSTAL_VERSION) ## Git tag/branch/sha1 to checkout and build source 9 | PACKAGE_ITERATION ?= 1 10 | FORCE_GIT_TAGGED ?= 1 ## Require build to be based on git tag/branch 11 | 12 | PREVIOUS_CRYSTAL_RELEASE_DARWIN_TARGZ ?= ## url to crystal-{version}-{package}-darwin-x86_64.tar.gz 13 | 14 | OUTPUT_DIR = build 15 | 16 | # mimics the tgz_package.rb version mangling 17 | DARWIN_ARCH = $(shell uname -m) 18 | DARWIN_PREFIX = crystal-$(CRYSTAL_VERSION)-$(PACKAGE_ITERATION) 19 | DARWIN_NAME = $(DARWIN_PREFIX)-darwin-$(DARWIN_ARCH).tar.gz 20 | DARWIN_PKG_NAME = $(DARWIN_PREFIX).$(DARWIN_ARCH).pkg 21 | 22 | .PHONY: all 23 | all: darwin-previous $(OUTPUT_DIR)/$(DARWIN_NAME) $(OUTPUT_DIR)/$(DARWIN_PKG_NAME) ## Build compressed omnibus and distribution packages [default] 24 | 25 | .PHONY: help 26 | help: ## Show this help 27 | @echo 28 | @printf '\033[34mtargets:\033[0m\n' 29 | @grep -hE '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) |\ 30 | sort |\ 31 | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}' 32 | @echo 33 | @printf '\033[34moptional variables:\033[0m\n' 34 | @grep -hE '^[a-zA-Z_-]+ \?=.*?## .*$$' $(MAKEFILE_LIST) |\ 35 | sort |\ 36 | awk 'BEGIN {FS = " \\?=.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}' 37 | @echo 38 | @printf '\033[34mrecipes:\033[0m\n' 39 | @grep -hE '^##.*$$' $(MAKEFILE_LIST) |\ 40 | awk 'BEGIN {FS = "## "}; /^## [a-zA-Z_-]/ {printf " \033[36m%s\033[0m\n", $$2}; /^## / {printf " %s\n", $$2}' 41 | 42 | .PHONY: darwin-previous 43 | darwin-previous: $(CURDIR)/../omnibus/crystal-darwin-x86_64/embedded/bin/crystal ## download previous crystal darwin release 44 | 45 | # Once there are prior builds for arm64, this can use DARWIN_ARCH 46 | $(CURDIR)/../omnibus/crystal-darwin-x86_64/embedded/bin/crystal: 47 | curl -L -o /tmp/crystal-darwin-x86_64.tar.gz $(PREVIOUS_CRYSTAL_RELEASE_DARWIN_TARGZ) \ 48 | && mkdir -p $(CURDIR)/../omnibus/crystal-darwin-x86_64 \ 49 | && tar xfz /tmp/crystal-darwin-x86_64.tar.gz -C $(CURDIR)/../omnibus/crystal-darwin-x86_64 --strip-components=1 \ 50 | && rm /tmp/crystal-darwin-x86_64.tar.gz \ 51 | && chmod +x $(CURDIR)/../omnibus/crystal-darwin-x86_64/embedded/bin/crystal 52 | 53 | $(OUTPUT_DIR)/$(DARWIN_NAME) $(OUTPUT_DIR)/$(DARWIN_PKG_NAME): ## Build omnibus crystal project 54 | ifeq ($(FORCE_GIT_TAGGED), 0) 55 | rm -Rf $(CURDIR)/tmp && mkdir -p $(CURDIR)/tmp && cd $(CURDIR)/tmp \ 56 | && git clone "$(CRYSTAL_REPO)" \ 57 | && cd crystal \ 58 | && git checkout $(CRYSTAL_SHA1) \ 59 | && git checkout -b $(CRYSTAL_VERSION) 60 | endif 61 | 62 | mkdir -p $(OUTPUT_DIR) \ 63 | && cd ../omnibus \ 64 | && if [ "$(FORCE_GIT_TAGGED)" -eq "0" ]; then export CRYSTAL_SRC=$(CURDIR)/tmp/crystal/.git; fi \ 65 | && export MACOSX_DEPLOYMENT_TARGET=11.0 \ 66 | && export SDKROOT=$(shell xcrun --sdk macosx --show-sdk-path) \ 67 | && bundle exec omnibus clean crystal shards --log-level=warn \ 68 | && bundle exec omnibus build crystal \ 69 | && cp ./pkg/$(DARWIN_NAME) $(CURDIR)/$(OUTPUT_DIR)/$(subst x86_64,universal,$(subst arm64,universal,$(DARWIN_NAME))) \ 70 | && cp ./pkg/$(DARWIN_PKG_NAME) $(CURDIR)/$(OUTPUT_DIR)/$(subst x86_64,universal,$(subst arm64,universal,$(DARWIN_PKG_NAME))) 71 | 72 | .PHONY: clean 73 | clean: ## Clean up build directory 74 | rm -Rf $(OUTPUT_DIR) 75 | rm -Rf $(CURDIR)/tmp 76 | rm -Rf $(CURDIR)/../omnibus/pkg/crystal-* 77 | rm -Rf $(CURDIR)/../omnibus/pkg/version-* 78 | rm -Rf $(CURDIR)/../omnibus/crystal-darwin-* 79 | rm -Rf /var/cache/omnibus/* 80 | rm -Rf /opt/crystal/* 81 | -------------------------------------------------------------------------------- /omnibus/config/software/crystal.rb: -------------------------------------------------------------------------------- 1 | CRYSTAL_VERSION = ENV['CRYSTAL_VERSION'] 2 | CRYSTAL_SHA1 = ENV['CRYSTAL_SHA1'] 3 | FIRST_RUN = ENV["FIRST_RUN"] 4 | CRYSTAL_SRC = (ENV['CRYSTAL_SRC'] || "").strip 5 | 6 | name "crystal" 7 | default_version CRYSTAL_VERSION 8 | skip_transitive_dependency_licensing true 9 | 10 | if CRYSTAL_SRC.empty? 11 | source git: "https://github.com/crystal-lang/crystal" 12 | else 13 | source git: CRYSTAL_SRC 14 | end 15 | 16 | dependency "pcre2" 17 | dependency "bdw-gc" 18 | dependency "llvm_bin" unless FIRST_RUN 19 | dependency "libffi" 20 | 21 | env = with_standard_compiler_flags(with_embedded_path( 22 | "LIBRARY_PATH" => "#{install_dir}/embedded/lib", 23 | "CRYSTAL_LIBRARY_PATH" => "#{install_dir}/embedded/lib", 24 | )) 25 | env["CFLAGS"] << " -fPIC -arch arm64 -arch x86_64" 26 | env["CPPFLAGS"] = env["CPPFLAGS"].gsub("-arch arm64 -arch x86_64", "") 27 | 28 | unless FIRST_RUN 29 | llvm_bin = Omnibus::Software.load(project, "llvm_bin", nil) 30 | end 31 | 32 | output_path = "#{install_dir}/embedded/bin" 33 | output_bin = "#{output_path}/crystal" 34 | 35 | if FIRST_RUN 36 | env["PATH"] = "#{project_dir}/deps:#{env["PATH"]}" 37 | else 38 | env["PATH"] = "#{llvm_bin.project_dir}/bin:#{project_dir}/deps:#{env["PATH"]}" 39 | end 40 | 41 | if macos? || mac_os_x? 42 | env["CRYSTAL_PATH"] = "lib:/private/var/cache/omnibus/src/crystal/src" 43 | else 44 | env["CRYSTAL_PATH"] = "lib:#{project_dir}/src" 45 | end 46 | 47 | build do 48 | command "git checkout #{CRYSTAL_SHA1}", cwd: project_dir 49 | 50 | mkdir "#{project_dir}/deps" 51 | make "deps", env: env 52 | mkdir ".build" 53 | command "echo #{Dir.pwd}", env: env 54 | 55 | crflags = "--no-debug" 56 | 57 | copy "#{Dir.pwd}/crystal-#{ohai['os']}-x86_64/embedded/bin/crystal", ".build/crystal" 58 | 59 | # Compile native 60 | native_target = "#{ohai['kernel']['machine']}-apple-macosx#{ENV["MACOSX_DEPLOYMENT_TARGET"]}" 61 | make "crystal stats=true release=true FLAGS=\"#{crflags}\" CRYSTAL_CONFIG_TARGET=#{native_target} CRYSTAL_CONFIG_LIBRARY_PATH= O=#{output_path}", env: env 62 | move output_bin, "#{output_bin}_#{ohai['kernel']['machine']}" 63 | 64 | # Clean up 65 | make "clean_cache clean", env: env 66 | 67 | # Restore native compiler w/ cross-compile support 68 | mkdir ".build" 69 | copy "#{output_bin}_#{ohai['kernel']['machine']}", ".build/crystal" 70 | 71 | # Cross-compile for other arch 72 | 73 | make "deps", env: env 74 | 75 | other_machine = ohai['kernel']['machine'] == "x86_64" ? "arm64" : "x86_64" 76 | other_target = "#{other_machine}-apple-macosx#{ENV["MACOSX_DEPLOYMENT_TARGET"]}" 77 | make "crystal stats=true release=true target=#{other_target} FLAGS=\"#{crflags}\" CRYSTAL_CONFIG_TARGET=#{other_target} CRYSTAL_CONFIG_LIBRARY_PATH= O=#{output_path}", env: env 78 | 79 | command "clang #{output_path}/crystal.o -o #{output_bin}_#{other_machine} -target #{other_target} src/llvm/ext/llvm_ext.o `llvm-config --libs --system-libs --ldflags 2>/dev/null` -lstdc++ -lpcre2-8 -lgc -lpthread -liconv -ldl -v", env: env 80 | delete "#{output_path}/crystal.o" 81 | 82 | # Lipo them up 83 | command "lipo -create -output #{output_bin} #{output_bin}_x86_64 #{output_bin}_arm64" 84 | delete "#{output_bin}_x86_64" 85 | delete "#{output_bin}_arm64" 86 | 87 | block do 88 | raise "Could not build crystal" unless File.exist?(output_bin) 89 | 90 | if macos? || mac_os_x? 91 | otool_libs = `otool -L #{output_bin}` 92 | if otool_libs.include?("/usr/local/lib") || otool_libs.include?('/opt/homebrew/lib') 93 | raise "Found local libraries linked to the generated compiler:\n#{otool_libs}" 94 | end 95 | end 96 | end 97 | 98 | sync "#{project_dir}/src", "#{install_dir}/src" 99 | sync "#{project_dir}/etc", "#{install_dir}/etc" 100 | sync "#{project_dir}/samples", "#{install_dir}/samples" 101 | mkdir "#{install_dir}/bin" 102 | 103 | erb source: "crystal.erb", 104 | dest: "#{install_dir}/bin/crystal", 105 | mode: 0755, 106 | vars: { install_dir: install_dir } 107 | end 108 | -------------------------------------------------------------------------------- /docker/Makefile: -------------------------------------------------------------------------------- 1 | # Recipes for this Makefile 2 | 3 | ## Build all docker images 4 | ## $ make VERSION=1.18.2 5 | ## Build specific docker images 6 | ## $ make build-ubuntu VERSION=1.18.2 7 | ## $ make build-alpine-build VERSION=1.18.2 8 | ## 9 | ## Push all docker images to registry 10 | ## $ make build VERSION=1.18.2 PUSH=1 11 | ## Push a specific docker image to registry 12 | ## $ make build-ubuntu VERSION=1.18.2 PUSH=1 13 | ## $ make build-alpine-build VERSION=1.18.2 PUSH=1 14 | ## 15 | ## Run smoke tests 16 | ## $ make smoke-all 17 | ## $ make smoke-ubuntu-build 18 | ## $ make smoke-alpine-runtime 19 | 20 | VERSION ?= ## Version name of the source tarballs 21 | TARBALLS ?= ./tarballs## Path to folder which contains the Crystal tarballs to install in docker images. 22 | PUSH ?= ## Directly push images to registry 23 | 24 | BUILD_CONTEXT := ./build-context 25 | TAG := crystallang/crystal:$(VERSION)## Base tag of the docker image. Classifiers like `-ubuntu` and `-build` will be appended. 26 | 27 | PLATFORM := linux/amd64,linux/arm64 28 | comma:=, 29 | PLATFORM_TARBALLS := $(patsubst linux/%,$(BUILD_CONTEXT)/crystal-%.tar.gz,$(subst $(comma), ,$(PLATFORM))) 30 | 31 | .PHONY: all 32 | all: ## Build all images 33 | all: build-ubuntu 34 | all: build-ubuntu-build 35 | all: build-alpine 36 | all: build-alpine-build 37 | 38 | $(BUILD_CONTEXT)/crystal-amd64.tar.gz: $(TARBALLS)/crystal-$(VERSION)-1-linux-x86_64.tar.gz | $(BUILD_CONTEXT) 39 | cp $< $@ 40 | 41 | $(BUILD_CONTEXT)/crystal-arm64.tar.gz: $(TARBALLS)/crystal-$(VERSION)-1-linux-aarch64.tar.gz | $(BUILD_CONTEXT) 42 | cp $< $@ 43 | 44 | $(BUILD_CONTEXT): 45 | mkdir -p $@ 46 | 47 | .PHONY: build-alpine 48 | build-alpine: alpine.Dockerfile $(PLATFORM_TARBALLS) 49 | docker buildx build $(if $(PUSH),--push,) --platform $(PLATFORM) --file alpine.Dockerfile -t $(TAG)-alpine --target runtime $(BUILD_CONTEXT) 50 | 51 | .PHONY: build-alpine-build 52 | build-alpine-build: alpine.Dockerfile $(PLATFORM_TARBALLS) 53 | docker buildx build $(if $(PUSH),--push,) --platform $(PLATFORM) --file alpine.Dockerfile -t $(TAG)-alpine-build --target build $(BUILD_CONTEXT) 54 | 55 | .PHONY: build-ubuntu 56 | build-ubuntu: ubuntu.Dockerfile $(PLATFORM_TARBALLS) 57 | docker buildx build $(if $(PUSH),--push,) --platform $(PLATFORM) --file ubuntu.Dockerfile -t $(TAG) --target runtime $(BUILD_CONTEXT) 58 | 59 | .PHONY: build-ubuntu-build 60 | build-ubuntu-build: ubuntu.Dockerfile $(PLATFORM_TARBALLS) 61 | docker buildx build $(if $(PUSH),--push,) --platform $(PLATFORM) --file ubuntu.Dockerfile -t $(TAG)-build --target build $(BUILD_CONTEXT) 62 | 63 | alpine-84codes: ## Build and push docker build images based on the base images from 84codes 64 | docker buildx build --build-arg crystal_version=$(VERSION) -f alpine-84codes.Dockerfile --platform linux/amd64,linux/arm64 --tag $(TAG)-alpine-84codes-build --push . 65 | 66 | ubuntu-84codes: ## Build and push docker build images based on the base images from 84codes 67 | docker buildx build --build-arg crystal_version=$(VERSION) -f ubuntu-84codes.Dockerfile --platform linux/amd64,linux/arm64 --tag $(TAG)-ubuntu-84codes-build --push . 68 | 69 | .PHONY: smoke-all 70 | smoke-all: ## Run smoke tests on all docker images 71 | smoke-all: smoke-alpine 72 | smoke-all: smoke-alpine-build 73 | smoke-all: smoke-ubuntu 74 | smoke-all: smoke-ubuntu-build 75 | 76 | .PHONY: smoke-% 77 | smoke-%: # Run smoke tests on docker images 78 | docker run --rm -v $(CURDIR)/smoke.sh:/smoke.sh -e VERSION=$(VERSION) $(TAG)$(subst -ubuntu,,-$*) /smoke.sh $* 79 | 80 | .PHONY: clean 81 | clean: ## Clean up build context 82 | rm -Rf $(BUILD_CONTEXT) 83 | 84 | .PHONY: help 85 | help: ## Show this help 86 | @echo 87 | @printf '\033[34mtargets:\033[0m\n' 88 | @grep -hE '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) |\ 89 | sort |\ 90 | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}' 91 | @echo 92 | @printf '\033[34mconfiguration variables:\033[0m\n' 93 | @grep -hE '^[a-zA-Z0-9_-]+ \?=.*?## .*$$' $(MAKEFILE_LIST) |\ 94 | sort |\ 95 | awk 'BEGIN {FS = " \\?=.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}' 96 | @echo 97 | @printf '\033[34mrecipes:\033[0m\n' 98 | @grep -hE '^##.*$$' $(MAKEFILE_LIST) |\ 99 | awk 'BEGIN {FS = "## "}; /^## [a-zA-Z_-]/ {printf " \033[36m%s\033[0m\n", $$2}; /^## / {printf " %s\n", $$2}' 100 | -------------------------------------------------------------------------------- /packages/README.md: -------------------------------------------------------------------------------- 1 | # Packages on Open Build Service 2 | 3 | [OBS](https://openbuildservice.org) builds the .deb and .rpm repositories and publishes them in their repositories. 4 | 5 | We're using separate OBS projects for the different release strategies: 6 | 7 | * Stable releases: https://build.opensuse.org/package/show/devel:languages:crystal/crystal 8 | * Nightly releases: https://build.opensuse.org/package/show/devel:languages:crystal:nightly/crystal 9 | * Unstable releases (currently unused): https://build.opensuse.org/package/show/devel:languages:crystal:unstable/crystal 10 | 11 | Each project can contain multiple packages. Currently, there is only a `crystal` package in each project. 12 | 13 | The tarballs with the generic linux binaries are statically linked and should work on any linux distribution. 14 | We use them as a basis for all packages. OBS does not rebuild the compiler. It just packages them. 15 | 16 | ## Nightly releases 17 | 18 | Nightlies are uploaded automatically in the `push_obs_nightly` job on circle ci. 19 | The ci job authenticates as crystalbot. This user account has only access to the nightly project. 20 | 21 | ## Stable releases 22 | 23 | Stable (and unstable releases) are pushed manually to the OBS project. 24 | 25 | In the future, we could even consider automating this, but it's fairly easy to do and just another point on the release check list. 26 | 27 | ## Publishing a new release 28 | 29 | To publish a new release, we need to update the source files and version information in the OBS project. 30 | 31 | While this can be done via the web UI, it's far easier using the command line client [osc](https://openbuildservice.org/help/manuals/obs-user-guide/cha.obs.osc.html). 32 | 33 | ### Setup OSC 34 | 35 | A dockerfile provided at https://github.com/crystal-lang/osc-docker ([`crystallang/osc`](https://hub.docker.com/r/crystallang/osc) on dockerhub) contains all the necessary utilities for running osc. 36 | 37 | NOTE: While there are osc packages for other distributions, they are likely broken and it's strongly advised to run it on openSUSE. 38 | 39 | To avoid manual sign in, you can configure OBS credentials in `~/.oscrc`. See [`obs-setup.sh`](./obs-setup.sh) for the template. 40 | We use our personal SUSE user accounts to authenticate with build.opensuse.org. Crystalbot is only responsible for pushing nightly updates. 41 | 42 | NOTE: Source code management in OBS packages is based on subversion. OSC is basically a frontend with reduced functionality (but more OBS-specific features). 43 | 44 | ### Update package 45 | 46 | With osc, we check out the package configuration, update the version information and source tarballs, and finally push it back to OBS. 47 | 48 | The entire round trip is implemented in [`obs-push.sh`](./obs-push.sh). This script is targeted for the automatic nightly workflow. For manually published builds it's advisable to run the commands separately. 49 | 50 | ```terminal-session 51 | # Checkout OBS project 52 | osc checkout "$PROJECT" "$PACKAGE" 53 | cd "$PROJECT/$PACKAGE" 54 | 55 | # Copy build artifacts and update versions 56 | 57 | # Update changes file 58 | osc vc 59 | 60 | # Check changes 61 | osc diff 62 | 63 | # Commit changes and push to OBS 64 | osc commit 65 | ``` 66 | 67 | NOTE: The `osc commit` command directly pushes to the remote repository. This is different from git, where a commit is only local and you need to explicitly push. 68 | 69 | Before committing the changes, you may use `osc build` for a local test to see if everything works. This uses the default build target, but you can specify a repository name and architecture are arguments (for example `osc build Debian_10 x86_64`). 70 | 71 | Alternatively, you can use a branch package to run a test build on OBS. 72 | 73 | ### Test build 74 | 75 | To test if a build succeeds, we can use a branching strategy. In contrast to git, where you would create a new branch in the repository, in OBS you branch the entire project. The branch project is created in your personal namespace (`home:$USERNAME:branches:$PROJECT`). 76 | 77 | After creating the branch package, you check that out locally, apply the changes and commit (see [*Update package*](#Update package)). OBS then builds the packages in your branch project. If everything is green, you create a submit request which would pull the changes into the main project (similar to a pull request on GitHub). 78 | 79 | See [*Branching a Package* in the OBS Beginner's Guide](https://openbuildservice.org/help/manuals/obs-user-guide/art.obs.bg.html#sec.obsbg.uc.branchprj) for more details on this workflow. 80 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | CRYSTAL_REPO ?= https://github.com/crystal-lang/crystal ## Allow to override the official repo with fork or local 2 | CRYSTAL_VERSION ?= ## How the binaries should be branded 3 | CRYSTAL_SHA1 ?= $(CRYSTAL_VERSION) ## Git tag/branch/sha1 to checkout and build source (default: `$(CRYSTAL_VERSION)`) 4 | CRYSTAL_DOCKER_IMAGE ?= crystallang/crystal:$(CRYSTAL_VERSION)-build ## Which crystal docker build image to use (default: `$(CRYSTAL_VERSION)-build`) 5 | 6 | OUTPUT_DIR = build 7 | OUTPUT_DOCS_BASE_NAME = crystal-$(CRYSTAL_VERSION)-docs 8 | 9 | AWS_CLI = docker run --rm -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -v $$(pwd):/mnt -w /mnt amazon/aws-cli:2.2.44 10 | S3_ENDPOINT = s3://$(AWS_BUCKET)/api 11 | AWS_BUCKET = crystal-api 12 | 13 | BUILD_ARGS = --build-arg crystal_docker_image=$(CRYSTAL_DOCKER_IMAGE) --build-arg output_docs_base_name=$(OUTPUT_DOCS_BASE_NAME) --build-arg crystal_repo=$(CRYSTAL_REPO) --build-arg crystal_sha1=$(CRYSTAL_SHA1) 14 | 15 | .PHONY: all 16 | all: $(OUTPUT_DIR)/$(OUTPUT_DOCS_BASE_NAME).tar.gz ## Build docs tarball 17 | 18 | $(OUTPUT_DIR)/$(OUTPUT_DOCS_BASE_NAME).tar.gz: $(OUTPUT_DIR) 19 | docker build $(BUILD_ARGS) -t crystal-build-temp . 20 | container_id="$$(docker create crystal-build-temp)" \ 21 | && docker cp "$$container_id":/output/$(OUTPUT_DOCS_BASE_NAME).tar.gz $(OUTPUT_DIR)/ \ 22 | && docker cp "$$container_id":/output/versions.json $(OUTPUT_DIR)/versions-$(CRYSTAL_VERSION).json \ 23 | && docker rm -v "$$container_id" 24 | 25 | $(OUTPUT_DIR): 26 | mkdir -p $(OUTPUT_DIR) 27 | 28 | .PHONY: clean 29 | clean: ## Clean up build directory 30 | rm -Rf $(OUTPUT_DIR) 31 | 32 | .PHONE: publish_docs 33 | publish_docs: dist-docs dist-docs_versions ## Publish API docs to S3 34 | 35 | .PHONY: dist-docs 36 | dist-docs: $(OUTPUT_DIR)/api-$(CRYSTAL_VERSION) ## Sync API docs to `s3://$(AWS_BUCKET)/api/$(CRYSTAL_VERSION)` 37 | gzip $(OUTPUT_DIR)/api-$(CRYSTAL_VERSION)/index.json 38 | mv $(OUTPUT_DIR)/api-$(CRYSTAL_VERSION)/index.json.gz $(OUTPUT_DIR)/ 39 | $(AWS_CLI) s3 sync "$ $@ 63 | 64 | .PHONY: get-website-configuration 65 | get-website-configuration: ## Pull website configuration from S3 bucket (run as `make pull-website-configuration -s > aws-config.json`) 66 | $(AWS_CLI) s3api get-bucket-website --bucket "$(AWS_BUCKET)" 67 | 68 | .PHONY: $(OUTPUT_DIR)/aws-config.json 69 | $(OUTPUT_DIR)/aws-config.json: aws-config.json $(OUTPUT_DIR) 70 | sed 's/$${CRYSTAL_VERSION}/$(CRYSTAL_VERSION)/g' "$<" > $@ 71 | 72 | .PHONY: help 73 | help: ## Show this help 74 | @echo 75 | @printf '\033[34mtargets:\033[0m\n' 76 | @grep -hE '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) |\ 77 | sort |\ 78 | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}' 79 | @echo 80 | @printf '\033[34mconfiguration variables:\033[0m\n' 81 | @grep -hE '^[a-zA-Z0-9_-]+ \?=.*?## .*$$' $(MAKEFILE_LIST) |\ 82 | sort |\ 83 | awk 'BEGIN {FS = " \\?=.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}' 84 | @echo 85 | @printf '\033[34mrecipes:\033[0m\n' 86 | @grep -hE '^##.*$$' $(MAKEFILE_LIST) |\ 87 | awk 'BEGIN {FS = "## "}; /^## [a-zA-Z_-]/ {printf " \033[36m%s\033[0m\n", $$2}; /^## / {printf " %s\n", $$2}' 88 | -------------------------------------------------------------------------------- /linux/Makefile: -------------------------------------------------------------------------------- 1 | # Recipes for this Makefile 2 | 3 | ## Build everything 4 | ## $ make CRYSTAL_VERSION=0.xx.y PREVIOUS_CRYSTAL_RELEASE_LINUX64_TARGZ=... 5 | ## Build just 64bit distribution packages 6 | ## $ make package64 CRYSTAL_VERSION=0.xx.y PREVIOUS_CRYSTAL_RELEASE_LINUX64_TARGZ=... 7 | ## Build everything for final release 8 | ## $ make clean all no_cache=true pull_images=true release=true CRYSTAL_VERSION=0.xx.y PREVIOUS_CRYSTAL_RELEASE_LINUX64_TARGZ=... 9 | 10 | no_cache ?= ## Disable the docker build cache 11 | pull_images ?= ## Always pull docker images to ensure they're up to date 12 | release ?= ## Create an optimized build for the final release 13 | arch ?= $(shell uname -m)## Target arch to build (x86_64, aarch64) 14 | # ^-- no space before comment otherwise it's appended to $arch! 15 | 16 | CRYSTAL_REPO ?= https://github.com/crystal-lang/crystal ## Allow to override the official repo with fork or local 17 | CRYSTAL_VERSION ?= ## How the binaries should be branded 18 | CRYSTAL_SHA1 ?= $(CRYSTAL_VERSION) ## Git tag/branch/sha1 to checkout and build source 19 | PACKAGE_ITERATION ?= 1 20 | PACKAGE_MAINTAINER = Crystal Team 21 | 22 | PREVIOUS_CRYSTAL_VERSION ?= ## Version of the bootstrap compiler 23 | PREVIOUS_CRYSTAL_PACKAGE_ITERATION ?= 1## Package iteration of the bootstrap compiler 24 | PREVIOUS_CRYSTAL_RELEASE_LINUX64_TARGZ ?= https://github.com/crystal-lang/crystal/releases/download/$(PREVIOUS_CRYSTAL_VERSION)/crystal-$(PREVIOUS_CRYSTAL_VERSION)-$(PREVIOUS_CRYSTAL_PACKAGE_ITERATION)-linux-$(arch).tar.gz ## url to crystal-{version}-{package}-linux-{arch}.tar.gz 25 | 26 | SHARDS_VERSION = v0.19.1 27 | GC_VERSION = v8.2.8 28 | LIBPCRE2_VERSION = 10.46 29 | 30 | OUTPUT_DIR = build 31 | OUTPUT_BASENAME64 = $(OUTPUT_DIR)/crystal-$(CRYSTAL_VERSION)-$(PACKAGE_ITERATION)-linux-$(arch) 32 | 33 | DOCKER_BUILD_ARGS = $(if $(no_cache),--no-cache )$(if $(pull_images),--pull ) --progress=plain 34 | 35 | BUILD_ARGS_COMMON = $(DOCKER_BUILD_ARGS) \ 36 | $(if $(release),--build-arg release=true) \ 37 | --build-arg crystal_repo=$(CRYSTAL_REPO) \ 38 | --build-arg crystal_version=$(CRYSTAL_VERSION) \ 39 | --build-arg crystal_sha1=$(CRYSTAL_SHA1) \ 40 | --build-arg shards_version=$(SHARDS_VERSION) \ 41 | --build-arg gc_version=$(GC_VERSION) \ 42 | --build-arg package_iteration=$(PACKAGE_ITERATION) 43 | 44 | BUILD_ARGS64 = $(BUILD_ARGS_COMMON) \ 45 | --build-arg previous_crystal_release=$(PREVIOUS_CRYSTAL_RELEASE_LINUX64_TARGZ) \ 46 | --build-arg musl_target=$(arch)-linux-musl \ 47 | --build-arg gnu_target=$(arch)-unknown-linux-gnu 48 | 49 | BUILD_ARGS64_BUNDLED = $(BUILD_ARGS64) \ 50 | --build-arg libpcre2_version=$(LIBPCRE2_VERSION) 51 | 52 | .PHONY: all 53 | all: all64 ## Build all distribution tarballs [default] 54 | 55 | .PHONY: all64 56 | all64: compress64 clean_tmp ## Build distribution tarballs for 64 bits 57 | 58 | .PHONY: help 59 | help: ## Show this help 60 | @echo 61 | @printf '\033[34mtargets:\033[0m\n' 62 | @grep -hE '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) |\ 63 | sort |\ 64 | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}' 65 | @echo 66 | @printf '\033[34moptional variables:\033[0m\n' 67 | @grep -hE '^[a-zA-Z0-9_-]+ \?=.*?## .*$$' $(MAKEFILE_LIST) |\ 68 | sort |\ 69 | awk 'BEGIN {FS = " \\?=.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}' 70 | @echo 71 | @printf '\033[34mrecipes:\033[0m\n' 72 | @grep -hE '^##.*$$' $(MAKEFILE_LIST) |\ 73 | awk 'BEGIN {FS = "## "}; /^## [a-zA-Z_-]/ {printf " \033[36m%s\033[0m\n", $$2}; /^## / {printf " %s\n", $$2}' 74 | 75 | .PHONY: build 76 | build: $(OUTPUT_BASENAME64).tar ## Build the raw uncompressed tarball 77 | 78 | $(OUTPUT_BASENAME64).tar: Dockerfile 79 | mkdir -p $(OUTPUT_DIR) 80 | docker build $(BUILD_ARGS64) -t crystal-build-temp . 81 | container_id="$$(docker create crystal-build-temp)" \ 82 | && docker cp "$$container_id":/output/crystal-$(CRYSTAL_VERSION)-$(PACKAGE_ITERATION).tar $@ \ 83 | && docker rm -v "$$container_id" 84 | 85 | $(OUTPUT_BASENAME64)-bundled.tar: $(OUTPUT_BASENAME64)-bundled 86 | tar -C $(OUTPUT_BASENAME64)-bundled -cf $@ ./ 87 | 88 | $(OUTPUT_BASENAME64)-bundled: $(OUTPUT_BASENAME64).tar $(OUTPUT_DIR)/bundled-libs.tar 89 | rm -rf $@ 90 | mkdir -p $@ 91 | tar -C $@ -xf $(OUTPUT_BASENAME64).tar 92 | tar -C $@ -xf $(OUTPUT_DIR)/bundled-libs.tar 93 | 94 | $(OUTPUT_DIR)/bundled-libs.tar: bundled.dockerfile 95 | mkdir -p $(OUTPUT_DIR) 96 | docker build $(BUILD_ARGS64_BUNDLED) -t crystal-build-temp -f bundled.dockerfile . 97 | container_id="$$(docker create crystal-build-temp)" \ 98 | && docker cp "$$container_id":/output/bundled-libs.tar $@ \ 99 | && docker rm -v "$$container_id" 100 | 101 | .PHONY: compress64 102 | compress64: $(OUTPUT_BASENAME64).tar.gz $(OUTPUT_BASENAME64).tar.xz $(OUTPUT_BASENAME64)-bundled.tar.gz ## Build compressed tarballs 103 | 104 | $(OUTPUT_DIR)/%.gz: $(OUTPUT_DIR)/% 105 | gzip -c $< > $@ 106 | 107 | $(OUTPUT_DIR)/%.xz: $(OUTPUT_DIR)/% 108 | xz -T 0 -c $< > $@ 109 | 110 | .PHONY: clean 111 | clean: ## Clean up build directory 112 | rm -Rf $(OUTPUT_DIR) 113 | 114 | .PHONY: clean_tmp 115 | clean_tmp: ## Clean up temporary build artifacts 116 | rm -Rf $(OUTPUT_DIR)/bundled-libs.tar 117 | rm -Rf $(OUTPUT_BASENAME64)-bundled 118 | -------------------------------------------------------------------------------- /packages/scripts/install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | _help() { 4 | cat <] [--channel=stable|unstable|nightly] 9 | 10 | - crystal-version: "latest", or a minor release version like 1.0 or 1.1 (Default: latest) 11 | - channel: "stable", "unstable", "nightly" (Default: stable) 12 | 13 | REQUIREMENTS 14 | 15 | - Run as root 16 | - The following packages need to be installed already: 17 | - gnupg ca-certificates apt-transport-https (on Debian/Ubuntu) 18 | 19 | NOTES 20 | 21 | The following files may be updated: 22 | 23 | - /etc/apt/sources.list.d/crystal.list (on Debian/Ubuntu) 24 | - /etc/yum.repos.d/crystal.repo (on CentOS/Fedora) 25 | 26 | The following packages may be installed: 27 | 28 | - wget (on Debian/Ubuntu when missing) 29 | - curl (on openSUSE when missing) 30 | - yum-utils (on CentOS/Fedora when using --version=x.y.z) 31 | 32 | This script source and issue-tracker can be found at: 33 | 34 | - https://github.com/crystal-lang/distribution-scripts/tree/master/packages/scripts/install.sh 35 | 36 | END 37 | } 38 | 39 | set -eu 40 | 41 | OBS_PROJECT=${OBS_PROJECT:-"devel:languages:crystal"} 42 | DISTRO_REPO=${DISTRO_REPO:-} 43 | CRYSTAL_VERSION=${CRYSTAL_VERSION:-"latest"} 44 | CHANNEL="stable" 45 | 46 | _error() { 47 | echo >&2 "ERROR: $*" 48 | } 49 | 50 | _warn() { 51 | echo >&2 "WARNING: $*" 52 | } 53 | 54 | _check_version_id() { 55 | if [[ -z "${VERSION_ID}" ]]; then 56 | _error "Unable to identify distribution repository for ${ID}. Please, report to https://forum.crystal-lang.org/c/help-support/11" 57 | exit 1 58 | fi 59 | } 60 | 61 | _discover_distro_repo() { 62 | if [[ -r /etc/os-release ]]; then 63 | source /etc/os-release 64 | elif [[ -r /usr/lib/os-release ]]; then 65 | source /usr/lib/os-release 66 | else 67 | _error "Unable to identify distribution. Please, report to https://forum.crystal-lang.org/c/help-support/11" 68 | exit 1 69 | fi 70 | 71 | case "$ID" in 72 | debian) 73 | if [[ -z "${VERSION_ID:-}" ]]; then 74 | VERSION_ID="Unstable" 75 | elif [[ "$VERSION_ID" == "9" ]]; then 76 | VERSION_ID="$VERSION_ID.0" 77 | fi 78 | _check_version_id 79 | 80 | DISTRO_REPO="Debian_${VERSION_ID}" 81 | ;; 82 | ubuntu) 83 | _check_version_id 84 | DISTRO_REPO="xUbuntu_${VERSION_ID}" 85 | ;; 86 | fedora) 87 | _check_version_id 88 | if [[ "${VERSION}" == *"Prerelease"* ]]; then 89 | DISTRO_REPO="Fedora_Rawhide" 90 | else 91 | DISTRO_REPO="Fedora_${VERSION_ID}" 92 | fi 93 | ;; 94 | centos) 95 | _check_version_id 96 | DISTRO_REPO="CentOS_${VERSION_ID}" 97 | ;; 98 | rhel) 99 | _check_version_id 100 | DISTRO_REPO="RHEL_${VERSION_ID}" 101 | ;; 102 | opensuse-tumbleweed) 103 | DISTRO_REPO="openSUSE_Tumbleweed" 104 | ;; 105 | opensuse-leap) 106 | _check_version_id 107 | DISTRO_REPO="${VERSION_ID}" 108 | ;; 109 | "") 110 | _error "Unable to identify distribution. You may specify one with environment variable DISTRO_REPO" 111 | _error "Please, report to https://forum.crystal-lang.org/c/help-support/11" 112 | exit 1 113 | ;; 114 | *) 115 | # If there's no dedicated repository for the distro, try to figure out 116 | # if the distro is apt, dnf or rpm based and use a default repository. 117 | _discover_package_manager 118 | 119 | case "$PACKAGE_MANAGER" in 120 | apt) 121 | DISTRO_REPO="Debian_Unstable" 122 | ;; 123 | dnf) 124 | DISTRO_REPO="Fedora_Rawhide" 125 | ;; 126 | yum) 127 | DISTRO_REPO="RHEL_7" 128 | ;; 129 | unsupported_package_manager) 130 | _error "Unable to identify distribution type ($ID). You may specify a repository with the environment variable DISTRO_REPO" 131 | _error "Please, report to https://forum.crystal-lang.org/c/help-support/11" 132 | exit 1 133 | ;; 134 | esac 135 | esac 136 | } 137 | 138 | _discover_package_manager() { 139 | [[ $(command -v apt-get) ]] && PACKAGE_MANAGER="apt" && return 140 | [[ $(command -v dnf) ]] && PACKAGE_MANAGER="dnf" && return 141 | [[ $(command -v yum) ]] && PACKAGE_MANAGER="yum" && return 142 | PACKAGE_MANAGER="unsupported_package_manager" 143 | } 144 | 145 | if [[ $EUID -ne 0 ]]; then 146 | _error "This script must be run as root" 147 | exit 1 148 | fi 149 | 150 | # Parse --version= and --channel= arguments 151 | 152 | for i in "$@" 153 | do 154 | case $i in 155 | --crystal=*) 156 | CRYSTAL_VERSION="${i#*=}" 157 | shift 158 | echo "The argument --crystal= has been deprecated, please use --version= instead." >&2 159 | ;; 160 | --version=*) 161 | CRYSTAL_VERSION="${i#*=}" 162 | shift 163 | ;; 164 | --channel=*) 165 | CHANNEL="${i#*=}" 166 | shift 167 | ;; 168 | --help) 169 | _help 170 | exit 0 171 | shift 172 | ;; 173 | *) 174 | _warn "Invalid option $i" 175 | ;; 176 | esac 177 | done 178 | 179 | case $CHANNEL in 180 | stable) 181 | ;; 182 | nightly | unstable) 183 | OBS_PROJECT="${OBS_PROJECT}:${CHANNEL}" 184 | ;; 185 | *) 186 | _error "Unsupported channel $CHANNEL" 187 | exit 1 188 | ;; 189 | esac 190 | 191 | if [[ -z "${DISTRO_REPO}" ]]; then 192 | _discover_distro_repo 193 | fi 194 | 195 | _install_apt() { 196 | if ! command -v wget &> /dev/null || ! command -v gpg &> /dev/null; then 197 | [[ -f /etc/apt/sources.list.d/crystal.list ]] && rm -f /etc/apt/sources.list.d/crystal.list 198 | apt-get update 199 | apt-get install -y wget gpg 200 | fi 201 | 202 | # Add repo signign key 203 | wget -qO- https://download.opensuse.org/repositories/${OBS_PROJECT//:/:\/}/${DISTRO_REPO}/Release.key | gpg --dearmor | tee /etc/apt/trusted.gpg.d/devel_languages_crystal.gpg > /dev/null 204 | echo "deb http://download.opensuse.org/repositories/${OBS_PROJECT//:/:\/}/${DISTRO_REPO}/ /" | tee /etc/apt/sources.list.d/crystal.list 205 | apt-get update 206 | 207 | if [[ "$CRYSTAL_VERSION" == "latest" ]]; then 208 | apt-get install -y crystal 209 | else 210 | apt-get install -y "crystal${CRYSTAL_VERSION}" 211 | fi 212 | } 213 | 214 | _install_rpm_key() { 215 | rpm --verbose --import https://build.opensuse.org/projects/${OBS_PROJECT}/signing_keys/download?kind=gpg 216 | } 217 | 218 | _add_yum_repo() { 219 | cat > /etc/yum.repos.d/crystal.repo < /dev/null; then 254 | zypper refresh 255 | zypper install -y curl 256 | fi 257 | 258 | _install_rpm_key 259 | zypper --non-interactive addrepo https://download.opensuse.org/repositories/${OBS_PROJECT//:/:\/}/$DISTRO_REPO/${OBS_PROJECT}.repo 260 | zypper --non-interactive refresh 261 | 262 | if [[ "$CRYSTAL_VERSION" == "latest" ]]; then 263 | zypper --non-interactive install crystal 264 | else 265 | zypper --non-interactive install "crystal${CRYSTAL_VERSION}" 266 | fi 267 | } 268 | 269 | # Add repo 270 | case $DISTRO_REPO in 271 | Debian*) 272 | _install_apt 273 | ;; 274 | xUbuntu*) 275 | _install_apt 276 | ;; 277 | Fedora*) 278 | _install_dnf 279 | ;; 280 | RHEL*) 281 | _install_yum 282 | ;; 283 | CentOS*) 284 | _install_yum 285 | ;; 286 | 15.* | openSUSE*) 287 | _install_zypper 288 | ;; 289 | *) 290 | _error "Unable to install for $DISTRO_REPO. Please, report to https://forum.crystal-lang.org/c/help-support/11" 291 | exit 1 292 | ;; 293 | esac 294 | -------------------------------------------------------------------------------- /processes/crystal-release.md: -------------------------------------------------------------------------------- 1 | # Crystal release process checklist 2 | 3 | Add an issue `Crystal release X.Y.Z` in 4 | https://github.com/crystal-lang/distribution-scripts/issues with a copy of this 5 | document. In this way it's easy to track the progress of the release (*Helper: 6 | (`distribution-scripts`) 7 | [`scripts/prepare-crystal-release.sh`](./scripts/prepare-crystal-release.sh)*) 8 | 9 | ## Release preparation 10 | 11 | 1. [ ] (minor) Announce expected release date (${RELEASE_DATE}) and time span for feature freeze (starting on ${FREEZE_PERIOD}) 12 | * (minor) Feature freeze is about two weeks before release 13 | 2. Set date on the milestone 14 | 3. [ ] Prepare the changelog entry: (`crystal`) [`scripts/update-changelog.cr ${VERSION}`](https://github.com/crystal-lang/crystal/blob/master/scripts/update-changelog.cr) from the HEAD of the release branch (or `master`) 15 | * Ensure that all merged PRs are added to the milestone (check [`is:pr is:merged sort:updated-desc no:milestone`](https://github.com/crystal-lang/crystal/pulls?q=is%3Apr+is%3Amerged+sort%3Aupdated-desc+no%3Amilestone+-label%3Astatus%3Areverted+base%3Amaster+merged%3A%3E%3D2023-01-01)). 16 | * Ensure that all milestoned PRs are properly labelled (check [`is:pr is:merged sort:updated-desc no:label milestone:${VERSION}`](https://github.com/crystal-lang/crystal/pulls?q=is%3Apr+is%3Amerged+sort%3Aupdated-desc+milestone%3A${VERSION}+no%3Alabel)). 17 | * Ensure the milestone has `Due date` set. 18 | 4. [ ] Start preparing release notes, publish draft in [`crystal-lang/crystal-website`](https://github.com/crystal-lang/crystal-website/) (summary of changes that are most relevant for users) 19 | 5. [ ] (minor) Start feature freeze period (on ${FREEZE_PERIOD}) 20 | * (minor) Either no merging of features into `master` or split off release branch for backporting bugfixes. 21 | 6. [ ] Publish release PR draft 22 | * (minor) It should contain the expected date of the release. 23 | * It should be populated with updates to `CHANGELOG.md`, `src/VERSION` and the version in `shard.yml`. 24 | 7. [ ] (minor) Ensure documentation for language and compiler changes and other relevant changes is up to date. 25 | * (minor) [Crystal Book](https://github.com/crystal-lang/crystal-book/) 26 | * (minor) Update language specification 27 | * (minor) Update compiler manual 28 | * (minor) Add or update guides / tutorials? 29 | 8. [ ] (minor) Look for library updates, check and document compatibility at https://crystal-lang.org/reference/man/required_libraries.html and in lib bindings 30 | 9. [ ] Ensure that [test-ecosystem](https://github.com/crystal-lang/test-ecosystem) functions and succeeds on master 31 | * Run [*CI Workflow*](https://github.com/crystal-lang/test-ecosystem/actions/workflows/ci.yml) on `master` (uses nightly build) 32 | 33 | ## Release process (on ${RELEASE_DATE}) 34 | 35 | ### Source release 36 | 37 | 1. [ ] Finalize the changelog PR 38 | * Make sure all changes are mentioned in the changelog 39 | * Check release date 40 | * Un-draft the PR 41 | 2. [ ] (minor) Split off release branch `release/${VERSION%.*}` from `master` to trigger Maintenance CI 42 | 3. [ ] Verify Maintenance CI workflow succeeds on the HEAD of the release 43 | branch: https://app.circleci.com/pipelines/github/crystal-lang/crystal?branch=release%2F${VERSION%.*} 44 | 4. [ ] Smoke test with [test-ecosystem](https://github.com/crystal-lang/test-ecosystem) 45 | * Run [*CI Workflow*](https://github.com/crystal-lang/test-ecosystem/actions/workflows/ci.yml) with `crystal=branch:release/{VERSION%.*}`. 46 | 5. [ ] Merge the changelog PR 47 | 6. [ ] Make the release and publish it on GitHub: (`crystal`) [`../distribution-scripts/processes/scripts/make-crystal-release.sh`](https://github.com/crystal-lang/distribution-scripts/blob/master/processes/scripts/make-crystal-release.sh) (run from `crystallang/crystal@${VERSION}` work tree). This performs these steps: 48 | 1. Tag & annotate the commit with the changelog using `` pattern as version 49 | * `git tag -s -a -m ${VERSION} ${VERSION}` 50 | * `git push --tags` 51 | 2. Publish Github release (https://github.com/crystal-lang/crystal/releases/new) 52 | * Copy the changelog section as description 53 | * Binaries are added later 54 | 8. [ ] Close milestone (https://github.com/crystal-lang/crystal/milestones) 55 | 9. [ ] Wait for the release build in circle CI (https://app.circleci.com/pipelines/github/crystal-lang/crystal) 56 | 10. [ ] Fast-forward `release/${VERSION%.*}` to `master@${VERSION}` 57 | 58 | ### Binary releases 59 | 60 | 1. Publish build artifacts from CircleCI and GitHub Actions to GitHub release. For `URL_TO_CIRCLECI_ARTIFACT` grab the URL 61 | of any of the build artifacts in circleCI (doesn't matter which). 62 | * [ ] Upload build artifacts from CircleCI: (`crystal`) [`../distribution-scripts/processes/scripts/publish-crystal-packages-on-github.sh $URL_TO_CIRCLECI_ARTIFACT`](https://github.com/crystal-lang/distribution-scripts/blob/master/processes/scripts/publish-crystal-packages-on-github.sh) (run from `crystallang/crystal@${VERSION}` work tree) 63 | * `crystal-*-darwin-*.tar.gz` 64 | * `crystal-*-linux-*.tar.gz` 65 | * `crystal-*.pkg` 66 | * `crystal-*-docs.tar.gz` 67 | * [ ] Upload build artifacts from GHA (Windows): 68 | * Windows CI: `crystal.zip` -> `crystal-${VERSION}-windows-x86_64-msvc-unsupported.zip` 69 | * Windows CI: `crystal-installer.zip` -> unzip -> `crystal-${VERSION}-windows-x86_64-msvc-unsupported.exe` 70 | * MinGW-w64 CI: `x86_64-mingw-w64-crystal.zip` -> `crystal-${VERSION}-windows-x86_64-gnu-unsupported.zip` 71 | * MinGW-w64 CI: `aarch64-mingw-w64-crystal.zip` -> `crystal-${VERSION}-windows-aarch64-gnu-unsupported.zip` 72 | 2. [ ] Publish the GitHub release 73 | 3. [ ] Push changes to OBS for building linux packages 74 | 1. Checkout https://github.com/crystal-lang/distribution-scripts and go to [`./packages`](../packages) 75 | 2. Configure build.opensuse.org credentials in environment variables: 76 | * `export OBS_USER=` 77 | * `export OBS_PASSWORD=` 78 | 3. (minor) Update the `crystal` package: (`distribution-scripts`) [`./obs-release.sh devel:languages:crystal crystal ${VERSION}`](../packages/obs-release.sh) 79 | * (minor) Uses the docker image `crystallang/osc` to run the CLI client for OBS. 80 | * (minor) The script creates a branch in you home project, updates the version and pushes it back to OBS. 81 | * (minor) You can also run the commands from that file manually and check build locally with 82 | * (minor) `osc build xUbuntu_20.04 x86_64` 83 | * (minor) `osc build Fedora_Rawhide x86_64` 84 | 4. (minor) Create the `crystal${VERSION%.*}` package: (`distribution-scripts`) [`./obs-new-minor.sh devel:languages:crystal crystal${VERSION%.*} ${VERSION} crystal${OLD_VERSION%.*}`](../packages/obs-new-minor.sh) 85 | 5. (patch) Update the `crystal${VERSION%.*}` package: (`distribution-scripts`) [`./obs-release.sh devel:languages:crystal crystal${VERSION%.*} ${VERSION}`](../packages/obs-release.sh) 86 | 6. Now OBS builds the packages. It’s best to follow the build status in the browser: 87 | 1. `open https://build.opensuse.org/package/show/home:$OBS_USER:branches:devel:languages:crystal/crystal` 88 | 1. `open https://build.opensuse.org/package/show/home:$OBS_USER:branches:devel:languages:crystal/crystal${VERSION%.*}` 89 | 2. Wait for all package build jobs to finish and succeed 90 | 7. When everything is green, create a submit request against the original 91 | packages: *Submit package* link in the page actions (left sidebar) in your branch. 92 | 8. (optional) Verify package installation 93 | * (`distribution-scripts/packages`) `OBS_PROJECT=devel:languages:crystal bats test` 94 | 4. [ ] Tag `latest` docker images 95 | * Versioned docker images have been pushed to Docker Hub. 96 | * Now just assign the `latest` tags: 97 | * (`distribution-scripts`) `./docker/apply-latest-tags.sh ${VERSION}` 98 | 5. [ ] Publish snap package 99 | - On https://snapcraft.io/crystal/releases promote the `latest/edge` release to `latest/beta` and then `latest/stable` 100 | 6. [ ] Check PR for homebrew: https://github.com/Homebrew/homebrew-core/pulls?q=is%3Apr+crystal+sort%3Aupdated-desc 101 | * It should've been automatically created 102 | 103 | ### Publish documentation for the release 104 | 105 | 1. [ ] Publish API docs 106 | 1. Have `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` env variables defined 107 | * Keys can be generated at https://console.aws.amazon.com/iam/home#/security_credentials (contact a Manas admin if you don't have access). 108 | 2. Run (`distribution-scripts`) `make -C docs publish_docs release_latest_docs CRYSTAL_VERSION=${VERSION}` to publish docs to `api/${VERSION}`, apply redirect from `api/latest` to `api/${VERSION}` and set the 404 error page 109 | 3. Update API docs' 404 page to add `` in the `` 110 | 2. [ ] (minor) Publish Crystal book 111 | 1. (minor) Make sure `release/${OLD_VERSION%.*}` branch is merged into `master` (if not, create a PR; **it needs to be merged as a merge commit**) 112 | 2. (minor) Create `release/${VERSION%.*}` branch and push it to `crystal-lang/crystal-book` (deployment happens automatically in GHA) 113 | 3. (minor) Verify that deployment was successful 114 | 115 | ### Release announcements 116 | 117 | 1. [ ] Publish release notes on the website 118 | - Make sure all links to API docs point to `/api/${VERSION}/` 119 | - Insert number of changes and contributers 120 | 2. [ ] Wait for website to build, then visit the release notes page. This should 121 | create a thread for comments on the forum. Publish that topic 122 | ("List topic" in the wrench icon) and add tag `release`. 123 | 1. [ ] Announce on social media accounts (via Buffer; credentials are in Passbolt) and pin release posts 124 | 3. [ ] (minor) Have the project manager post the release in https://opencollective.com/crystal-lang 125 | 126 | ## Post-release 127 | 1. [ ] Create a pull request to update `master` branch to use released version: 128 | (`crystal`) [`scripts/release-update.sh 129 | ${VERSION}`](https://github.com/crystal-lang/crystal/blob/master/scripts/release-update.sh) 130 | * Edit PREVIOUS_CRYSTAL_BASE_URL in `.circleci/config.yml` 131 | * Edit DOCKER_TEST_PREFIX in `bin/ci` 132 | * Edit `prepare_build` on_osx download package and folder 133 | * Edit ` .github/workflows/*.yml` to point to docker image 134 | * Edit `shell.nix` `latestCrystalBinary` using `nix-prefetch-url --unpack ` 135 | * Branch: `infra/release-update`. Commit message: `Update previous Crystal release ${VERSION}` 136 | 2. [ ] (minor) Increment `src/VERSION` and version in `shard.yml` to the next minor plus `-dev` suffix 137 | 3. [ ] (minor) Perform uncomment/todos left in the repo 138 | 4. [ ] Merge `release/${VERSION%.*}` branch into `master` (if the two have diverged) 139 | - This needs to be a *merge commit*. Those are disabled in the GitHub UI. 140 | - Create branch and PR: 141 | ```sh 142 | git fetch upstream release/${VERSION%.*} master 143 | git switch -c merge/${VERSION} upstream/master 144 | git merge upstream/release/${VERSION%.*} 145 | # resolve conflicts 146 | git commit -m 'Merge `release/${VERSION%.*}` into master' 147 | git log --graph --decorate --pretty=oneline --abbrev-commit 148 | git push -u upstream merge/${VERSION} 149 | gh pr create --title 'Merge `release/${VERSION%.*}`@`%{VERSION} into `master`' --label 'topic:infrastructure' 150 | ``` 151 | - Merge PR **locally**: 152 | ```sh 153 | git switch master 154 | git merge --ff-only merge/${VERSION} 155 | # double check history 156 | git log --graph --decorate --pretty=oneline --abbrev-commit 157 | git push 158 | ``` 159 | - GitHub branch protection rules normally prevent direct pushes to 160 | `master`. This needs to be deactivated for this purpose, which can be on a 161 | per-user basis. 162 | - In case master has diverged, `--ff-only` merge will fail. Then you can 163 | first rebase `merge/${VERSION}` on current master with `git rebase master --rebase-merges`. 164 | --------------------------------------------------------------------------------