Skip to content
This repository has been archived by the owner on Nov 14, 2023. It is now read-only.

Commit

Permalink
Merge pull request #26 from jabbera/v5
Browse files Browse the repository at this point in the history
V5
  • Loading branch information
jabbera authored Mar 28, 2018
2 parents 86418e3 + bba765f commit 9ecced0
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 15 deletions.
21 changes: 12 additions & 9 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,29 @@
"sourceMaps": true,
"env": {
// This is the tag to be created
"RELEASE_RELEASENAME": "Mike - 1",
// This only supports TfsGit currently.
"RELEASE_ARTIFACTS_MASTER_BRANCH_REPOSITORY_PROVIDER": "TfsGit",
// The commit to tag
"RELEASE_ARTIFACTS_MASTER_BRANCH_SOURCEVERSION": "b950f0e25df229dee0fe7ff5ff7a6194f9580b21",
// The build id to get the repository id from. This won't be needed onece: https://github.com/Microsoft/vsts-agent/issues/976 is completed.
"RELEASE_ARTIFACTS_MASTER_BRANCH_BUILDID": "27",
"RELEASE_RELEASENAME": "Release - 1.0.20",

"RELEASE_ARTIFACTS_SCRUMM-SAMPLE-BUILD1_REPOSITORY_PROVIDER": "TfsGit",
"RELEASE_ARTIFACTS_SCRUMM-SAMPLE-BUILD1_SOURCEVERSION": "88c2da89b3aab9b33a2c205e5cf31f22d79b0a1a",
"RELEASE_ARTIFACTS_SCRUMM-SAMPLE-BUILD1_REPOSITORY_ID": "4c9a5185-5d8f-4d36-935a-da19e0c4f97b",

"RELEASE_ARTIFACTS_SCRUMM-SAMPLE-BUILD_REPOSITORY_PROVIDER": "TfsGit",
"RELEASE_ARTIFACTS_SCRUMM-SAMPLE-BUILD_SOURCEVERSION": "1dea04b2c6a3524b53a1904c20af77b3418694cb",
"RELEASE_ARTIFACTS_SCRUMM-SAMPLE-BUILD_REPOSITORY_ID": "4c9a5185-5d8f-4d36-935a-da19e0c4f97b",

// Regex Settings
"INPUT_staticTagName": "DEV1",
"INPUT_regexFlags": "",
"INPUT_searchRegex": "",
"INPUT_replacePattern": "",
"INPUT_branchFolder": "patch/subpatch/",
"INPUT_branchFolder": "",


// Set these as an environment variables
//"ENDPOINT_AUTH_PARAMETER_SystemVssConnection_AccessToken": "<Your token>",
//"ENDPOINT_URL_SystemVssConnection": "https://<your account>.vsrm.visualstudio.com/",

"VSTS_PUBLIC_VARIABLES": "[\"RELEASE.ARTIFACTS.MASTER.BRANCH.REPOSITORY.PROVIDER\", \"RELEASE.ARTIFACTS.MASTER.BRANCH.SOURCEVERSION\", \"RELEASE.ARTIFACTS.MASTER.BRANCH.BUILDID\", \"RELEASE.RELEASENAME\"]"
"VSTS_PUBLIC_VARIABLES": "[\"RELEASE.ARTIFACTS.SCRUMM-SAMPLE-BUILD1.REPOSITORY.PROVIDER\", \"RELEASE.ARTIFACTS.SCRUMM-SAMPLE-BUILD1.SOURCEVERSION\", \"RELEASE.ARTIFACTS.SCRUMM-SAMPLE-BUILD1.REPOSITORY.ID\", \"RELEASE.ARTIFACTS.SCRUMM-SAMPLE-BUILD.REPOSITORY.PROVIDER\", \"RELEASE.ARTIFACTS.SCRUMM-SAMPLE-BUILD.SOURCEVERSION\", \"RELEASE.ARTIFACTS.SCRUMM-SAMPLE-BUILD.REPOSITORY.ID\",\"RELEASE.RELEASENAME\"]"
}
}
]
Expand Down
112 changes: 106 additions & 6 deletions Tasks/common/GitRefCreator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export abstract class GitRefCreator {
let gitapi: git.IGitApi = connect.getGitApi();
let bldapi: bld.IBuildApi = connect.getBuildApi();

let artifactData: IArtifactData[] = await this.getAllGitArtifacts(bldapi);
let artifactData: IArtifactData[] = await this.getAllGitArtifacts(bldapi, gitapi);

if (artifactData.length === 0) {
tl.warning("No TfsGit artifacts found.");
Expand Down Expand Up @@ -76,7 +76,7 @@ export abstract class GitRefCreator {
return defaultValue;
}

private async getAllGitArtifacts(bldapi: bld.IBuildApi): Promise < IArtifactData[] > {
private async getAllGitArtifacts(bldapi: bld.IBuildApi, gitapi: git.IGitApi): Promise < IArtifactData[] > {
let artifactNames: IArtifactData[] = [];
let regexp: RegExp = new RegExp("RELEASE\.ARTIFACTS\.(.*)\.REPOSITORY\.PROVIDER", "gi");

Expand All @@ -94,22 +94,122 @@ export abstract class GitRefCreator {

let name: string = match[1];
tl.debug(`Getting repository id for artifact: ${name}`);
let repositoryId: string = await this.getRepositoryIdFromBuildNumber(bldapi, name); // This should really be available via a variable
let repositoryId: string = await this.getRepositoryId(bldapi, name); // This should really be available via a variable
if (repositoryId == null) {
continue; // Error already logged
}

let artifact: IArtifactData = {
"name": name,
"commit": tl.getVariable(`RELEASE.ARTIFACTS.${name}.SOURCEVERSION`),
"repositoryId": repositoryId,
"repositoryId": repositoryId.toLowerCase(),
"oldCommitId": "0000000000000000000000000000000000000000",
};

artifactNames.push(artifact);
}

return artifactNames;
return await this.filterArtifacts(gitapi, artifactNames);
}

// This is meant to fix https://github.com/jabbera/vsts-git-release-tag/issues/23
// The user is using the same repo, but 2 different commits via 2 different artifacts.
// For a given repository we should select only the most current commit.
// My kingdom for a groupby
private async filterArtifacts(gitapi: git.IGitApi, artifacts: IArtifactData[]) {
if (artifacts.length <= 1) {
return artifacts;
}

artifacts.sort( (x, y) => {
if (x.repositoryId === y.repositoryId) return 0;
if (x.repositoryId < y.repositoryId) return -1;
// if (tuple[0] > tuple[1])
return 1;
});

artifacts = this.filterIncludedArtifacts(artifacts);

let i: number;
for (i = 1; i < artifacts.length; i++) {
const prev: IArtifactData = artifacts[i - 1];
const current: IArtifactData = artifacts[i];

if (prev.repositoryId !== current.repositoryId) {
continue;
}

if (prev.commit === current.commit) {
continue;
}

let search = <giti.GitQueryCommitsCriteria> {
ids: [prev.commit, current.commit],
};

tl.debug(`Attempting to determine which commit was last. Prev: ${prev.commit} Current: ${current.commit} for repository: ${prev.repositoryId}`);

const commits: giti.GitCommitRef[] = await gitapi.getCommitsBatch(search, prev.repositoryId);
if (commits.length !== 2) {
tl.setResult(tl.TaskResult.Failed, `Cannot resolve difference most recent between two commits: ${prev.commit} ${current.commit}`);
return artifacts;
}

let firstCommitArtifactIndex: number;
let secondCommitArtifactIndex: number;

if (artifacts[i - 1].commit === commits[0].commitId.toLowerCase()) {
firstCommitArtifactIndex = i - 1;
secondCommitArtifactIndex = i;
} else {
firstCommitArtifactIndex = i;
secondCommitArtifactIndex = i - 1;
}

tl.debug(`Commit Info: { Id: ${commits[0].commitId} Date: ${commits[0].committer.date}} {Id: ${commits[1].commitId} Date: ${commits[1].committer.date}}`);

if (commits[0].committer.date < commits[1].committer.date) {
tl.debug(`Winning commit: ${commits[1].commitId}`);
artifacts[firstCommitArtifactIndex].commit = artifacts[secondCommitArtifactIndex].commit;
} else {
tl.debug(`Winning commit: ${commits[0].commitId}`);
artifacts[secondCommitArtifactIndex].commit = artifacts[firstCommitArtifactIndex].commit;
}
}

return artifacts;
}

private filterIncludedArtifacts(artifacts: IArtifactData[]): IArtifactData[] {
const includeMultiline: string[] = tl.getDelimitedInput("artifactIncludeList", "\r", false);
let includedArtifacts: Set<string>;

if (includeMultiline === null || includeMultiline.length === 0) {
tl.debug("inlcuding all artifacts");
includedArtifacts = new Set<string>(artifacts.map((x) => x.name));
}
else {
tl.debug("Filtering artifacts");
includedArtifacts = new Set<string>(includeMultiline);
}

tl.debug(`Before filter count: ${artifacts.length}`);
artifacts = artifacts.filter( (value) => includedArtifacts.has(value.name));
tl.debug(`After filter count ${artifacts.length}`);
return artifacts;
}

private async getRepositoryId(bldapi: bld.IBuildApi, name: string): Promise < string > {
let repositoryidVariable: string = `RELEASE.ARTIFACTS.${name}.REPOSITORY_ID`;
let repositoryid: string = tl.getVariable(repositoryidVariable);

if (repositoryid === null || repositoryid === "") {
// This is a fallback to support TFS 2015
return await this.getRepositoryIdFromBuildNumber(bldapi, name);
}

tl.debug(`Got repositoryid from variable: ${repositoryid}`);
return repositoryid;
}

private async getRepositoryIdFromBuildNumber(bldapi: bld.IBuildApi, name: string): Promise < string > {
Expand All @@ -122,7 +222,7 @@ export abstract class GitRefCreator {
}

let build: bldi.Build = await bldapi.getBuild(Number(buildid));
tl.debug(`Got repositoryid: ${build.repository.id}`);
tl.debug(`Got repositoryid from build: ${build.repository.id}`);
return build.repository.id;
}

Expand Down
9 changes: 9 additions & 0 deletions Tasks/git-branch-on-release-task/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@
"required": false,
"helpMarkDown": "The replacement patten corresponding to the regex above. Default is empty string",
"groupName": "advanced"
},
{
"name": "artifactIncludeList",
"type": "multiLine",
"label": "Artifacts to include",
"defaultValue": "",
"required": false,
"helpMarkDown": "An optional list of artifacts to include. If empty, use all. Newline delimited.",
"groupName": "advanced"
}
],
"execution": {
Expand Down
9 changes: 9 additions & 0 deletions Tasks/git-tag-on-release-task/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@
"required": false,
"helpMarkDown": "The replacement patten corresponding to the regex above. Default is empty string",
"groupName": "advanced"
},
{
"name": "artifactIncludeList",
"type": "multiLine",
"label": "Artifacts to include",
"defaultValue": "",
"required": false,
"helpMarkDown": "An optional list of artifacts to include. If empty, use all. Newline delimited.",
"groupName": "advanced"
}
],
"execution": {
Expand Down
3 changes: 3 additions & 0 deletions overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ Branching:

The branch folder allows you to specify a subfolder to branch to. Adding to the example above. If the Branch Folder was set to: 'patch' the ref that would be created is: /refs/heads/patch/v3.0.17270.8

* Changes in 5.0.X
* Support multiple artifcats from the same repository with different commits. Newest to be commited wins.
* Support an artifact filter if you need to include only a subset of artifacts.
* Changes in 4.0.1
* Update the error log to include previous commit id
* Changes in 4.0.0
Expand Down

0 comments on commit 9ecced0

Please sign in to comment.