Skip to content

Commit

Permalink
Merge pull request #27 from nkdAgility/topic/enable-rerunning
Browse files Browse the repository at this point in the history
Topic/enable rerunning
  • Loading branch information
MrHinsh authored Jul 2, 2024
2 parents 400ca01 + 2c5c383 commit bb89dfd
Show file tree
Hide file tree
Showing 9 changed files with 244 additions and 104 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ jobs:
}
if ( "${{needs.Setup.outputs.GitVersion_PreReleaseLabel}}" -eq "" ) {
echo "Creating a release."
gh release create v${{needs.Setup.outputs.GitVersion_SemVer}} ./AzureDevOpsWorkItemClone-v${{needs.Setup.outputs.GitVersion_SemVer}}-win-x64.zip --generate-notes --discussion-category "General"
gh release create v${{needs.Setup.outputs.GitVersion_SemVer}} ./AzureDevOpsWorkItemClone-v${{needs.Setup.outputs.GitVersion_SemVer}}-win-x64.zip --generate-notes --discussion-category "Announcements"
exit 0
}
shell: pwsh
Expand Down
2 changes: 2 additions & 0 deletions AzureDevOps-workitem-clone.sln
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F583DC39-F8DC-46A8-80E8-AC0458DEE366}"
ProjectSection(SolutionItems) = preProject
TestData\ADO_TESTProjPipline_V03.json = TestData\ADO_TESTProjPipline_V03.json
GitVersion.yml = GitVersion.yml
.github\workflows\main.yml = .github\workflows\main.yml
EndProjectSection
EndProject
Global
Expand Down
265 changes: 173 additions & 92 deletions AzureDevOps.WorkItemClone.ConsoleUI/Commands/WorkItemCloneCommand.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ internal class WorkItemCloneCommandSettings : BaseCommandSettings
[CommandOption("--ClearCache")]
[JsonIgnore]
public bool ClearCache { get; set; }
[Description("Use this run name to execute. This will create a unique folder under the CachePath for storing run specific data and status. Defaults to yyyyyMMddHHmmss.")]
[CommandOption("--RunName")]
[JsonIgnore]
public string? RunName { get; set; }
//------------------------------------------------
[CommandOption("--outputPath|--cachePath")]
[DefaultValue("./cache")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ internal abstract class WorkItemCommandBase<TSettings> : AsyncCommand<TSettings>

internal void CombineValuesFromConfigAndSettings(WorkItemCloneCommandSettings settings, WorkItemCloneCommandSettings config)
{
config.RunName = settings.RunName != null ? settings.RunName : DateTime.Now.ToString("yyyyyMMddHHmmss");
config.configFile = EnsureConfigFileAskIfMissing(config.configFile = settings.configFile != null ? settings.configFile : config.configFile);
config.inputJsonFile = EnsureJsonFileAskIfMissing(config.inputJsonFile = settings.inputJsonFile != null ? settings.inputJsonFile : config.inputJsonFile);
config.CachePath = EnsureCachePathAskIfMissing(config.CachePath = settings.CachePath != null ? settings.CachePath : config.CachePath);
Expand All @@ -29,7 +30,7 @@ internal void CombineValuesFromConfigAndSettings(WorkItemCloneCommandSettings se
config.targetOrganization = EnsureOrganizationAskIfMissing(config.targetOrganization = settings.targetOrganization != null ? settings.targetOrganization : config.targetOrganization);
config.targetProject = EnsureProjectAskIfMissing(config.targetProject = settings.targetProject != null ? settings.targetProject : config.targetProject, config.targetOrganization);
config.targetAccessToken = EnsureAccessTokenAskIfMissing(settings.targetAccessToken != null ? settings.targetAccessToken : config.targetAccessToken, config.targetOrganization);
config.targetParentId = EnsureParentIdAskIfMissing(config.targetParentId = settings.targetParentId != null ? settings.targetParentId : config.targetParentId);
config.targetParentId = EnsureParentIdAskIfMissing(config.targetParentId = settings.targetParentId != null ? settings.targetParentId : config.targetParentId);
}
internal int EnsureParentIdAskIfMissing(int? parentId)
{
Expand All @@ -45,14 +46,8 @@ internal int EnsureParentIdAskIfMissing(int? parentId)
return parentId.Value;
}

internal List<jsonWorkItem> LoadJsonFile(string? jsonFile)
private List<jsonWorkItem> DeserializeWorkItemList(string jsonFile)
{
jsonFile = EnsureJsonFileAskIfMissing(jsonFile);
if (!System.IO.File.Exists(jsonFile))
{
AnsiConsole.MarkupLine("[red]Error:[/] No JSON file was found.");
throw new Exception(jsonFile + " not found.");
}
List<jsonWorkItem> configWorkItems;
try
{
Expand All @@ -72,6 +67,31 @@ internal List<jsonWorkItem> LoadJsonFile(string? jsonFile)
return configWorkItems;
}

internal List<jsonWorkItem> DeserializeWorkItemList(WorkItemCloneCommandSettings config)
{
string CachedRunJson = System.IO.Path.Combine(config.CachePath, config.RunName, "input.json");
if (System.IO.File.Exists(CachedRunJson))
{
// Load From Run Cache
config.inputJsonFile = CachedRunJson;
return DeserializeWorkItemList(CachedRunJson);
} else
{
// Load new
config.inputJsonFile = EnsureJsonFileAskIfMissing(config.inputJsonFile);
if (!System.IO.File.Exists(config.inputJsonFile))
{
AnsiConsole.MarkupLine("[red]Error:[/] No JSON file was found.");
throw new Exception(config.inputJsonFile + " not found.");
}

List<jsonWorkItem> inputWorkItems;
inputWorkItems= DeserializeWorkItemList(config.inputJsonFile);
System.IO.File.WriteAllText(CachedRunJson, JsonConvert.SerializeObject(inputWorkItems, Formatting.Indented));
return inputWorkItems;
}
}

internal string EnsureJsonFileAskIfMissing(string? jsonFile)
{
if (jsonFile == null)
Expand Down Expand Up @@ -203,6 +223,7 @@ internal void WriteOutSettings(WorkItemCloneCommandSettings config)
.AddColumn(new TableColumn("Value"))
.AddEmptyRow()
.AddRow("configFile", config.configFile != null ? config.configFile : "NOT SET")
.AddRow("runName", config.RunName != null ? config.RunName : "NOT SET")
.AddRow("CachePath", config.CachePath != null ? config.CachePath : "NOT SET")
.AddRow("inputJsonFile", config.inputJsonFile != null ? config.inputJsonFile : "NOT SET")
.AddEmptyRow()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
},
"Clone": {
"commandName": "Project",
"commandLineArgs": "clone --jsonFile ..\\..\\..\\..\\..\\TestData\\ADO_TESTProjPipline_V03.json --templateAccessToken tqvemdfaucnfhr7fwr2f5ebunncgfxeps5owjmsriu6e3uti7dya --targetAccessToken ay5xc2kn7pka35nkx5coiey6fo4twjjc6yvtp5i3xcsmw5fu65ja "
"commandLineArgs": "clone --RunName Run1 --jsonFile ..\\..\\..\\..\\..\\TestData\\ADO_TESTProjPipline_V03.json "
},
"empty": {
"commandName": "Project"
Expand Down
2 changes: 0 additions & 2 deletions AzureDevOps.WorkItemClone/DataContracts/WorkItemAdd.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ namespace AzureDevOps.WorkItemClone.DataContracts
public class WorkItemAdd
{
public List<Operation> Operations { get; set; } = new List<Operation>();
public WorkItemFull? ItemFromtemplate { get; set; }
public jsonWorkItem ItemFromConfig { get; set; }
}

public abstract class Operation
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Clones work items from a template project to a target project incorproating a JS
- `--config` - The path to the configuration file. Default is `.\configuration.json`. This can be used to had code paramiters... Command line params overrides the configuration file.
- `--CachePath` - Folder used to cache data like the template. Default is `.\cache`.
- `--inputJsonFile` - The path to the JSON file that instructs the creation of the work items
- `--runname` - The name of the run. Default is the current DateTime. Use this to rerun a creation that failed or was interupted.

*Template Parameters* - The template contains the Descrition, Acceptance Criteria and relationship to other work itsm that we will clone.

Expand All @@ -45,6 +46,22 @@ Clones work items from a template project to a target project incorproating a JS
clone --inputJsonFile ..\\..\\..\\..\\TestData\\ADO_TESTProjPipline_V03.json --targetParentId 540 --templateAccessToken tqvemdfaucsriu6e3uti7dya --targetAccessToken ay5xc2kn5i3xcsmw5fu65ja
```

#### Runs

The consept of runs is to allow users to restart a failed or interupted run. The run name is used to identify the run and the cache is used to store the state of the run.

The example below will create a subfolder to the cache called `Bob` where it will store the state of the run. If the run fails or is interupted you can restart the run by using the same run name. Rerunning the same run will not create duplicate work items and will not rebuild the output file that is generated in steps 4 and 5. It will reuse the existing one. If you need to change the input file then you will need to create a new run.

When using the `--runname` parameter the `--inputJsonFile ` will not be used if a cache exists for the run. The input file will be read from the cache.

*Typical usage*:

```powershell
clone --runname Bob --inputJsonFile ..\\..\\..\\..\\TestData\\ADO_TESTProjPipline_V03.json --targetParentId 540 --templateAccessToken tqvemdfaucsriu6e3uti7dya --targetAccessToken ay5xc2kn5i3xcsmw5fu65ja
```



### `init`

Leads you through the process of creating a configuration file.
Expand Down
17 changes: 17 additions & 0 deletions docs/Home.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Clones work items from a template project to a target project incorproating a JS
- `--config` - The path to the configuration file. Default is `.\configuration.json`. This can be used to had code paramiters... Command line params overrides the configuration file.
- `--CachePath` - Folder used to cache data like the template. Default is `.\cache`.
- `--inputJsonFile` - The path to the JSON file that instructs the creation of the work items
- `--runname` - The name of the run. Default is the current DateTime. Use this to rerun a creation that failed or was interupted.

*Template Parameters* - The template contains the Descrition, Acceptance Criteria and relationship to other work itsm that we will clone.

Expand All @@ -45,6 +46,22 @@ Clones work items from a template project to a target project incorproating a JS
clone --inputJsonFile ..\\..\\..\\..\\TestData\\ADO_TESTProjPipline_V03.json --targetParentId 540 --templateAccessToken tqvemdfaucsriu6e3uti7dya --targetAccessToken ay5xc2kn5i3xcsmw5fu65ja
```

#### Runs

The consept of runs is to allow users to restart a failed or interupted run. The run name is used to identify the run and the cache is used to store the state of the run.

The example below will create a subfolder to the cache called `Bob` where it will store the state of the run. If the run fails or is interupted you can restart the run by using the same run name. Rerunning the same run will not create duplicate work items and will not rebuild the output file that is generated in steps 4 and 5. It will reuse the existing one. If you need to change the input file then you will need to create a new run.

When using the `--runname` parameter the `--inputJsonFile ` will not be used if a cache exists for the run. The input file will be read from the cache.

*Typical usage*:

```powershell
clone --runname Bob --inputJsonFile ..\\..\\..\\..\\TestData\\ADO_TESTProjPipline_V03.json --targetParentId 540 --templateAccessToken tqvemdfaucsriu6e3uti7dya --targetAccessToken ay5xc2kn5i3xcsmw5fu65ja
```



### `init`

Leads you through the process of creating a configuration file.
Expand Down

0 comments on commit bb89dfd

Please sign in to comment.