Where does GitLab execute its environment job? - environment

I'm looking over the docs on environments. I'm trying to understand what these statements actually mean in terms of what server executes the script.
Environments are like tags for your CI jobs, describing where code gets deployed.
The environment keyword is just a hint for GitLab that this job actually deploys to this environment's name.
It makes use of non-difinitive terms 'like' and 'hint' so does it actually execute on Runners tagged with the environment name?
It also states:
If you have a deployment service such as Kubernetes enabled for your project, you can use it to assist with your deployments
Is that a requirement to utilize environments or just a helpful manager?
And I guess my final question would be, if I have multiple runners tagged with an environment (assuming that is how it works) would the job execute on all runners unlike tags which just choose any runner that matches?

The environment name has no effect on the execution location, it is used for display purposes in the Environment UI.
Tags are still specified on the deployment step to determine where execution is run. This does not require Kubernetes to use, but I suspect that functionality with environment management is greatly reduced.

Related

Promoting code through environments in AWS Fargate

I have a scheduled job that I want to run in AWS Fargate. I have so far setup a CloudWatch schedule that runs a lambda function that starts the task. I'm using a task definition for each of my environments, but I'm struggling to find an easy way for our QA and PM to promote code from the dev environment to QA, Staging, and Prod. Each environment will have its own CloudWatch rule and its own lambda function.
How can I setup deployments to each environment, preferably without building a web interface tool that will allow them to select versions from a dropdown or something? I also have to consider that each environment will need its own environment variables that may need to change on the fly.
We're going to be using CircleCI's approval hold to manage deployment to each environment. This solution doesn't offer any easy rollback of versions, but documentation can be found here.

Jenkins with Shared jobs

I am working with Jenkins, and we have quite a few projects that all use the same tasks, i.e. we set a few variables, change the version, restore packages, start sonarqube, build the solution, run unit/integration tests, stop sonarqube etc. The only difference would be like {Solution_Name}, everything else is exactly the same.
What my question is, is there a way to create 1 'Shared' job, that does all that work, while the job for building the project passes the variables down to that shared worker job. What i'm looking for is the ability to not have to create all the tasks for all of our services/components. It be really nice if each of our services/components could have only 2 tasks, one to set the variables, another to run the shared job.
Is this possible?
Thanks in advance.
You could potentially benefit from looking into the new pipelines as code feature.
https://jenkins.io/doc/book/pipeline/
Using this pattern, you define your build pipeline in a groovy script rather than the jenkins' UI. This script is then kept in the codebase of the project it builds in a file called Jenkinsfile.
By checking this pipeline into a git repository, you can create a minimal configuration on the jenkins' side and simply tell it to look towards a specific repo and do the things that pipeline says to do.
There's a few benefits to this approach if it works for your setup. The big one being that your build pipeline will be fully versioned just like the project it builds. And the repository becomes portable, easily able to be built on any jenkins' installation across as many jobs as long as the pipeline plugins are installed.

CI/CD with Jenkins and Vagrant

I wanted to build a Jenkins server which would run test of my puppet code on Vagrant. The issue I found is that the we run our server as VMs already, either in vmWare or AWS and Vagrant will not work as another virtualisation.
Does anyone have an idea how can I create a test platform for my puppet code. What I want to test the deployment of manifest on the nodes them self i.e. If I deploy a class web server or make changes to it I would like to check if it affects/breaks deployment of other classes.
The idea would be to iterate over all the classes/roles and see if the deployments are passing. I would like to make it automatic and independent of our engineers. At the moment we are running manual test with vagrant up however there are too many roles to do that by hand.
Any ideas how can I tackle this?
You can use either Docker or AWS provider for Vagrant.
In case of AWS provider you need to set-up RSync to get your environment into newly launched instance.
If your Vagrant scripts are robust, you can use the same script for both local deployment on your workstation and AWS/Docker deployment on CI server.
There are drawbacks to doing these techniques, in case of Docker you are limited to the same kernel that Jenkins server is running, in case of AWS you will incur additional costs. However, for AWS your don't need to allocate as much resources for your Jenkins server, so you might even save money this way because you will be using paying for extra VMs only when you are running you tests. Just make sure you will shut them down after you done.
Is there any special reason why you want to use vagrant? I'm not sure if you are setting up your production environment with vagrant or not.
In case you are not bound to vagrant, I would recommend you to think about using a docker image to prepare a lightweight environment to run your setups and verifications in.
When doing your tests, spin up a container from your image that contains your puppet distribution and run your setups/tests inside. If you have special kernel requirements, use a separate jenkins slave/agent machine rather than executing jobs on the jenkins master.
If you are not sure how to get started using jenkins with docker, have a look into the examples section of the Jenkins Documentation. The provided examples are showing the declarative pipeline syntax thats still a bit new. Also consider the collapsed Toggle Scripted Pipeline Sections which show the groovy pipeline scripts that are alot more forgiving for jenkins pipeline beginners.
Those should be quite good pointers to get started with running+testing your puppet scripts inside docker. For building and using a docker image there should be more than enough tutorials out there.
Let me know if this was a hint in the right direction or if I mistinterpreted your question.

setting and accessing global environment variable in Jenkins

I have a Jenkins pipeline view. Say for example the first job is BUILD followed by DEPLOY and TEST job. What I'm trying to achieve here is to have a 'rollback logic' in the test job, meaning when the test job is run and it is successful I want to set current build no as a global environment variable (so that I can potentially access build number from any job) possibly called TESTED_BUILD_NO. But if test fails then I want to trigger DEPLOY job by passing TESTED_BUILD_NO which will deploy last test build.
There is a plugin called promotion builds plugin, it mentions PROMOTION_BUILD_NO variable but when I look at /env-vars.html it is not listed there. I tired looking at api/xml as well but no mention of any promotion variables. Can this logic I mention here be achieved using this plugin? If not how is global environment set and accessed in Jenkins?
Instead of using global variables, you can always use lastStableBuild, which is automatically set by jenkins. In DEPLOY job, use link to lastStableBuild from TEST job, which form is : http://JENKINS_ADDRESS/job/JENKINS_JOB/lastStableBuild/
According to jenkins wiki:
Stable build A build is stable if it was built successfully and no publisher reports it as unstable.
You are best advised to manage global variables from the system management screens:
Manage Jenkins -> Configure System -> Global Properties
Much more reliable compared to setting these externally to Jenkins.
this can be changed using script or via execute shell/batch.
Or you can use simple groovy scrip to change the value based on Previous command/build status.

How do you manage multiple releases in multiple environments in continuous integration/delivery?

I am trying to wrap my head around this. Most CI/CD examples/projects have a single master that is always released, and have some variant of, e.g. git-flow, to have a develop branch. Once tagged, it goes to master.
Either way, master is always released to production.
But in the real world as I see it, there are human gates for release to production and other environments. What mechanism do you use to manage the deployment of different versions?
For example:
v1.5 is the current production release
v1.6 has passed all tests, artifacts are ready, it is tagged as valid, but business decides to deploy it only to staging, awaiting an opportune moment to deploy
v1.5 is deployed to a demo environment
v2.0 has also passed all tests, but is in UAT, subject to the customer being happy, as it is a major release
There could be many more such environments - production, staging, UAT, demo, demo2, etc.
What mechanism do you use to handle the tagging of a particular version for a particular environment, and the actual deployment thereof?
Although there a probably a few ways to do it, I use the build pipeline plugin https://wiki.jenkins-ci.org/display/JENKINS/Build+Pipeline+Plugin Along with the copy artifacts plugin https://wiki.jenkins-ci.org/display/JENKINS/Copy+Artifact+Plugin
With these, you can create individual jobs for each piece of your environment, and link them altogether.
So as in your example, the pipeline would look like:
Build -> Test and Deploy to UAT (2.0) -> deploy to staging(1.6) -> demo(1.5) -> prod (1.5)
Each piece represents a different build in jenkins. The idea behind continuous integration is you create the binaries once, and you carry it down the pipeline, only changing configuration pieces along the way. In a build job, the artifacts are created and then archived. In any jobs after, the artifact is picked up from the upstream job, some stuff is done, and then it get's re-archived for the next downstream job. So the deploy to staging would go to the Test and Deploy to Uat job to get its binary. The entire concept of Continuous Delivery boils down to the the build pipeline. http://en.wikipedia.org/wiki/Continuous_delivery (and yes I did just cite wikipedia).
As for tagging individual binaries for specific environments, that is by definition, not continuous integration. A binary is suppose to be created in a way that it can easily be propagated from one environment to the next. So unfortunately, individual builds for specific environments can never be continuous delivery. You can use jenkins as a CI server all you want, but if your process does not match, you will never achieve true continuous integration.
Braching, merging and checkins always seems to be a touchy subject when it comes to Continuous Integration, so I won't go into it much. But a lot of people share the idea that : "If different members of the team are working on separate branches, then by definition, they not participating in continuous integration process." http://eugenedvorkin.com/continuous-integration-strategies-for-branching-and-merging/
EDIT
For Flagging specific builds, it sounds like your looking to take use of this feature : https://wiki.jenkins-ci.org/display/JENKINS/Fingerprint ... Which gets the job done effectively, giving you the entire life of any individual artifact. A bit more complex solution would be artifactory, which is essentially artifact source control.
I explained the concept of the deployment process above, and without information on your specific environment it is hard to go much further. But for me, for java applications deployed to tomcat containers, the deploy plugin works great https://wiki.jenkins-ci.org/display/JENKINS/Deploy+Plugin
You shouldn't have to worry about selection of which artifact to deploy. The pipeline should be setup to always deploy the latest artifact that was archived in its corresponding upstream job.
Maybe Docker can help you out with this issue. It is able to deploy images of projects to a specific environment. If that environment has a docker client or a docker deamon you are able to request specific information about that environment and the project (to be) deployed on it.
Jenkins can still play a huge part in your pipeline for the integration part and you could let docker do the delivery part.
Docker: https://www.docker.com
Docker plugin for jenkins: https://wiki.jenkins-ci.org/display/JENKINS/Docker+build+step+plugin
Docker also has support for windows machines and .NET.

Resources