diff --git a/Jenkinsfile b/Jenkinsfile index 55c0225..78f5f6d 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() @@ -33,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') { @@ -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,59 @@ 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 ) { + 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, + parameters: [[ + $class: 'StringParameterValue', + name: 'filename', + value: "${debname}_${version}_amd64.deb" + ]] + ) + + sh "docker push benediktkr/emacs:${docker_tag}" sh "docker push benediktkr/emacs:${version}" - build job: "/utils/apt", wait: false } + } } 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 )