Restrict people from running production pipelines - gitlab

I'm evaluating gitlab community edition as a self hosted version. Everything is fine with the product except anyone who has access to pipelines (master or admin) can run deployment on production.
I saw their issue board and i see that this is a feature that will not be coming to gitlab anytime soon.
See https://gitlab.com/gitlab-org/gitlab-ce/issues/20261
For now, I plan on deploying my spring boot applications using the following strategy.
A separate runner installed on the production server
There will be an install script with instructions some where in production server
gitlab-runner user will only have permissions to run the above specific script (Somehow).
Have validations in the script for GITLAB_USER_NAME variable.
But I also see that there are disadvantages in this approach.
GITLAB_USER_NAME is an environment variable which can be overridden easily thus compromising the validation.
Things are complicated when introducing new prod servers.
Too many changes apart from .gitlab-ci.yml... CI/CD was supposed to be simple not painful...
Do I have any alternate approaches or hacks for this...?

Related

Terraform mixed VCS + API driven runs, applying non-default-branch configuration versions

I am using a terraform enterprise instance to manage three workspaces that represent infrastructure for the various environments of an application (development, pre-prod and prod have isolated infrastructure). The workspaces themselves are configured using a tfe_workspace resource.
I'm using a VCS-driven flow to create the configuration versions as I need speculative plan runs on PRs and I'm fine with automatic runs being created for master. I'm using the API to determine when to apply runs so that the staging environment can be applied and have automated tests run against it before the production workspace run is applied.
This works fairly well, except that I have been unable to use the api to apply non-default-branch configuration versions (i.e. from a PR) to the development workspace. Any run I create using a configuration version that was not created from the master branch does creates a plan-only run.
Is there a way via the Terraform Enterprise API to apply a PR configuration version?
I was able to work around this by not reusing the PR's configuration version, and creating one of my own via the API instead.

What workflow should I use to deploy a NodeJS app to a fixed server?

I work at a tiny company where deployment is mainly done by pulling master to a production server and running several scripts. We use PM2 which has some simple deployment features, but I'm not sure how to arrange the moving parts together to make everyone happy.
What I want to accomplish is having one fire-and-forget command to run on my dev machine that will result in everything being where it's supposed to be. What my boss wants to accomplish is to at no point have to do any lengthy step on the server to minimize downtime - so no building and no NPM install. To this end he wants builds and node_modules in Git and I think that's an abomination before the gods, so I'm trying to figure out how to avoid those.
Things that are a no-go for now: building and deploying Docker images, CI/CD. We don't have the infrastructure set up for those, and I'm more interested in using tools we already have and getting rid of human intervention in those. (Their popularity unfortunately also makes it hard to research best practices for more legacy environments.)
I'm not very familiar with PM2 and most of my experience is in environments where deployment was somebody else's job, so what I'm looking for is an outline of what gets done to what where provided by somebody that actually knows what they're talking about.
My current rough idea is:
Switch the project to Yarn 2 and use it's zero-install capability to have dependencies in Git but sane.
In a Docker container on the dev machine, do a clean checkout, install, and build. (This is to get rid of "works on my machine" issues and avoid inadvertently checking in macOS binaries.)
Push this to a release branch - these are the only ones where build outputs and such are allowed.
Then use PM2 to pull this specific branch and reload on the target machine.
Is this something that looks workable? Am I missing something? Is it possible to somehow avoid the release branches?

Good practices for pulling from git repo into production server

I have a DigitalOcean VPS with ubuntu and a few laravel projects, for my projects initial setup I do a git clone to create a folder with my application files from my online repository.
I do all development work in my local machine, where I have two branches (master and develop), what I do is merge develop into my local master, then I push from master into my local repository.
Nw back into my production server, when I want to add all the changes added into production I do a git pull from origin, so far this has resulted into git telling me to stash my changes, why is this?
What would be the best approach to pull changes into production server? take in mind that my production server has no working directory perse, all I do in my VPS is either clone or push upgrades into production.
You can take a look at the CI/CD (continuous integration / continuous delivery) systems. GitLab for example offer free-to-use plan for small teams.
You can create a pipeline with a manual deploy step (you have to press a button after the code is merged to the master branch) and use whatever tool you like to deploy your code (scp, rsync, ftp, sftp etc.).
And the biggest benefit is that you can have multiple intermediate steps (even for the working branches) where you can run unit tests which would prevent you to upload failing builds (whenever you merge non-working code)
For the first problem, do a git status on production to see which files that git sees as changed or added and consider adding them to your .gitignore file (which itself should be a part of your repo). Laravel generally has good defaults for these, but you might have added things or deviated from them in the process of upgrading Laravel.
For the deployment, the best practice is to have something that is consistent, reproducible, loggable, and revertable. For this, I would recommend choosing a deployment utility. These usually do pretty much the same thing:
You define deployment parameters in code, which you can commit as a part of your repo (not passwords, of course, but things like the server name, deploy path, and deploy tasks).
You initiate a deploy directly from your local computer.
The script/utility SSH's into your target server and pulls the latest code from the remote git repo (authorized via SSH key forwarded into the server) into a 'release' folder.
The script does any additional tasks you define (composer install, npm run prod, systemctl restart php-fpm, soft-linking shared files like .env, and etc.)
The script soft-links the document root to your new 'release' folder, which results in an essentially zero-downtime deployment. If any of the previous steps fail, or you find a bug in the latest release, you just soft-link to the previous release folder and your site still works.
Here are some solutions you can check out that all do this sort of thing:
Laravel Envoyer: A 1st-party (paid) service that allows you to deploy via a web-based GUI.
Laravel Envoy: A 1st-party (free) package that allows you to connect to your prod server and script deployment tasks. It's very bare-bones in that you have to write all of the commands yourself, but some may prefer that.
Capistrano: This is (free) a tried-and-tested popular ruby-based deployment utility.
Deployer: The (free) PHP equivalent of Capistrano. Easier to use, has a lot of built-in tasks (including a Laravel one), and doesn't require ruby.
Using these utilities is not necessarily exclusive of doing CI/CD if you want to go that route. You can use these tools to define the CD step in your pipeline while still doing other steps beforehand.

How does deployment on remote servers work?

I'm a bit new to version control and deployment environments and I've come to a halt in my learning about the matter: how do deployment environments work if developers can't work on the same local machine and are forced to always work on a remote server?
How should the flow of the deployment environments be set up according to best practices?
For this example I considered three deployment environments: development, staging and production; and three storage environments: local, repository server and final server.
This is the flow chart I came up with but I have no idea if it's right or how to properly implement it:
PS. I was thinking the staging tests on the server could have restricted access through login or ip checks, in case you were wondering.
I can give you (according to my experience) a good and straightforwarfd practice, this is not the only approach as there is not a unique standard on how to work on all projects:
Use a distributed version control system (like git/github):
Make a private/public repository to handle your project
local Development:
Developers will clone the project from your repo and contribute to it, it is recommended that each one work on a branch, and create a new branch for each new feature
Within your team, there is one responsible for merging the branches that are ready with the master branch
I Strongly suggest working on a Virtual Machine during Development:
To isolate the dev environment from the host machine and deal with dependencies
To have a Virtual Machine identic to the remote production server
Easy to reset, remove, reproduce
...
I suggest using VirtualBox for VM provider and Vagrant for provisioning
I suggest that your project folder be a shared folder between your host machine and your VM, so, you will write your source codes on your host OS using the editor you love, and at the same time this code exists and runs inside your VM, is in't that amazingly awesome ?!
If you are working with python I also strongly recommend using virtual environments (like virtualenv or anaconda) to isolate and manage inner dependencies
Then each developer after writing some source code, he can commit and push his changes to the repository
I suggest using project automation setup tools like (fabric/fabtools for python):
Making a script or something that with one click or some commands, reproduces all the environment and all the dependencies and everything needed by the project to be up and running, so all developers backend, frontend, designers... no matter their knowlege nor their host machine types can get the project running very merely. I also suggest doing the same thing to the remote servers whether manually or with tools like (fabric/fabtools)
The script will mainly install os dependencies, then project dependencies, then cloning the project repo from your Version Control, and to do so, you need to Give the remote servers (testing, staging, and production) access to the Repository: add ssh public keys of each server to the keys in your Version Control system (or use agent forwarding with fabric)
Remote servers:
You will need at least a production server which makes your project accessible to the end-users
it is recommended that you also have a testing and staging servers (I suppose that you know the purpose of each one)
Deployment flow: Local-Repo-Remote server, how it works ?:
Give the remote servers (testing, staging, and production) access to the Repository: add ssh public keys of each server to the keys in your Version Control system (or user agent forwarding with fabric)
The developer writes the code on his machine
Eventually writes tests for his code and runs them locally (and on the testing server)
The developer commits and pushes his code to the branch he is using to the remote Repository
Deployment:
5.1 If you would like to deploy a feature branch to testing or staging:
ssh access to the server and then cd to the project folder (cloned from repo manually or by automation script)
git checkout <the branch used>
git pull origin <the branch used>
5.2 If you would like to deploy to production:
Make a pull request and after the pull request gets validated by the manager and merged with master branch
ssh access to the server and then cd to the project folder (cloned from repo manually or by automation script)
git checkout master # not needed coz it should always be on the master
git pull origin master
I suggest writing a script like with fabric/fabtools or use tools like Jenkins to automate the deployment task.
VoilĂ ! Deployment is done!
This is a bit simplified approach, there are still a bunch of other recommended and best practice tools and tasks.

Deployment after CI builds

Im pretty new to CI so bear with me here. I have just setup an instance of Team City in on a local machine, and I can clearly see the benefits.
The one thing we do want understand is how we can managed the deployment aspect of CI. What we really want to achieve are two builds:
1) We check in to our source repository and the CI server notices the change and compiles the code, tests etc.
2) We manually trigger a build that compiles the code, copies the code to a remote server and update its IIS mappings.
Now the first build is pretty much wrapped up with TeamCity. But I assume that the deployment aspect of this is going to involve some scripting (Nant, MsBuild, Rake etc) is this correct?
If this is the case, I can see that transferring files from the build machine to a remote server will be ok, but will we be able to update IIS mappings without being on the same network? For that matter where is THE correct place to deploy a CI server, should is live on the same network as the apps we deploy?
Finally, we have been (rather unorthadoxily) using IronRuby to run rake scripts as our build runner. This is simply because we like Rake, but if we were to look at Nant/Msbuild do they have any baked in tasks that would simplify what we are trying to achieve?
Cheers, Chris.
We use MSBuild exclusively, just a choice. I am sure Nant and the others do things just as well. We only publish to a dev environment (for dev testing) and a stage environment (Where QA actually tests). I would not suggest that you put the production system push on this as the temptation to force builds might be too great for some people.
We use some of the MSBuild Community Tasks

Resources