From 2e49103399b65beb04fce6ff05bee0f0f9df64df Mon Sep 17 00:00:00 2001 From: Benedikt Kristinsson Date: Mon, 1 Mar 2021 16:13:53 +0100 Subject: [PATCH 1/3] accept a paremeter for build mode (and parameterized cron job to run both options), one to build the latest version from the master branch and one that check out the most recent tag/release and builds that. can also accept the name of a tag to build. reads the version number from configure.ac. --- Jenkinsfile | 125 +++++++++++++++++++++++++++++++++------------- README.md | 13 +++-- debian/Dockerfile | 52 +++++++++++-------- debian/package.sh | 30 ++++++++--- 4 files changed, 153 insertions(+), 67 deletions(-) mode change 100644 => 100755 debian/package.sh diff --git a/Jenkinsfile b/Jenkinsfile index 55c0225..595f1e9 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,12 +1,32 @@ def version = "" -def amzn_prefix = "/home/bkristinsson/.local" +def debname = "emacs" +def amzn_prefix = "/home/benedikt.kristinsson/.local" def timer = currentBuild.getBuildCauses()[0]["shortDescription"].matches("Started by timer") def skip_build = false +def docker_tag = "latest" + +def get_version() { + return sh( + script: "grep AC_INIT configure.ac | awk -F',' '{print \$2}'", + returnStdout: true + ).trim() +} + + +def build_exists(String version) { + return fileExists( + "${env.JENKINS_HOME}/artifacts/emacs_${version}.deb" + ) +} pipeline { agent any + parameters { + string(name: 'build_mode', defaultValue: 'master') + } triggers { - cron('@daily') + parameterizedCron('''@daily%%build_mode=master + @daily%%build_mode=stable''') } options { timestamps() @@ -56,42 +76,56 @@ pipeline { // to get the latest minor relase instead, // check out the emacs-$MAJOR branch (not tag) + def latest_tag = sh( - script: 'git describe --tags --abbrev=0', + script: "git for-each-ref --sort=-creatordate --format='%(refname:lstrip=2)' 'refs/tags/emacs-*' --count 1", returnStdout: true ) - version = latest_tag.split('-')[1].trim() - - sh "git checkout refs/tags/${latest_tag}" - sh "git --no-pager show --oneline -s" - - def build_exists = fileExists( - "${env.JENKINS_HOME}/artifacts/emacs-${version}.tar.gz" - ) - skip_build = (timer && build_exists) - echo "latest tag reachable from master: ${latest_tag}" - echo "build for ${version} exists: ${build_exists}" - echo "started by timer: ${timer}" - echo "skip building: ${skip_build}" + + if (params.build_mode == "master") { + debname = "emacs-nightly" + docker_tag = "latest" + // no `git checkout`, jenkins has already + // checked out master from origin. + } + else if (params.build_mode == "stable") { + def ref = "refs/tags/" + latest_tag + sh "git checkout -f ${ref}" + + debname = "emacs" + docker_tag = "stable" + } + else if (params.build_mode.startsWith("emacs-")) { + def ref = "refs/tags/" + params.build_mode + sh "git checkout -f ${ref}" + + debname = "emacs" + docker_tag = version + } + else { + error("unkonwn build_mode param") + } + + version = get_version() + currentBuild.displayName += " - ${debname} v${version}" + currentBuild.description = params.build_mode + echo "version: ${version}" + + if (timer && build_exists(version)) { + echo "build for ${version} exists" + echo "skipping building steps" + skip_build = true + } } } } } - stage('amzn') { - when { expression { skip_build == false } } - steps { - sh "docker build -f amzn/Dockerfile --build-arg PREFIX=${amzn_prefix} --build-arg VERSION=${version} -t emacs-amzn:${version}-amzn ." - sh "docker container create --name emacs_amzn_builder emacs-amzn:${version}-amzn " - sh "docker container cp emacs_amzn_builder:/emacs/amzn/ dist/" - } - } - stage ('deb: build emacs') { when { expression { skip_build == false } } steps { - sh "docker build -f debian/Dockerfile --build-arg PREFIX=/emacs/target --build-arg VERSION=${version} --target builder -t benediktkr/emacs:builder-${version} ." + sh "docker build --pull -f debian/Dockerfile --build-arg VERSION=${version} --build-arg DEBNAME=${debname} --target builder -t benediktkr/emacs:builder-${version} ." sh "docker container create --name emacs_debian_builder benediktkr/emacs:builder-${version}" dir('dist/') { @@ -102,30 +136,51 @@ pipeline { stage('deb: container') { when { expression { skip_build == false } } steps { - sh "docker build -f debian/Dockerfile -t benediktkr/emacs:${version} ." + sh "docker build --pull -f debian/Dockerfile --build-arg VERSION=${version} --build-arg DEBNAME=${debname} --target final -t benediktkr/emacs:${version} ." + sh "docker tag benediktkr/emacs:${version} benediktkr/emacs:${docker_tag}" + } } + stage('amzn') { + when { + expression { skip_build == false } + expression { build_mode == "stable" } + } + steps { + sh "docker build -f amzn/Dockerfile --build-arg PREFIX=${amzn_prefix} --build-arg VERSION=${version} -t emacs-amzn:${version}-amzn ." + sh "docker container create --name emacs_amzn_builder emacs-amzn:${version}-amzn " + sh "docker container cp emacs_amzn_builder:/emacs/amzn/ dist/" + } + } + } post { success { - archiveArtifacts( - artifacts: 'dist/*/*.tar.gz,dist/debian/*.deb', - fingerprint: true - ) - sh "cp dist/*/*.tar.gz ${env.JENKINS_HOME}/artifacts" - sh "cp dist/debian/*.deb ${env.JENKINS_HOME}/artifacts" - script { if ( !skip_build ) { - sh "docker push benediktkr/emacs:${version}" + archiveArtifacts( + artifacts: 'dist/*/*.tar.gz,dist/debian/*.deb', + fingerprint: true + ) + + sh "cp dist/*/*.tar.gz ${env.JENKINS_HOME}/artifacts" + sh "cp dist/debian/*.deb ${env.JENKINS_HOME}/artifacts" + build job: "/utils/apt", wait: false + + sh "docker push benediktkr/emacs:${docker_tag}" + sh "docker push benediktkr/emacs:${version}" } + } } cleanup { + script { if (! skip_build ) { + sh "rm dist/*/*.tar.gz || true" + sh "rm dist/debian/*.deb || true" sh "docker container rm emacs_debian_builder || true" sh "docker container rm emacs_amzn_builder || true" } diff --git a/README.md b/README.md index 90f0486..7de7cbc 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,21 @@ # emacs-docker [![Build Status](https://jenkins.sudo.is/buildStatus/icon?job=ben%2Femacs-docker%2Fmaster&style=flat-square)](https://jenkins.sudo.is/job/ben/job/emacs-docker/job/master/) -![Docker Image Version (latest by date)](https://img.shields.io/docker/v/benediktkr/emacs?style=flat-square) +![Docker Image Version (latest semver)](https://img.shields.io/docker/v/benediktkr/emacs?sort=semver&style=flat-square) ![Docker Image Size (latest by date)](https://img.shields.io/docker/image-size/benediktkr/emacs?sort=date&style=flat-square) -Builds the latest stable emacs in a docker image, packages it as `.deb` and `.tar.gz` and then publishe a [docker image to Docker Hub](https://hub.docker.com/r/benediktkr/emacs-docker/) with emacs installed: + +Builds both the latest version from `master` in the repo, and looks for the newest tag (release) and builds that. Builds are packaged as `.deb` and `.tar.gz` and then publishe a [docker image to Docker Hub](https://hub.docker.com/r/benediktkr/emacs/) with emacs installed. + +The `latest` tag follows the master branch builds. ``` docker run --rm -it benediktkr/emacs:27.1 + +docker run --rm -it benedikt/emacs:latest ``` - -The `.deb` package is uploaded to [apt.sudo.is](https://apt.sudo.is). - +The `.deb` packages are uploaded to [apt.sudo.is](https://apt.sudo.is). ``` wget -q -O - https://apt.sudo.is/KEY.gpg | sudo apt-key add - diff --git a/debian/Dockerfile b/debian/Dockerfile index 21ceb4a..d00865a 100644 --- a/debian/Dockerfile +++ b/debian/Dockerfile @@ -1,44 +1,56 @@ FROM debian:bullseye as base -ARG VERSION=27.1 ARG CPU_COUNT=8 ARG PREFIX=/emacs/target +ARG EMACS_UID=1337 -ENV VERSION=${VERSION} -ENV PREFIX=${PREFIX} +ENV PREFIX=/emacs/target ENV DEBIAN_FRONTEND=noninteractive -RUN mkdir -p /emacs/target && \ - apt-get update && \ +RUN useradd -m -d /emacs -u ${EMACS_UID} emacs +RUN apt-get update && apt-get -y install nettle-dev + +WORKDIR /emacs + +FROM base as builder + +RUN apt-get update && \ apt-get install -y wget build-essential autoconf texinfo gnutls-bin \ libgnutls28-dev pkg-config libncurses-dev patchelf \ + libacl1-dev \ ruby ruby-dev rubygems build-essential git && \ gem install --no-document fpm -FROM base as builder -ADD emacs-src/ /emacs/emacs-${VERSION} -WORKDIR /emacs/emacs-${VERSION} +ARG VERSION +ENV VERSION=${VERSION} + +COPY --chown=emacs:emacs emacs-src/ /emacs/emacs-src +USER emacs +WORKDIR /emacs/emacs-src +RUN mkdir /emacs/target # --exec-prefix=$PREFIX # --prefix=$PREFIX RUN ./autogen.sh \ - && ./configure --with-x=no CFLAGS="-I$ORIGIN/include" LDFLAGS="-L$ORIGIN/lib -Wl,-rpath=\\\$\$ORIGIN/../lib" -RUN make -j${CPU_COUNT} -RUN make install prefix=$PREFIX -j${CPU_COUNT} + && ./configure --with-x=no CFLAGS="-I$ORIGIN/include" LDFLAGS="-L$ORIGIN/lib -Wl,-rpath=\\\$\$ORIGIN/../lib" > /emacs/configure.log +RUN make -j${CPU_COUNT} > /emacs/make.log +RUN make install prefix=$PREFIX -j${CPU_COUNT} > /emacs/makeinstall.log +ARG DEBNAME=emacs ADD debian/package.sh /usr/local/bin/package.sh -RUN chmod +x /usr/local/bin/package.sh -RUN /usr/local/bin/package.sh +RUN /usr/local/bin/package.sh ${BUILD_MODE} -FROM builder as final +FROM base as final -WORKDIR /emacs -RUN rm -rf /emacs/emacs-${VERSION} #&& rm -rf /emacs/target - # enable when everything is included +ARG VERSION +ARG DEBNAME=emacs +ENV DEBNAME=${DEBNAME} -RUN dpkg -i /emacs/debian/emacs_27.1_amd64.deb \ - && rm -rf /emacs/debian +COPY --from=builder /emacs/debian/${DEBNAME}_${VERSION}_amd64.deb / +RUN dpkg -i /${DEBNAME}_${VERSION}_amd64.deb \ + && rm /${DEBNAME}_${VERSION}_amd64.deb + +USER emacs RUN /usr/local/bin/emacs --version - CMD ["/usr/local/bin/emacs"] diff --git a/debian/package.sh b/debian/package.sh old mode 100644 new mode 100755 index 1baec5b..e5eb213 --- a/debian/package.sh +++ b/debian/package.sh @@ -7,6 +7,10 @@ if [ -z "$VERSION" ]; then echo "varible VERSION must be set!" exit 1 fi +if [ -z "$DEBNAME" ]; then + echo "varible DEBNAME must be set!" + exit 1 +fi BUILDS=/emacs/debian @@ -22,14 +26,19 @@ BUILDS=/emacs/debian echo $PREFIX +## this is all commented out for now, since for me it is only on the +## amzn specific builds that i need an executable with the libs in the +## build. +## this also had some weird side effects on Ubuntu. + # copying some lib files -cp /lib/x86_64-linux-gnu/librt.so.1 $PREFIX/lib/ -cp /lib/x86_64-linux-gnu/libtinfo.so.6 $PREFIX/lib/ -cp /usr/lib/x86_64-linux-gnu/libgnutls.so.30 $PREFIX/lib/ +#cp /lib/x86_64-linux-gnu/librt.so.1 $PREFIX/lib/ +#cp /lib/x86_64-linux-gnu/libtinfo.so.6 $PREFIX/lib/ +#cp /usr/lib/x86_64-linux-gnu/libgnutls.so.30 $PREFIX/lib/ # might not work on ubuntu -cp /usr/lib/x86_64-linux-gnu/libnettle.so.8 $PREFIX/lib/ -cp /usr/lib/x86_64-linux-gnu/libhogweed.so.6 $PREFIX/lib/ +#cp /usr/lib/x86_64-linux-gnu/libnettle.so.8 $PREFIX/lib/ +#cp /usr/lib/x86_64-linux-gnu/libhogweed.so.6 $PREFIX/lib/ # shown as inlcuded by ldd but havent been needed so far # cp /lib/x86_64-linux-gnu/libanl.so.1 $PREFIX/lib/ @@ -51,6 +60,7 @@ cp /usr/lib/x86_64-linux-gnu/libhogweed.so.6 $PREFIX/lib/ # in the output we see that the binary is dynamically linking the # files we copied ldd $PREFIX/bin/emacs +$PREFIX/bin/emacs --version mkdir -p $BUILDS @@ -64,10 +74,16 @@ mkdir -p $BUILDS # make a .deb with fpm ( # set dependencies (check with apt) - DEPENDS="-d nettle-dev" #DEPENDS="" - fpm -t deb -v ${VERSION} -n emacs $DEPENDS -s dir $PREFIX/=/usr/local + + # if [ "$DEBNAME" == "emacs-nightly" ]; then + # $SUFFIX="+$(date +'%Y%M%d')" + # else + # SUFFIX="" + # fi + + fpm -t deb -v ${VERSION} -n ${DEBNAME} ${DEPENDS} -s dir $PREFIX/=/usr/local cp *.deb $BUILDS ) -- 2.40.1 From bf56bdf279c1431627e513ef3313d85952d440ec Mon Sep 17 00:00:00 2001 From: Benedikt Kristinsson Date: Tue, 2 Mar 2021 02:54:07 +0100 Subject: [PATCH 2/3] job param" --- Jenkinsfile | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 595f1e9..8a186d3 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -167,7 +167,15 @@ pipeline { sh "cp dist/*/*.tar.gz ${env.JENKINS_HOME}/artifacts" sh "cp dist/debian/*.deb ${env.JENKINS_HOME}/artifacts" - build job: "/utils/apt", wait: false + build( + job: "/utils/apt", + wait: false, + parameters: [[ + $class: 'StringParameterValue', + name: 'filename', + value: "${debname}_${version}_amd64.deb" + ]] + ) sh "docker push benediktkr/emacs:${docker_tag}" sh "docker push benediktkr/emacs:${version}" -- 2.40.1 From a9d97073d8b10c1ce326fb5245da7b67b6e8a0bf Mon Sep 17 00:00:00 2001 From: Benedikt Kristinsson Date: Tue, 2 Mar 2021 03:26:42 +0100 Subject: [PATCH 3/3] fix --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 8a186d3..78f5f6d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -53,7 +53,7 @@ pipeline { url: 'https://git.sudo.is/mirrors/emacs.git' ]], //branches: [[name: "refs/tags/emacs-${env.VERSION}"]] - branches: [[name: "master"]] + //branches: [[name: "master"]] ]) dir('emacs-src') { -- 2.40.1