Added PHP & NPM doc

This commit is contained in:
Ionut Staicu 2016-09-04 23:20:54 +03:00
parent 256a7735f8
commit 09beeb87ce
2 changed files with 156 additions and 0 deletions

View File

@ -14,6 +14,12 @@ Apart from those, here is an collection of tutorials and guides on setting up yo
- [Test a Phoenix application](test-phoenix-application.md)
- [Using `dpl` as deployment tool](deployment/README.md)
- [Example project that shows how to use Review Apps](https://gitlab.com/gitlab-examples/review-apps-nginx/)
- [Run PHP Composer & NPM scripts then deploy them to a stage server](deployment/composer-npm-deploy.md)
- Help your favorite programming language and GitLab by sending a merge request
with a guide for that language.
## Outside the documentation
- [Blog post about using GitLab CI for iOS projects](https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/)
- [Repositories with examples for various languages](https://gitlab.com/groups/gitlab-examples)
- [The .gitlab-ci.yml file for GitLab itself](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml)

View File

@ -0,0 +1,150 @@
## Running Composer and NPM scripts with deployment via SCP
This guide covers the building dependencies of a PHP project while compiling assets via a NPM script.
While is possible to create your own image with custom PHP and Node JS versione, for brevity, we will use an existing [Docker image](https://hub.docker.com/r/tetraweb/php/) that contains both PHP and NodeJS installed.
```yaml
image: tetraweb/php
```
The next step is to install zip/unzip packages and make composer available. We will place these on `before_scripts` section:
```yaml
before_script:
- apt-get update
- apt-get install zip unzip
- php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
- php composer-setup.php
- php -r "unlink('composer-setup.php');"
```
This will make sure we will have all required stuff ready to use. Next, we want to run `composer update` to fetch all PHP dependencies and `npm install` to load node packages then run the `npm` script. We need to append them into `before_script` section:
```yaml
before_script:
# ...
- php composer.phar update
- npm install
- npm run deploy
```
In this particular case, the `npm deploy` script is a Gulp script that do the following:
1. Compile CSS & JS
2. Create sprites
3. Copy various assets (images, fonts) around
4. Replaces some strings
All these operations will put all files into a `build` folder, which is ready to be deployed to a live server.
### How to transfer files on a live server?
You have multiple options: rsync, scp, sftp and so on. For now, we will use scp. To make this work, you need to add a gitlab Secret Variable (accessible on _gitlab.com/your-project-name/variables_). That variable will be called `STAGING_PRIVATE_KEY` and it's the **private** ssh key of your server.
#### Security tip
Create an user that have access **only** to the folder that need to be updated!
After you create that variable, you need to make sure that key will be added to the docker container on run:
```yaml
before_script:
# - ....
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- mkdir -p ~/.ssh
- eval $(ssh-agent -s)
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
```
In order, this means that:
1. We check if the `ssh` is available and we install it if it's not;
2. create the `~/.ssh` folder;
3. we make sure we're running bash;
4. we disable host checking (we don't ask for user accept when we first connect to a server; and since every build will equal a first connect, we kind of need this)
And this is basically al you need on `before_script` section.
## How to deploy things?
As we stated above, we need to deploy the `build` folder from the docker image to our server. To do so, we create a new job:
```yaml
stage_deploy:
artifacts:
paths:
- build/
only:
- dev
script:
- ssh-add <(echo "$STAGING_PRIVATE_KEY")
- ssh -p22 server_user@server_host "mkdir htdocs/wp-content/themes/_tmp"
- scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/_tmp
- ssh -p22 server_user@server_host "mv htdocs/wp-content/themes/live htdocs/wp-content/themes/_old && mv htdocs/wp-content/themes/_tmp htdocs/wp-content/themes/live"
- ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/_old"
```
### What's going on here?
1. `only:dev` means that this build will run only when something is pushed on the `dev` branch. You can remove this block completely and have everything be ran on every push (but probably this is something you don't want)
2. `ssh-add ...` we will add that private key you added on the web UI to the docker container
3. we will connect via `ssh` and create a new `_tmp` folder
4. we will connect via `scp` and upload the `build` folder (which was generated by a `npm` script) to our previously created `_tmp` folder
5. We will connect again to `ssh` and move the `live` folder to an `_old` folder, then move `_tmp` to `live`.
6. We connect to ssh and remove the `_old` folder
What's the deal with the artifacts? We just tell Gitlab CI to keep the `build` directory (later on, you can download that as needed).
#### Why we do it this way?
If you're using this only for stage server, you could do this in two steps:
```yaml
- ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/live/*"
- scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/live
```
The problem is that there will be a small period of time when you won't have the app on your server.
So we use so many steps because we want to make sure that at any given time we have a functional app in place.
## Where to go next?
Since this was a WordPress project, I gave real life code snippets. Some ideas you can pursuit:
- Having a slightly different script for `master` branch will allow you to deploy to a production server from that branch and to a stage server from any other branches;
- Instead of pushing it live, you can push it to WordPress official repo (with creating a SVN commit & stuff);
- You could generate i18n text domains on the fly;
---
Our final `.gitlab-ci.yml` will look like this:
```yaml
image: tetraweb/php
before_script:
- apt-get update
- apt-get install zip unzip
- php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
- php composer-setup.php
- php -r "unlink('composer-setup.php');"
- php composer.phar update
- npm install
- npm run deploy
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- mkdir -p ~/.ssh
- eval $(ssh-agent -s)
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
stage_deploy:
artifacts:
paths:
- build/
only:
- dev
script:
- ssh-add <(echo "$STAGING_PRIVATE_KEY")
- ssh -p22 server_user@server_host "mkdir htdocs/wp-content/themes/_tmp"
- scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/_tmp
- ssh -p22 server_user@server_host "mv htdocs/wp-content/themes/live htdocs/wp-content/themes/_old && mv htdocs/wp-content/themes/_tmp htdocs/wp-content/themes/live"
- ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/_old"