如何将git修订包含在angular-cli应用程序中?

时间:2017-02-10 08:52:53

标签: angular angular-cli

我需要在angular2应用程序上显示关于页面的git修订版。该项目基于angular-cli。

如何扩展构建,以便将git修订版放在例如environment.ts或应用程序可访问的其他位置?

9 个答案:

答案 0 :(得分:38)

根据@Yuri的建议,我能够通过使用npm脚本来解决这个问题。

  1. 在angular-cli项目的根目录中定义git.version.ts

    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');    
    
  4. 注意,使用angular-cli v7.0.6时,我还必须更改package.json中的脚本调用:

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

答案 1 :(得分:6)

  1. git-version.js添加到根。此代码将执行git命令并将输出写入git-version.json文件。
const childProcess = require('child_process');
const { writeFileSync } = require('fs');

const longSHA = childProcess.execSync("git rev-parse HEAD").toString().trim();
const shortSHA = childProcess.execSync("git rev-parse --short HEAD").toString().trim();
const branch = childProcess.execSync('git rev-parse --abbrev-ref HEAD').toString().trim();
const authorName = childProcess.execSync("git log -1 --pretty=format:'%an'").toString().trim();
const commitTime = childProcess.execSync("git log -1 --pretty=format:'%cd'").toString().trim();
const commitMsg = childProcess.execSync("git log -1 --pretty=%B").toString().trim();
const totalCommitCount = childProcess.execSync("git rev-list --count HEAD").toString().trim();

const versionInfo = {
    shortSHA: shortSHA,
    SHA : longSHA,
    branch: branch,
    lastCommitAuthor: authorName,
    lastCommitTime: commitTime,
    lastCommitMessage: commitMsg,
    lastCommitNumber: totalCommitCount
}

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

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

此代码将生成git-version.json文件:-

{
  "shortSHA": "0e786d4",
  "SHA": "0e786d4ad3778463f6f30c28f254cc85c24eb4b3",
  "branch": "master",
  "lastCommitAuthor": "'saurabh'",
  "lastCommitTime": "'Thu Apr 9 12:59:16 2020 +0530'",
  "lastCommitMessage": "Commit message",
  "lastCommitNumber": "200"
}

根据您的要求修改以上代码。

运行:node git-version.js这将在git-version.json目录中生成src

  1. 在构建之前或之后运行此代码。将新脚本添加到package.json
"scripts": {
   "ng": "ng",
   "start": "ng serve",
   "build": "ng build",
   "test": "ng test",
   "lint": "ng lint",
   "e2e": "ng e2e",
   "build.prod": "node git-version.js && ng build --prod"
 }
  1. 运行:-npm run build.prod
欢迎

改进代码的建议:)

答案 2 :(得分:5)

其他答案很有帮助,但我更喜欢一种更简单,直接的方法。这是我的。

运行npm install --save dev git-describe。然后将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或您想使用的其他任何地方,versionInfoapp.component.ts

答案 3 :(得分: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 :(得分:1)

我选择了Vilmantas Baranauskas的修改版本

我已将src/index.html移至src/index.base.html并在HEAD中添加了空<meta name="revision" content="">

示例:

<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 :(得分:1)

显示分支名称并提交哈希

受主项目目录中的答案repo Seba ArceJeroen启发,我有一些不同的方法:

  • 执行:npm install git-rev-sync --save(此lib赋予哈希和分支名称的访问权限)
  • 添加带有以下正文的文件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);

  • package.json的{​​{1}}中添加scripts
  • 在您的主应用程序文件中,例如"build": "node git-version-gen.js && ng build ..."如下使用它

app.component.ts

使用此功能有什么好处?

  • 我们在此处创建import { gitVersion } from '../../../environments/git-version'; // ... constructor() { console.log(`GIT branch:`,gitVersion.branch); console.log(`GIT commit:`,gitVersion.commit); }文件,因此这是TypeScript,而不是.json-与您的环境文件类似,这将打开您的代码编辑器(例如VSCode)的支持

  • 您具有提交哈希nad分支名称的权限(lib src/environments/git-version.ts没有为分支名称赋予acces)

  • 如果您提交生成的git-describe文件而不是将其放入git-version.ts,则项目将在没有构建的情况下运行(例如,由.gitignore),并且新开​​发人员将不会感到困惑缺少一些“神秘”文件...-但是选择取决于您。

  • 跨平台-已在Azure(windows),MacOs(类似于Linux)上进行测试

答案 6 :(得分:0)

对于角度6

1将git-describe安装为开发依赖项

With ActiveDocument
  .Fields.Add Range:=Selection.Sections.First.Footers(wdHeaderFooterPrimary).Range.Characters.Last, _
    Type:=wdFieldEmpty, Text:="PRINTDATE \@""'This document was last printed on 'DD MMM YYYY""", PreserveFormatting:=False
End With

2在您的根项目中,创建一个grab-git-info.js

 npm i git-describe -s

grab-git-info.js脚本的输出将是/ src /下的“ git-version.json”文件,其中将包含我们应用程序所需的所有git信息。

为了能够导入json文件(或其他任何json文件),我们需要添加一个定义文件来声明添加的模块,以便Typescript编译器能够识别它。

  1. 在您的/ src下,创建typesings.d.ts文件(在此处https://angular.io/guide/typescript-configuration#typescript-typings中了解更多有关typeings.d.ts的信息)

/src/typings.d.ts:

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

从这一点开始,您可以将/ src下的任何json文件作为模块导入!

在您的组件中,您可以导入此json

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

在html

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

最后  添加,最重要的是,在构建之前运行脚本

在package.json中添加:

 Rev: {{git.hash}}

并使用

运行该应用
"scripts": {
  "ng": "ng",
  "start": "ng serve",
  "build": "node grab-git-info && ng build",

答案 7 :(得分:0)

我通过生成在安装后运行并在任何角度相关的脚本之前运行的预构建脚本来做到这一点


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

答案 8 :(得分:-1)

使用gulp-task和git-rev-sync使用gulp任务在build上添加hash和branch:

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