systemctl daemon-reload wrt buildd service changes.
Automate updating some extension lists from check-all-the-things.
Reported wishlist Debian bug #828128 against debsources.
Engage lizard mode! Wish for better display technology.
Nice vegetarian food with nice folks and
interesting discussions with interesting locals.
Polish and release check-all-the-things.
Close bugs I forgot to close in the changelog.
Add link to debian-boot on Debootstrap wiki page.
Notice first mockup of a theme for Debian stretch.
Answer a question about package naming on #debian-mentors.
Discuss the future of cross compilation on Debian.
Notice a talk about FOSSology & update a wiki page.
Mention AsteroidOS and MaruOS on the mobile wiki page.
Contemplate how close to the FSDG Debian might be
and approaches to improving that.
report-spam-debian-lists and
report-spam-debian-bugs scripts and manual BTS clicks.
Usual wondering why there isn't an RFC for MUA spam reporting.
Disturbed by the sudden appearance of an astronautess in the
orga room but placated by a plentiful supply of crisps.
Ask x32 folks about debian-x32.org vs x32 on ports.d.o.
Glad to just avoid the room shuffle dance.
Finish mime support for check-all-the-things.
Disappointed that piz.za does not actually resolve.
Amused by pollito's virtual tour of UTC.
Completely stuffed full of Butleritos.
Yoyodyne, Inc., hereby disclaims all copyright
interest in the program Gnomovision'
(which makes passes at compilers) written
by James Hacker.
signature of Ty Coon, 1 April 1989
Ty Coon, President of Vice"
[http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html
(It is a gross oversimplification, but for the purposes of OpenStack CI, Jenkins is pretty much used as a glorified ssh/scp wrapper. Zuul Version 3, under development, is working to remove the need for Jenkins to be involved at all).Well some recent security issues with Jenkins and other changes has led to a roll-out of what is being called Zuul 2.5, which has indeed removed Jenkins and makes extensive use of Ansible as the basis for running CI tests in OpenStack. Since I already had the diagram, it seems worth updating it for the new reality.
The process starts when a developer uploads their code to gerrit via the git-review tool. There is no further action required on their behalf and the developer simply waits for results of their jobs.
Gerrit provides a JSON-encoded "fire-hose" output of everything happening to it. New reviews, votes, updates and more all get sent out over this pipe. Zuul is the overall scheduler that subscribes itself to this information and is responsible for managing the CI jobs appropriate for each change.
Zuul has a configuration that tells it what jobs to run for what projects. Zuul can do lots of interesting things, but for the purposes of this discussion we just consider that it puts the jobs it wants run into gearman for a launcher to consume. gearman is a job-server; as they explain it "[gearman] provides a generic application framework to farm out work to other machines or processes that are better suited to do the work". Zuul puts into gearman basically a tuple (job-name, node-type) for each job it wants run, specifying the unique job name to run and what type of node it should be run on.
A group of Zuul launchers are subscribed to gearman as workers. It is these Zuul launchers that will consume the job requests from the queue and actually get the tests running. However, a launcher needs two things to be able to run a job a job definition (what to actually do) and a worker node (somewhere to do it). The first part what to do is provided by job-definitions stored in external YAML files. The Zuul launcher knows how to process these files (with some help from Jenkins Job Builder, which despite the name is not outputting XML files for Jenkins to consume, but is being used to help parse templates and macros within the generically defined job definitions). Each Zuul launcher gets these definitions pushed to it constantly by Puppet, thus each launcher knows about all the jobs it can run automatically. Of course Zuul also knows about these same job definitions; this is the job-name part of the tuple we said it put into gearman. The second part somewhere to run the test takes some more explaining. To the next point...
Several cloud companies donate capacity in their clouds for OpenStack to run CI tests. Overall, this capacity is managed by a customized management tool called nodepool (you can see the details of this capacity at any given time by checking the nodepool configuration). Nodepool watches the gearman queue and sees what requests are coming out of Zuul. It looks at node-type of jobs in the queue (i.e. what platform the job has requested to run on) and decides what types of nodes need to start and which cloud providers have capacity to satisfy demand. Nodepool will start fresh virtual machines (from images built daily as described in the prior post), monitor their start-up and, when they're ready, put a new "assignment job" back into gearman with the details of the fresh node. One of the active Zuul launchers will pick up this assignment job and register the new node to itself.
At this point, the Zuul launcher has what it needs to actually get jobs started. With an fresh node registered to it and waiting for something to do, the Zuul launcher can advertise its ability to consume one of the waiting jobs from the gearman queue. For example, if a ubuntu-trusty node is provided to the Zuul launcher, the launcher can now consume from gearman any job it knows about that is intended to run on an ubuntu-trusty node type. If you're looking at the launcher code this is driven by the NodeWorker class you can see this being created in response to an assignment via LaunchServer.assignNode. To actually run the job where the "job hits the metal" as it were the Zuul launcher will dynamically construct an Ansible playbook to run. This playbook is a concatenation of common setup and teardown operations along with the actual test scripts the jobs wants to run. Using Ansible to run the job means all the flexibility an orchestration tool provides is now available to the launcher. For example, there is a custom console streamer library that allows us to live-stream the console output for the job over a plain TCP connection, and there is the possibility to use projects like ARA for visualisation of CI runs. In the future, Ansible will allow for better coordination when running multiple-node testing jobs after all, this is what orchestration tools such as Ansible are made for! While the Ansible run can be fairly heavyweight (especially when you're talking about launching thousands of jobs an hour), the system scales horizontally with more launchers able to consume more work easily. When checking your job results on logs.openstack.org you will see a _zuul_ansible directory now which contains copies of the inventory, playbooks and other related files that the launcher used to do the test run.
Eventually, the test will finish. The Zuul launcher will put the result back into gearman, which Zuul will consume (log copying is interesting but a topic for another day). The testing node will be released back to nodepool, which destroys it and starts all over again nodes are not reused and also have no sensitive details on them, as they are essentially publicly accessible. Zuul will wait for the results of all jobs for the change and post the result back to Gerrit; it either gives a positive vote or the dreaded negative vote if required jobs failed (it also handles merges to git, but that is also a topic for another day).
chroot, lxd, schroot, null, schroot,
and qemu, which live in a directory virt/. (I've followed
autopkgtest 4.0 in dropping the adt-virt- prefix and other name
conventions.) Autopkgtest's directory structure looks like:
autopkgtest/
lib/
adt_testbed.py
adtlog.py
VirtSubproc.py
runner/
setup-commands/
ssh-setup/
tests/
tools/
virt/
chroot
lxc
lxd
null
qemu
schroot
ssh
Reprotest's directory structure looks like:
reprotest/
reprotest/
__init__.py
lib/
adt_testbed.py
adtlog.py
VirtSubproc.py
runner/
tools/
virt/
chroot
lxc
lxd
null
qemu
schroot
ssh
tests/
Autopkgtest doesn't contain any __init__.py files, which means that
from the perspective of Python none of its components are Python
packages. To enable the various components of autopkgtest test to
import each other as
implicit namespace packages,
there's a lot of explicit sys.path mutation code in the various
files like sys.path.insert(0, '/usr/share/autopkgtest/python') and
sys.path.insert(0,
os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
'lib')). For my design goals, there are two problems with this.
First, setuptools makes it very, very difficult to distribute code
that isn't in Python packages, so this approach more or less doesn't
work with PyPi at all. Second, different OSes have different
directory layouts for Python packages, so an absolute path like
/usr/share/autopkgtest/python isn't portable.
The main code of reprotest at the moment lives in its __init__.py.
The autopkgtest CLI of the main runner is specific to running tests,
so my entry point is going to be adt_testbed. My first attempt to
refactor this involved putting an empty __init__.py in lib/ to
turn into a package so that I could import the modules in the files in
lib/ using code like from reprotest.lib import adtlog. This works
fine for the files in lib/ and makes adt_testbed importable in the
main __init__.py. However, the executables in virt/, which are
invoked by subprocess calls in adt_testbed.py, also need to import
modules from lib/ for the various adtlog functions and the timeout
functions in VirtSubproc. After some trial-and-error, by replacing
the sys.path mutations in virt/ with sys.path.insert(0,
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))),
I managed to get the executables to run, though I still need to verify
that this works for both PyPi and apt. I'm not sure if this is the
best solution, so I may end up doing some kind of larger refactoring,
either changing all the subprocess calls in adt_testbed so they
work with reprotest.virt as a subpackage or reorganizing the rest of
the code somehow.
It's still not clear to me why autopkgtest uses its own special logging
module rather than the standard library's logging module. I thought
it might have something to do with combining the logging from a
process and its subprocesses, but because the Python subprocesses are
importing their own instances of the adtlog module, this isn't the
case. Another problem related to logging and debugging is that the
programs in virt/ interact through stdin and stdout, which means that
I haven't been able to use simple prints to help work out their state
during execution.
Now that I have adt_testbed working, my next step is to change the
code I've already written so that instead of executing commands
directly, it executes them through the autopkgtest interface.
A few more pictures
here. I
keep being amazed by the nature in this area, definitely my preferred
place in US from the relatively few I visited.
Had a nice dinner as well at Cafe Langley,
which surprisingly had reasonably-authentic Mediterranean food; the
Baba Ganoush was excellent.
Other than that outing, nothing worth describing, except that I really
missed my Zwift or outdoor rides. The experience of using the
stationary bikes in the hotel does not compare, so I resorted more to
running on the treadmill (hmm, Zwift for running, hmm ); if the foot
pod calibration is to be trusted, I continued to slightly improve my
1K, 1mi, and 5K times. Not bad, I might want to join some running
races as well this summer, but I need to take it easy though and make
sure to not get injured again.
And finally, week over, flew back home, slept a bit mid-day (which
will ruin my jet lag recovery program), unloaded my bike from the car
(and checked it still works), and and and got on the trainer and
did a Zwift ride. Jet lagged, but managed to beat my Watopia sprint
record by a tiny bit, and complete a new workout ( The Gorby ), which
was interesting. I can stop any time I want, definitely (I just need
to take a trip away from home ).
As some of the world knows full well by now, I've been noodling with Go
for a few years, working through its pros, its cons, and thinking a lot
about how humans use code to express thoughts and ideas. Go's got a lot of
neat use cases, suited to particular problems, and used in the right place,
you can see some clear massive wins.
I've started writing Debian tooling in Go, because it's a pretty natural fit.
Go's fairly tight, and overhead shouldn't be taken up by your operating system.
After a while, I wound up hitting the usual blockers, and started to build up
abstractions. They became pretty darn useful, so, this blog post is announcing
(a still incomplete, year old and perhaps API changing) Debian package for Go.
The Go importable name is pault.ag/go/debian. This contains a lot of utilities
for dealing with Debian packages, and will become an edited down "toolbelt"
for working with or on Debian packages.
Module Overview
Currently, the package contains 4 major sub packages. They're a changelog
parser, a control file parser, deb file format parser, dependency parser
and a version parser. Together, these are a set of powerful building blocks
which can be used together to create higher order systems with reliable
understandings of the world.
changelog
The first (and perhaps most incomplete and least tested) is a changelog file
parser.. This provides the
programmer with the ability to pull out the suite being targeted in the
changelog, when each upload was, and the version for each. For example, let's
look at how we can pull when all the uploads of Docker to sid took place:
func main()
resp, err := http.Get("http://metadata.ftp-master.debian.org/changelogs/main/d/docker.io/unstable_changelog")
if err != nil
panic(err)
allEntries, err := changelog.Parse(resp.Body)
if err != nil
panic(err)
for _, entry := range allEntries
fmt.Printf("Version %s was uploaded on %s\n", entry.Version, entry.When)
Version 1.8.3~ds1-2 was uploaded on 2015-11-04 00:09:02 -0800 -0800
Version 1.8.3~ds1-1 was uploaded on 2015-10-29 19:40:51 -0700 -0700
Version 1.8.2~ds1-2 was uploaded on 2015-10-29 07:23:10 -0700 -0700
Version 1.8.2~ds1-1 was uploaded on 2015-10-28 14:21:00 -0700 -0700
Version 1.7.1~dfsg1-1 was uploaded on 2015-08-26 10:13:48 -0700 -0700
Version 1.6.2~dfsg1-2 was uploaded on 2015-07-01 07:45:19 -0600 -0600
Version 1.6.2~dfsg1-1 was uploaded on 2015-05-21 00:47:43 -0600 -0600
Version 1.6.1+dfsg1-2 was uploaded on 2015-05-10 13:02:54 -0400 EDT
Version 1.6.1+dfsg1-1 was uploaded on 2015-05-08 17:57:10 -0600 -0600
Version 1.6.0+dfsg1-1 was uploaded on 2015-05-05 15:10:49 -0600 -0600
Version 1.6.0+dfsg1-1~exp1 was uploaded on 2015-04-16 18:00:21 -0600 -0600
Version 1.6.0~rc7~dfsg1-1~exp1 was uploaded on 2015-04-15 19:35:46 -0600 -0600
Version 1.6.0~rc4~dfsg1-1 was uploaded on 2015-04-06 17:11:33 -0600 -0600
Version 1.5.0~dfsg1-1 was uploaded on 2015-03-10 22:58:49 -0600 -0600
Version 1.3.3~dfsg1-2 was uploaded on 2015-01-03 00:11:47 -0700 -0700
Version 1.3.3~dfsg1-1 was uploaded on 2014-12-18 21:54:12 -0700 -0700
Version 1.3.2~dfsg1-1 was uploaded on 2014-11-24 19:14:28 -0500 EST
Version 1.3.1~dfsg1-2 was uploaded on 2014-11-07 13:11:34 -0700 -0700
Version 1.3.1~dfsg1-1 was uploaded on 2014-11-03 08:26:29 -0700 -0700
Version 1.3.0~dfsg1-1 was uploaded on 2014-10-17 00:56:07 -0600 -0600
Version 1.2.0~dfsg1-2 was uploaded on 2014-10-09 00:08:11 +0000 +0000
Version 1.2.0~dfsg1-1 was uploaded on 2014-09-13 11:43:17 -0600 -0600
Version 1.0.0~dfsg1-1 was uploaded on 2014-06-13 21:04:53 -0400 EDT
Version 0.11.1~dfsg1-1 was uploaded on 2014-05-09 17:30:45 -0400 EDT
Version 0.9.1~dfsg1-2 was uploaded on 2014-04-08 23:19:08 -0400 EDT
Version 0.9.1~dfsg1-1 was uploaded on 2014-04-03 21:38:30 -0400 EDT
Version 0.9.0+dfsg1-1 was uploaded on 2014-03-11 22:24:31 -0400 EDT
Version 0.8.1+dfsg1-1 was uploaded on 2014-02-25 20:56:31 -0500 EST
Version 0.8.0+dfsg1-2 was uploaded on 2014-02-15 17:51:58 -0500 EST
Version 0.8.0+dfsg1-1 was uploaded on 2014-02-10 20:41:10 -0500 EST
Version 0.7.6+dfsg1-1 was uploaded on 2014-01-22 22:50:47 -0500 EST
Version 0.7.1+dfsg1-1 was uploaded on 2014-01-15 20:22:34 -0500 EST
Version 0.6.7+dfsg1-3 was uploaded on 2014-01-09 20:10:20 -0500 EST
Version 0.6.7+dfsg1-2 was uploaded on 2014-01-08 19:14:02 -0500 EST
Version 0.6.7+dfsg1-1 was uploaded on 2014-01-07 21:06:10 -0500 EST
go-debian,
which is the control file parser
(otherwise sometimes known as deb822). This module was inspired by the way
that the json module works in Go, allowing for files to be defined in code
with a struct. This tends to be a bit more declarative, but also winds up
putting logic into struct tags, which can be a nasty anti-pattern if used too
much.
The first primitive in this module is the concept of a Paragraph, a struct
containing two values, the order of keys seen, and a map of string to string.
All higher order functions dealing with control files will go through this
type, which is a helpful interchange format to be aware of. All parsing of
meaning from the Control file happens when the Paragraph is unpacked into
a struct using reflection.
The idea behind this strategy that you define your struct, and let the Control
parser handle unpacking the data from the IO into your container, letting you
maintain type safety, since you never have to read and cast, the conversion
will handle this, and return an Unmarshaling error in the event of failure.
Additionally, Structs that define an anonymous member of control.Paragraph
will have the raw Paragraph struct of the underlying file, allowing the
programmer to handle dynamic tags (such as X-Foo), or at least, letting
them survive the round-trip through go.
The default decoder
contains an argument, the ability to verify the input control file using an
OpenPGP keyring, which is exposed to the programmer through the
(*Decoder).Signer() function. If the passed argument is nil, it will not
check the input file signature (at all!), and if it has been passed, any
signed data must be found or an error will fall out of the NewDecoder call.
On the way out, the opposite happens, where the struct is introspected,
turned into a control.Paragraph, and then written out to the io.Writer.
Here's a quick (and VERY dirty) example showing the basics of reading and
writing Debian Control files with go-debian.
package main
import (
"fmt"
"io"
"net/http"
"strings"
"pault.ag/go/debian/control"
)
type AllowedPackage struct
Package string
Fingerprint string
func (a *AllowedPackage) UnmarshalControl(in string) error
in = strings.TrimSpace(in)
chunks := strings.SplitN(in, " ", 2)
if len(chunks) != 2
return fmt.Errorf("Syntax sucks: '%s'", in)
a.Package = chunks[0]
a.Fingerprint = chunks[1][1 : len(chunks[1])-1]
return nil
type DMUA struct
Fingerprint string
Uid string
AllowedPackages []AllowedPackage control:"Allow" delim:","
func main()
resp, err := http.Get("http://metadata.ftp-master.debian.org/dm.txt")
if err != nil
panic(err)
decoder, err := control.NewDecoder(resp.Body, nil)
if err != nil
panic(err)
for
dmua := DMUA
if err := decoder.Decode(&dmua); err != nil
if err == io.EOF
break
panic(err)
fmt.Printf("The DM %s is allowed to upload:\n", dmua.Uid)
for _, allowedPackage := range dmua.AllowedPackages
fmt.Printf(" %s [granted by %s]\n", allowedPackage.Package, allowedPackage.Fingerprint)
...
The DM Allison Randal <allison@lohutok.net> is allowed to upload:
parrot [granted by A4F455C3414B10563FCC9244AFA51BD6CDE573CB]
...
The DM Benjamin Barenblat <bbaren@mit.edu> is allowed to upload:
boogie [granted by 3224C4469D7DF8F3D6F41A02BBC756DDBE595F6B]
dafny [granted by 3224C4469D7DF8F3D6F41A02BBC756DDBE595F6B]
transmission-remote-gtk [granted by 3224C4469D7DF8F3D6F41A02BBC756DDBE595F6B]
urweb [granted by 3224C4469D7DF8F3D6F41A02BBC756DDBE595F6B]
...
The DM <aelmahmoudy@sabily.org> is allowed to upload:
covered [granted by 41352A3B4726ACC590940097F0A98A4C4CD6E3D2]
dico [granted by 6ADD5093AC6D1072C9129000B1CCD97290267086]
drawtiming [granted by 41352A3B4726ACC590940097F0A98A4C4CD6E3D2]
fonts-hosny-amiri [granted by BD838A2BAAF9E3408BD9646833BE1A0A8C2ED8FF]
...
...
deb module. This contains code to handle reading
Debian 2.0 .deb files. It contains a wrapper that will parse the control
member, and provide the data member through the
archive/tar interface.
Here's an example of how to read a .deb file, access some metadata, and
iterate over the tar archive, and print the filenames of each of the
entries.
func main()
path := "/tmp/fluxbox_1.3.5-2+b1_amd64.deb"
fd, err := os.Open(path)
if err != nil
panic(err)
defer fd.Close()
debFile, err := deb.Load(fd, path)
if err != nil
panic(err)
version := debFile.Control.Version
fmt.Printf(
"Epoch: %d, Version: %s, Revision: %s\n",
version.Epoch, version.Version, version.Revision,
)
for
hdr, err := debFile.Data.Next()
if err == io.EOF
break
if err != nil
panic(err)
fmt.Printf(" -> %s\n", hdr.Name)
Epoch: 0, Version: 1.3.5, Revision: 2+b1
-> ./
-> ./etc/
-> ./etc/menu-methods/
-> ./etc/menu-methods/fluxbox
-> ./etc/X11/
-> ./etc/X11/fluxbox/
-> ./etc/X11/fluxbox/window.menu
-> ./etc/X11/fluxbox/fluxbox.menu-user
-> ./etc/X11/fluxbox/keys
-> ./etc/X11/fluxbox/init
-> ./etc/X11/fluxbox/system.fluxbox-menu
-> ./etc/X11/fluxbox/overlay
-> ./etc/X11/fluxbox/apps
-> ./usr/
-> ./usr/share/
-> ./usr/share/man/
-> ./usr/share/man/man5/
-> ./usr/share/man/man5/fluxbox-style.5.gz
-> ./usr/share/man/man5/fluxbox-menu.5.gz
-> ./usr/share/man/man5/fluxbox-apps.5.gz
-> ./usr/share/man/man5/fluxbox-keys.5.gz
-> ./usr/share/man/man1/
-> ./usr/share/man/man1/startfluxbox.1.gz
...
dependency package provides an interface to parse and compute
dependencies. This package is a bit odd in that, well, there's no other
library that does this. The issue is that there are actually two different
parsers that compute our Dependency lines, one in Perl (as part of dpkg-dev)
and another in C (in dpkg).
To date, this has resulted in me filing
three
different
bugs.
I also found a broken package in the
archive,
which actually resulted in another bug being (totally accidentally)
already fixed.
I hope to continue to run the archive through my parser in hopes of finding
more bugs! This package is a bit complex, but it basically just returns what
amounts to be an AST
for our Dependency lines. I'm positive there are bugs, so file them!
func main()
dep, err := dependency.Parse("foo bar, baz, foobar [amd64] bazfoo [!sparc], fnord:armhf [gnu-linux-sparc]")
if err != nil
panic(err)
anySparc, err := dependency.ParseArch("sparc")
if err != nil
panic(err)
for _, possi := range dep.GetPossibilities(*anySparc)
fmt.Printf("%s (%s)\n", possi.Name, possi.Arch)
foo (<nil>)
baz (<nil>)
fnord (armhf)
go-debian package.
This was nearly entirely his work (with a one or two line function I added
later), and was amazingly helpful to have. Thank you!
This module implements Debian version comparisons and parsing, allowing for
sorting in lists, checking to see if it's native or not, and letting the
programmer to implement smart(er!) logic based on upstream (or Debian)
version numbers.
This module is extremely easy to use and very straightforward, and not worth
writing an example for.
Final thoughts
This is more of a "Yeah, OK, this has been useful enough to me at this point
that I'm going to support this" rather than a "It's stable!" or even
"It's alive!" post. Hopefully folks can report bugs and help iterate on
this module until we have some really clean building blocks to build
solid higher level systems on top of. Being able to have multiple libraries
interoperate by relying on go-debian will be a massive ease.
I'm in need of more documentation, and to finalize some parts of the older
sub package APIs, but I'm hoping to be at a "1.0" real soon now.
http://social.gl-como.it/photos/valhalla/image/e8ee069635b2823e168c358d2a753f14
Wheezy's LTS period started a few weeks ago and the LTS team had to make an
early support decision concerning the Java eco-system since Wheezy ships two Java
runtime environments OpenJDK 6 and
OpenJDK 7. (To be fair, there are
actually three but gcj has
been superseded by OpenJDK a long time ago and the latter should be preferred
whenever possible.)
OpenJDK 6 is currently maintained by Red Hat and we mostly rely on their
upstream work as well as on package updates from Debian's maintainer Matthias Klose and
Tiago St rmer Daitx from Ubuntu. We already knew that both intend
to support OpenJDK 6 until April 2017 when Ubuntu 12.04 will reach its
end-of-life. Thus we had basically two options, supporting OpenJDK 6 for another
twelve months or dropping support right from the start. One of my first steps
was to ask for feedback and advice on
debian-java since
supporting only one JDK seemed to be the more reasonable solution. We agreed on warning users
via various channels about the intended change, especially about possible
incompatibilities
with OpenJDK 7. Even Andrew Haley, OpenJDK 6 project lead, participated in the discussion and confirmed that, while still supported, OpenJDK 6 security
releases are "always the last in the queue when there is urgent work to be
done".
I informed debian-lts about
my findings and issued a call for tests later.
Eventually we decided to concentrate our efforts on OpenJDK
7 because we are confident that for the
majority of our users one Java implementation is sufficient during a stable
release cycle. An immediate positive effect in making OpenJDK 7 the default is that
resources can be relocated to more pressing issues. On the other hand we were
also forced to make compromises. The switch to a newer default implementation
usually triggers a major transition with dozens of FTBFS bugs and the OpenJDK 7
transition
was no exception. I pondered about the usefulness of fixing all these bugs for
Wheezy LTS again and focussing on runtime issues instead and finally decided
that the latter was both more reasonable and more economic.
Different from regular default Java changes, users will still be able to use OpenJDK 6 to
compile their packages and the security impact for development systems is in general neglectable.
More important was to avoid runtime installations of OpenJDK 6. I identified eighteen
packages that strictly depended on the now obsolete JRE and fixed those
issues
on 4 May 2016 together with an update of
java-common and announced the switch to
OpenJDK 7 with a Debian NEWS file.
If you are not a regular reader of Debian
news and also not subscribed to
debian-lts,
debian-lts-announce or
debian-java, remember 26 June
2016 is the day when OpenJDK 7 will be made the default Java implementation in
Wheezy LTS. Of course there is no need to wait. You can switch right now:
sudo update-alternatives --config java
I wanted to write this blogpost since April, and even announced it in two previous posts, but never got to actually write it until now. And with the recent events in Snappy and Flatpak land, I can not defer this post any longer (unless I want to answer the same questions over and over on IRC ^^).
As you know, I develop the Limba 3rd-party software installer since 2014 (see this LWN article explaining the project better then I could do
) which is a spiritual successor to the Listaller project which was in development since roughly 2008. Limba got some competition by Flatpak and Snappy, so it s natural to ask what the projects next steps will be.
Meeting with the competition
At last FOSDEM and at the GNOME Software sprint this year in April, I met with Alexander Larsson and we discussed the rather unfortunate situation we got into, with Flatpak and Limba being in competition.
Both Alex and I have been experimenting with 3rd-party app distribution for quite some time, with me working on Listaller and him working on Glick and Glick2. All these projects never went anywhere. Around the time when I started Limba, fixing design mistakes done with Listaller, Alex started a new attempt at software distribution, this time with sandboxing added to the mix and a new OSTree-based design of the software-distribution mechanism. It wasn t at all clear that XdgApp, later to be renamed to Flatpak, would get huge backing by GNOME and later Red Hat, becoming a very promising candidate for a truly cross-distro software distribution system.
The main difference between Limba and Flatpak is that Limba allows modular runtimes, with things like the toolkit, helper libraries and programs being separate modules, which can be updated independently. Flatpak on the other hand, allows just one static runtime and enforces everything that is not in the runtime already to be bundled with the actual application. So, while a Limba bundle might depend on multiple individual other bundles, Flatpak bundles only have one fixed dependency on a runtime. Getting a compromise between those two concepts is not possible, and since the modular vs. static approach in Limba and Flatpak where fundamental, conscious design decisions, merging the projects was also not possible.
Alex and I had very productive discussions, and except for the modularity issue, we were pretty much on the same page in every other aspect regarding the sandboxing and app-distribution matters.
Sometimes stepping out of the way is the best way to achieve progress
So, what to do now? Obviously, I can continue to push Limba forward, but given all the other projects I maintain, this seems to be a waste of resources (Limba eats a lot of my spare time). Now with Flatpak and Snappy being available, I am basically competing with Canonical and Red Hat, who can make much more progress faster then I can do as a single developer. Also, Flatpaks bigger base of contributors compared to Limba is a clear sign which project the community favors more.
Furthermore, I started the Listaller and Limba projects to scratch an itch. When being new to Linux, it was very annoying to me to see some applications only being made available in compiled form for one distribution, and sometimes one that I didn t use. Getting software was incredibly hard for me as a newbie, and using the package-manager was also unusual back then (no software center apps existed, only package lists). If you wanted to update one app, you usually needed to update your whole distribution, sometimes even to a development version or rolling-release channel, sacrificing stability.
So, if now this issue gets solved by someone else in a good way, there is no point in pushing my solution hard. I developed a tool to solve a problem, and it looks like another tool will fix that issue now before mine does, which is fine, because this longstanding problem will finally be solved. And that s the thing I actually care most about.
I still think Limba is the superior solution for app distribution, but it is also the one that is most complex and requires additional work by upstream projects to use it properly. Which is something most projects don t want, and that s completely fine.
And that being said: I think Flatpak is a great project. Alex has much experience in this matter, and the design of Flatpak is sound. It solves many issues 3rd-party app development faces in a pretty elegant way, and I like it very much for that. Also the focus on sandboxing is great, although that part will need more time to become really useful. (Aside from that, working with Alexander is a pleasure, and he really cares about making Flatpak a truly cross-distributional, vendor independent project.)
Moving forward
So, what I will do now is not to stop Limba development completely, but keep it going as a research project. Maybe one can use Limba bundles to create Flatpak packages more easily. We also discussed having Flatpak launch applications installed by Limba, which would allow both systems to coexist and benefit from each other. Since Limba (unlike Listaller) was also explicitly designed for web-applications, and therefore has a slightly wider scope than Flatpak, this could make sense.
In any case though, I will invest much less time in the Limba project. This is good news for all the people out there using the Tanglu Linux distribution, AppStream-metadata-consuming services, PackageKit on Debian, etc. those will receive more attention
An integral part of Limba is a web service called LimbaHub to accept new bundles, do QA on them and publish them in a public repository. I will likely rewrite it to be a service using Flatpak bundles, maybe even supporting Flatpak bundles and Limba bundles side-by-side (and if useful, maybe also support AppImageKit and Snappy). But this project is still on the drawing board.
Let s see
P.S: If you come to Debconf in Cape Town, make sure to not miss my talks about AppStream and bundling
Hi to all the souls on planet.debian.orgreprotest, including a
discussion on different types of build variations and the difficulties of
specifying certain types of variations.SOURCE_DATE_EPOCH spec explaining FORCE_SOURCE_DATE.
Some upstream build tools (e.g. TeX, see below) have expressed a desire to
control which cases of embedded timestamps should obey SOURCE_DATE_EPOCH.
They were not convinced by our arguments on why this is a bad idea, so we
agreed on an environment variable FORCE_SOURCE_DATE for them to implement
their desired behaviour - named generically, so that at least we can set it
centrally. For more details, see the text just linked. However, we strongly
urge most build tools not to use this, and instead obey SOURCE_DATE_EPOCH
unconditionally in all cases.
Toolchain fixes
SOURCE_DATE_EPOCH support for all engines except LuaTeX and original TeX.SOURCE_DATE_EPOCH corner cases, eventually
resulting in the FORCE_SOURCE_DATE proposal from above.-fdebug-prefix-map in DW_AT_producer, thanks to original patch by
Daniel Kahn Gillmor.SOURCE_DATE_EPOCH applied upstream, original patch by Alexis
Bienven e.SOURCE_DATE_EPOCH, thanks to original patch by Alexis Bienven e.9F6C6333 that corresponds to both key
1AE0322EB8F74717BDEABF1D44BB1BA79F6C6333 and
88BB08F633073D7129383EE71EA37A0C9F6C6333, and you don't know which of the two
to use.
You go to http://pgp.cs.uu.nl/ and find out that the site uses short key IDs,
so the two keys are indistinguishable.
Building on Clint's hopenpgp-tools,
I made a script that
screenscrapes http://pgp.cs.uu.nl/ for trust paths, downloads all the
potentially connecting keys in a temporary keyring, and runs hkt findpaths on
it:
$ ./verify-trust-paths 1793D6AB75663E6BF104953A634F4BD1E7AD5568 1AE0322EB8F74717BDEABF1D44BB1BA79F6C6333 hkt (hopenpgp-tools) 0.18 Copyright (C) 2012-2016 Clint Adams hkt comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. (4,[1,4,3,6]) (1,1793D6AB75663E6BF104953A634F4BD1E7AD5568) (3,F8921D3A7404C86E11352215C7197699B29B232A) (4,C331BA3F75FB723B5873785B06EAA066E397832F) (6,1AE0322EB8F74717BDEABF1D44BB1BA79F6C6333) $ ./verify-trust-paths 1793D6AB75663E6BF104953A634F4BD1E7AD5568 88BB08F633073D7129383EE71EA37A0C9F6C6333 hkt (hopenpgp-tools) 0.18 Copyright (C) 2012-2016 Clint Adams hkt comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. (0,[])
Next.