CI common practices for docker + helm monorepo? - docker

I have a git repo for a project, which contains both the Dockerfile (in the root directory)and the helm chart (under chart/). The versioning of the docker image and the helm repo are separate, with the following requirements:
if the application code is changed, a new (semver) version of the docker image must be built and pushed, and a new version of the helm chart (version in Chart.yaml), referencing the new image tag (appVersion in Chart.yaml), must be packaged and pushed
if the helm chart itself is changed (eg changes in templates), a new version of the chart (version in Chart.yaml) must also be packaged and pushed.
Changes might happen directly in the master branch, or in a branch that is subsequently merged into master, so I imagine the above actions have to happen either upon push to master, or upon merges into master (in both cases, there might be a testing phase prior to the build, but I think this doesn't change the problem).
First of all, is the above setup the common practice?
Second, I'm not sure about where to save versions. I've read that saving versions in the repo (eg with a VERSIONS file or something) is bad practice, so I was thinking of using git tags, but how? We'd need two series of tags, one for the image and the other for the chart, is it how people do that? Or how would one go about this? Also, where should the version bump happen? Is it normal to have the CI pipeline itself do the bump and commit? Or should it come from the committer?
Thinking out loud, I would like to avoid having the CI do commits and pushes, because I fear that people would then forget to pull and would do local commits before, which would in turn pollute the git history with merges.
So one idea, if going with the automatic version bumping, could be to store the versions in a database or external storage and have the CI pipeline retrieve them, do the necessary bumping and then store them again. In this case I suppose I would have to establish a rule for bumping, for example always bump the patch version. Is this common practice, at least in some scenarios?
If instead we let the developers choose when and what to bump, how do they communicate that? (even in this case, there's still an automated part: when the docker image has been bumped, the helm chart version should be bumped automatically) I've read about conventional commits, but still, they don't store the actual versions. Where do I store the image and chart versions? Should I make them use tags? (but then, two separate series? How?)
Sorry if this all sounds confused, but that's because I am too.
This is my first try at setting up CI for a repo and I'm struggling to find examples, so I'm thinking that I'm either using a wrong approach or missing something obvious.
Thanks for any help!

Related

How to display configuration differences between two jenkins Jenkins builds?

I want to display non-code differences between current build and the latest known successful build on Jenkins.
By non-code differences I mean things like:
Environment variables (includes Jenkins parameters) (set), maybe with some filter
Version of system tool packages (rpm -qa | sort)
Versions of python packages installed (pip freeze)
While I know how to save and archive these files as part of the build, the only part that is not clear is how to generate the diff/change-report regarding differences found between current build and the last successful build.
Please note that I am looking for a pipeline compatible solution and ideally I would prefer to make this report easily accessible on Jenkins UI, like we currently have with SCM changelogs.
Or to rephrase this, how do I create build manifest and diff it against last known successful one? If anyone knows a standard manifest format that can easily be used to combine all these information it would be great.
you always ask the most baller questions, nice work. :)
we always try to push as many things into code as possible because of the same sort of lack of traceability you're describing with non-code configuration. we start with using Jenkinsfiles, so we capture a lot of the build configuration there (in a way that still shows changes in source control). for system tool packages, we get that into the app by using docker and by inheriting from a specific tag of the docker base image. so even if we want to change system packages or even the python version, for example, that would manifest as an update of the FROM line in the app's Dockerfile. Even environment variables can be micromanaged by docker, to address your other example. There's more detail about how we try to sidestep your question at https://jenkins.io/blog/2017/07/13/speaker-blog-rosetta-stone/.
there will always be things that are hard to capture as code, and builds will therefore still fail and be hard to debug occasionally, so i hope someone pipes up with a clean solution to your question.

Change the release process from SNAPSHOT to build number

Currently we are using axion-release-plugin to control our release process. Now we would like to drop the SNAPSHOT and introduce the build number in our release process. So that we can achieve CI.
Basically currently we are using version 1.0.0-SNAPSHOT and now we need something like 1.0.0-BUILDNUMBER or 1.0.BUILDNUMBER from Jenkins.
Please provide any solution or plugin we can use with gradle.
I'm actually quite happy with nebula-release-plugin developed by NetFlix. It can generate a unique version number based on branches and tags in your git repo.
By default it counts with using git flow, but you can reconfigure the behaviour. Take a look :)

Docker: What are the best practices when tagging images for an environment

I have multiple environments. They are debug, dev, and prod. I'd like to refer to an image by the latest dev (latest) or dev (version 1.1) or prod (latest). How would I go about tagging builds and pushes?
My first thought was to create separate repositories for each environment debug, dev, and prod. But I am starting to wonder if I can do this with just one repository. If its possible to do with one container what would the syntax be when building and pushing?
This is what has worked best for me and my team and I recommend it:
I recommend having a single repo per project for all environments, it is easier to manage. Especially if you have microservices, then your project is composed by multiple microservices. Managing one repo per env per project is a pain.
For example, I have a users api.
The docker repo is users. And this repo is used by alpha, dev and beta.
We create an env variable called $DOCKER_TAG in our CI/CD service and set it at the time the build is created, like this:
DOCKER_TAG: $(date +%Y%m%d).$BUILD_NUMBER => This is in bash.
Where $BUILD_NUMBER is previously set by the build being run when the CI/CD run is triggered. For example, when we merge a PR, a build is triggered, as build no. 1, so $BUILD_NUMBER: 1.
The resulting tag looks like this when used: 20171612.1
so our docker image is: users:20171612.1
Why this format?
It allows us to deploy the same tag on different environments with a
run task.
It helps us keep track when an image was created and what
build it belongs to.
Through the build number, we can find the commit information and map all together as needed, nice for trobleshooting.
It allows us to use the same docker repo per project.
It is nice to know when we created the image from the tag itself.
So, when we merge, we create a single build. Then that build is deployed as needed to the different environments. We don't create an independent build per environment. And we keep track on what's deployed where.
If there's a bug in an environment with certain tag, we pull such tag, build and trobleshoot and reproduce the issue under that condition. If we find an issue, we have the build number in the tag 20171612.1 so we know the build no. 1 has the issue. We check our CI/CD service and that tells us what commit is the most current. We check out that commit hash from git and debug and fix the issue. Then we deploy it as a hotfix, for example.
If you don't have a CI/CD yet, and you are doing this manually, just set the tag in that format manually (pretty much type the full string as is) and instead of a build number, use a commit short git hash (if you are using git):
20170612.ed73d4f
So you know what is the most current commit so you can troubleshoot issues with a specific image and map back to the code to create fixes as needed.
You can also define any other suffix for your tag that maps to the code version, so you can easily troubleshoot (e.g. map to git tags if you are using those).
Try it, adjust it as need it and do what it works best for you and your team. There's many ways to go around tagging. We tried many and this one is our favorite so far.
Hope this is of help.
There's two schools of thought, stable tagging, where you update a single tag, and unique tagging. Each have their pros and cons. Stable tags can create instability when deploying to self healing clusters as a new node might pull a new version, while the rest of the cluster is running a slightly older version. Unique tagging is a best practice for deployment. However, to manage base image updates of OS & Framework patching, you'll want to build upon stable tags in your dockerfile, and enable automatic container builds. For a more detailed walk through, with visuals, here's a post:
https://blogs.msdn.microsoft.com/stevelasker/2018/03/01/docker-tagging-best-practices-for-tagging-and-versioning-docker-images/
I think "lastest" is for the last productive image. It is what I expect in the docker hub, although there are no images in development.
On the other hand you can use tags like for example 0.0.1-dev. When this image is finished you can do the tag again and push, and then the repository will detect that the layers are already in the repository.
Now when you are about a candidate version to come out to production, you have to only have the semantic version despite not being in an environment pruduccion. That's what I would do.

Whats the best way to support next versions of your SDKs/Frameworks in GitHub or Bitbucket?

I mean is it ok to have v1.0 as main branch and v2.0 as subbranch? And what if I'll create v3.0 SDK, subbranch of a branch v2.0?
OR
create new repo with "v2.0"/"v3.0" postfixes?
So the question is: what is the best way to support multiple different versions of your SDK and in the same time keep them in one place ?
Thx.
I would definitely create different repos per version. Assuming that those versions are different enough to be called 1.0, 2.0, 3.0. That will make life really easy for you in order to manage pull requests. Also better when it comes to branch generation.
IMHO, if you keep only one branch alive and overwrite versions, could be a mess in the end. Imagine that you have a new feature under development (v1.0) pending from an specific commit, whilst v2.0 has been improved and it os ready to be delivered. Sum up a pull request from a developer that has fixed loads of bugs in an early release of v1.0....
In this case, again IMHO, divide and conquer. Repo per version. Branches per status (feature branches, stable branches, release branches), and pull requests to handle external changes.
Hope you like it!

Using git for version control [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is a version control system? How is Git useful?
I am new to Ruby on Rails platform, and so this may sound a little naive.
Why and when do we store our work in a version control system like git?
I mean what is the advantage of it ! Can't we just keep it in our local machine ?
Advantages for using git/source control:
For yourself
Remembering what you have coded and when you did it
Being able to compare what you did to previous work
Allow you to work on something experimental, and if it doesn't work switch it back to where it was before
Working with a team
It makes working with others easier - you can work on the same file at the same time and really easily combine your changes.
It will allow you to work in multiple locations and easily have the most recent code
It will help in deploying your code to a server
Git workflow for teams
Git branching model
When to store or commit your work:
You want to do this each time you finish on a particular "idea" or piece of work you are working on. This means you can have a useful commit message and can go back im time to that feature you just wrote or that bug that you just fixed.
How often and when to commit
Reasons for using Git over other source control
Its fast (switching branches is really fast and you have a local copy, so you dont have to communicate to a server for a lot of things unless you want to push or pull changes to the server)
Yes, this seems quite naive, but every question is worth asking!
First of all, using a SCM (software configuration manager) will greatly help you in a number of scenarios:
trying out experimental features without touching the main code
developing several independent ideas at the same time
recovering from failed changes, whenever they are complex and include changes in multiple files.
tracking the exact code used in a specific release, to fix a reported bug.
This doesn't even start to touch the infinite amount of work you'd have if working in a team without SCM.
And using a SCM doesn't involve network, git and any other distributed SCM is equally valid for local development, as the repository is all in your computer. You just don't pull and push.
The choice is not whether to store code in version control versus storing it on your local machine. In fact, unlike other version control systems (like Subversion, known also as svn), Git does not need a server to run.
Version control makes it easy to understand what changes were made, view and restore older versions of files, and even import changes from one version to another.
RETRIEVAL: Imagine you are working on a project on your own. You delete an old file you don't think you need anymore. A week later, you realize that the file was very important. If you use version control, you can see what the file looked like just before you deleted it, and restore it as if it were never deleted. Also, most changes committed to version control contain messages; if you join a team and the previous developer used version control (with good commit messages) you can get an easier context for when changes were made and why.
MULTIPLE RELEASES (BRANCHES): Now imagine that your software is version 1.0. You're busy working on version 2.0, but someone files a bug. What can you do? With version control, you can zoom back to version 1.0, make some changes, and then create version 1.0.1. Most version control platforms even let you apply the changes made in version 1.0.1 onto the work you're doing in version 2.0.
MULTIPLE FEATURES: Your software is so successful, you start releasing it weekly. However, not every feature is ready for release. First you start working on the widget feature, than you start working on the doodad feature. If you work on both of these at the same time, you may have two half-coded features in development at the same time, and nothing is working well enough to release. With version control, once one of the features is done, you can merge it into the "main" release as if you wrote it in one day.
COLLABORATION: Finally, now imagine that you're in a team of five or six developers all working on the same code. Naturally, you don't want to email zip files of code back and forth, especially when every developer is working on a separate feature. With version control, you can have a single history, to which all of your developers write and read.
Naturally, some of the above can be done by keeping multiple copies of the same files in different adjacent directories. The benefit of version control software is that it can handle much of the work for you while avoiding duplicating the same file over and over on your disk.
Long winded--sorry--but hope that helps!
Advantages of using git:
Code will be safe in remote repo, even if the local project crashes
You can try out new things without worrying about previous works as they can retrieved
The code can accessed from anywhere in the world
When working in team, all the work will be stored in a single place so that it will be accessible to everybody in your team
Each and every change can be tracked easily, who did it and when they did it
Deployment of application will more easier
You can have multiple versions/branches so that it will be easy for you to identify the new features added to the application in every version
you see #arulmr, #kieran-andrews, #Jeff and #rewritten that post many advantages but still if you want learn more in details you can see below links
1) http://git-scm.com/book/ch8-1.html
2) http://www-oss.fnal.gov/~mengel/git_vs_subversion.html.bak
3) https://git.wiki.kernel.org/index.php/GitSvnComparison
4) http://www.wikivs.com/wiki/Git_vs_Subversion #History, Architecture, Licensing, Performance, Features of git and svn
now the difference between git and subversion
1) http://boxysystems.com/index.php/5-fundamental-differences-between-git-svn/

Resources