├── .github └── workflows │ └── build.yml ├── .gitignore ├── .travis.yml ├── .travis └── scan-container.sh ├── 1.0 ├── Dockerfile ├── root │ ├── opt │ │ └── app-root │ │ │ ├── .bashrc │ │ │ ├── .slynk.lisp │ │ │ ├── etc │ │ │ └── scl_enable │ │ │ ├── install.lisp │ │ │ └── quicklisp-mirror.patch │ └── usr │ │ └── bin │ │ └── cgroup-limits ├── s2i-lisp.json └── s2i │ └── bin │ ├── assemble │ ├── run │ └── usage ├── LICENSE ├── Makefile ├── README.md ├── hack ├── build.sh ├── common.mk ├── update-base.sh ├── update-quicklisp.sh └── update-sbcl.sh ├── lisp-image-streams.json ├── lisp-web-basic-s2i.json └── tekton └── s2i-lisp-task.yaml /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | # Controls when the action will run. 4 | on: 5 | # Triggers the workflow on push or pull request events but only for the master branch 6 | push: 7 | branches: [ master ] 8 | pull_request: 9 | branches: [ master ] 10 | 11 | # Allows you to run this workflow manually from the Actions tab 12 | workflow_dispatch: 13 | 14 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 15 | jobs: 16 | build: 17 | name: Build image 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@v2 21 | 22 | - name: Get quicklisp version 23 | id: date 24 | run: echo "::set-output name=date::$(date -d $(grep http://beta.quicklisp.org 1.0/root/opt/app-root/install.lisp | awk -F'/' '{ print $6 }') +%Y%m%d)" 25 | 26 | - name: Get short git commit hash 27 | id: hash 28 | run: echo "::set-output name=hash::${GITHUB_SHA::7}" 29 | 30 | - name: Get run number 31 | id: run 32 | run: echo "::set-output name=run::${GITHUB_RUN_NUMBER}" 33 | 34 | - name: Buildah Action 35 | id: build-image 36 | uses: redhat-actions/buildah-build@v2 37 | with: 38 | context: "1.0" 39 | image: lisp-10-ubi9 40 | tags: latest ${{ steps.hash.outputs.hash }} ${{ steps.date.outputs.date }} ${{ steps.date.outputs.date }}.${{ steps.run.outputs.run }} 41 | dockerfiles: | 42 | 1.0/Dockerfile 43 | build-args: | 44 | 45 | - name: Push To quay.io 46 | id: push-to-quay 47 | uses: redhat-actions/push-to-registry@v2 48 | with: 49 | image: ${{ steps.build-image.outputs.image }} 50 | tags: ${{ steps.build-image.outputs.tags }} 51 | registry: quay.io/containerlisp 52 | username: ${{ secrets.QUAY_USERNAME }} 53 | password: ${{ secrets.QUAY_PASSWORD }} 54 | 55 | - name: Print image url 56 | run: echo "Image pushed to ${{ steps.push-to-quay.outputs.registry-paths }}" 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | Dockerfile.version 3 | .travis/microscanner 4 | Dockerfile.scan 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | language: c 4 | 5 | env: 6 | global: 7 | - COMMIT=${TRAVIS_COMMIT::7} 8 | - DREPO=containerlisp/lisp-10-ubi9 9 | - QREPO=quay.io/containerlisp/lisp-10-ubi9 10 | - RLGL_POLICY=https://github.com/container-lisp/rlgl-policy.git 11 | 12 | services: 13 | - docker 14 | 15 | before_install: 16 | - make 17 | - travis_wait 59 sleep infinity & 18 | - # ./.travis/scan-container.sh 19 | 20 | script: 21 | - ls 22 | 23 | after_success: 24 | - if [ "$TRAVIS_BRANCH" == "master" ]; then 25 | echo Logging in, tagging and pushing; 26 | docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD" quay.io; 27 | QLTAG=$(date -d $(grep http://beta.quicklisp.org 1.0/root/opt/app-root/install.lisp | awk -F'/' '{ print $6 }') +%Y%m%d); 28 | # Push to Docker Hub 29 | docker tag $DREPO:latest $DREPO:$QLTAG; 30 | docker tag $DREPO:latest $DREPO:$QLTAG.$TRAVIS_BUILD_NUMBER; 31 | docker tag $DREPO:latest $DREPO:$COMMIT; 32 | docker push $DREPO:latest; 33 | docker push $DREPO:$QLTAG; 34 | docker push $DREPO:$QLTAG.$TRAVIS_BUILD_NUMBER; 35 | docker push $DREPO:$COMMIT; 36 | # Push to Quay 37 | docker tag $DREPO:latest $QREPO:$QLTAG; 38 | docker tag $DREPO:latest $QREPO:$QLTAG.$TRAVIS_BUILD_NUMBER; 39 | docker tag $DREPO:latest $QREPO:$COMMIT; 40 | docker push $QREPO:latest; 41 | docker push $QREPO:$QLTAG; 42 | docker push $QREPO:$QLTAG.$TRAVIS_BUILD_NUMBER; 43 | docker push $QREPO:$COMMIT; 44 | fi 45 | - echo All done. 46 | -------------------------------------------------------------------------------- /.travis/scan-container.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ----------------------------------------------------------------------------- 4 | # Copyright 2019, 2020 Anthony Green 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); you 7 | # may not use this file except in compliance with the License. You may 8 | # obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 | # implied. See the License for the specific language governing 16 | # permissions and limitations under the License. 17 | # 18 | # ----------------------------------------------------------------------------- 19 | # Scan our image, $REPO:latest, with multiple container scanners, 20 | # checking for known vulnerabilities. Use Red Light Green Light to 21 | # evaluate the scan results against the policy specified in git at 22 | # $RLGL_POLICY. See https://github.com/atgreen/red-light-green-light 23 | # for details. 24 | # ----------------------------------------------------------------------------- 25 | 26 | # Experiment by scanning an old container image... 27 | # REPO=containerlisp/lisp-10-ubi8:20190711.62 28 | # docker pull containerlisp/lisp-10-ubi8:20190711.62 29 | 30 | set -euo pipefail 31 | IFS=$'\n\t' 32 | 33 | set -x 34 | 35 | # ----------------------------------------------------------------------------- 36 | # Configure the rlgl cli. 37 | 38 | # Download and extract the client 39 | wget -qO - https://rl.gl/cli/rlgl-linux-amd64.tgz | \ 40 | tar --strip-components=2 -xvzf - ./rlgl/rlgl 41 | 42 | # Log into the server 43 | ./rlgl login --key=$RLGL_KEY https://rl.gl 44 | 45 | # Generate a player ID for use during report evaluation 46 | ID=$(./rlgl start) 47 | 48 | # Set the policy 49 | RLGL_POLICY=https://github.com/container-lisp/rlgl-policy.git 50 | 51 | # ----------------------------------------------------------------------------- 52 | # Use the Clair scanner... 53 | # ----------------------------------------------------------------------------- 54 | 55 | # travis-ci comes with postgresql on, which clashes with the postgresql we're 56 | # about to fire up. 57 | sudo apt-get --yes remove postgresql\* > /dev/null 2>&1 58 | docker run -d --name db arminc/clair-db 59 | sleep 15 # wait for db to come up 60 | docker run -p 6060:6060 --link db:postgres -d --name clair arminc/clair-local-scan 61 | sleep 1 62 | DOCKER_GATEWAY=$(docker network inspect bridge --format "{{range .IPAM.Config}}{{.Gateway}}{{end}}") 63 | 64 | wget -qO clair-scanner https://github.com/arminc/clair-scanner/releases/download/v12/clair-scanner_linux_amd64 65 | ls -l 66 | chmod +x clair-scanner 67 | 68 | ./clair-scanner --ip="$DOCKER_GATEWAY" -r clair-report.json $REPO 69 | ./rlgl e --id=$ID --policy=$RLGL_POLICY clair-report.json 70 | 71 | # ----------------------------------------------------------------------------- 72 | # Use Anchore's inline scanner... 73 | # ----------------------------------------------------------------------------- 74 | 75 | curl -s https://ci-tools.anchore.io/inline_scan-v0.4.1 | bash -s -- -t 3300 -r $REPO 76 | ls -lRt 77 | if test -f anchore-reports/*-vuln.json; then 78 | ./rlgl e --id=$ID --policy=$RLGL_POLICY anchore-reports/*-vuln.json 79 | fi 80 | 81 | # ----------------------------------------------------------------------------- 82 | # Use Aqua Security's microscanner... 83 | # ----------------------------------------------------------------------------- 84 | 85 | if [[ -z "${AQUACODE}" ]]; then 86 | echo "Skipping AquaSecurity Scan. Missing AQUACODE environment variable." 87 | else 88 | if ! test -f microscanner; then 89 | wget https://get.aquasec.com/microscanner 90 | chmod +x microscanner 91 | fi 92 | 93 | cat > Dockerfile.scan <= $PHYSICAL_MEMORY_LIMIT_IN_BYTES)); then 28 | MEMORY_LIMIT_IN_BYTES=$PHYSICAL_MEMORY_LIMIT_IN_BYTES 29 | fi 30 | else 31 | export MEMORY_LIMIT_IN_BYTES=$PHYSICAL_MEMORY_LIMIT_IN_BYTES 32 | fi 33 | # Set a memory limit in MB 34 | export MEMORY_LIMIT=$((MEMORY_LIMIT_IN_BYTES/1024/1024)) 35 | 36 | # CPU Count 37 | export CPU_CORES=$(grep -c ^processor /proc/cpuinfo) 38 | -------------------------------------------------------------------------------- /1.0/s2i-lisp.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "List", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "name": "s2i-lisp" 6 | }, 7 | "items": [ 8 | { 9 | "kind": "BuildConfig", 10 | "apiVersion": "v1", 11 | "metadata":{ 12 | "name": "lisp-ubi9-build" 13 | }, 14 | "spec": { 15 | "triggers": [ 16 | { 17 | "type": "GitHub", 18 | "github": { 19 | "secret": "secret101" 20 | } 21 | }, 22 | { 23 | "type": "ImageChange", 24 | "imageChange": {} 25 | } 26 | ], 27 | "source" : { 28 | "type" : "Git", 29 | "git" : { 30 | "uri": "git://github.com/container-lisp/s2i-lisp.git" 31 | }, 32 | "contextDir": "1.0" 33 | }, 34 | "strategy": { 35 | "type": "Docker", 36 | "dockerStrategy": { 37 | "env": [ 38 | { 39 | "name": "IMAGE_NAME", 40 | "value": "openshift/lisp-ubi9" 41 | }], 42 | "from": { 43 | "kind": "ImageStreamTag", 44 | "name": "swarm-ubi9:latest" 45 | } 46 | } 47 | }, 48 | "output": { 49 | "to": { 50 | "kind": "ImageStreamTag", 51 | "name": "lisp-ubi9:latest" 52 | } 53 | } 54 | } 55 | }, 56 | { 57 | "kind": "ImageStream", 58 | "apiVersion": "v1", 59 | "metadata": { 60 | "name": "lisp-ubi9" 61 | }, 62 | "spec": { 63 | "dockerImageRepository": "", 64 | "tags": [ 65 | { 66 | "name": "latest", 67 | "annotations": { 68 | "description": "Common Lisp S2I image", 69 | "iconClass": "icon-lisp", 70 | "tags": "builder,lisp", 71 | "supports": "lisp:1", 72 | "version": "1.0" 73 | } 74 | } 75 | ] 76 | } 77 | } 78 | ] 79 | } 80 | -------------------------------------------------------------------------------- /1.0/s2i/bin/assemble: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | source cgroup-limits 6 | 7 | DYNAMIC_SPACE_SIZE=${APP_MEM-$((MEMORY_LIMIT * 90 / 100))} 8 | 9 | SBCL_OPTS=( 10 | --dynamic-space-size "${DYNAMIC_SPACE_SIZE}" 11 | --disable-debugger 12 | ) 13 | 14 | echo "---> Installing application source ..." 15 | whoami 16 | PROJECT_PATH=./quicklisp/local-projects/${APP_SYSTEM_NAME} 17 | 18 | mkdir -vp "${PROJECT_PATH}" 19 | cp -Rf /tmp/src/. "${PROJECT_PATH}" 20 | 21 | # Move local projects into the quicklisp local-projects dir 22 | find "${PROJECT_PATH}" 23 | if [ -d "${PROJECT_PATH}/local-projects" ]; then 24 | if ! [ -z "$(ls -A ${PROJECT_PATH}/local-projects)" ]; then 25 | echo " > setting up local projects $(ls -A ${PROJECT_PATH}/local-projects)" 26 | mv ${PROJECT_PATH}/local-projects/* ./quicklisp/local-projects 27 | else 28 | echo " > no local projects" 29 | fi 30 | else 31 | echo " > no local-projects dir" 32 | fi 33 | 34 | echo "---> Building your Common Lisp application from source ..." 35 | if [ -n "${APP_BUILD_SCRIPT}" ]; then 36 | SBCL_OPTS=( 37 | "${SBCL_OPTS[@]}" 38 | --load "${PROJECT_PATH}/$(eval echo ${APP_BUILD_SCRIPT})" 39 | ) 40 | else 41 | SBCL_OPTS=( 42 | "${SBCL_OPTS[@]}" 43 | --eval "(ql:quickload :$(eval echo ${APP_SYSTEM_NAME}))" 44 | --eval "(quit)" 45 | ) 46 | fi 47 | 48 | echo sbcl "${SBCL_OPTS[@]}" 49 | sbcl "${SBCL_OPTS[@]}" 50 | 51 | chown -R 1001 ./quicklisp 52 | find /opt/app-root/.cache/common-lisp/ -type d | xargs -n1 chmod 775 53 | -------------------------------------------------------------------------------- /1.0/s2i/bin/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source cgroup-limits 4 | 5 | DYNAMIC_SPACE_SIZE=${APP_MEM-$((MEMORY_LIMIT * 90 / 100))} 6 | 7 | if [ -n "$APP_SCRIPT" ]; then 8 | PROJECT_PATH=./quicklisp/local-projects/${APP_SYSTEM_NAME} 9 | SBCL_OPTS=( 10 | "${SBCL_OPTS[@]}" 11 | --dynamic-space-size "${DYNAMIC_SPACE_SIZE}" 12 | --lose-on-corruption 13 | --disable-debugger 14 | --load "${PROJECT_PATH}/$(eval echo ${APP_SCRIPT})" 15 | ) 16 | else 17 | SBCL_OPTS=( 18 | "${SBCL_OPTS[@]}" 19 | --dynamic-space-size "${DYNAMIC_SPACE_SIZE}" 20 | --lose-on-corruption 21 | --disable-debugger 22 | --eval "(ql:quickload :$(eval echo ${APP_SYSTEM_NAME}))" 23 | --eval "$(eval echo ${APP_EVAL})" 24 | ) 25 | fi 26 | 27 | 28 | trap 'kill -TERM $PID' TERM 29 | sbcl "${SBCL_OPTS[@]}" & 30 | PID=$! 31 | wait $PID 32 | trap - TERM 33 | wait $PID 34 | exit $? 35 | -------------------------------------------------------------------------------- /1.0/s2i/bin/usage: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | DISTRO=`cat /etc/*-release | grep ^ID= | grep -Po '".*?"' | tr -d '"'` 4 | 5 | cat <> "${dockerfile}.version" 39 | if [[ "${UPDATE_BASE}" == "1" ]]; then 40 | BUILD_OPTIONS+=" --pull=true" 41 | fi 42 | docker build ${BUILD_OPTIONS} -t ${IMAGE_NAME} -f "${dockerfile}.version" . 43 | if [[ "${SKIP_SQUASH}" != "1" ]]; then 44 | squash "${dockerfile}.version" 45 | fi 46 | rm -f "${DOCKERFILE_PATH}.version" 47 | } 48 | 49 | # Install the docker squashing tool[1] and squash the result image 50 | # [1] https://github.com/goldmann/docker-squash 51 | function squash { 52 | # FIXME: We have to use the exact versions here to avoid Docker client 53 | # compatibility issues 54 | easy_install -q --user docker_py==1.7.2 docker-squash==1.0.1 55 | base=$(awk '/^FROM/{print $2}' $1) 56 | ${HOME}/.local/bin/docker-squash -f $base ${IMAGE_NAME} 57 | } 58 | 59 | # Versions are stored in subdirectories. You can specify VERSION variable 60 | # to build just one single version. By default we build all versions 61 | dirs=${VERSION:-$VERSIONS} 62 | 63 | for dir in ${dirs}; do 64 | case " $OPENSHIFT_NAMESPACES " in 65 | *\ ${dir}\ *) ;; 66 | *) NAMESPACE="containerlisp/" 67 | esac 68 | 69 | IMAGE_NAME="${NAMESPACE}${BASE_IMAGE_NAME}-${dir//./}-${OS}" 70 | 71 | if [[ -v TEST_MODE ]]; then 72 | IMAGE_NAME+="-candidate" 73 | fi 74 | 75 | echo "-> Building ${IMAGE_NAME} ..." 76 | 77 | pushd ${dir} > /dev/null 78 | docker_build_with_version Dockerfile 79 | 80 | if [[ -v TEST_MODE ]]; then 81 | IMAGE_NAME=${IMAGE_NAME} test/run 82 | 83 | if [[ $? -eq 0 ]] && [[ "${TAG_ON_SUCCESS}" == "true" ]]; then 84 | echo "-> Re-tagging ${IMAGE_NAME} image to ${IMAGE_NAME%"-candidate"}" 85 | docker tag -f $IMAGE_NAME ${IMAGE_NAME%"-candidate"} 86 | fi 87 | fi 88 | 89 | popd > /dev/null 90 | done 91 | -------------------------------------------------------------------------------- /hack/common.mk: -------------------------------------------------------------------------------- 1 | SKIP_SQUASH?=1 2 | 3 | build = hack/build.sh 4 | 5 | OS = ubi9 6 | 7 | script_env = \ 8 | SKIP_SQUASH=$(SKIP_SQUASH) \ 9 | UPDATE_BASE=$(UPDATE_BASE) \ 10 | VERSIONS="$(VERSIONS)" \ 11 | OS=$(OS) \ 12 | VERSION=$(VERSION) \ 13 | BASE_IMAGE_NAME=$(BASE_IMAGE_NAME) \ 14 | OPENSHIFT_NAMESPACES="$(OPENSHIFT_NAMESPACES)" 15 | 16 | .PHONY: build 17 | build: 18 | $(script_env) $(build) 19 | 20 | .PHONY: test 21 | test: 22 | $(script_env) TAG_ON_SUCCESS=$(TAG_ON_SUCCESS) TEST_MODE=true $(build) 23 | -------------------------------------------------------------------------------- /hack/update-base.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -x 3 | # Update the LISP_BASE_BUILD_DATE environment variable in order to 4 | # trigger a rebuild of the image. Trigger this when there are CVE 5 | # errata from the base OS image to be applied. 6 | 7 | die() { 8 | echo "$@" 9 | exit 1 10 | } 11 | 12 | which grype &>/dev/null || die "This script requires grype." 13 | 14 | echo "Scanning latest image for fixed vulnerabilities..." 15 | podman rmi quay.io/containerlisp/lisp-10-ubi9:latest > /dev/null 16 | VULNS=$(grype -q -o table --only-fixed quay.io/containerlisp/lisp-10-ubi9:latest | grep -i rpm | grep -v suppressed | awk '{printf("%25s\t%s\n", $1, $5)}') 17 | 18 | if ! test -z "$VULNS"; then 19 | LISP_BASE_BUILD_DATE=$(date) 20 | sed -i "s/LISP_BASE_BUILD_DATE=.*/LISP_BASE_BUILD_DATE=\"$LISP_BASE_BUILD_DATE\"/g" ../1.0/Dockerfile 21 | echo "Adding git commit" 22 | git add ../1.0/Dockerfile && git commit -m "Fix vulnerabilities in the base image. 23 | 24 | $VULNS" 25 | else 26 | echo "Nothing to do" 27 | fi 28 | -------------------------------------------------------------------------------- /hack/update-quicklisp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Update URL to point to the up-to-date quicklisp dist in the 4 | # install.lisp file and commit the changes to the repository. This 5 | # script checks the quicklisp website to fetch the latest quicklisp 6 | # dist URL. 7 | 8 | INSTALL=../1.0/root/opt/app-root/install.lisp 9 | QL="http://beta.quicklisp.org/dist/quicklisp.txt" 10 | 11 | die() { 12 | echo "$@" 13 | exit 1 14 | } 15 | 16 | which wget &>/dev/null || die "This script requires wget." 17 | 18 | [ -f "$INSTALL" ] || die "File $INSTALL does not exist." 19 | 20 | URL_OLD=$(grep "defvar \*dist-url\*" "$INSTALL" | \ 21 | perl -n -e 'm!(https?://.*/distinfo.txt)!; print "$1"') 22 | [ -n "$URL_OLD" ] || die "Could not determine current ql-dist version in ${INSTALL}!" 23 | 24 | URL_NEW=$(wget -O - -q "$QL" | grep ^canonical-distinfo-url: | awk '{print $2}') 25 | [ -n "$URL_NEW" ] || die "Could not determine up-to-date quicklisp dist from ${QL}!" 26 | 27 | VERSION=$(echo "$URL_NEW" | perl -ne 'm/(\d{4}-\d{2}-\d{2})/; print "$1"') 28 | [ -n "$VERSION" ] || die "Could not determine version string from URL ${URL_NEW}!" 29 | 30 | if [ "$URL_OLD" == "$URL_NEW" ]; then 31 | echo "Quicklisp dist is up-to-date ($URL_NEW)." 32 | exit 0 33 | fi 34 | 35 | echo "Replacing $URL_OLD with $URL_NEW in $INSTALL..." 36 | sed -i -e "s!${URL_OLD}!${URL_NEW}!" "$INSTALL" || \ 37 | die "Error updating quicklisp dist URL." 38 | 39 | git add "$INSTALL" && git commit -m "Bump quicklisp dist version to $VERSION" 40 | -------------------------------------------------------------------------------- /hack/update-sbcl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Find up-to-date SBCL version for x86-64 linux on sbcl.org and update 4 | # Dockerfiles if necessary. It will check for the existence of the new 5 | # remote file and add a git commit. Run the script from the path it 6 | # resides in, or change FILES appropriately. 7 | 8 | die() { 9 | echo "$@" 10 | exit 1 11 | } 12 | 13 | FILES=( ../1.0/Dockerfile ) 14 | 15 | which wget &>/dev/null || die "This script requires wget." 16 | 17 | V_NEW=$(wget -q -O - "http://sbcl.org/platform-table.html" | \ 18 | grep "tar.bz2?download" | head -1 | \ 19 | perl -n -e 'm/sbcl-(\d+\.\d+\.\d+)-source.tar.bz2/; print "$1"' ) 20 | [ -n "$V_NEW" ] || die "Could not find new sbcl version on sbcl.org." 21 | 22 | CHANGED=n 23 | 24 | update_file() { 25 | local file="$1" 26 | local v_old=$(grep SBCL_VERSION= "$file" | \ 27 | perl -n -e 'm/=(\d+\.\d+\.\d+)/; print "$1"') 28 | [ -n "$v_old" ] || die "Could not find old sbcl version in $file!" 29 | 30 | if [ "$v_old" == "$V_NEW" ]; then 31 | echo "SBCL as specified in $file is already up-to-date." 32 | return 0 33 | fi 34 | CHANGED=y 35 | 36 | echo "Updating SBCL_VERSION in $file from $v_old to $V_NEW" 37 | sed -i -e "s/SBCL_VERSION=$v_old/SBCL_VERSION=$V_NEW/g" "$file" || \ 38 | die "Error replacing version strings, please check manually!" 39 | 40 | DL_LINK=$(grep --only-matching "https://.*/sbcl-.*.tar.bz2" "$file" | \ 41 | sed -e "s/\${SBCL_VERSION}/$V_NEW/g") 42 | echo "Checking for remote file existence at $DL_LINK..." 43 | wget -nv --method HEAD "$DL_LINK" || die "Failed to confirm remote file existence." 44 | } 45 | 46 | for f in "${FILES[@]}"; do 47 | echo "Updating file $f" 48 | update_file "$f" 49 | done 50 | 51 | if [ $CHANGED == y ]; then 52 | echo "Adding git commit" 53 | git add "${FILES[@]}" && git commit -m "Update SBCL to $V_NEW" 54 | else 55 | echo "All files already up-to-date." 56 | fi 57 | -------------------------------------------------------------------------------- /lisp-image-streams.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "List", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "name": "lisp-image-streams", 6 | "annotations": { 7 | "description": "ImageStream definitions for Commons Lisp app foundations.", 8 | "openshift.io/provider-display-name": "The container-lisp hackers" 9 | } 10 | }, 11 | "items": [ 12 | { 13 | "kind": "ImageStream", 14 | "apiVersion": "v1", 15 | "metadata": { 16 | "name": "s2i-lisp", 17 | "annotations": { 18 | "openshift.io/display-name": "SBCL", 19 | "openshift.io/provider-display-name": "The container-lisp hackers" 20 | } 21 | }, 22 | "spec": { 23 | "tags": [ 24 | { 25 | "name": "latest", 26 | "annotations": { 27 | "openshift.io/display-name": "SBCL", 28 | "description": "Build and run Common Lisp applications using Quicklisp and SBCL.", 29 | "iconClass": "icon-rh-openjdk", 30 | "tags": "builder,lisp,commonlisp,hidden", 31 | "supports": "commonlisp", 32 | "sampleRepo": "https://github.com/container-lisp/sample-lisp-app", 33 | "sampleContextDir": "", 34 | "version": "latest" 35 | }, 36 | "from": { 37 | "kind": "DockerImage", 38 | "name": "containerlisp/s2i-lisp" 39 | } 40 | } 41 | ] 42 | } 43 | } 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /lisp-web-basic-s2i.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "Template", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "annotations": { 6 | "iconClass": "icon-rh-openjdk", 7 | "tags": "lisp", 8 | "version": "1.0.0", 9 | "openshift.io/display-name": "Lisp", 10 | "openshift.io/provider-display-name": "The container-lisp hackers", 11 | "description": "An example Lisp web application using SBCL.", 12 | "template.openshift.io/long-description": "This template defines resources needed to develop Common Lisp based web applications." 13 | }, 14 | "name": "lisp-web-basic-s2i" 15 | }, 16 | "labels": { 17 | "template": "lisp-web-basic-s2i" 18 | }, 19 | "message": "A new Common Lisp application has been created in your project. A [slynk](https://github.com/joaotavora/sly) server will start on port 4005 of this container. You can forward port 4005 to your local host and connect to it with [SLY](https://github.com/joaotavora/sly) for interactive [Emacs](https://www.gnu.org/software/emacs/) based development. Just identify the pod running your container with `oc get pods`, and then....```oc port-forward sample-lisp-app-1-h5o5f 4005``` Follow this up in Emacs with... ```M-x sly-connect RET RET``` To teach Emacs how to translate filenames between the remote and local machines, you'll need to define [```sly-filename-translations```](http://joaotavora.github.io/sly/#Setting-up-pathname-translations).", 20 | "parameters": [ 21 | { 22 | "description": "The name for the application.", 23 | "displayName": "Application Name", 24 | "name": "APPLICATION_NAME", 25 | "value": "lisp-app", 26 | "required": true 27 | }, 28 | { 29 | "description": "Custom hostname for http service route. Leave blank for default hostname, e.g.: -.", 30 | "displayName": "Custom http Route Hostname", 31 | "name": "HOSTNAME_HTTP", 32 | "value": "", 33 | "required": false 34 | }, 35 | { 36 | "description": "Git source URI for application", 37 | "displayName": "Git Repository URL", 38 | "name": "SOURCE_REPOSITORY_URL", 39 | "value": "https://github.com/container-lisp/sample-lisp-app", 40 | "required": true 41 | }, 42 | { 43 | "description": "Git branch/tag reference", 44 | "displayName": "Git Reference", 45 | "name": "SOURCE_REPOSITORY_REF", 46 | "value": "master", 47 | "required": false 48 | }, 49 | { 50 | "description": "Path within Git project to build; empty for root project directory.", 51 | "displayName": "Context Directory", 52 | "name": "CONTEXT_DIR", 53 | "value": "", 54 | "required": false 55 | }, 56 | { 57 | "description": "GitHub trigger secret", 58 | "displayName": "Github Webhook Secret", 59 | "name": "GITHUB_WEBHOOK_SECRET", 60 | "from": "[a-zA-Z0-9]{8}", 61 | "generate": "expression", 62 | "required": true 63 | }, 64 | { 65 | "description": "Generic build trigger secret", 66 | "displayName": "Generic Webhook Secret", 67 | "name": "GENERIC_WEBHOOK_SECRET", 68 | "from": "[a-zA-Z0-9]{8}", 69 | "generate": "expression", 70 | "required": true 71 | }, 72 | { 73 | "description": "Namespace in which the ImageStreams for Lisp images are installed. These ImageStreams are normally installed in the openshift namespace. You should only need to modify this if you've installed the ImageStreams in a different namespace/project.", 74 | "displayName": "ImageStream Namespace", 75 | "name": "IMAGE_STREAM_NAMESPACE", 76 | "value": "openshift", 77 | "required": true 78 | } 79 | ], 80 | "objects": [ 81 | { 82 | "kind": "Service", 83 | "apiVersion": "v1", 84 | "spec": { 85 | "ports": [ 86 | { 87 | "port": 8080, 88 | "targetPort": 8080 89 | } 90 | ], 91 | "selector": { 92 | "deploymentConfig": "${APPLICATION_NAME}" 93 | } 94 | }, 95 | "metadata": { 96 | "name": "${APPLICATION_NAME}", 97 | "labels": { 98 | "application": "${APPLICATION_NAME}" 99 | }, 100 | "annotations": { 101 | "description": "The application's http port." 102 | } 103 | } 104 | }, 105 | { 106 | "kind": "Route", 107 | "apiVersion": "v1", 108 | "id": "${APPLICATION_NAME}-http", 109 | "metadata": { 110 | "name": "${APPLICATION_NAME}", 111 | "labels": { 112 | "application": "${APPLICATION_NAME}" 113 | }, 114 | "annotations": { 115 | "description": "Route for application's http service." 116 | } 117 | }, 118 | "spec": { 119 | "host": "${HOSTNAME_HTTP}", 120 | "to": { 121 | "name": "${APPLICATION_NAME}" 122 | } 123 | } 124 | }, 125 | { 126 | "kind": "ImageStream", 127 | "apiVersion": "v1", 128 | "metadata": { 129 | "name": "${APPLICATION_NAME}", 130 | "labels": { 131 | "application": "${APPLICATION_NAME}" 132 | } 133 | } 134 | }, 135 | { 136 | "kind": "BuildConfig", 137 | "apiVersion": "v1", 138 | "metadata": { 139 | "name": "${APPLICATION_NAME}", 140 | "labels": { 141 | "application": "${APPLICATION_NAME}" 142 | } 143 | }, 144 | "spec": { 145 | "source": { 146 | "type": "Git", 147 | "git": { 148 | "uri": "${SOURCE_REPOSITORY_URL}", 149 | "ref": "${SOURCE_REPOSITORY_REF}" 150 | }, 151 | "contextDir": "${CONTEXT_DIR}" 152 | }, 153 | "strategy": { 154 | "type": "Source", 155 | "sourceStrategy": { 156 | "forcePull": true, 157 | "from": { 158 | "kind": "ImageStreamTag", 159 | "namespace": "${IMAGE_STREAM_NAMESPACE}", 160 | "name": "s2i-lisp:latest" 161 | } 162 | } 163 | }, 164 | "output": { 165 | "to": { 166 | "kind": "ImageStreamTag", 167 | "name": "${APPLICATION_NAME}:latest" 168 | } 169 | }, 170 | "triggers": [ 171 | { 172 | "type": "GitHub", 173 | "github": { 174 | "secret": "${GITHUB_WEBHOOK_SECRET}" 175 | } 176 | }, 177 | { 178 | "type": "Generic", 179 | "generic": { 180 | "secret": "${GENERIC_WEBHOOK_SECRET}" 181 | } 182 | }, 183 | { 184 | "type": "ImageChange", 185 | "imageChange": {} 186 | }, 187 | { 188 | "type": "ConfigChange" 189 | } 190 | ] 191 | } 192 | }, 193 | { 194 | "kind": "DeploymentConfig", 195 | "apiVersion": "v1", 196 | "metadata": { 197 | "name": "${APPLICATION_NAME}", 198 | "labels": { 199 | "application": "${APPLICATION_NAME}" 200 | } 201 | }, 202 | "spec": { 203 | "strategy": { 204 | "type": "Recreate" 205 | }, 206 | "triggers": [ 207 | { 208 | "type": "ImageChange", 209 | "imageChangeParams": { 210 | "automatic": true, 211 | "containerNames": [ 212 | "${APPLICATION_NAME}" 213 | ], 214 | "from": { 215 | "kind": "ImageStreamTag", 216 | "name": "${APPLICATION_NAME}:latest" 217 | } 218 | } 219 | }, 220 | { 221 | "type": "ConfigChange" 222 | } 223 | ], 224 | "replicas": 1, 225 | "selector": { 226 | "deploymentConfig": "${APPLICATION_NAME}" 227 | }, 228 | "template": { 229 | "metadata": { 230 | "name": "${APPLICATION_NAME}", 231 | "labels": { 232 | "deploymentConfig": "${APPLICATION_NAME}", 233 | "application": "${APPLICATION_NAME}" 234 | } 235 | }, 236 | "spec": { 237 | "terminationGracePeriodSeconds": 75, 238 | "containers": [ 239 | { 240 | "name": "${APPLICATION_NAME}", 241 | "image": "${APPLICATION_NAME}", 242 | "imagePullPolicy": "Always", 243 | "env": [ 244 | ], 245 | "ports": [ 246 | { 247 | "name": "http", 248 | "containerPort": 8080, 249 | "protocol": "TCP" 250 | } 251 | ] 252 | } 253 | ] 254 | } 255 | } 256 | } 257 | } 258 | ] 259 | } 260 | -------------------------------------------------------------------------------- /tekton/s2i-lisp-task.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1alpha1 2 | kind: Task 3 | metadata: 4 | name: s2i-lisp 5 | spec: 6 | inputs: 7 | resources: 8 | - name: source 9 | type: git 10 | params: 11 | - name: PATH_CONTEXT 12 | description: The location of the path to run s2i from. 13 | default: . 14 | - name: TLSVERIFY 15 | description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS registry) 16 | default: "true" 17 | outputs: 18 | resources: 19 | - name: image 20 | type: image 21 | steps: 22 | - name: generate 23 | image: quay.io/openshift-pipeline/s2i 24 | workingdir: /workspace/source 25 | command: ['s2i', 'build', '$(inputs.params.PATH_CONTEXT)', 'quay.io/containerlisp/lisp-10-ubi9', '--as-dockerfile', '/gen-source/Dockerfile.gen'] 26 | volumeMounts: 27 | - name: gen-source 28 | mountPath: /gen-source 29 | resources: 30 | limits: 31 | cpu: 500m 32 | memory: 1Gi 33 | requests: 34 | cpu: 500m 35 | memory: 1Gi 36 | - name: build 37 | image: quay.io/buildah/stable 38 | workingdir: /gen-source 39 | command: ['buildah', 'bud', '--tls-verify=$(inputs.params.TLSVERIFY)', '--layers', '-f', '/gen-source/Dockerfile.gen', '-t', '$(outputs.resources.image.url)', '.'] 40 | volumeMounts: 41 | - name: varlibcontainers 42 | mountPath: /var/lib/containers 43 | - name: gen-source 44 | mountPath: /gen-source 45 | resources: 46 | limits: 47 | cpu: 500m 48 | memory: 1Gi 49 | requests: 50 | cpu: 500m 51 | memory: 1Gi 52 | securityContext: 53 | privileged: true 54 | - name: push 55 | image: quay.io/buildah/stable 56 | command: ['buildah', 'push', '--tls-verify=$(inputs.params.TLSVERIFY)', '$(outputs.resources.image.url)', 'docker://$(outputs.resources.image.url)'] 57 | volumeMounts: 58 | - name: varlibcontainers 59 | mountPath: /var/lib/containers 60 | resources: 61 | limits: 62 | cpu: 500m 63 | memory: 1Gi 64 | requests: 65 | cpu: 500m 66 | memory: 1Gi 67 | securityContext: 68 | privileged: true 69 | volumes: 70 | - name: varlibcontainers 71 | emptyDir: {} 72 | - name: gen-source 73 | emptyDir: {} 74 | --------------------------------------------------------------------------------