Monday, March 12, 2018

Moving and renaming projects in OBS

For some part of our software project lifecycle with http://42ity.org/ we use an on-premise setup of OBS aka OpenSUSE Build Service, at least initially that was the name (not to be confused with Open Broadcaster Software) ;) Having a local setup allows us to modify and manage it in ways the common cloud service can not be changed to our whim.

One such issue we were facing recently was that a few packages (ultimate recipes) were placed into wrong projects or sub-projects (a scope to group packages for the purposes of dependencies, upgrades, etc.). This caused a mess, because beside the pedantic "it is not clean" complaints, packages at different levels ended up building against different dependencies - and it this case it was not intended (sometimes it is, hence the scoping). Packages have a history that tracks evolution of a recipe, and sometimes it is important to keep it for development reference, or even as part of the workflow in our case (determine whether *this* version of the Git sources was packaged earlier).

Unfortunately, OBS does not directly support moving such data around nor even renaming packages. You can "branch" packages (to track an original package's changes and merge them with customized bits of the clone), but that's about it. Thanks to help on the IRC channel, however, we found a way to do it on the backend, fiddling under the hood.

BEWARE THAT SUCH FIDDLING CAN EAT YOUR DATA AND BLOW UP YOUR SERVER!
Take backups or snapshots before following these notes!

Now, it is important to keep in mind that OBS is a wad of scripts written in several languages for different purposes, such as a Ruby web-frontend, a perl backend for scheduling etc., shell scripts to deal with OS nuances such as build-root setup... and the backend involves (and represents) a database to keep some info and claim unique IDs among other stuff, while a lot is kept in arcane directory structures as files placed in expected locations with expected names and contents and role in the overall solution. So fiddling under the hood is tweaking the implementation detail, and might not work the same way in all versions (FWIW, ours is based on a Nov 2015 release) and might have poorly traceable consequences. Still, it worked for us once so I decided to record the experience :)

1. Identify the poorly named package. For the recent example's sake, it will be a "fty:master:/appliance:/fosspkg" which used a third-party FOSS package "fosspkg" almost verbatim - just added the pkgconfig files that configure scripts in some of our components relied on and the original code did not provide. The problem here was that the top-level project "fty:master" ended up using the upstream distributions' version of the package for its builds and tests, while its sub-project "appliance" used another - so preinstall images (made in top-level project) did not match, and our own common components subsequently placed into the top-level project did not even build (needed those pkgconfig files). We want this "fosspkg" recipe moved upwards, to the top-level project.

2. Create a new empty "fty:master:/fosspkg" recipe, using the common web-gui "Create package" link (or CLI, or REST API) so the system properly assigns the new IDs and other resources it wants.

3. Fire up an SSH session to the OBS master server, where the fun happens henceforth. If you used packaged setup initially, the data to modify will be in several locations under "/srv/obs" directory:
  • /srv/obs/sources/fosspkg contains the source code (reused by all packages with the same name located under different projects), and likely remains unchanged.
  • /srv/obs/trees/fty:master:appliance/fosspkg and /srv/obs/trees/fty:master/fosspkg contain files with references to metadata for each commit into the repo (list of source and other files with their hashes that comprise this or that revision of the recipe) - just copy the files from original version into the newly created one.
  • /srv/obs/projects/fty:master:appliance.pkg/ and /srv/obs/projects/fty:master.pkg/ directories contain some *.xml, *.del, *.rev and *.mrev files for each package in this project (e.g. fosspkg.xml and fosspkg.mrev for initial state). Copy over the original package's REV file, migrate carefully the XML file contents, into the new location. TODO: Not sure what should be done with the MREV file - is it safe replace the new one with the old one (moved away into "fosspkg.mrev.del")?
    • The XML file contains the description, title, enabled build targets (if customized compared to the project level) and such - you might transplant the description for example, if you haven't done so with web-gui already; note that COPYING the XML file verbatim is not a good idea, as it references the "project" in its top tag (can copy and edit, though, if there were many custom settings);
    • The REV text-table file contains the actual history of the package - which revision was done when and which number it was in the order of succession, as well as other revision-specific details; is not initially there before the first upload of actual contents into the package;
    • The MREV file seems track the initial creation of the component? :)
    • The DEL files track components that were recipe'd before, but have since been deleted.
  • /srv/obs/repos/fty:/master:/appliance/Distro_X.Y/ and /srv/obs/repos/fty:/master/Distro_X.Y/ contain build products of the project (including package sources and architecture-specific subdirectories). To avoid rebuilds, you can copy over the products from the old location into the new one (this might make sense if builds are costly, but if the actual dependencies have changed due to relocation - you might miss out on something here). To free up resources of the server, you can otherwise remove the build products of the original package you are essentially removing.
  • /srv/obs/build/fty:master:appliance/Distro_X.Y/ARCH/ and /srv/obs/build/fty:master/Distro_X.Y/ARCH/ contain the latest build results (binaries, logfile, reason) as well as the history of builds (when, what, how long) - move it over as well, to keep the history tracking. Beside the "fosspkg" package subdirectory under ARCH, note also the ":full", ":repo", ":logfiles.*" and ":meta" ones - move over their contents for "*fosspkg*" matching files as well.
  • Revise with a shell command like:
    # find /srv/obs -name '*fosspkg*' 2>/dev/null | grep master
    that there is nothing unexpected under any "appliance" related locations.
  • Refresh the new package's page in OBS web-gui. It may display that the builds are "broken" since it has no metadata about last build in its binary tables. Go to Repositories tab to "Explicitly disable" and then "Take default" the Build Flag - if all went well, the system should discover that it was built, and the status will become "succeeded" with the old build's logs seen upon clicking.
  • If the original recipe was "Branched" into other projects, branch the new one into desired locations; carry over customizations that the branch might have (if any) - the web-gui might help with its show of differences.
  • Semi-Finally, disable all the flags in Repository tab of the original obsoleted recipe (so it is in fact not built nor used), and perhaps use
    osc wipebinaries --build-disabled fty:master:appliance fosspkg
    - hopefully this would e.g. rectify the binary metadata we did not touch under the "build" directories.
  • Note that as far as OBS recalculating the dependencies, nothing happened (via web-gui) to trigger rebuilds of stuff that is impacted by your changed package. Probably it is up to you to determine the scope of fallout and trigger the rebuilds.
    • For greater consistency, and if your time/cost constraints permit (this sort of things is always done in a rush, right?) go into the new component's build states (in the Web-GUI) and click Trigger Rebuild. This would ensure the build products are re-done honestly, and downstream stuff is triggered honestly.
    • You might have some luck with e.g.
      # osc whatdependson fty:master fosspkg Debian_8.0 x86_64
      at least for dependent packages right inside the same project level.
    • Also a direct search in the filesystem like
      # grep fosspkg /srv/obs/build/fty\:master/Debian_8.0/x86_64/*/.meta.success
      might help.
  • Finally, when you're sure the new one works well - delete the original with web-gui.

No comments:

Post a Comment