Skip to content

Commit

Permalink
Add tool for upgrading from v7 to v8 (#291)
Browse files Browse the repository at this point in the history
* Add tool for upgrading from v7 to v8

* rename cli tool and include release pipeline
  • Loading branch information
tjololo authored Aug 28, 2023
1 parent 6ce0799 commit d21de61
Show file tree
Hide file tree
Showing 9 changed files with 847 additions and 4 deletions.
41 changes: 37 additions & 4 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
name: Pack and publish nugets
name: Pack and publish

on:
release:
types:
- published

jobs:
build-pack:
release-nugets:
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
Expand All @@ -17,7 +18,6 @@ jobs:
uses: actions/setup-dotnet@v3
with:
dotnet-version: |
5.0.x
6.0.x
- name: Install deps
run: |
Expand All @@ -33,4 +33,37 @@ jobs:
dotnet --version
- name: Publish
run: |
dotnet nuget push src/**/bin/Release/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }}
dotnet nuget push src/**/bin/Release/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }}
release-upgrade-tool:
if: startsWith(github.ref, 'refs/tags/altinn-app-cli')
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./cli-tools/altinn-app-cli
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Install dotnet6
uses: actions/setup-dotnet@v3
with:
dotnet-version: |
6.0.x
- name: Build bundles
run: |
make bundles
- name: Upload files to release
uses: softprops/action-gh-release@v1
with:
files: |
publish/archives/osx-x64.tar.gz
publish/archives/osx-arm64.tar.gz
publish/archives/linux-x64.tar.gz
publish/archives/linux-arm64.tar.gz
publish/archives/win-x64.zip
publish/archives/osx-x64.tar.gz.sha512
publish/archives/osx-arm64.tar.gz.sha512
publish/archives/linux-x64.tar.gz.sha512
publish/archives/linux-arm64.tar.gz.sha512
publish/archives/win-x64.zip.sha512
42 changes: 42 additions & 0 deletions cli-tools/altinn-app-cli/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Path: Makefile

build:
dotnet build

executable-osx-x64:
dotnet publish -c Release -o publish/osx-x64 -r osx-x64 --self-contained

executable-osx-arm64:
dotnet publish -c Release -o publish/osx-arm64 -r osx-arm64 --self-contained

executable-win-x64:
dotnet publish -c Release -o publish/win-x64 -r win-x64 --self-contained

executable-linux-x64:
dotnet publish -c Release -o publish/linux-x64 -r linux-x64 --self-contained

executable-linux-arm64:
dotnet publish -c Release -o publish/linux-arm64 -r linux-arm64 --self-contained

executables: executable-osx-x64 executable-osx-arm64 executable-win-x64 executable-linux-x64 executable-linux-arm64

archives:
mkdir -p publish/archives
tar -czvf publish/archives/osx-x64.tar.gz publish/osx-x64/altinn-app-cli
tar -czvf publish/archives/osx-arm64.tar.gz publish/osx-arm64/altinn-app-cli
tar -czvf publish/archives/linux-x64.tar.gz publish/linux-x64/altinn-app-cli
tar -czvf publish/archives/linux-arm64.tar.gz publish/linux-arm64/altinn-app-cli
zip -r publish/archives/win-x64.zip publish/win-x64/altinn-app-cli.exe

checksums:
sha512sum publish/archives/osx-x64.tar.gz > publish/archives/osx-x64.tar.gz.sha512
sha512sum publish/archives/osx-arm64.tar.gz > publish/archives/osx-arm64.tar.gz.sha512
sha512sum publish/archives/linux-x64.tar.gz > publish/archives/linux-x64.tar.gz.sha512
sha512sum publish/archives/linux-arm64.tar.gz > publish/archives/linux-arm64.tar.gz.sha512
sha512sum publish/archives/win-x64.zip > publish/archives/win-x64.zip.sha512

bundles: executables archives checksums

clean:
dotnet clean
rm -rf publish/
191 changes: 191 additions & 0 deletions cli-tools/altinn-app-cli/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
using System.CommandLine;
using System.Reflection;
using altinn_app_cli.v7Tov8.CodeRewriters;
using altinn_app_cli.v7Tov8.ProcessRewriter;
using altinn_app_cli.v7Tov8.ProjectChecks;
using altinn_app_cli.v7Tov8.ProjectRewriters;
using Microsoft.Build.Locator;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.MSBuild;

namespace altinn_app_upgrade_cli;

class Program
{
static async Task<int> Main(string[] args)
{
int returnCode = 0;
var projectFolderOption = new Option<string>(name: "--folder", description: "The project folder to read", getDefaultValue: () => "CurrentDirectory");
var projectFileOption = new Option<string>(name: "--project", description: "The project file to read relative to --folder", getDefaultValue: () => "App/App.csproj");
var processFileOption = new Option<string>(name: "--process", description: "The process file to read relative to --folder", getDefaultValue: () => "App/config/process/process.bpmn");
var targetVersionOption = new Option<string>(name: "--target-version", description: "The target version to upgrade to", getDefaultValue: () => "8.0.0-preview.9");
var skipCsprojUpgradeOption = new Option<bool>(name: "--skip-csproj-upgrade", description: "Skip csproj file upgrade", getDefaultValue: () => false);
var skipCodeUpgradeOption = new Option<bool>(name: "--skip-code-upgrade", description: "Skip code upgrade", getDefaultValue: () => false);
var skipProcessUpgradeOption = new Option<bool>(name: "--skip-process-upgrade", description: "Skip process file upgrade", getDefaultValue: () => false);
var rootCommand = new RootCommand("Command line interface for working with Altinn 3 Applications");
var upgradeCommand = new Command("upgrade", "Upgrade an app from v7 to v8")
{
projectFolderOption,
projectFileOption,
processFileOption,
targetVersionOption,
skipCsprojUpgradeOption,
skipCodeUpgradeOption,
skipProcessUpgradeOption,
};
rootCommand.AddCommand(upgradeCommand);
var versionCommand = new Command("version", "Print version of altinn-app-cli");
rootCommand.AddCommand(versionCommand);

upgradeCommand.SetHandler(async (projectFolder, projectFile, processFile, targetVersion, skipCodeUpgrade, skipProcessUpgrade, skipCsprojUpgrade) =>
{
if (projectFolder == "CurrentDirectory")
{
projectFolder = Directory.GetCurrentDirectory();
}
if (File.Exists(projectFolder))
{
Console.WriteLine($"Project folder {projectFolder} does not exist. Please supply location of project with --folder [path/to/project]");
returnCode = 1;
return;
}
FileAttributes attr = File.GetAttributes(projectFolder);
if ((attr & FileAttributes.Directory) != FileAttributes.Directory)
{
Console.WriteLine($"Project folder {projectFolder} is a file. Please supply location of project with --folder [path/to/project]");
returnCode = 1;
return;
}
if (!Path.IsPathRooted(projectFolder))
{
projectFile = Path.Combine(Directory.GetCurrentDirectory(), projectFolder, projectFile);
processFile = Path.Combine(Directory.GetCurrentDirectory(), projectFolder, processFile);
}
else
{
projectFile = Path.Combine(projectFolder, projectFile);
processFile = Path.Combine(projectFolder, processFile);
}
var projectChecks = new ProjectChecks(projectFile);
if (!projectChecks.SupportedSourceVersion())
{
Console.WriteLine($"Version(s) in project file {projectFile} is not supported. Please upgrade to version 7.0.0 or higher.");
returnCode = 2;
return;
}
if (!skipCsprojUpgrade)
{
returnCode = await UpgradeNugetVersions(projectFile, targetVersion);
}
if (!skipCodeUpgrade && returnCode == 0)
{
returnCode = await UpgradeCode(projectFile);
}
if (!skipProcessUpgrade && returnCode == 0)
{
returnCode = await UpgradeProcess(processFile);
}
if (returnCode == 0)
{
Console.WriteLine("Upgrade completed without errors. Please verify that the application is still working as expected.");
}
else
{
Console.WriteLine("Upgrade completed with errors. Please check for errors in the log above.");
}
},
projectFolderOption, projectFileOption, processFileOption, targetVersionOption, skipCodeUpgradeOption, skipProcessUpgradeOption, skipCsprojUpgradeOption);
versionCommand.SetHandler(() =>
{
var version = Assembly.GetEntryAssembly()?.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion ?? "Unknown";
Console.WriteLine($"altinn-app-cli v{version}");
});
await rootCommand.InvokeAsync(args);
return returnCode;
}

static async Task<int> UpgradeNugetVersions(string projectFile, string targetVersion)
{
if (!File.Exists(projectFile))
{
Console.WriteLine($"Project file {projectFile} does not exist. Please supply location of project with --project [path/to/project.csproj]");
return 1;
}

Console.WriteLine("Trying to upgrade nuget versions in project file");
var rewriter = new ProjectFileRewriter(projectFile, targetVersion);
await rewriter.Upgrade();
Console.WriteLine("Nuget versions upgraded");
return 0;
}

static async Task<int> UpgradeCode(string projectFile)
{
if (!File.Exists(projectFile))
{
Console.WriteLine($"Project file {projectFile} does not exist. Please supply location of project with --project [path/to/project.csproj]");
return 1;
}

Console.WriteLine("Trying to upgrade references and using in code");

MSBuildLocator.RegisterDefaults();
var workspace = MSBuildWorkspace.Create();
var project = await workspace.OpenProjectAsync(projectFile);
var comp = await project.GetCompilationAsync();
if (comp == null)
{
Console.WriteLine("Could not get compilation");
return 1;
}
foreach (var sourceTree in comp.SyntaxTrees)
{
SemanticModel sm = comp.GetSemanticModel(sourceTree);
TypesRewriter rewriter = new(sm);
SyntaxNode newSource = rewriter.Visit(await sourceTree.GetRootAsync());
if (newSource != await sourceTree.GetRootAsync())
{
await File.WriteAllTextAsync(sourceTree.FilePath, newSource.ToFullString());
}
UsingRewriter usingRewriter = new();
var newUsingSource = usingRewriter.Visit(newSource);
if (newUsingSource != newSource)
{
await File.WriteAllTextAsync(sourceTree.FilePath, newUsingSource.ToFullString());
}
}

Console.WriteLine("References and using upgraded");
return 0;
}

static async Task<int> UpgradeProcess(string processFile)
{
if (!File.Exists(processFile))
{
Console.WriteLine($"Process file {processFile} does not exist. Please supply location of project with --process [path/to/project.csproj]");
return 1;
}

Console.WriteLine("Trying to upgrade process file");
ProcessUpgrader parser = new(processFile);
parser.Upgrade();
await parser.Write();
var warnings = parser.GetWarnings();
foreach (var warning in warnings)
{
Console.WriteLine(warning);
}

Console.WriteLine(warnings.Any() ? "Process file upgraded with warnings. Review the warnings above and make sure that the process file is still valid." : "Process file upgraded");

return 0;
}
}
42 changes: 42 additions & 0 deletions cli-tools/altinn-app-cli/altinn-app-cli.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>altinn_app_cli</RootNamespace>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
<RuntimeIdentifier>osx-x64</RuntimeIdentifier>
<AssemblyName>altinn-app-cli</AssemblyName>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>false</PublishTrimmed>
<PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Build.Locator" Version="1.4.1" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.6.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="4.6.0" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="MinVer" Version="4.3.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="All" />
</ItemGroup>
<PropertyGroup>
<RepoRoot>$([System.IO.Directory]::GetParent($(MSBuildThisFileDirectory)).Parent.FullName)</RepoRoot>
<MinVerDefaultPreReleasePhase>preview</MinVerDefaultPreReleasePhase>
<MinVerTagPrefix>altinn-app-cli</MinVerTagPrefix>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<LangVersion>10.0</LangVersion>
</PropertyGroup>

<Target Name="AssemblyVersionTarget" AfterTargets="MinVer" Condition="'$(MinVerVersion)'!=''">
<PropertyGroup>
<Version>$(MinVerMajor).$(MinVerMinor).$(MinVerPatch)</Version>
</PropertyGroup>
</Target>
</Project>
Loading

0 comments on commit d21de61

Please sign in to comment.