morganestes
10/31/2018 - 5:00 PM

Gulp tasks failing in GitLab CI

Gulp tasks failing in GitLab CI

dist/
bin/
node_modules/
vendor/
.csscomb.json
.deployignore
.editorconfig
.eslintignore
.gitignore
.gitlab-ci.yml
.jsbeautifyrc
composer.json
composer.lock
CONTRIBUTING.md
gulpfile.js
LICENSE
package-lock.json
package.json
phpcs.xml.dist
README.md
CHANGELOG.md
customizer.dat
LICENSE.md
widgets.wie
node_modules
aws.json
ssl.json
.DS_Store
/languages/
/assets/styles/min/
/assets/scripts/min/

/vendor/
/dist/
/style.css
image: bigwing/php-node-ci:latest

stages:
  - build
  - deploy

cache:
  key: "$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHA"
  untracked: false
  paths:
    - node_modules/
    - vendor/

build:
  stage: build
  variables:
    CI_DEBUG_TRACE: "false"
  artifacts:
    name: "$CI_COMMIT_SHA"
    paths:
      - dist/
    untracked: false
  script:
    - echo 'Building theme files...'
    - npm i -g npm
    - export BLUEBIRD_WARNINGS=0
    - npm ci
    - composer self-update
    - composer install --no-ansi --no-dev --no-interaction --no-progress --no-scripts
    - export DISABLE_NOTIFIER=true
    - gulp dist
  only:
    - staging
    - master
  tags:
    - gitlab-org

deploy_staging:
  environment:
    name: Staging
    url: https://staging.mycoolproject.com/
  stage: deploy
  variables:
    CI_DEBUG_TRACE: "false"
  script:
    - sh bin/deploy.sh $STAGE_USER $STAGE_PASS $STAGE_HOST $STAGE_PATH $CI_PROJECT_DIR/dist
  only:
    - staging
  tags:
    - gitlab-org

deploy_production:
  environment:
    name: Production
    url: https://mycoolproject.com/
  stage: deploy
  variables:
      CI_DEBUG_TRACE: "false"
  script:
    - sh bin/deploy.sh $PROD_USER $PROD_PASS $PROD_HOST $PROD_PATH $CI_PROJECT_DIR/dist
  only:
    - master
  tags:
    - gitlab-org
//process.env.DISABLE_NOTIFIER = true; // Uncomment to disable all Gulp notifications.
'use strict';

/**
 * Studio Pro.
 *
 * This file adds gulp tasks to the Studio Pro theme.
 *
 * @author SEO themes
 */

// Require our dependencies.
const autoprefixer = require( 'autoprefixer' ),
      mqpacker     = require( 'css-mqpacker' ),
      gulp         = require( 'gulp' ),
      babel        = require( 'gulp-babel' ),
      cache        = require( 'gulp-cached' ),
      cleancss     = require( 'gulp-clean-css' ),
      concat       = require( 'gulp-concat' ),
      csscomb      = require( 'gulp-csscomb' ),
      cssnano      = require( 'gulp-cssnano' ),
      del          = require( 'del' ),
      filter       = require( 'gulp-filter' ),
      imagemin     = require( 'gulp-imagemin' ),
      notify       = require( 'gulp-notify' ),
      pixrem       = require( 'gulp-pixrem' ),
      plumber      = require( 'gulp-plumber' ),
      postcss      = require( 'gulp-postcss' ),
      pump         = require( 'pump' ),
      rename       = require( 'gulp-rename' ),
      sass         = require( 'gulp-sass' ),
      sort         = require( 'gulp-sort' ),
      sourcemaps   = require( 'gulp-sourcemaps' ),
      uglify       = require( 'gulp-uglify' ),
      wpPot        = require( 'gulp-wp-pot' ),
      zip          = require( 'gulp-zip' ),
      focus        = require( 'postcss-focus' );

sass.compiler = require( 'node-sass' );

// Set assets paths.
const paths = {
	all: ['./**/*', '!./node_modules/', '!./node_modules/**', '!./screenshot.png', '!./assets/images/**'],
	concat: ['assets/scripts/concat/*.js'],
	images: ['assets/images/*', '!assets/images/*.svg'],
	php: ['./*.php', './**/*.php', './**/*.php', '!./vendor/**/*.php'],
	scripts: ['assets/scripts/scripts.js', 'assets/scripts/customize.js'],
	styles: ['assets/styles/*.scss', '!assets/styles/min/'],
	dist: ['./dist']
};

/**
 * Compile WooCommerce styles.
 *
 * https://www.npmjs.com/package/gulp-sass
 */
gulp.task( 'styles:woocommerce', () => {

	/**
	 * Process WooCommerce styles.
	 */
	return gulp.src( 'assets/styles/woocommerce.scss' )

	// Notify on error
		.pipe( plumber( {
			errorHandler: notify.onError( "Error: <%= error.message %>" )
		} ) )

		// Initialize source map.
		.pipe( sourcemaps.init() )

		// Process sass
		.pipe( sass( {
			outputStyle: 'expanded'
		} ).on( 'error', sass.logError ) )

		// Pixel fallbacks for rem units.
		.pipe( pixrem() )

		// Parse with PostCSS plugins.
		.pipe( postcss( [
			autoprefixer(),
			mqpacker( {
				sort: true
			} ),
			focus(),
		] ) )

		// Combine similar rules.
		.pipe( cleancss( {
			level: {
				2: {
					all: true
				}
			}
		} ) )

		// Minify and optimize style.css again.
		.pipe( cssnano( {
			safe: false,
			discardComments: {
				removeAll: true,
			},
		} ) )

		// Add .min suffix.
		.pipe( rename( {
			suffix: '.min'
		} ) )

		// Write source map.
		.pipe( sourcemaps.write( './', {
			includeContent: false,
		} ) )

		// Output non minified css to theme directory.
		.pipe( gulp.dest( 'assets/styles/min/' ) )

		// Filtering stream to only css files.
		.pipe( filter( '**/*.css' ) )

		// Notify on successful compile (uncomment for notifications).
		.pipe( notify( "Compiled: <%= file.relative %>" ) );
} );

gulp.task( 'styles:main', ( done ) => {

	pump( [gulp.src( 'assets/styles/style.scss' ),
	       plumber( {
		       errorHandler: notify.onError( "Error: <%= error.message %>" )
	       } ),
	       sourcemaps.init(),
	       sass( {
		       outputStyle: 'expanded'
	       } ),
	       pixrem( {
		       replace: true
	       } ),
	       postcss( [
		       autoprefixer(),
		       mqpacker( {
			       sort: true
		       } ),
		       focus(),
	       ] ),
	       csscomb(),
	       gulp.dest( '.' ),
	       gulp.dest( 'assets/styles' ),
	       notify( "Compiled: <%= file.relative %>" ),
	       sass( {
		       outputStyle: 'compressed'
	       } ),
	       cleancss( {
		       level: {
			       2: {
				       all: true
			       }
		       }
	       } ),
	       cssnano( {
		       safe: false,
		       discardComments: {
			       removeAll: true,
		       },
	       } ),
	       cache( 'styles' ),
	       rename( {
		       suffix: '.min'
	       } ),
	       sourcemaps.write( '.', {
		       includeContent: false,
	       } ),
	       gulp.dest( 'assets/styles/min' ),
	       filter( '**/*.css' ),
	       notify( "Compiled: <%= file.relative %>" ),
		], done()
	);

} );

/**
 * Compile Sass.
 *
 * https://www.npmjs.com/package/gulp-sass
 */
gulp.task( 'styles', gulp.series( 'styles:woocommerce', 'styles:main' ) );

/**
 * Concat javascript files.
 */
gulp.task( 'scripts:concat', () => {

	return gulp.src( paths.concat )

	// Notify on error.
		.pipe( plumber( {
			errorHandler: notify.onError( "Error: <%= error.message %>" )
		} ) )

		// Concatenate scripts.
		.pipe( concat( 'scripts.js' ) )

		// Output the processed js to this directory.
		.pipe( gulp.dest( 'assets/scripts' ) );
} );

/**
 * Process and minify javascript files.
 *
 * https://www.npmjs.com/package/gulp-uglify
 */
gulp.task( 'scripts:minify', ( done ) => {

	pump( [gulp.src( paths.scripts ),

		// Notify on error.
		   plumber( {
			   errorHandler: notify.onError( "Error: <%= error.message %>" )
		   } ),

		// Source maps init.
		   sourcemaps.init(),

		   babel( {
			   presets: ['@babel/env']
		   } ),

		// Cache files to avoid processing files that haven't changed.
		   cache( 'scripts' ),

		// Add .min suffix.
		   rename( {
			   suffix: '.min'
		   } ),

		// Minify.
		   uglify(),

		// Write source map.
		   sourcemaps.write( './', {
			   includeContent: false,
		   } ),

		// Output the processed js to this directory.
		   gulp.dest( 'assets/scripts/min' ),

		// Notify on successful compile.
		   notify( "Minified: <%= file.relative %>" )
	], done() );
} );


gulp.task( 'scripts', gulp.series( 'scripts:concat', 'scripts:minify' ) );

/**
 * Optimize images.
 *
 * https://www.npmjs.com/package/gulp-imagemin
 */
gulp.task( 'images', () => {

	return gulp.src( paths.images )

	// Notify on error.
		.pipe( plumber( {
			errorHandler: notify.onError( "Error: <%= error.message %>" )
		} ) )

		// Cache files to avoid processing files that haven't changed.
		.pipe( cache( 'images' ) )

		// Optimize images.
		.pipe( imagemin( {
			progressive: true
		} ) )

		// Output the optimized images to this directory.
		.pipe( gulp.dest( 'assets/images' ) )

		// Notify on successful compile.
		.pipe( notify( "Optimized: <%= file.relative %>" ) );
} );

/**
 * Scan the theme and create a POT file.
 *
 * https://www.npmjs.com/package/gulp-wp-pot
 */
gulp.task( 'translate', () => {

	return gulp.src( paths.php )

		.pipe( plumber( {
			errorHandler: notify.onError( "Error: <%= error.message %>" )
		} ) )

		.pipe( sort() )

		.pipe( wpPot( {
			domain: 'candid-studio-pro',
			destFile: false,
			package: 'Candid Studio Pro',
			bugReport: 'https://bigwing.com/',
			lastTranslator: 'BigWing Team <wordpress@bigwing.com>',
			team: 'BigWing Web Team <wordpress@bigwing.com>'
		} ) )

		.pipe( cache( 'translate' ) )

		.pipe( gulp.dest( './languages/candid-studio-pro.pot' ) );
} );

/**
 * Package theme.
 *
 * https://www.npmjs.com/package/gulp-zip
 */
gulp.task( 'zip', () => {

	return gulp.src( ['./**/*', '!./node_modules/', '!./node_modules/**', '!./aws.json'] )
		.pipe( zip( __dirname.split( "/" ).pop() + '.zip' ) )
		.pipe( gulp.dest( '../../' ) );
} );

/**
 * Process tasks and reload browsers on file changes.
 *
 * https://www.npmjs.com/package/browser-sync
 */
gulp.task( 'watch', done => {

	// Run tasks when files change.
	gulp.watch( paths.styles, gulp.series( ['styles'] ) );
	gulp.watch( paths.concat, gulp.series( ['scripts'] ) );
	gulp.watch( paths.images, gulp.series( ['images'] ) );

	done();
} );

gulp.task( 'build', gulp.parallel( 'styles', 'scripts', 'images' ) );

/**
 * Create default task.
 */
gulp.task( 'default', gulp.series( 'watch', 'build' ) );

/**
 * Read the .deployignore file and use those lines to build the files for transfer.
 */
const buildDeployPaths = ( ignorefile = './.deployignore' ) => {
	const fs = require( 'fs' );

	let deployPaths = ['./**/*', '!assets/styles/**/*.scss'];

	/**
	 * readFileSync returns a Buffer, so it has to be converted before we can use it.
	 * @type {string[]}
	 */
	let ignore = fs.readFileSync( ignorefile ).toString().split( '\n' );

	if ( typeof ignore !== 'object' || 0 === ignore.length ) {
		return deployPaths;
	}

	for ( let line in ignore ) {
		let path = ignore[line];

		if ( '' === path ) {
			break;
		}

		/* Ensure directories also explicitly get all child files added.
		 * They also need to get the trailing slash removed so Gulp glob will
		 * see them as directories. Otherwise, we get a bunch of empty dirs in
		 * the deploy folder that get transferred.
		 */
		if ( path.endsWith( '/' ) ) {
			deployPaths.push( `!${path}**` );
			path = path.replace( /\/$/, '' );
		}

		deployPaths.push( `!${path}` );
	}

	console.log( deployPaths );

	return deployPaths;
};

/**
 * Clean the distribution folder.
 */
gulp.task( 'clean:dist', () => del( [ './dist/**/*', './dist', './dist/' ] ) );

/**
 * Bundle theme files into a distribution folder.
 */
gulp.task( 'bundle', () => {
	let files = buildDeployPaths();

	return gulp.src( files, { allowEmpty: true } )
		.pipe( gulp.dest( paths.dist ) );
} );

/**
 * Build files that can be distributed for production use.
 */
gulp.task( 'dist', gulp.series( gulp.parallel( 'build', 'translate' ), 'clean:dist', 'bundle' ) );