Как включить git версию в приложение angular -cli?

Мне нужно отобразить версию git на моем приложении angular2 о странице. Проект основан на angular -cli.

Как можно построить расширение, чтобы версия git была помещена, например, в environment.ts или в другое место, доступное для приложения?

Ответ 1

Как подсказал @Yuri, я смог решить эту проблему с помощью сценариев npm.

  1. Определил git.version.ts в корне проекта angular-cli:

    import fs = require('fs');
    import { Observable } from 'rxjs';
    
    let exec = require('child_process').exec;
    
    const revision = new Observable<string>(s => {
        exec('git rev-parse --short HEAD',
            function (error: Error, stdout: Buffer, stderr: Buffer) {
                if (error !== null) {
                    console.log('git error: ' + error + stderr);
                }
                s.next(stdout.toString().trim());
                s.complete();
            });
    });
    
    const branch = new Observable<string>(s => {
        exec('git rev-parse --abbrev-ref HEAD',
            function (error: Error, stdout: Buffer, stderr: Buffer) {
                if (error !== null) {
                    console.log('git error: ' + error + stderr);
                }
                s.next(stdout.toString().trim());
                s.complete();
            });
    });
    
    Observable
        .combineLatest(revision, branch)
        .subscribe(([revision, branch]) => {
            console.log('version: '${process.env.npm_package_version}', revision: '${revision}', branch: '${branch}'');
    
            const content = '// this file is automatically generated by git.version.ts script\n' +
                'export const versions = {version: '${process.env.npm_package_version}', revision: '${revision}', branch: '${branch}'};';
    
            fs.writeFileSync(
                'src/environments/versions.ts',
                content,
                {encoding: 'utf8'}
            );
        });
    
  2. Добавлен хук предварительной сборки в package.json:

    "scripts": {
        "ng": "ng",
        ...
        "start": "ng serve --proxy proxy-config.json",
        "prebuild.prod": "ts-node git.version.ts",
        "build.prod": "ng build -prod",
        ...
    },
    
  3. Используйте сгенерированный src/environments/versions.ts в приложении.

    ОБНОВЛЕНИЕ 10/2018: Вот более читаемая версия скрипта, rxjs-version-agnostic:

    import { writeFileSync } from 'fs';
    import { dedent } from 'tslint/lib/utils';
    
    const util = require('util');
    const exec = util.promisify(require('child_process').exec);
    
    async function createVersionsFile(filename: string) {
      const revision = (await exec('git rev-parse --short HEAD')).stdout.toString().trim();
      const branch = (await exec('git rev-parse --abbrev-ref HEAD')).stdout.toString().trim();
    
      console.log('version: '${process.env.npm_package_version}', revision: '${revision}', branch: '${branch}'');
    
      const content = dedent'
          // this file is automatically generated by git.version.ts script
          export const versions = {
            version: '${process.env.npm_package_version}',
            revision: '${revision}',
            branch: '${branch}'
          };';
    
      writeFileSync(filename, content, {encoding: 'utf8'});
    }
    
    createVersionsFile('src/environments/versions.ts');    
    

Обратите внимание, что при использовании angular-cli v7.0.6 мне также пришлось изменить вызов скрипта в package.json:

"scripts": {
    ...
    "prebuild.prod": "ts-node -O '{\"module\": \"commonjs\"}' git.version.ts",
    ...
},

Ответ 2

Другие ответы были полезны, но я предпочел более простой, прямой подход. Здесь мой.

Запустите npm install git-describe --save-dev. Затем добавьте git-version.js в корень:

// This script runs operations *synchronously* which is normally not the best
// approach, but it keeps things simple, readable, and for now is good enough.

const { gitDescribeSync } = require('git-describe');
const { writeFileSync } = require('fs');

const gitInfo = gitDescribeSync();
const versionInfoJson = JSON.stringify(gitInfo, null, 2);

writeFileSync('git-version.json', versionInfoJson);

При желании вы можете добавить /git-version.json в ваш файл .gitignore.

Обновите ваш package.json чтобы сделать что-то вроде этого:

"scripts": {
  "build": "node git-version.js && ng build"
}

Затем добавьте version-info.ts в корень вашего проекта:

export const versionInfo = (() => {
  try {
    // tslint:disable-next-line:no-var-requires
    return require('../../git-version.json');
  } catch {
    // In dev the file might not exist:
    return { tag: 'v0.0.0', hash: 'dev' };
  }
})();

И import в versionInfo в вашем app.component.ts или где - нибудь еще вы хотели бы использовать его.

Ответ 3

Мне нравится, чтобы все было просто. Можете добавить в свой index.html:

<script>window.version = '{git-hash}';</script>

Затем добавьте скрипт postbuild в свой package.json:

"postbuild": "sed -i '' \"s/{git\\-hash}/$(git rev-parse --short HEAD)/g\" dist/*/index.html"

Не элегантно ни в коем случае. Лично я создаю объект в window с различной информацией о сборке (время, версия и сводная ссылка о выпуске).

Чтобы оставаться более "чистым", вставьте строку {git-hash} в environment.prod.ts и запустите sed для всех созданных файлов main-*.js.

"postbuild": "sed -i '' \"s/{git\\-hash}/$(git rev-parse --short HEAD)/g\" dist/*/main-*.js"

Обратите внимание, что вы всегда будете видеть, что '{git-hash}' работает локально, поскольку он заменяет только пост-сборку. Если вы замените его перед сборкой, то, очевидно, не сможете заменить его в будущих сборках локально, и, скорее всего, это случайно проверит.

---- ОБНОВЛЕНИЕ ----

Закончилось создание библиотеки для получения различной информации. Только в конечном итоге использовать версию, время сборки и commitTime лично.

https://www.npmjs.com/package/@rippell/ngx-build-info

Ответ 4

Я пошел с модифицированной версией Вильмантаса Баранаускаса

Я переместил src/index.html в src/index.base.html и добавил пустой <meta name="revision" content=""> внутри HEAD

Пример:

<head>
<meta charset="utf-8">
<title>MySuperAwesome Angular</title>
<base href="/">

<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="revision" content="">
<link rel="icon" type="image/x-icon" href="favicon.ico">

Затем измените git.version.ts следующим образом:

import 'rxjs/add/observable/combineLatest';

import { readFileSync, writeFileSync } from 'fs';
import { join } from 'path';
import { Observable } from 'rxjs/Observable';

const indexBasePath = join(__dirname, 'src');

const exec = require('child_process').exec;

const revObs = new Observable<string>(s => {
  exec('git rev-parse --short HEAD',
  function (error: Error, stdout: Buffer, stderr: Buffer) {
    if (error !== null) {
      console.log('git error: ' + error + stderr);
    }
    s.next(stdout.toString().trim());
    s.complete();
  });
});

const branchObs = new Observable<string>(s => {
  exec('git rev-parse --abbrev-ref HEAD',
  function (error: Error, stdout: Buffer, stderr: Buffer) {
    if (error !== null) {
      console.log('git error: ' + error + stderr);
    }
    s.next(stdout.toString().trim());
    s.complete();
  });
});

Observable
.combineLatest(revObs, branchObs)
.subscribe(([revision, branch]) => {
  console.log(`revision: '${revision}', branch: '${branch}'`);

  const baseHTML = readFileSync(join(indexBasePath, 'index.base.html'), 'utf8');
  const html = baseHTML
    .replace('<meta name="revision" content="">', `<meta name="revision" content="${ revision }">`);

  writeFileSync(
    join(indexBasePath, 'index.html'),
    html,
    { encoding: 'utf8' }
  );
});

В этом примере я помещаю только ревизию, но вы можете быть более тщательным и поместить ветку и версию внутри раздела html HEAD

Ответ 5

Я сделал это, сгенерировав сценарий prebuild, который запускается после postinstall и запускается перед любым связанным сценарием


const fs =  require('fs');
const git = require('git-rev-sync');
var mkdirp = require('mkdirp');

const releaseTag = git.tag();
const template = 'export const gitTag = '${releaseTag}';\n';

mkdirp('./generated', function(err) {
    fs.writeFileSync('./generated/git-tag.ts', template, { encoding: 'UTF-8' });
});

который сгенерировал файл git-tag.ts:

export const gitTag = 'xxxxxxx';

и теперь вы просто используете в компоненте

import { gitTag } from '[pathToRoot]/generated/git-tag';

также добавить .gitignore

generated

Ответ 6

Отобразить имя ветки и зафиксировать хэш

У меня немного другой подход, вдохновленный ответами repo SebaArce и Jeroen, в главном каталоге проекта:

  • выполнить: npm install git-rev-sync --save (эта библиотека предоставляет доступ к хешу и имени ветки)
  • добавить файл git-version-gen.js со следующим телом

const git  = require('git-rev-sync');
const { writeFileSync } = require('fs');

const gitInfo = { commit: git.short(), commitLong: git.long(), branch: git.branch() };
const ts = 'export const gitVersion = ' + JSON.stringify(gitInfo, null, 2);

writeFileSync('src/environments/git-version.ts', ts);

Ответ 7

Просто установите этот пакет git-revision-webpack-plugin

Простой плагин webpack, который генерирует файлы VERSION и COMMITHASH во время сборки на основе локального репозитория git.

Пример кода:

Внутри вашего webpack.config.js (или любого файла dev-prod)

const GitRevisionPlugin = require('git-revision-webpack-plugin');
const gitRevisionPlugin = new GitRevisionPlugin();

plugins: [
    new DefinePlugin({
      'VERSION': JSON.stringify(gitRevisionPlugin.version()),
      'COMMITHASH': JSON.stringify(gitRevisionPlugin.commithash()),
      'BRANCH': JSON.stringify(gitRevisionPlugin.branch()),
    }),
  ]

В вашем шаблоне (Angular):

{{ VERSION }} 
{{ COMMITHASH }}
{{ BRANCH }}

Ответ 8

Для угловых 6

1 Установите git-description как зависимость для разработчиков

 npm i git-describe -s

2 В вашем корневом проекте создайте файл grab-git-info.js

   const { gitDescribeSync } = require('git-describe');
   const { writeFileSync } = require('fs');
   const path = require('path');
   const info = gitDescribeSync();
   const infoJson = JSON.stringify(info, null, 2);
   writeFileSync(path.join(__dirname, '/src/git-version.json'), infoJson);

Результатом скрипта grab-git-info.js будет файл 'git-version.json в каталоге /src/, который будет содержать всю информацию о git, необходимую нашему приложению.

Чтобы иметь возможность импортировать файл json (или любой другой файл json), нам нужно добавить файл определения, объявляющий добавленный модуль, чтобы компилятор Typescript распознал его.

  1. В вашем /src создайте файл typings.d.ts (подробнее о typings.d.ts читайте здесь: https://angular.io/guide/typescript-configuration#typescript-typings)

/src/typings.d.ts:

 declare module '*.json' {
   const value: any;
   export default value;
 }

С этого момента вы можете импортировать любой файл json, расположенный в /src, как модуль!

В вашем компоненте вы можете импортировать этот JSON

 import * as data from '../../../git-version.json';
 ...
 public git = data;

В HTML

 Rev: {{git.hash}}

Наконец добавьте и самое главное, запустите скрипт перед сборкой

В package.json добавьте:

"scripts": {
  "ng": "ng",
  "start": "ng serve",
  "build": "node grab-git-info && ng build",

И запустите приложение с

 npm run build

Ответ 9

Используйте gulp задачу с помощью gulp -replace и git -rev-sync, чтобы добавить хэш и ветку в сборке:

1) Создайте задачу gulp

var gulp            =    require('gulp'),
    replace         =    require('gulp-replace'),
    git             =    require('git-rev-sync'),

gulp.task('git', function () {
    gulp.src('src/index.html')
        .pipe(replace('{{git-branch}}', git.branch()))
        .pipe(replace('{{git-hash}}', git.short()))
        .pipe(gulp.dest('src/'))
});

// Build Tasks
gulp.task('build', ['git']);

2) Добавьте следующий код в index.html:

{{git-branch}}@{{git-hash}}

3) Запустите

gulp build