Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.0.2 Release #10

Merged
merged 1 commit into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Generate and Deploy DocFX Documentation

on:
push:
branches:
- main

jobs:
build-and-deploy:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Set up .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.x'

- name: Install DocFX
run: dotnet tool install -g docfx

- name: Add .dotnet/tools to PATH
run: echo "::add-path::${HOME}/.dotnet/tools"

- name: Build DocFX site
working-directory: ./docs
run: docfx

- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/_site
publish_branch: gh-pages
keep_files: false
52 changes: 46 additions & 6 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,13 @@ jobs:
- name: Build
run: dotnet build --configuration Release --no-restore

- name: Install ReportGenerator
run: dotnet tool install -g dotnet-reportgenerator-globaltool

- name: Test
run: dotnet test --no-build --configuration Release --verbosity normal
run: |
dotnet test --configuration Release tests/Tableau.Migration.App.Core.Tests/ /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput=../../CoreCoverage.xml
dotnet test --configuration Release tests/Tableau.Migration.App.GUI.Tests /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput=../../GUICoverage.xml
env:
TABLEAU_CLOUD_URL: ${{ secrets.TABLEAU_CLOUD_URL }}
TABLEAU_CLOUD_SITE: ${{ secrets.TABLEAU_CLOUD_SITE }}
Expand All @@ -36,9 +41,44 @@ jobs:
TABLEAU_SERVER_TOKEN_NAME: ${{ secrets.TABLEAU_SERVER_TOKEN_NAME }}
TABLEAU_SERVER_TOKEN: ${{ secrets.TABLEAU_SERVER_TOKEN }}

- name: Run dotnet format
run: dotnet format --verbosity diagnostic
- name: Generate coverage report
env:
PATH: $PATH:/home/runner/.dotnet/tools # Adds dotnet tools to PATH
run: reportgenerator -reports:"./*Coverage.xml" -targetdir:./coverage-report -reporttypes:"Html;TextSummary"

- name: Comment coverage summary on PR
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const summary = fs.readFileSync('./coverage-report/Summary.txt', 'utf8');
// Split the summary by lines and get the first 18
const topSummary = summary.split('\n').slice(0, 18).join('\n');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## Code Coverage Summary\n\`\`\`\n${topSummary}\n\`\`\``
});

# Skipping for now due to line ending mismatches
# - name: Run dotnet format
# id: format
# run: |
# dotnet format --verbosity diagnostic > format.log
# grep -q 'Formatted code file' format.log || exit 0
# exit 1

- name: Check format results
if: failure()
run: echo "Formatting issues found. Please run 'dotnet format' locally and fix the issues."
# - name: Check format results
# if: failure()
# uses: actions/github-script@v6
# with:
# github-token: ${{ secrets.GITHUB_TOKEN }}
# script: |
# github.rest.issues.createComment({
# issue_number: context.issue.number,
# owner: context.repo.owner,
# repo: context.repo.repo,
# body: "Formatting issues were found and fixed. Please run 'dotnet format' locally to ensure your code is properly formatted."
# })
6 changes: 1 addition & 5 deletions BUILD.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Tableau ESMB Migration App
# Tableau Migration App
Tableau express migration application to migrate data sources from Tableau Server to Tableau Cloud.
Requirements doc can be found [here](https://docs.google.com/document/d/1DXrYdTbS5aGcZeicNVAdD1tvGRwtH1Yj/edit#heading=h.gjdgxs).

Expand All @@ -12,10 +12,6 @@ Requirements doc can be found [here](https://docs.google.com/document/d/1DXrYdTb
* Tableau.Migration.App.GUI - Gui implementation using Avalonia framework.

# Building
## From Container
The dockerfile is defined in the `Dockerfile` from the project root.
```
docker build .
```
## From Source Root
```
Expand Down
3 changes: 2 additions & 1 deletion docs/docs/gui.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ Currently we have the following defined service interfaces:
The top level view used to hold all visible elements is located in the [MainWindow](/api/Tableau.Migration.App.GUI.Views.MainWindow.html) view.

## View Models
All ViewModels are named based on their appropriate View name. i.e. the [MainWindow](/api/Tableau.Migration.App.GUI.Views.MainWindow.html) view has an associatedv [MainWindowViewModel](api/Tableau.Migration.App.GUI.ViewModels.MainWindowViewModel.html).
All ViewModels are named based on their appropriate View name. i.e. the [MainWindow](/api/Tableau.Migration.App.GUI.Views.MainWindow.html) view has an associatedv [MainWindowViewModel](/api/Tableau.Migration.App.GUI.ViewModels.MainWindowViewModel.html)


There exist 2 abstract classes defined in the ViewModel folder:
- [**ViewModelBase**](/api/Tableau.Migration.App.GUI.ViewModels.ViewModelBase.html) - The base class of a ViewModel.
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
4 changes: 4 additions & 0 deletions docs/toc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- name: Docs
href: docs/
- name: API
href: api/
4 changes: 4 additions & 0 deletions scripts/gen_report.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/bash
dotnet test tests/Tableau.Migration.App.Core.Tests/ /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput=../../CoreCoverage.xml
dotnet test tests/Tableau.Migration.App.GUI.Tests /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput=../../GUICoverage.xml
reportgenerator -reports:"./*Coverage.xml" -targetdir:./coverage-report -reporttypes:"Html;TextSummary"
2 changes: 2 additions & 0 deletions src/Tableau.Migration.App.Core/Entities/AppSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
// limitations under the License.
// </copyright>

namespace Tableau.Migration.App.Core.Entities;

/// <summary>
/// App settings to be loaded.
/// </summary>
Expand Down
36 changes: 34 additions & 2 deletions src/Tableau.Migration.App.Core/Entities/DetailedMigrationResult.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// <copyright file="DetailedMigrationResult.cs" company="Salesforce, Inc.">
// <copyright file="DetailedMigrationResult.cs" company="Salesforce, Inc.">
// Copyright (c) 2024, Salesforce, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2
//
Expand Down Expand Up @@ -26,4 +26,36 @@ namespace Tableau.Migration.App.Core.Entities;
/// </summary>
public record struct DetailedMigrationResult(
ITableauMigrationService.MigrationStatus status,
IReadOnlyList<Exception> errors);
IReadOnlyList<Exception> errors);

/// <summary>
/// Builder to build a <see cref="DetailedMigrationResult" />.
/// </summary>
public static class DetailedMigrationResultBuilder
{
/// <summary>
/// Build a Detailed Migration Result.
/// </summary>
/// <param name="status">The Tableau Migration SDK Status.</param>
/// <param name="errors">The errors from migration.</param>
/// <returns>The <see cref="DetailedMigrationResult" />.</returns>
public static DetailedMigrationResult Build(
MigrationCompletionStatus status, IReadOnlyList<Exception> errors)
{
ITableauMigrationService.MigrationStatus newStatus;
switch (status)
{
case MigrationCompletionStatus.Completed:
newStatus = ITableauMigrationService.MigrationStatus.SUCCESS;
break;
case MigrationCompletionStatus.Canceled:
newStatus = ITableauMigrationService.MigrationStatus.CANCELED;
break;
default: // ITableauMigrationService.MigrationStatus.FAILURE
newStatus = ITableauMigrationService.MigrationStatus.FAILURE;
break;
}

return new DetailedMigrationResult(newStatus, errors);
}
}
31 changes: 29 additions & 2 deletions src/Tableau.Migration.App.Core/Entities/MigrationActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,48 @@ namespace Tableau.Migration.App.Core.Entities;
/// </summary>
public class MigrationActions
{
private static List<string> actionsCache = new List<string>();

/// <summary>
/// Gets the list of actions available from the Tableau Migration SDK and the order in which they are migrated.
/// </summary>
public static List<string> Actions
{
get
{
var result = ServerToCloudMigrationPipeline
if (actionsCache.Count > 0)
{
return actionsCache;
}

actionsCache = ServerToCloudMigrationPipeline
.ContentTypes
.Select(
contentType => GetActionTypeName(contentType.ContentType)).ToList();
return result;
actionsCache.Insert(0, "Setup");

return actionsCache;
}
}

/// <summary>
/// Get the index of a migration action.
/// </summary>
/// <param name="action">The migration action name.</param>
/// <returns>The migration index for the provided action.</returns>
public static int GetActionIndex(string action)
{
for (int i = 0; i < Actions.Count; i++)
{
if (action == Actions[i])
{
return i;
}
}

return -1;
}

/// <summary>
/// Returns the action type names from the SDK.
/// </summary>
Expand Down
67 changes: 67 additions & 0 deletions src/Tableau.Migration.App.Core/Entities/MigrationTimerEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// <copyright file="MigrationTimerEvent.cs" company="Salesforce, Inc.">
// Copyright (c) 2024, Salesforce, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2
//
// Licensed under the Apache License, Version 2.0 (the "License")
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

namespace Tableau.Migration.App.Core.Entities;
using System;

/// <summary>
/// Possible value types for Migration Timer Events.
/// </summary>
public enum MigrationTimerEventType
{
/// <summary>
/// Event fired when Migration has started.
/// </summary>
MigrationStarted,

/// <summary>
/// Event fired when Migration has either completed or failed.
/// </summary>
Migrationfinished,

/// <summary>
/// Event fired when a Migration Action has completed.
/// </summary>
MigrationActionCompleted,
}

/// <summary>
/// Migration Time events to be triggered.
/// </summary>
public class MigrationTimerEvent : EventArgs
{
private DateTime migrationStartTime;
private Dictionary<string, DateTime> actionStartTimes;
private Dictionary<string, DateTime> actionStopTimes;

/// <summary>
/// Initializes a new instance of the <see cref="MigrationTimerEvent" /> class.
/// </summary>
/// <param name="eventType">The event type.</param>
public MigrationTimerEvent(MigrationTimerEventType eventType)
{
this.EventType = eventType;
this.migrationStartTime = DateTime.Now;
this.actionStartTimes = new Dictionary<string, DateTime>();
this.actionStopTimes = new Dictionary<string, DateTime>();
}

/// <summary>
/// Gets the Migration event type.
/// </summary>
public MigrationTimerEventType EventType { get; }
}
9 changes: 1 addition & 8 deletions src/Tableau.Migration.App.Core/Entities/ProgressEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,14 @@ public class ProgressEventArgs : EventArgs
/// <summary>
/// Initializes a new instance of the <see cref="ProgressEventArgs" /> class.
/// </summary>
/// <param name="action">The action.</param>
/// <param name="message">The message.</param>
public ProgressEventArgs(string action, string message)
public ProgressEventArgs(string message)
{
this.Message = message;
this.Action = action;
}

/// <summary>
/// Gets something.
/// </summary>
public string Message { get; }

/// <summary>
/// Gets something.
/// </summary>
public string Action { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class EmailDomainMapping :
ITableauCloudUsernameMapping
{
private readonly string domain;
private ILogger<EmailDomainMapping>? logger;

/// <summary>
/// Initializes a new instance of the <see cref="EmailDomainMapping"/> class.
Expand All @@ -44,10 +45,11 @@ public class EmailDomainMapping :
public EmailDomainMapping(
IOptions<EmailDomainMappingOptions> options,
ISharedResourcesLocalizer localizer,
ILogger<EmailDomainMapping> logger)
ILogger<EmailDomainMapping>? logger)
: base(localizer, logger)
{
this.domain = options.Value.EmailDomain;
this.logger = logger;
}

/// <summary>
Expand All @@ -71,6 +73,12 @@ public EmailDomainMapping(
return userMappingContext.MapTo(domain.Append(userMappingContext.ContentItem.Name)).ToTask();
}

if (string.IsNullOrEmpty(this.domain))
{
this.logger?.LogInformation("No domain mapping provided and no email found.");
return userMappingContext.ToTask();
}

// Takes the existing username and appends the domain to build the email
var email = $"{userMappingContext.ContentItem.Name}@{this.domain}";

Expand Down
Loading
Loading