diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bee8a64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/.metadata-lib b/.metadata-lib deleted file mode 100644 index e894146..0000000 --- a/.metadata-lib +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env bash - -_awkArch() { - local version="$1"; shift - local awkExpr="$1"; shift - awk "$@" "/^#|^\$/ { next } $awkExpr" "$version/release-architectures" -} - -dpkgArches() { - local version="$1"; shift - _awkArch "$version" '{ print $2 }' -} - -hasBashbrewArch() { - local version="$1"; shift - local bashbrewArch="$1"; shift - - _awkArch "$version" 'BEGIN { exitCode = 1 } $1 == bashbrewArch { exitCode = 0 } END { exit exitCode }' -v bashbrewArch="$bashbrewArch" -} - -dpkgToRustArch() { - local version="$1"; shift - local dpkgArch="$1"; shift - _awkArch "$version" '$2 == dpkgArch { print $3; exit }' -v dpkgArch="$dpkgArch" -} - -rustupVersion() { - local version="$1"; shift - cat "$version/rustup-version" | tr -d '\n' -} - -_generateParentRepoToArches() { - local repo="$1"; shift - local officialImagesUrl='https://github.com/docker-library/official-images/raw/master/library/' - - eval "declare -g -A parentRepoToArches=( $( - find -name 'Dockerfile' -exec awk ' - toupper($1) == "FROM" && $2 !~ /^('"$repo"'|scratch|microsoft\/[^:]+)(:|$)/ { - print "'"$officialImagesUrl"'" $2 - } - ' '{}' + \ - | sort -u \ - | xargs bashbrew cat --format '[{{ .RepoName }}:{{ .TagName }}]="{{ join " " .TagEntry.Architectures }}"' - ) )" -} -_generateParentRepoToArches 'rust' - -parentArches() { - local version="$1"; shift # "1.19.0", etc - local variant="$1"; shift # "", "stretch", etc - - local parent="$(awk 'toupper($1) == "FROM" { print $2 }' "$version/$variant/Dockerfile")" - echo "${parentRepoToArches[$parent]:-}" -} -variantArches() { - local version=$1; shift # "1.19.0", etc - local variant=$1; shift # "", "stretch", etc - - local parentArches="$(parentArches "$version" "$variant")" - - local variantArches=() - for arch in $parentArches; do - if hasBashbrewArch "$version" "$arch"; then - variantArches+=( "$arch" ) - fi - done - echo "${variantArches[*]}" -} diff --git a/.travis.yml b/.travis.yml index a98f371..896c14b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,10 +2,13 @@ language: bash services: docker env: - - VERSION=1.37.0 VARIANT=buster/slim - - VERSION=1.37.0 VARIANT=buster - - VERSION=1.37.0 VARIANT=stretch/slim +#VERSIONS - VERSION=1.37.0 VARIANT=stretch + - VERSION=1.37.0 VARIANT=stretch/slim + - VERSION=1.37.0 VARIANT=buster + - VERSION=1.37.0 VARIANT=buster/slim + - VERSION=1.37.0 VARIANT=alpine3.10 +#VERSIONS install: - git clone https://github.com/docker-library/official-images.git ~/official-images diff --git a/1.37.0/alpine3.10/Dockerfile b/1.37.0/alpine3.10/Dockerfile new file mode 100644 index 0000000..5ea80f4 --- /dev/null +++ b/1.37.0/alpine3.10/Dockerfile @@ -0,0 +1,22 @@ +FROM alpine:3.10 + +RUN apk add --no-cache \ + ca-certificates \ + gcc + +ENV RUSTUP_HOME=/usr/local/rustup \ + CARGO_HOME=/usr/local/cargo \ + PATH=/usr/local/cargo/bin:$PATH \ + RUST_VERSION=1.37.0 + +RUN set -eux; \ + url="https://static.rust-lang.org/rustup/archive/1.19.0/x86_64-unknown-linux-musl/rustup-init"; \ + wget "$url"; \ + echo "b535be813cd89000044764806f569a8c1428417d4226f16ee9993867f0c4ea4e *rustup-init" | sha256sum -c -; \ + chmod +x rustup-init; \ + ./rustup-init -y --no-modify-path --default-toolchain $RUST_VERSION; \ + rm rustup-init; \ + chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \ + rustup --version; \ + cargo --version; \ + rustc --version; diff --git a/Dockerfile-alpine.template b/Dockerfile-alpine.template new file mode 100644 index 0000000..5bb3328 --- /dev/null +++ b/Dockerfile-alpine.template @@ -0,0 +1,22 @@ +FROM alpine:%%TAG%% + +RUN apk add --no-cache \ + ca-certificates \ + gcc + +ENV RUSTUP_HOME=/usr/local/rustup \ + CARGO_HOME=/usr/local/cargo \ + PATH=/usr/local/cargo/bin:$PATH \ + RUST_VERSION=%%RUST-VERSION%% + +RUN set -eux; \ + url="https://static.rust-lang.org/rustup/archive/%%RUSTUP-VERSION%%/x86_64-unknown-linux-musl/rustup-init"; \ + wget "$url"; \ + echo "%%RUSTUP-SHA256%% *rustup-init" | sha256sum -c -; \ + chmod +x rustup-init; \ + ./rustup-init -y --no-modify-path --default-toolchain $RUST_VERSION; \ + rm rustup-init; \ + chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \ + rustup --version; \ + cargo --version; \ + rustc --version; diff --git a/generate-stackbrew-library.sh b/generate-stackbrew-library.sh deleted file mode 100755 index 89b88b5..0000000 --- a/generate-stackbrew-library.sh +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env bash -set -Eeuo pipefail - -declare -A aliases=( - [1.37.0]='1 1.37 latest' -) - -defaultDebianSuite='buster' -declare -A debianSuites=( -) - -self="$(basename "$BASH_SOURCE")" -cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" - -source '.metadata-lib' - -versions=( */ ) -versions=( "${versions[@]%/}" ) - -# sort version numbers with highest first -IFS=$'\n'; versions=( $(echo "${versions[*]}" | sort -rV) ); unset IFS - -# get the most recent commit which modified any of "$@" -fileCommit() { - git log -1 --format='format:%H' HEAD -- "$@" -} - -# get the most recent commit which modified "$1/Dockerfile" or any file COPY'd from "$1/Dockerfile" -dirCommit() { - local dir="$1"; shift - ( - cd "$dir" - fileCommit \ - Dockerfile \ - $(git show HEAD:./Dockerfile | awk ' - toupper($1) == "COPY" { - for (i = 2; i < NF; i++) { - print $i - } - } - ') - ) -} - -cat <<-EOH -# this file is generated via https://github.com/rust-lang-nursery/docker-rust/blob/$(fileCommit "$self")/$self - -Maintainers: Steven Fackler (@sfackler) -GitRepo: https://github.com/rust-lang-nursery/docker-rust.git -EOH - -# prints "$2$1$3$1...$N" -join() { - local sep="$1"; shift - local out; printf -v out "${sep//%/%%}%s" "$@" - echo "${out#$sep}" -} - -for version in "${versions[@]}"; do - debianSuite="${debianSuites[$version]:-$defaultDebianSuite}" - - for v in \ - {stretch,buster}{,/slim} \ - ; do - dir="$version/$v" - variant="$(basename "$v")" - - if [ "$variant" = 'slim' ]; then - # convert "slim" into "slim-jessie" - # https://github.com/docker-library/ruby/pull/142#issuecomment-320012893 - variant="$variant-$(basename "$(dirname "$v")")" - fi - - [ -f "$dir/Dockerfile" ] || continue - - commit="$(dirCommit "$dir")" - - versionAliases=( - $version - ${aliases[$version]:-} - ) - - variantAliases=( "${versionAliases[@]/%/-$variant}" ) - case "$variant" in - *-"$debianSuite") # "slim-stretch", etc need slim - variantAliases+=( "${versionAliases[@]/%/-${variant%-$debianSuite}}" ) - ;; - esac - variantAliases=( "${variantAliases[@]//latest-/}" ) - - versionSuite="${debianSuites[$version]:-$defaultDebianSuite}" - - case "$v" in - *) variantArches="$(variantArches "$version" "$v")" ;; - esac - - if [ "$variant" = "$debianSuite" ]; then - variantAliases+=( "${versionAliases[@]}" ) - fi - - echo - cat <<-EOE - Tags: $(join ', ' "${variantAliases[@]}") - Architectures: $(join ', ' $variantArches) - GitCommit: $commit - Directory: $dir - EOE - done -done diff --git a/update.sh b/update.sh deleted file mode 100755 index 180129b..0000000 --- a/update.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env bash -set -Eeuo pipefail - -cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" - -source '.metadata-lib' - -versions=( "$@" ) -if [ ${#versions[@]} -eq 0 ]; then - versions=( */ ) -fi -versions=( "${versions[@]%/}" ) - -# see http://stackoverflow.com/a/2705678/433558 -sed_escape_rhs() { - echo "$@" | sed -e 's/[\/&]/\\&/g' | sed -e ':a;N;$!ba;s/\n/\\n/g' -} - -travisEnv= -for version in "${versions[@]}"; do - rustupVersion=$(rustupVersion "$version") - linuxArchCase='dpkgArch="$(dpkg --print-architecture)"; '$'\\\n' - linuxArchCase+=$' ''case "${dpkgArch##*-}" in '$'\\\n' - for dpkgArch in $(dpkgArches "$version"); do - rustArch="$(dpkgToRustArch "$version" "$dpkgArch")" - sha256="$(curl -fsSL "https://static.rust-lang.org/rustup/archive/${rustupVersion}/${rustArch}/rustup-init.sha256" | awk '{ print $1 }')" - linuxArchCase+=$' '"$dpkgArch) rustArch='$rustArch'; rustupSha256='$sha256' ;; "$'\\\n' - done - linuxArchCase+=$' ''*) echo >&2 "unsupported architecture: ${dpkgArch}"; exit 1 ;; '$'\\\n' - linuxArchCase+=$' ''esac' - - for variant in stretch buster; do - if [ -d "$version/$variant" ]; then - sed -r \ - -e 's!%%RUST-VERSION%%!'"$version"'!g' \ - -e 's!%%RUSTUP-VERSION%%!'"$rustupVersion"'!g' \ - -e 's!%%DEBIAN-SUITE%%!'"$variant"'!g' \ - -e 's!%%ARCH-CASE%%!'"$(sed_escape_rhs "$linuxArchCase")"'!g' \ - Dockerfile-debian.template > "$version/$variant/Dockerfile" - travisEnv='\n - VERSION='"$version VARIANT=$variant$travisEnv" - fi - - if [ -d "$version/$variant/slim" ]; then - sed -r \ - -e 's!%%RUST-VERSION%%!'"$version"'!g' \ - -e 's!%%RUSTUP-VERSION%%!'"$rustupVersion"'!g' \ - -e 's!%%DEBIAN-SUITE%%!'"$variant"'!g' \ - -e 's!%%ARCH-CASE%%!'"$(sed_escape_rhs "$linuxArchCase")"'!g' \ - Dockerfile-slim.template > "$version/$variant/slim/Dockerfile" - travisEnv='\n - VERSION='"$version VARIANT=$variant/slim$travisEnv" - fi - done -done - -travis="$(awk -v 'RS=\n\n' '$1 == "env:" { $0 = "env:'"$travisEnv"'" } { printf "%s%s", $0, RS }' .travis.yml)" -echo "$travis" > .travis.yml diff --git a/x.py b/x.py new file mode 100755 index 0000000..a365a7a --- /dev/null +++ b/x.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python3 + +from collections import namedtuple +from urllib import request +import os +import subprocess +import sys + +rust_version = "1.37.0" +rustup_version = "1.18.3" + +DebianArch = namedtuple("DebianArch", ["bashbrew", "dpkg", "rust"]) + +debian_arches = [ + DebianArch("amd64", "amd64", "x86_64-unknown-linux-gnu"), + DebianArch("arm32v7", "armhf", "armv7-unknown-linux-gnueabihf"), + DebianArch("arm64v8", "arm64", "aarch64-unknown-linux-gnu"), + DebianArch("i386", "i386", "i686-unknown-linux-gnu"), +] + +debian_variants = [ + "stretch", + "buster", +] + +default_debian_variant = "buster" + +alpine_versions = [ + "3.10", +] + +default_alpine_version = "3.10" + +def rustup_hash(arch, version=None): + if version is None: + version = rustup_version + url = f"https://static.rust-lang.org/rustup/archive/{version}/{arch}/rustup-init.sha256" + with request.urlopen(url) as f: + return f.read().decode('utf-8').split()[0] + +def read_file(file): + with open(file, "r") as f: + return f.read() + +def write_file(file, contents): + dir = os.path.dirname(file) + if dir and not os.path.exists(dir): + os.makedirs(dir) + with open(file, "w") as f: + f.write(contents) + +def update_debian(): + arch_case = 'dpkgArch="$(dpkg --print-architecture)"; \\\n' + arch_case += ' case "${dpkgArch##*-}" in \\\n' + for arch in debian_arches: + hash = rustup_hash(arch.rust) + arch_case += f" {arch.dpkg}) rustArch='{arch.rust}'; rustupSha256='{hash}' ;; \\\n" + arch_case += ' *) echo >&2 "unsupported architecture: ${dpkgArch}"; exit 1 ;; \\\n' + arch_case += ' esac' + + template = read_file("Dockerfile-debian.template") + slim_template = read_file("Dockerfile-slim.template") + + for variant in debian_variants: + rendered = template \ + .replace("%%RUST-VERSION%%", rust_version) \ + .replace("%%RUSTUP-VERSION%%", rustup_version) \ + .replace("%%DEBIAN-SUITE%%", variant) \ + .replace("%%ARCH-CASE%%", arch_case) + write_file(f"{rust_version}/{variant}/Dockerfile", rendered) + + rendered = slim_template \ + .replace("%%RUST-VERSION%%", rust_version) \ + .replace("%%RUSTUP-VERSION%%", rustup_version) \ + .replace("%%DEBIAN-SUITE%%", variant) \ + .replace("%%ARCH-CASE%%", arch_case) + write_file(f"{rust_version}/{variant}/slim/Dockerfile", rendered) + +def update_alpine(): + template = read_file("Dockerfile-alpine.template") + alpine_rustup_version = "1.19.0" + + for version in alpine_versions: + rendered = template \ + .replace("%%RUST-VERSION%%", rust_version) \ + .replace("%%RUSTUP-VERSION%%", alpine_rustup_version) \ + .replace("%%TAG%%", version) \ + .replace("%%RUSTUP-SHA256%%", rustup_hash("x86_64-unknown-linux-musl", alpine_rustup_version)) + write_file(f"{rust_version}/alpine{version}/Dockerfile", rendered) + +def update_travis(): + file = ".travis.yml" + config = read_file(file) + + versions = "" + for variant in debian_variants: + versions += f" - VERSION={rust_version} VARIANT={variant}\n" + versions += f" - VERSION={rust_version} VARIANT={variant}/slim\n" + + for version in alpine_versions: + versions += f" - VERSION={rust_version} VARIANT=alpine{version}\n" + + marker = "#VERSIONS\n" + split = config.split(marker) + rendered = split[0] + marker + versions + marker + split[2] + write_file(file, rendered) + +def file_commit(file): + return subprocess.run( + ["git", "log", "-1", "--format=%H", "HEAD", "--", file], + capture_output = True) \ + .stdout \ + .decode('utf-8') \ + .strip() + +def version_tags(): + parts = rust_version.split(".") + tags = [] + for i in range(len(parts)): + tags.append(".".join(parts[:i + 1])) + return tags + +def single_library(tags, architectures, dir): + return f""" +Tags: {", ".join(tags)} +Architectures: {", ".join(architectures)} +GitCommit: {file_commit(os.path.join(dir, "Dockerfile"))} +Directory: {dir} +""" + +def generate_stackbrew_library(): + commit = file_commit("x.py") + + library = f"""\ +# this file is generated via https://github.com/rust-lang-nursery/docker-rust/blob/{commit}/x.py + +Maintainers: Steven Fackler (@sfackler) +GitRepo: https://github.com/rust-lang-nursery/docker-rust.git +""" + + for variant in debian_variants: + tags = [] + for version_tag in version_tags(): + tags.append(f"{version_tag}-{variant}") + tags.append(variant) + if variant == default_debian_variant: + for version_tag in version_tags(): + tags.append(version_tag) + tags.append("latest") + + library += single_library( + tags, + map(lambda a: a.bashbrew, debian_arches), + os.path.join(rust_version, variant)) + + tags = [] + for version_tag in version_tags(): + tags.append(f"{version_tag}-slim-{variant}") + tags.append(f"slim-{variant}") + if variant == default_debian_variant: + for version_tag in version_tags(): + tags.append(f"{version_tag}-slim") + tags.append("slim") + + library += single_library( + tags, + map(lambda a: a.bashbrew, debian_arches), + os.path.join(rust_version, variant, "slim")) + + for version in alpine_versions: + tags = [] + for version_tag in version_tags(): + tags.append(f"{version_tag}-alpine{version}") + tags.append(f"alpine{version}") + if version == default_alpine_version: + for version_tag in version_tags(): + tags.append(f"{version_tag}-alpine") + tags.append("alpine") + + library += single_library( + tags, + ["amd64"], + os.path.join(rust_version, f"alpine{version}")) + + print(library) + +def usage(): + print(f"Usage: {sys.argv[0]} update|generate-stackbrew-library") + sys.exit(1) + +if __name__ == "__main__": + if len(sys.argv) != 2: + usage() + + task = sys.argv[1] + if task == "update": + update_debian() + update_alpine() + update_travis() + elif task == "generate-stackbrew-library": + generate_stackbrew_library() + else: + usage()