75 votes

Construire automatiquement le module NPM lors de l'installation à partir de Github

Étant donné qu'un projet lib/ dir ne doit pas être cochée dans le dépôt Git parce que les fichiers qu'il contient sont dérivées des fichiers (à partir du processus de construction). Lors de l'installation d'un package à partir du projet github (en cours de développement par exemple) l' lib/ dir n'existe pas, donc si le paquet package.jsons' main champ de points (par exemple) lib/index.js, le package ne peut pas être compilé lors de l'importation parce que ces fichiers n'existent pas dans le référentiel, et donc dans le package installé en node_modules. Cela signifie que le paquet doit construite (comme c'était avant la sortie), seulement cette fois localement afin que l' lib répertoire (ou ce que les autres fichiers sont générés pendant le processus de génération) sont ajoutés dans le répertoire du module.

En supposant qu'il existe un build script au sein de l' package.json fichier scripts domaine, peut le package être configuré pour s'exécuter automatiquement dans la situation où il est installé depuis github seulement? Si non, quelle est la meilleure approche pour s'assurer qu'il est construit lorsque installé à partir de github?

Il y a maintenant prepublish, prepublishOnly et prepare du cycle de vie des crochets, mais aucun de fournir une réponse à ce problème, car ils ne permettent pas de moyen de distinguer entre la source de l'installation. En bref, oui, ils vous permettent de construire sur installer, mais ils ne permettent pas à vous appuyer sur installer à partir de github seulement. Il y a non seulement aucune raison de forcer une génération, lorsque les gens d'installer à partir de la ngp, mais plus important encore, les dépendances de développement ne sera pas installé (par exemple, babel ce qui est essentiel à la construction).

Je suis conscient d'une stratégie pour faire face à ce problème:

  • Fourche / branche le repo
  • construire localement
  • supprimer l' lib/ dir de .gitignore et l'archiver.
  • installer le module à partir de votre fourche/direction de la
  • Lorsque vous êtes prêt pour une PR / rebase ajouter lib/ dir d' .gitignore et de supprimer dir à partir de git.

Mais c'est loin d'être idéale. Je suppose que cela pourrait être automatisée avec un githook bien. Ainsi, chaque vous pousser à maîtriser le projet s'appuie également et pousse à une branche distincte.

Il y a une question fermée sur des MNP Github avec aucune résolution - seulement beaucoup de gens qui veulent une solution. À partir de cette question, il est clair que l'utilisation d' prepare n'est pas la réponse.

Mon cas d'utilisation, c'est que je suis en train d'élaborer un module qui est utilisé dans un certain nombre d'autres projets. Je veux consommer de la dernière version du module sans avoir à pousser un communiqué de MNP à chaque fois que je l'ai mise à jour de la base de code - je préfère faire sortir de moins en moins de rejets quand je suis prêt, mais j'ai encore besoin de consommer quoi que la dernière version de la lib est sur Github.

Note: j'ai également contacté des MNP soutien à l'égard de cette question et je vais ajouter leur réponse, si je reçois un.

30voto

Piotr Styczyński Points 787

Edit: Détecter si le colis est en cours d'installation à partir de repo git

Je n'ai pas compris la question correctement. Ci-dessous sont des choses que j'ai écrit, mais sont un peu hors-sujet. Pour l'instant, si vous voulez exécuter build.js seulement lors de l'installation de repo:

Fichiers dans repo:

 .gitignore
 .npmignore
 ThisIsNpmPackage
 build.js
 package.json

L' .gitginore:

ThisIsNpmPackage

L' .npmignore:

!ThisIsNpmPackage

Dans le package.json:

"scripts": {
    "install": "( [ ! -f ./ThisIsNpmPackage ] && [ ! -f ./AlreadyInstalled ] && echo \"\" > ./AlreadyInstalled && npm install . && node ./build.js ) || echo \"SKIP: NON GIT SOURCE\""
}

L'idée est de rendre le fichier ThisIsNpmPackage disponible sur le repo, mais pas dans le package npm.

Installer le crochet c'est juste un morceau de bashy script pour vérifier si ThisIsNpmPackage existe. Si oui, alors nous exécutons npm install . (cela permettra de s'assurer que nous avons devDependencies. Fichier AlreadyInstalled est généré pour éviter de boucle infinie (npm install de manière récursive invoquer installer le crochet)

Lors de la publication, je n' git push et npm publish
Notez que mnp publier peut être automatisée par le biais d'outils CI - githooks

Ce petit hack avec le fichier ThisIsNpmPackage rend la détection de source disponible.

Les résultats de l'invocation d' npm install dumb-package:

"IGNORER: NON-SOURCE DE GIT"

Et l'exécution d' npm install https://github.com/styczynski/dumb-package

Les fichiers seront construits

Les questions

Les principaux problèmes auxquels nous sommes confrontés ici sont les suivantes:

  • Avez à faire, npm publish ... à chaque fois

    Parfois, c'est trop de douleur pour corriger un petit bug, puis poussez vers le repo et oublier de le publier sur npm. Quand je travaillais avec un microservices projet qui a environ 5 autonome sous-projets divisés en modules, le problème que j'ai trouvé un problème, il fixe et oublier de le publier dans chaque endroit que j'ai eu était vraiment ennuyeux.

  • Ne veux pas pousser lib dans les pensions de titres, parce que c'est dérivée à partir de sources

  • La relocalisation et la fusion est encore plus ennuyeux.

  • Pas de gâchis, avec .gitgnore

    Bon, je sais que le problème lorsque vous avez une source de fichiers que vous devez inclure à l'intérieur de pensions, mais jamais les modifier, ou parfois supprimer? C'est tout simplement malade.

Edit: mnp crochets

Comme @Roy Tinker a mentionné, il existe la possibilité qu'un package pour exécuter une commande lors de l'installation.
Il peut être réalisé via npm crochets.

"install": "npm run build"

Et nous exécutons l':

npm install https://github.com/<user>/<package>

Edit:
OP question des commentaires:

Mais cela va lancer une installation pour tout le monde de télécharger le module de mnp droit? Cela est particulièrement problématique étant donné que les dev dépendances ne seront pas installées pour les personnes téléchargeant le module de mnp. Les libs utilisées pour construire l'application de la tour de babel, etc ne sera pas installé.

Remarque: Mais si vous voulez une version spécifique de l'ensemble (production/dev) avec ou sans dev dépendances vous pouvez l'installer via:

npm install --only=dev

L' --seulement={prod[oupe]|dev[développement]} argument sera la cause soit seulement devDependencies ou seulement non-devDependencies être installé indépendamment de la NODE_ENV.

Une meilleure solution, à mon avis, est d'utiliser:

npm install <git remote url>

Et puis à l'intérieur de paquet.json préciser:

"scripts": {
    "prepare": "npm run build"
}

Si le package installé contient préparer un script, de ses dépendances et devDependencies sera installé, et le préparer script sera exécuté, avant que le paquet est emballé et installé.

Exemple:

npm install git+https://isaacs@github.com/npm/npm.git

Lire le mécanisme national de prévention docs là: npm install

Edit: module de proxy (technique avancée)

C'est une sorte de mauvaise pratique, mais bon à savoir.

Parfois (comme dans le cas de l' Électron cadre vous avez besoin d'installer d'autres paquets externes ou des ressources/des modules en fonction de diverses conditions).

Dans ces cas, le proxy idée est utilisée:

  • Vous faire un module qui se comporte comme installateur et installe, en fonction des choses que vous voulez

Dans votre cas, préparer script sera suffisant, mais je laisse cette option, car il peut être parfois utile.

L'idée est que vous écrivez un module et d'écrire une installation kook pour elle:

"scripts": {
    "install": "<do the install>"
}

Dans ce scénario, vous pouvez placer là:

npm install . && npm run build

Qui installer tous les devDependencies de toute façon (comme cités préparer des cas), mais c'est un peu du piratage informatique.

Si vous souhaitez en faire le vrai piratage il y a:

 "scripts": {
    "install": "curl -L -J -O \"<some_url>\""
 }

qui télécharger manuellement les fichiers à l'aide de -nix commande curl

Il devrait être évité, mais il y a une option dans le cas du module qui a d'énormes fichiers binaires pour chaque plate-forme et que vous ne souhaitez pas installer tous.

Comme dans le cas de l'Électron où vous avez compilé les fichiers binaires (chacun pour la plate-forme séparée)

Si vous voulez que les gens font install package pas install package-linux ou package-window etc.

Afin de vous fournir des personnalisés install script dans l' package.json

{
  ...
  "scripts": {
     "install": "node ./install_platform_dep.js"
  }
}

Puis lors de l'installation d' module le install_platform_dep.js script sera exécuté. À l'intérieur d' install_platform_dep.js vous placez:

// For Windows...
if(process.platform === 'win32') {
    // Trigger Windows module installation
    exec('npm install fancy-module-windows', (err, stdout, stderr) => {
         // Some error handling...
    }
} else if ... // Process other OS'es

Et ce uniquement de façon manuelle installe tout.

Remarque: une Fois de plus, cette approche est utilisable avec la plate-forme en fonction des modules et si vous utilisez que c'est probablement le problème de conception avec votre code.

Construire sur la CI

Ce qui me vient à l'esprit est la solution que j'ai utilisé vraiment pour une longue période (de construction automatique avec CI des services).

La plupart des services CI' objectif principal est de tester/build/publier votre code lorsque l'on pousse à la branche ou à faire d'autres actions avec le repo.

L'idée est que vous fournissez fichier de paramètres (comme travis.yml ou .gitlab-ci.yml) et les outils de prendre soin de tout le reste.

Si vous avez vraiment ne voulez pas inclure la lib dans le projet, seulement de la confiance IC à tout faire:

  • Githook va déclencher la construction lors de la validation (sur une branche ou tout autre - c'est juste une question de configs)
  • CI permettra de construire vos fichiers, puis les passer à la phase de test et de publier

Maintenant, je travaille sur Gitlab sur mon propre projet de faire (comme une partie de hobby) certains page web. Le Gitlab configuration qui crée le projet ressemble à cela:

image: tetraweb/php

cache:
  untracked: true
  paths:
    - public_html/
    - node_modules/

before_script:
  - apt-get update

stages:
  - build
  - test
  - deploy

build_product:
  stage: build
  script:
    - npm run test

build_product:
  stage: build
  script:
    - npm run build

deploy_product:
  stage: deploy
  script:
    - npm run deploy

Quand j'ai fusionner dans la branche principale les événements suivants se produisent:

  • CI exécute build stade
  • Si la génération réussit alors test stade est lancé
  • Si test phase est ok, alors enfin la scène deploy est déclenchée

Le script est la liste des commandes unix pour être exécuté.

Vous pouvez spécifier n'importe quel Panneau de l'image dans le fichier de configuration, afin de l'utiliser en fait une version Unix que vous voulez avec certains (ou pas) préinstallé outils.

Il s'agit d'un package de déploiement-git qui déploie des objets pour le désiré des pensions de la branche.

Ou ici (Travis CI) le morceau de config qui publie des objets pour les pensions de titres:

travis-publier-à-git

(Je l'ai utilisé par moi-même)

Alors, bien sûr, vous pouvez indiquer CI s'exécuter:

npm publish .

Parce que CI exécute des commandes Unix, alors il peut (au moins un groupe de CI de fournisseurs de là):

  • Publier des balises (balise de version peut-être?)
  • Déclencheur de script pour mettre à jour la version du projet dans tous les fichiers readme et partout
  • Vous envoyer une notification si toutes les phases réussi

Donc ce que je fais:
Je m'engage, de pousser et de laisser les outils de faire tout ce que je veux.
En attendant, je fais aussi d'autres changements et après un à dix minutes en obtenir la mise à jour du rapport par mail.

Il y a beaucoup de CI fournisseur de:

Ici je joins un autre exemple de mon autre projet (.travis.yml):

language: generic
install:
    - npm install
script:
    - chmod u+x ./utest.sh 
    - chmod u+x ./self_test/autodetection_cli/someprogram.sh
    - cd self_test && bash ../utest.sh --ttools stime --tno-spinner

Si vous configurez CI de pousser et de publier votre colis, vous pouvez toujours être sûr d'utiliser la dernière pointe de la version de votre code sans se soucier hein, je dois courir aussi cette commande maintenant... problème.

Je vous recommande de choisir l'un de l'IC fournisseurs là-bas.
Les meilleurs d'entre eux vous offrons des centaines de capacités!

Lorsque vous obtenez automatiquement utilisé pour faire publier, de test et de phases de construction, vous verrez comment elle aide à profiter de la vie!
Alors pour commencer un autre projet avec des scripts automatiques il suffit de copier les configs!

Résumé

À mon avis mnp préparer script est une option.
Vous pouvez aussi peut-être envie d'essayer d'autres.

Chacune des méthodes décrites ci-dessus a ses inconvénients et peut être utilisé en fonction de ce que vous voulez atteindre.
Je veux juste offrir des options espère que certains d'entre eux seront s'adapter à votre problème!

24voto

Cameron Tacklind Points 343

prepare est la bonne manière

Si vous avez un référentiel avec des fichiers source, mais une "construction" de l'étape est nécessaire pour l'utiliser, prepare fait exactement ce que vous voulez dans tous les cas (comme des mnp 4).

prepare: Exécuter les deux AVANT que le paquet est emballé et a publié, le local npm install sans arguments, et lors de l'installation de git dépendances.

Vous pouvez même mettre vos dépendances de construction en devDependencies et ils seront installés avant l' prepare est exécutée.

Voici un exemple d'un paquet de mine qui utilise cette méthode.


Des problèmes avec l' .gitignore

Il y a un problème avec cette option est beaucoup de gens. Lors de la préparation d'une dépendance, Mnp et Fils vont seulement de conserver les fichiers qui sont répertoriés dans l' files de la section de l' package.json.

On peut voir qu' files valeurs par défaut pour tous les fichiers inclus et pense qu'ils ont fait. Ce qui est facilement oubliée, c'est que .npmignore principalement remplace l' files directive et, si .npmignore n'existe pas, .gitignore est utilisé à la place.

Donc, si vous avez construit votre fichiers listés en .gitignore comme une personne saine d'esprit, ne pas la liste de vos fichiers construits en files, et n'utilisez pas un .npmignore fichier prepare sera semble cassé.

Si vous corrigez files pour inclure uniquement les fichiers construits ou ajouter un vide .npmignore, vous êtes tous ensemble.

4voto

Roy Tinker Points 8054

En supposant qu'il existe un build script dans le package.fichier json scripts du domaine, peut le package être configuré pour s'exécuter automatiquement dans cette situation?

Oui. Il y a 2 choses que vous devez faire:

  1. Assurez-vous que votre système utilise npm ou yarn pour installer le package à partir de GitHub. Si ce paquet est une dépendance d'un autre paquet, vous pouvez utiliser le GitHub de l'URL à la place du numéro de version en package.json. Sinon, la commande suivante fonctionne:

    npm install https://github.com/YourUser/your-package
    

    Vous pouvez ajouter /tags/v1.0.0 ou que ce soit à la fin de l'URL si vous êtes après une balise spécifique ou de la branche.

  2. Ajouter les éléments suivants à l' scripts dans votre module package.json:

    "install": "npm run build"
    

install est un crochet qui le package manager s'exécute après l'installation du module. (preinstall et postinstall aussi -- voir la documentation).

Documentation: https://docs.npmjs.com/misc/scripts

3voto

DS. Points 3577

ÉDITÉ 2

C'est une bonne question. Il est trop mauvais, il n'est pas reconnu solution fiable, mais la suite semble fonctionner.

Créer un .buildme fichier de marqueurs, et de s'engager à git.

En package.json:

  "files": ["lib"],
  "scripts": {
    "build": "echo DO WHAT YOU NEED TO BUILD",
    "prepack": "[ ! -f .buildme ] || npm run build",
    "preinstall": "[ ! -f .buildme ] || npm run build"
  },

Voici les choses à noter.

  1. Le spécial .buildme fichier de marqueurs doivent être exclus du mécanisme national de prévention package avec l' "files" - clé, ou par l'intermédiaire de .npmignore.

  2. L' prepack crochet s'exécute lorsque vous publiez (prepublishOnly peut aussi travailler, mais c'est bien que avec des prepack, npm pack va produire une bonne archive).

  3. Lors de l'installation de mnp, preinstall s'exécute, mais ne fait rien car .buildme est manquant (grâce à l' [ ! -f .buildme ] de la clause).

  4. Lors de l'installation à partir de github, .buildme n'existe pas. Sur npm6, prepack crochet court le construire (et produit un forfait sans .buildme), et preinstall ne fait rien. Sur le fil 1.12, preinstall le construire.

  5. Si vous installez une version mise à jour à partir de github, preinstall fonctionnera de nouveau, et de construire à nouveau.

REMARQUE: Lors de l'installation à partir de github, c'est à la personne de l'installation à en avoir assez de votre paquet devDependencies déjà installé pour que la compilation fonctionne. (Cette solution n'essayez pas d'installer automatiquement devDependencies.)

C'est tout. Il semble que ça fonctionne avec des varios combinaisons de mnp 6 et le fil 1.12.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X