# Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD

> 原文：[https://docs.gitlab.com/ee/ci/examples/deployment/composer-npm-deploy.html](https://docs.gitlab.com/ee/ci/examples/deployment/composer-npm-deploy.html)

*   [How to transfer files to a live server](#how-to-transfer-files-to-a-live-server)
    *   [Security tip](#security-tip)
*   [How to deploy](#how-to-deploy)
    *   [Why we do it this way](#why-we-do-it-this-way)
*   [Where to go next](#where-to-go-next)

# Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD[](#running-composer-and-npm-scripts-with-deployment-via-scp-in-gitlab-cicd "Permalink")

本指南涵盖了在使用[GitLab CI / CD](../../README.html)通过 NPM 脚本编译资产时，如何构建 PHP 项目的依赖项.

虽然可以使用自定义的 PHP 和 Node.js 版本创建自己的映像，但为了简便起见，我们将使用既包含 PHP 又安装 Node.js 的现有[Docker 映像](https://hub.docker.com/r/tetraweb/php/) .

```
image: tetraweb/php 
```

下一步是安装 zip / unzip 软件包并使 composer 可用. 我们将它们放在`before_script`部分中：

```
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');" 
```

这将确保我们已准备好所有要求. 接下来，我们要运行`composer install`来获取所有 PHP 依赖项，然后运行`npm install`来加载 Node.js 包，然后运行`npm`脚本. 我们需要将它们附加到`before_script`部分：

```
before_script:
  # ...
  - php composer.phar install
  - npm install
  - npm run deploy 
```

在此特定情况下， `npm deploy`脚本是执行以下操作的 Gulp 脚本：

1.  编译 CSS 和 JS
2.  Create sprites
3.  复制各种资产（图像，字体）
4.  替换一些字符串

所有这些操作会将所有文件放入一个`build`文件夹，该文件夹准备好部署到实时服务器中.

## How to transfer files to a live server[](#how-to-transfer-files-to-a-live-server "Permalink")

您有多种选择：rsync，SCP，SFTP 等. 现在，我们将使用 SCP.

为此，您需要添加一个 GitLab CI / CD 变量（可在`gitlab.example/your-project-name/variables` ）. 该变量将称为`STAGING_PRIVATE_KEY` ，它是服务器的**私密** SSH 密钥.

### Security tip[](#security-tip "Permalink")

创建一个**仅**可以访问需要更新的文件夹的用户.

创建该变量后，需要确保在运行时将密钥添加到 Docker 容器中：

```
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' 
```

按顺序，这意味着：

1.  我们检查`ssh-agent`是否可用，如果没有，则安装它.
2.  我们创建`~/.ssh`文件夹.
3.  我们确保正在运行 bash.
4.  我们禁用主机检查（当我们首次连接到服务器时，我们不要求用户接受，并且由于每个作业都将等同于首次连接，因此我们有点需要这样做）.

这基本上是您在`before_script`部分中所需要的.

## How to deploy[](#how-to-deploy "Permalink")

如上所述，我们需要将 Docker 镜像中的`build`文件夹部署到我们的服务器. 为此，我们创建了一个新作业：

```
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" 
```

这是细分：

1.  `only:dev`表示仅当将某些内容推送到`dev`分支时，此构建才会运行. 您可以完全删除此块，并在每次推送时都运行所有内容（但是这可能是您不想要的）
2.  `ssh-add ...`我们会将您在 Web UI 上添加的私钥添加到 Docker 容器中
3.  我们将通过`ssh`连接并创建一个新的`_tmp`文件夹
4.  我们将通过`scp`连接并将`build`文件夹（由`npm`脚本生成）上传到我们先前创建的`_tmp`文件夹中
5.  我们将再次通过`ssh`连接，然后将`live`文件夹移至`_old`文件夹，然后将`_tmp`移至`live` .
6.  我们连接到 SSH 并删除`_old`文件夹

这些文物怎么处理？ 我们只是告诉 GitLab CI / CD 保留`build`目录（以后，您可以根据需要下载该目录）.

### Why we do it this way[](#why-we-do-it-this-way "Permalink")

如果仅将其用于舞台服务器，则可以分两个步骤进行操作：

```
- 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 
```

问题在于，服务器将在短时间内没有该应用程序.

因此，对于生产环境，我们使用其他步骤来确保在任何给定时间都可以使用功能正常的应用程序.

## Where to go next[](#where-to-go-next "Permalink")

由于这是一个 WordPress 项目，因此我给出了真实的代码片段. 您可以追求一些进一步的想法：

*   `master`分支的脚本稍有不同，将使您可以从该分支部署到生产服务器，并从任何其他分支部署到阶段服务器.
*   除了将其实时发布之外，您还可以将其推送到 WordPress 官方存储库（创建 SVN 提交等）.
*   您可以动态生成 i18n 文本域.

* * *

我们最终的`.gitlab-ci.yml`将如下所示：

```
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 install
  - 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" 
```