Skip to content

Commit

Permalink
Added code to sanitize Partition- and Rowkeys. Refactored to use buil…
Browse files Browse the repository at this point in the history
…ders for LatestReleases/Publications.
  • Loading branch information
marcduiker committed Mar 24, 2019
1 parent 7ade736 commit 0c36335
Show file tree
Hide file tree
Showing 13 changed files with 193 additions and 57 deletions.
52 changes: 41 additions & 11 deletions src/AzureFunctionsUpdates.UnitTests/Models/LatestReleasesTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using AzureFunctionsUpdates.Models;
using AzureFunctionsUpdates.UnitTests.TestObjectBuilders;
using AzureFunctionsUpdates.UnitTests.TestObjectBuilders;
using FluentAssertions;
using System;
using AzureFunctionsUpdates.Builders;
using AzureFunctionsUpdates.Models.RepositoryReleases;
using Xunit;

Expand All @@ -17,9 +17,14 @@ public void GivenHistoryReleaseIsNullRelease_WhenIsNewAndShouldBeStoredIsCalled_
var repoConfig = RepositoryConfigurationBuilder.BuildOne(repoName);
var releasesFromGitHub = RepositoryReleaseBuilder.BuildListContainingOneWithReleaseId(repoName, 1);
var releasesFromHistory = RepositoryReleaseBuilder.BuildListContainingOneNullRelease(repoName);

var releaseMatchFunction = ReleaseFunctionBuilder.BuildForMatchingRepositoryName();

// Act
var latestReleases = new LatestReleases(repoConfig, releasesFromGitHub, releasesFromHistory);
var latestReleases = LatestObjectsBuilder.Build<RepositoryConfiguration, RepositoryRelease, LatestReleases>(
repoConfig,
releasesFromGitHub,
releasesFromHistory,
releaseMatchFunction);

// Assert
latestReleases.IsNewAndShouldBeStored.Should().BeTrue("because no release was found in history data.");
Expand All @@ -34,9 +39,14 @@ public void GivenHistoryReleaseIsReleaseWithMatchingReleaseId_WhenIsNewAndShould
var repoConfig = RepositoryConfigurationBuilder.BuildOne(repoName);
var releasesFromGitHub = RepositoryReleaseBuilder.BuildListContainingOneWithReleaseId(repoName, releaseId);
var releasesFromHistory = RepositoryReleaseBuilder.BuildListContainingOneWithReleaseId(repoName, releaseId);

var releaseMatchFunction = ReleaseFunctionBuilder.BuildForMatchingRepositoryName();

// Act
var latestReleases = new LatestReleases(repoConfig, releasesFromGitHub, releasesFromHistory);
var latestReleases = LatestObjectsBuilder.Build<RepositoryConfiguration, RepositoryRelease, LatestReleases>(
repoConfig,
releasesFromGitHub,
releasesFromHistory,
releaseMatchFunction);

// Assert
latestReleases.IsNewAndShouldBeStored.Should().BeFalse("because the releaseIds are equal");
Expand All @@ -50,9 +60,14 @@ public void GivenHistoryReleaseIsNullReleaseAndGitHubReleaseIsNullRelease_WhenIs
var repoConfig = RepositoryConfigurationBuilder.BuildOne(repoName);
var releasesFromGitHub = RepositoryReleaseBuilder.BuildListContainingOneNullRelease(repoName);
var releasesFromHistory = RepositoryReleaseBuilder.BuildListContainingOneNullRelease(repoName);

var releaseMatchFunction = ReleaseFunctionBuilder.BuildForMatchingRepositoryName();

// Act
var latestReleases = new LatestReleases(repoConfig, releasesFromGitHub, releasesFromHistory);
var latestReleases = LatestObjectsBuilder.Build<RepositoryConfiguration, RepositoryRelease, LatestReleases>(
repoConfig,
releasesFromGitHub,
releasesFromHistory,
releaseMatchFunction);

// Assert
latestReleases.IsNewAndShouldBeStored.Should().BeFalse("because there is no result from GitHub");
Expand All @@ -68,9 +83,14 @@ public void GivenHistoryReleaseIsReleaseWithNonMatchingReleaseId_WhenIsNewAndSho
var repoConfig = RepositoryConfigurationBuilder.BuildOne(repoName);
var releasesFromGitHub = RepositoryReleaseBuilder.BuildListContainingOneWithReleaseId(repoName, releaseIdGithub);
var releasesFromHistory = RepositoryReleaseBuilder.BuildListContainingOneWithReleaseId(repoName, releaseIdHistory);
var releaseMatchFunction = ReleaseFunctionBuilder.BuildForMatchingRepositoryName();

// Act
var latestReleases = new LatestReleases(repoConfig, releasesFromGitHub, releasesFromHistory);
var latestReleases = LatestObjectsBuilder.Build<RepositoryConfiguration, RepositoryRelease, LatestReleases>(
repoConfig,
releasesFromGitHub,
releasesFromHistory,
releaseMatchFunction);

// Assert
latestReleases.IsNewAndShouldBeStored.Should().BeTrue("because the releaseIds are not equal");
Expand All @@ -87,9 +107,14 @@ public void GivenHistoryReleaseIsNullReleaseAndGitHubReleaseIsWithinTimeWindow_W
var repoConfig = RepositoryConfigurationBuilder.BuildOne(repoName);
var releasesFromGitHub = RepositoryReleaseBuilder.BuildListContainingOneWithReleaseIdAndDate(repoName, releaseIdGithub, gitHubReleaseDate);
var releasesFromHistory = RepositoryReleaseBuilder.BuildListContainingOneNullRelease(repoName);
var releaseMatchFunction = ReleaseFunctionBuilder.BuildForMatchingRepositoryName();

// Act
var latestReleases = new LatestReleases(repoConfig, releasesFromGitHub, releasesFromHistory);
var latestReleases = LatestObjectsBuilder.Build<RepositoryConfiguration, RepositoryRelease, LatestReleases>(
repoConfig,
releasesFromGitHub,
releasesFromHistory,
releaseMatchFunction);

// Assert
latestReleases.IsNewAndShouldBeStored.Should().BeTrue("because the release is not in history yet.");
Expand All @@ -107,9 +132,14 @@ public void GivenHistoryReleaseIsNullReleaseAndGitHubReleaseIsOutsideTimeWindow_
var repoConfig = RepositoryConfigurationBuilder.BuildOne(repoName);
var releasesFromGitHub = RepositoryReleaseBuilder.BuildListContainingOneWithReleaseIdAndDate(repoName, releaseIdGithub, gitHubReleaseDate);
var releasesFromHistory = RepositoryReleaseBuilder.BuildListContainingOneNullRelease(repoName);
var releaseMatchFunction = ReleaseFunctionBuilder.BuildForMatchingRepositoryName();

// Act
var latestReleases = new LatestReleases(repoConfig, releasesFromGitHub, releasesFromHistory);
var latestReleases = LatestObjectsBuilder.Build<RepositoryConfiguration, RepositoryRelease, LatestReleases>(
repoConfig,
releasesFromGitHub,
releasesFromHistory,
releaseMatchFunction);

// Assert
latestReleases.IsNewAndShouldBeStored.Should().BeTrue("because the release is not in history yet.");
Expand Down
25 changes: 25 additions & 0 deletions src/AzureFunctionsUpdates.UnitTests/Storage/KeyFormatterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using AzureFunctionsUpdates.Storage;
using FluentAssertions;
using Xunit;

namespace AzureFunctionsUpdates.UnitTests.Storage
{
public class KeyFormatterTests
{
[Theory]
[InlineData("abcd123", "abcd123")]
[InlineData("abcd-123", "abcd-123")]
[InlineData("abcd?123", "abcd-123")]
[InlineData("abcd#123#", "abcd-123-")]
[InlineData("abcd/123", "abcd-123")]
[InlineData("abcd\\1?2#3", "abcd-1-2-3")]
public void SanitizeKeyTests(string oldKey, string newKey)
{
// Act
var result = KeyFormatter.SanitizeKey(oldKey);

// Assert
result.Should().Be(newKey);
}
}
}
7 changes: 3 additions & 4 deletions src/AzureFunctionsUpdates/Activities/PostUpdate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ public void Run(

var creds = new TwitterCredentials(consumerApiKey, consumerApiSecret, accessToken, accessTokenSecret);

var tweet = Auth.ExecuteOperationWithCredentials(creds, () =>
{
return Tweet.PublishTweet(message.Content);
});
var tweet = Auth.ExecuteOperationWithCredentials(creds, () => Tweet.PublishTweet(message.Content));

logger.LogInformation($"Finished {nameof(PostUpdate)} with tweet: {tweet.Url}.");
}
}
}
22 changes: 22 additions & 0 deletions src/AzureFunctionsUpdates/Builders/LatestObjectsBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AzureFunctionsUpdates.Models.RepositoryReleases;

namespace AzureFunctionsUpdates.Builders
{
public static class LatestObjectsBuilder
{
public static TLatest Build<TConfiguration, TMonitored, TLatest>(
TConfiguration configuration,
IEnumerable<TMonitored> newObjects,
IEnumerable<TMonitored> historicalObjects,
Func<TConfiguration, TMonitored, bool> matchObject) where TLatest : new()
{
var latestNew = newObjects.First(obj => matchObject(configuration, obj));
var latestHistorical = historicalObjects.First(obj => matchObject(configuration, obj));

return (TLatest)Activator.CreateInstance(typeof(TLatest), latestNew, latestHistorical);
}
}
}
14 changes: 14 additions & 0 deletions src/AzureFunctionsUpdates/Builders/PublicationFunctionBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using AzureFunctionsUpdates.Models.Publications;
using AzureFunctionsUpdates.Models.RepositoryReleases;

namespace AzureFunctionsUpdates.Builders
{
public static class PublicationFunctionBuilder
{
public static Func<PublicationConfiguration, Publication, bool> BuildForMatchingPublicationSource()
{
return (config, publication) => publication.PublicationSourceName.Equals(config.PublicationSourceName, StringComparison.InvariantCultureIgnoreCase);
}
}
}
13 changes: 13 additions & 0 deletions src/AzureFunctionsUpdates/Builders/ReleaseFunctionBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using AzureFunctionsUpdates.Models.RepositoryReleases;

namespace AzureFunctionsUpdates.Builders
{
public static class ReleaseFunctionBuilder
{
public static Func<RepositoryConfiguration, RepositoryRelease, bool> BuildForMatchingRepositoryName()
{
return (config, release) => release.RepositoryName.Equals(config.RepositoryName, StringComparison.InvariantCultureIgnoreCase);
}
}
}
26 changes: 11 additions & 15 deletions src/AzureFunctionsUpdates/Models/Publications/LatestPublications.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,21 @@ namespace AzureFunctionsUpdates.Models.Publications
{
public class LatestPublications
{
private readonly IReadOnlyList<Publication> _latestPublicationsFromWeb;
private readonly IReadOnlyList<Publication> _latestPublicationsFromHistory;
private readonly PublicationConfiguration _publicationConfiguration;

public LatestPublications()
{}

public LatestPublications(
PublicationConfiguration publicationConfiguration,
IReadOnlyList<Publication> latestReleasesFromGitHub,
IReadOnlyList<Publication> latestReleasesFromHistory)

Publication fromWeb,
Publication fromHistory)
{
this._publicationConfiguration = publicationConfiguration;
_latestPublicationsFromWeb = latestReleasesFromGitHub;
_latestPublicationsFromHistory = latestReleasesFromHistory;
}


FromWeb = fromWeb;
FromHistory = fromHistory;
}

public Publication FromWeb => _latestPublicationsFromWeb.First(publication => publication.PublicationSourceName.Equals(_publicationConfiguration.PublicationSourceName, StringComparison.InvariantCultureIgnoreCase));
public Publication FromWeb { get; }

public Publication FromHistory => _latestPublicationsFromHistory.First(publication => publication.PublicationSourceName.Equals(_publicationConfiguration.PublicationSourceName, StringComparison.InvariantCultureIgnoreCase));
public Publication FromHistory { get; }

public bool IsNewAndShouldBeStored
{
Expand Down
5 changes: 3 additions & 2 deletions src/AzureFunctionsUpdates/Models/Publications/Publication.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.WindowsAzure.Storage.Table;
using System;
using AzureFunctionsUpdates.Storage;

namespace AzureFunctionsUpdates.Models.Publications
{
Expand All @@ -17,9 +18,9 @@ public Publication(
string url,
string hashTags)
{
PartitionKey = publicationSourceName;
PartitionKey = KeyFormatter.SanitizeKey(publicationSourceName);
PublicationSourceName = publicationSourceName;
RowKey = $"{id}-{publicationDate}";
RowKey = KeyFormatter.SanitizeKey($"{id}-{publicationDate.ToUnixTimeSeconds()}");
Id = id;
PublicationDate = publicationDate;
Title = title;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,20 @@ namespace AzureFunctionsUpdates.Models.RepositoryReleases
{
public class LatestReleases
{
private readonly IReadOnlyList<RepositoryRelease> _latestReleasesFromGitHub;
private readonly IReadOnlyList<RepositoryRelease> _latestReleasesFromHistory;
private readonly RepositoryConfiguration _repository;
public LatestReleases()
{}

public LatestReleases(
RepositoryConfiguration repository,
IReadOnlyList<RepositoryRelease> latestReleasesFromGitHub,
IReadOnlyList<RepositoryRelease> latestReleasesFromHistory)
RepositoryRelease latestReleaseFromGitHub,
RepositoryRelease latestReleaseFromHistory)
{
_repository = repository;
_latestReleasesFromGitHub = latestReleasesFromGitHub;
_latestReleasesFromHistory = latestReleasesFromHistory;
FromGitHub = latestReleaseFromGitHub;
FromHistory = latestReleaseFromHistory;
}

public RepositoryRelease FromGitHub => _latestReleasesFromGitHub.First(release => release.RepositoryName.Equals(_repository.RepositoryName, StringComparison.InvariantCultureIgnoreCase));
public RepositoryRelease FromGitHub { get; }

public RepositoryRelease FromHistory => _latestReleasesFromHistory.First(release => release.RepositoryName.Equals(_repository.RepositoryName, StringComparison.InvariantCultureIgnoreCase));
public RepositoryRelease FromHistory { get; }

public bool IsNewAndShouldBeStored
{
Expand Down Expand Up @@ -53,8 +50,6 @@ bool IsWithinTimeWindow()
return DateTimeOffset.UtcNow.Subtract(FromGitHub.ReleaseCreatedAt).Days < MaximumNumberOfDaysToPostAboutNewlyFoundRelease;
}
}


}

public const int MaximumNumberOfDaysToPostAboutNewlyFoundRelease = 2;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using AzureFunctionsUpdates.Storage;
using Microsoft.WindowsAzure.Storage.Table;

namespace AzureFunctionsUpdates.Models.RepositoryReleases
Expand All @@ -19,8 +20,8 @@ public RepositoryRelease(
string hashTags
)
{
PartitionKey = repositoryName;
RowKey = $"{releaseId.ToString()}-{tagName}";
PartitionKey = KeyFormatter.SanitizeKey(repositoryName);
RowKey = KeyFormatter.SanitizeKey($"{releaseId.ToString()}-{tagName}");

ReleaseId = releaseId;
RepositoryName = repositoryName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,23 @@ public async Task Run(

var latestFromWeb = await Task.WhenAll(getLatestPublicationsFromWebTasks);
var latestFromHistory = await Task.WhenAll(getLatestPublicationsFromHistoryTasks);
var publicationMatchFunction = PublicationFunctionBuilder.BuildForMatchingPublicationSource();

foreach (var publicationConfiguration in publicationConfigurations)
{
var latestPublications = new LatestPublications(publicationConfiguration, latestFromWeb, latestFromHistory);
var latestPublications = LatestObjectsBuilder.Build<PublicationConfiguration, Publication, LatestPublications>(
publicationConfiguration,
latestFromWeb,
latestFromHistory,
publicationMatchFunction);

logger.LogInformation($"Publication: {publicationConfiguration.PublicationSourceName} " +
$"ID: {latestPublications.FromWeb.Id}," +
$"IsNewAndShouldBeStored: {latestPublications.IsNewAndShouldBeStored}, " +
$"IsNewAndShouldBePosted: {latestPublications.IsNewAndShouldBePosted}.");

if (latestPublications.IsNewAndShouldBeStored)
{
{
var isSaveSuccessful = await context.CallActivityWithRetryAsync<bool>(
nameof(SaveLatestPublication),
GetDefaultRetryOptions(),
Expand Down
Loading

0 comments on commit 0c36335

Please sign in to comment.