Выполнить сборку, только если есть изменения в src
История:
У нас есть команда тестировщиков, работающих над автоматизацией сквозных тестов с использованием транспортира для нашего внутреннего приложения AngularJS. Вот задача, которую они обычно выполняют для локального тестирования:
grunt.registerTask('e2e:local', [
'build:prod',
'connect:test',
'protractor:local'
]);
Он запускает задачу "build", запускает веб-сервер и запускает тесты e2e против локальной сборки.
Задача build:prod
определяется как:
grunt.registerTask(
'build:prod', [
'clean',
'copy:all',
'copy:assets',
'wiredep',
'ngtemplates',
'useminPrepare',
'concat',
'ngAnnotate',
'autoprefixer',
'uglify',
'cssmin',
'copy:cssfix',
'usemin',
'copy:html',
'bowercopy',
'template:setProdVersion'
]
);
Здесь у нас есть много подзадач (его определенно можно было бы улучшить, но теперь это выглядит так).
Проблема:
В настоящее время для завершения сборки требуется около 25 секунд. И каждый раз, когда человек запускает сквозные тесты, выполняется задача сборки.
Вопрос:
Как запустить задачу build:prod
только в том случае, если в каталоге src
есть изменения?
Обратите внимание, что здесь требуется сделать его прозрачным для тестеров, которые запускают тесты. Я не хочу, чтобы они помнили, когда им нужно выполнить сборку, а когда нет.
Другими словами, процесс должен быть автоматизирован. Цель состоит в том, чтобы автоматически определить, нужна ли сборка или нет.
Обратите внимание, что в идеале я хотел бы оставить задачу сборки как есть, так что, если она вызывается непосредственно через grunt build:prod
, она будет перестраиваться независимо от datestamp предыдущей сборки.
Мысли и попытки:
-
существует тесно связанный grunt-newer
пакет, но, поскольку у нас есть довольно сложная сборка, с задачей clean
в начале, Я не уверен, как применить его в моем случае
-
о чем я также думал, внутри задачи e2e:local
вручную проверять временные метки файлов внутри dist
и src
и, на основании этого, решить, требуется ли build:prod
для вызова. Я думаю, что это то, что grunt-newer
делает внутренне
-
мы начали использовать jit-grunt
, что помогло улучшить производительность
Ответы
Ответ 1
Вот идея, если вы используете git:
Как насчет использования чего-то вроде grunt-gitinfo и использования последнего фиксации в HEAD в качестве базы?
Идея такова:
- Вы создаете новую задачу grunt, которая проверяет последний хеш фиксации
- Вы сохранили этот хеш фиксации в файле, который добавлен в
gitignore
(и не находится в папке clean
, как правило, может быть в корне репо)
- Прежде чем сохранять файл, он проверит значение уже в нем (стандартный node
fs
модуль может легко читать/писать)
- Если хэш не соответствует, запустите задачу
build:prod
, а затем сохраните новый хеш фиксации
- Строка тестеров будет напрямую зависеть от вашей новой задачи вместо
build:prod
Другая опция (все еще используется git):
Вы можете использовать что-то вроде grunt-githooks и создать крюк git, который запускается после нажатия и вызывает git build:prod
, то вы можете удалить его из зависимостей задания grunt, которые тестируют тестеры.
У вас может быть другой код для проверки githook и его установки при необходимости, что может быть одноразовым дополнительным шагом для тестеров или, возможно, испечь в задаче grunt, которую они вызывают.
Ответ 2
Я удивлен, что никто еще не упомянул grunt-contrib-watch (он находится в gruntjs.com, и я подумал, что это довольно широко известно!). Из github: "Запускайте предопределенные задачи, когда наблюдаемые шаблоны файлов добавляются, изменяются или удаляются". - heres образец файла grunt, который будет запускать ваши задачи в любое время, когда любые .js файлы будут изменены в src/или в test/, или если файл Grunt будет изменен.
var filesToWatch = ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'];
grunt.initConfig({
watch: {
files: filesToWatch,
tasks: ['build:prod',
'connect:test',
'protractor:local']
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
У вас есть ваши разработчики, открывающие терминал и запускающие grunt watch
, прежде чем они начнут изменять файлы, и каждый раз, когда эти файлы будут изменены, задачи будут автоматически запущены (больше не возвращаться к терминалу для запуска grunt build:prod
каждый раз).
Это отличный пакет, и я предлагаю вам проверить его. - github - npmjs.org p >
npm install grunt-contrib-watch --save-dev
Ответ 3
Не ответ, который вы ищете с помощью grunt
, но это будет легко с gulp
.
var fs = require('fs');
var gulpif = require('gulp-if');
var sourceChanged = fs.statSync('build/directory').mtime > fs.statSync('source/directory').mtime;
gulp.task('build:prod', function() {
if (!sourceChanged) {
return false;
}
return gulp.src('./src/*.js')
.pipe(.... build ....)
.pipe(gulp.dest('./dist/'));
});
Ответ 4
Вот как мы выполнили некоторую работу Git HEAD sha для нашей сборки. Мы используем его для определения того, какая версия в настоящее время развернута в нашей производственной среде, но я вполне уверен, что вы могли бы переработать ее, чтобы вернуть логическое значение и запустить сборку, если это правда.
Gruntfile.js
function getHeadSha() {
var curr, match, next = 'HEAD';
var repoDir = process.env.GIT_REPO_DIR || path.join(__dirname, '..');
try {
do {
curr = grunt.file.read(path.join(repoDir, '.git', next)).trim();
match = curr.match(/^ref: (.+)$/);
next = match && match[1];
} while (next);
} catch(ex) {
curr = 'not-found';
}
return curr;
}
grunt.initConfig({
replace: {
applicationVersion: {
src: '<%= config.dist %>/index.html',
overwrite: true,
replacements: [{
from: '{{APPLICATION_VERSION}}',
to: getHeadSha
}]
}
}
});
grunt.registerTask('build', {
'replace:applicationVersion',
/** other tasks **/
});
grunt.registerTask('e2e:local', {
'check_if_we_should_build',
/** other tasks **/
});
index.html
<html data-version="{{APPLICATION_VERSION}}">
<!-- -->
</html>
Также существует пакет git -info, который упростит весь этот процесс, и мы перейдем к этому.
редактировать; Я просто заметил, что @meligy уже указал вам в направлении git -info. кредит, в котором должен быть предоставлен кредит.
Ответ 5
Я не уверен, что это было полезно или не так, но мы сделали это в нашем проекте, используя GULP framework. Мы записали наблюдателя в gulp, который постоянно проверяет изменение источника и запускает быструю функцию для создания проекта. Его тестовый вариант для проталкивателя.
gulp.task('dome', function () {
gulp.src(["maintest.js"])
.pipe(notify("Change Found , Executing Scripts."))
.pipe(protractor({
configFile: "conf.js",
args: ['--baseUrl', 'http://127.0.0.1:8000']
})).on('error', function (e) {
throw e
});
})
gulp.task('default', function () {
gulp.watch('./webpages/*.js', ['dome']);
gulp.watch('maintest.js', ['dome']);
gulp.watch('conf.js', ['dome']);
});
Ссылка на репо.
Ответ 6
У меня нет опыта в транспортире, но концептуально я думаю, что это может сработать.
Я предлагаю установить псевдоним в ~/.cshrc для запуска команд сборки, только если команда diff
возвращает true.
#./cshrc
alias build_on_diff 'diff -r branch_dir_1 branch_dir_2\
if ( $status == 1 ) then\
build:prod\
endif'
Просто замените команду diff
тем, что использует git, и она должна работать, если она возвращает статус 1 для обнаруженных различий. Мы применяем аналогичный метод на моем рабочем месте, чтобы избежать восстановления файлов, которые не изменились.