GulpJS - deploy com Rsync

Fazer deploy via FTP é um trabalho bem chato e custoso. Agora que já sabemos como usar o GulpJS, que tal utilizá-lo para fazer deploy do nosso projeto via SSH, usando Rsync, e com apenas um simples comando, sincronizar nosso ambiente local com o ambiente de produção? Duvida? Vem ver! ;)

E pra começar, vou mostrar que pra usar o Gulp, você não precisa ficar preso a um plugin específico. No repositório de plugins do GulpJS, se buscar por rsync, você vai encontrar o plugin gulp-rsync, mas não vamos utilizá-lo :P

Vamos usar um módulo do NodeJS, chamado rsyncwrapper.

Começando do começo

Vamos criar a estrutura do nosso projeto:

1
2
3
4
5
.
├── build
│   ├── // ... arquivos que irão para o servidor ...
├── gulpfile.js
└── package.json

Como você já sabe, o package.json deve ter somente {} como conteúdo.

No diretório build, você vai colocar os arquivos que quer que sejam enviados ao seu servidor.

OBSERVAÇÃO IMPORTANTE: para fazer deploy com Rsync, você precisa ter acesso SSH liberado no seu servidor! (melhor avisar, antes que alguém comente dizendo que não funcionou :P)

Sabendo disso, vamos instalar os módulos necessários:

1
npm i --save-dev gulp rsyncwrapper

Acho que isso eu não falei ainda, mas você pode instalar vários módulos de uma só vez :D
Nesse caso, estamos instalando o gulp e o rsyncwrapper ao mesmo tempo, e salvando no package.json.

E vamos configurar nosso gulpfile.js:

1
2
3
4
5
6
7
8
9
10
var gulp = require( 'gulp' );
var rsync = require( 'rsyncwrapper' ).rsync;

gulp.task( 'default', function() {
rsync({
src: './build/',
dest: 'user@domain.com:/path/on/your/server',
recursive: true
});
});

Essa é a configuração mais simples para usar o rsync. Adicionamos ao nosso gulpfile.js o gulp e o rsyncwrapper, chamando o método rsync, mas sem invocá-lo.

Dentro da task, passamos um objeto como parâmetro da função rsync, com duas propriedades:

  • src: Caminho dos arquivos que serão “deployados” para o servidor;
  • dest: Caminho NO SERVIDOR que receberá os arquivos.
  • recursive: Passa recursivamente pelos diretórios em src para enviar os arquivos.

O formato para o dest é o seguinte:

  • nome do seu usuário;
  • arroba (@);
  • seu domínio;
  • dois-pontos;
  • caminho no servidor que receberá os arquivos.

Listei para ficar fácil você saber o que precisa ser mantido, e o que você precisa editar. Não sei se precisava, mas enfim…

Fazendo isso, pode rodar o comando gulp no terminal e conferir os arquivos no seu servidor!

Mas não tenho nenhum feedback visual! Como vou saber quando terminou de enviar os arquivos?

O rsyncwrapper tem algumas propriedades que podemos utilizar para facilitar nossa vida. Vamos a elas. Altere seu gulpfile.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
var gulp = require( 'gulp' );
var rsync = require( 'rsyncwrapper' ).rsync;

gulp.task( 'default', function() {
rsync({
src: './build/',
dest: 'user@domain.com:/path/on/your/server',
recursive: true,
args: [ '--verbose' ]
}, function( error, stdout, stderr, cmd ) {
console.log( stdout, 'END!' );
});
});

Passamos no primeiro parâmetro um objeto para a função rsync, com as propriedades src e dest. Como segundo parâmetro, podemos passar uma função de callback que será executada assim que todos os arquivos forem enviados!

Adicionamos também um parâmetro args, que receberá argumentos, como se você estivesse usando o rsync na linha de comando xD

Podemos passar para essa propriedade, um array de argumentos. Para conhecer todos os argumentos disponíveis para o rsync, visite https://rsync.samba.org/ftp/rsync/rsync.html

Tá ficando bom! Mas eu tenho muitos arquivos! Eu posso acompanhar um a um, enquanto estiverem subindo?

Sim! O rsyncwrapper tem um método onStdout, que recebe um parâmetro com o Buffer do arquivo que está sendo enviado. Vamos ver como utilizá-lo (vou colocar só a função rsync agora):

1
2
3
4
5
6
7
8
9
10
11
rsync({
src: './build/',
dest: 'user@domain.com:/path/on/your/server',
recursive: true,
args: [ '--verbose' ],
onStdout: function( data ) {
console.log( data.toString() );
}
}, function( error, stdout, stderr, cmd ) {
console.log( 'END!' );
});

Usamos a forma mais bruta para mostrar o nome do arquivo: convertê-lo para String, usando o .toString(). Agora, a cada arquivo que subir, será mostrado o nome no terminal, para que você possa acompanhar o progresso :D

Removi também do função de callback o stdout, para não mostrar duplicado o retorno.

Extras

Ainda podemos deixar melhor :D

Temos uma propriedade exclude, que recebe um array de arquivos que você NÃO quer enviar. Exemplo: você quer ignorar um .htaccess, ou qualquer outro arquivo? Adicione-o ao array em exclude. Ficaria algo como:

1
exclude: [ '.htaccess', '.editorconfig', 'node_modules' ]

Você pode usar também as propriedades delete: true ou deleteAll: true.

deleteAll vai sincronizar os arquivos em src com o dest. Se você remover algo local, ele vai remover do servidor também. Bruto assim.

delete também sincroniza, porém ele ignora os arquivos em exclude. Se você tem, por exemplo, localmente um diretório node_modules que não quer enviar para o servidor, mas tem um diretório com o mesmo nome no servidor, mas não quer deletá-lo, usando o delete esse diretório se manterá lá. Caso contrário, use o deleteAll.

Muito cuidado com essas opções! Você pode perder seus dados importantes se não configurar corretamente! Faça testes antes e verifique se está tudo ok antes de continuar!

Podemos também setar um formato de comparação, usando compareMode: 'checksum' ou compareMode: 'sizeOnly. checksum compara por um checksum de 128bit. sizeOnly só verifica se o tamanho do arquivo mudou. Recomendo que use o checksum, pois é mais preciso.

Adicionando algumas dessas opções, nosso gulpfile.js ficaria assim:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var gulp = require( 'gulp' );
var rsync = require( 'rsyncwrapper' ).rsync;

gulp.task( 'default', function() {
rsync({
src: './build/',
dest: 'user@domain.com:/path/on/your/server',
recursive: true,
args: [ '--verbose' ],
deleteAll: true,
compareMode: 'checksum',
onStdout: function( data ) {
console.log( data.toString() );
}
}, function( error, stdout, stderr, cmd ) {
console.log( 'END!' );
});
});

Para ver todas as opções do rsyncwrapper, acesse: https://github.com/jedrichards/rsyncwrapper

Por hoje é isso! Mas ainda temos muita coisa de Gulp para mostrar! Continue acompanhando :D

Sobre o #1postperday: https://blog.da2k.com.br/2014/12/31/um-post-por-dia/

Tem alguma sugestão para os próximos posts do #1postperday? Deixe ela aqui: https://github.com/fdaciuk/fdaciuk.github.io/issues/1