Question Exécuter la construction seulement s'il y a des changements dans src


L'histoire:

Une équipe de testeurs travaille à l’automatisation de tests de bout en bout à l’aide de rapporteur pour notre application AngularJS interne. Voici la tâche qu'ils exécutent habituellement pour les tests "locaux":

grunt.registerTask('e2e:local', [
    'build:prod',
    'connect:test',
    'protractor:local'
]);

Il exécute la tâche "build", démarre un serveur Web et exécute les tests e2e sur la version locale.

le build:prod la tâche elle-même est définie comme suit:

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'
    ]
);

Ici, nous avons beaucoup de sous-tâches (cela pourrait certainement être amélioré, mais voici à quoi ça ressemble maintenant).

Le problème:

Actuellement, la compilation prend environ 25 secondes. Et, chaque fois qu'une personne exécute des tests de bout en bout, la tâche de génération est exécutée.

La question:

Comment puis-je exécuter le build:prod tâche que si il y a des changements dans src annuaire?


Notez que l'exigence ici est de le rendre transparent pour les testeurs qui exécutent les tests. Je ne veux pas qu'ils se rappellent quand ils doivent effectuer un build et quand ils ne le font pas.

En d'autres termes, le processus devrait être automatisé. Le but est de détecter automatiquement si la construction est nécessaire ou non.

Notez que, idéalement, je voudrais laisser la tâche de construction telle quelle, si elle est invoquée directement via grunt build:prod il reconstruirait indépendamment de l'horodatage de la version précédente.


Pensées et essais:

  • il y a le proche parent grunt-newer paquet, mais comme nous avons une construction plutôt compliquée, avoir un clean tâche au début, je ne sais pas comment l'appliquer dans mon cas

  • ce à quoi je pensais aussi était, à l'intérieur du e2e:local tâche, vérifiez manuellement l'horodatage des fichiers à l'intérieur dist et src et, sur cette base, décider si build:prod est nécessaire pour être invoqué. Je pense que c'est ce que grunt-newer fait en interne

  • nous avons commencé à utiliser jit-grunt qui a contribué à améliorer la performance


21
2017-07-02 18:30


origine


Réponses:


Voici une idée si vous utilisez git:

Que diriez-vous d'utiliser quelque chose comme grunt-gitinfo et utiliser le dernier commit dans HEAD comme base?

L'idée est la suivante:

  • Vous créez une nouvelle tâche qui vérifie le dernier hash de validation
  • Vous sauvegarderez ce hash de validation dans un fichier ajouté à gitignore (et n'est pas dans le clean dossier, peut généralement être à la racine de repo)
  • Avant de sauvegarder dans un fichier, il vérifie la valeur déjà présente (noeud standard fs le module peut faire la lecture / écriture facilement)
  • Si le hachage ne correspond pas, exécutez build:prod tâche puis enregistrer le nouveau hash de validation
  • La construction des testeurs dépendra de votre nouvelle tâche au lieu de build:prod directement

Une autre option (toujours en utilisant git):

Vous pouvez utiliser quelque chose comme grognements et créer un crochet Git qui s'exécute après tirer et appelle le git build:prod, alors vous pouvez le supprimer des dépendances de la tâche grunt que les testeurs exécutent.

Vous pourriez avoir un autre code pour vérifier githook et l'installer si nécessaire, ce qui peut représenter une étape supplémentaire pour les testeurs, ou peut-être être intégré à la tâche qu'ils appellent.


6
2017-07-06 17:04



Je suis surpris que personne n'ait mentionné grunt-contrib-watch encore (c'est dans le gruntjs.com exemple de fichier et je pensais que c'était assez communément connu!). Depuis github: "Exécuter des tâches prédéfinies à chaque fois que des modèles de fichiers surveillés sont ajoutés, modifiés ou supprimés." - contient un exemple de fichier grunt qui exécutera vos tâches chaque fois que des fichiers .js sont modifiés dans src / ou dans test /, ou si le fichier Gruntfile est modifié.

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

Vos développeurs ouvrent un terminal et exécutent grunt watch avant de commencer à modifier les fichiers, et chaque fois que ces fichiers sont modifiés, les tâches seront automatiquement exécutées (plus besoin de retourner au terminal pour exécuter grunt build:prod à chaque fois).

C'est un excellent paquet et je vous suggère de le vérifier. - github - npmjs.org

npm install grunt-contrib-watch --save-dev

5
2017-07-11 21:25



Pas la réponse que vous recherchez avec grunt, mais ce sera facile avec 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/'));
});

2
2017-07-07 01:09



Voici comment nous avons fait du travail de Git HEAD pour notre build. Nous l'utilisons pour déterminer quelle version est actuellement déployée dans notre environnement de production - mais je suis certain que vous pourriez la retravailler pour renvoyer une valeur booléenne et déclencher la génération si véridique.

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>

Il y a aussi le git-info paquet qui simplifierait tout ce processus, nous envisageons de passer à cela nous-mêmes.

modifier; Je viens de remarquer que @meligy vous a déjà orienté vers git-info. crédit lorsque le crédit est dû.


2
2017-07-10 08:18



Je ne suis pas sûr que ce soit utile ou non mais les mêmes choses que nous avons fait dans notre projet en utilisant Cadre GULP. Nous avons écrit un observateur dans la liste qui vérifie en permanence le changement de source et exécute une fonction rapide pour construire le projet. C'est un cas testeur de rapporteur.

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']);
});

Lien vers repo. 


1
2018-05-20 09:02



Je n'ai pas d'expérience avec le rapporteur, mais je pense que cela pourrait fonctionner sur le plan conceptuel.

Ce que je pourrais suggérer, c'est de définir un alias dans votre ~ / .cshrc pour qu'il exécute les commandes de construction uniquement si diff La commande retourne true.

#./cshrc

alias build_on_diff 'diff -r branch_dir_1 branch_dir_2\
if ( $status == 1 ) then\
build:prod\
endif'

Il suffit de remplacer le diff commande avec tout ce que git utilise, et cela devrait fonctionner à condition qu’il renvoie un statut 1 pour les différences détectées. Nous appliquons une méthode similaire sur mon lieu de travail pour éviter de reconstruire des fichiers qui n'ont pas été modifiés.


0
2017-07-06 19:10