Skip to content

Commit

Permalink
Merge pull request #25 from Lombiq/issue/OSOE-514
Browse files Browse the repository at this point in the history
OSOE-514: Deployment action with GitHub Actions and better configuration
  • Loading branch information
sarahelsaig authored Jan 5, 2023
2 parents e74a36b + 8746da2 commit fd9b798
Show file tree
Hide file tree
Showing 12 changed files with 468 additions and 105 deletions.
44 changes: 44 additions & 0 deletions .github/actions/deploy-media-theme/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Deploy Media Theme
description: Deploys an Orchard Core Media Theme to an Orchard site via Remote Deployment.

inputs:
theme-path:
required: false
default: "."
description: Path to the theme project.
base-theme-id:
required: false
description: ID of the base theme of the theme project, if any.
clear-media-folder:
required: false
default: "true"
description: When set to "true", will clear the Media folder of the Media Theme before deployment.

runs:
using: "composite"
steps:
- name: Install Lombiq.Hosting.MediaTheme.Deployer
shell: pwsh
run: |
dotnet tool install --global Lombiq.Hosting.MediaTheme.Deployer --version 2.0.2-alpha.0.osoe-514
- name: Deploy Media Theme
shell: pwsh
run: |
# Putting --base-id as last, so if it's empty, then the other parameters will still be parsed correctly.
$switches = @(
'--path', '${{ inputs.theme-path }}'
'--clear', '${{ inputs.clear-media-folder }}'
'--deployment-path', '${{ inputs.theme-path }}/Deployment'
'--remote-deployment-url', '${{ env.URL }}'
'--remote-deployment-client-name', '${{ env.CLIENT_NAME }}'
'--remote-deployment-client-api-key', '${{ env.CLIENT_API_KEY }}'
'--base-id', '${{ inputs.base-theme-id }}'
)
media-theme-deploy @switches
if ($LastExitCode -ne 0)
{
Write-Error "Deployment failed, see the errors above."
}
54 changes: 54 additions & 0 deletions .github/workflows/deploy-media-theme.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Deploy Media Theme

on:
workflow_call:
secrets:
CHECKOUT_TOKEN:
required: false
description: >
The GitHub token to authenticate checkout. Pass in a GitHub personal access token if authenticated submodules
are used.
URL:
required: true
description: The URL to use for Remote Deployment, as indicated on the Orchard Core admin.
CLIENT_NAME:
required: true
description: The "Client Name" part of the Remote Deployment client's credentials.
CLIENT_API_KEY:
required: true
description: The "Client API Key" part of the Remote Deployment client's credentials.
inputs:
theme-path:
required: false
type: string
default: "."
description: Path to the theme project.
base-theme-id:
required: false
type: string
description: ID of the base theme of the theme project, if any.
clear-media-folder:
required: false
type: string
default: "true"
description: When set to "true", will clear the Media folder of the Media Theme before deployment.

jobs:
deploy-media-theme:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: Lombiq/GitHub-Actions/.github/actions/checkout@dev
with:
token: ${{ secrets.CHECKOUT_TOKEN }}

- name: Deploy Media Theme
uses: Lombiq/Hosting-Media-Theme/.github/actions/deploy-media-theme@dev
env:
URL: ${{ secrets.URL }}
CLIENT_NAME: ${{ secrets.CLIENT_NAME }}
CLIENT_API_KEY: ${{ secrets.CLIENT_API_KEY }}
with:
theme-path: ${{ inputs.theme-path }}
base-theme-id: ${{ inputs.base-theme-id }}
clear-media-folder: ${{ inputs.clear-media-folder }}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Lombiq.Hosting.MediaTheme.Bridge.Constants;
using Lombiq.Hosting.MediaTheme.Bridge.Constants;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using OrchardCore.Media;
Expand Down Expand Up @@ -29,6 +29,8 @@ public async Task InvokeAsync(HttpContext context)
StringComparison.OrdinalIgnoreCase,
out _);

// Since this middleware needs to run early (see comment in Startup), the user's authentication state won't yet
// be available. So, we can't let people with the ManageMediaTheme permission still see the templates.
if (!isMediaThemeTemplateRequest)
{
await _next(context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ public class MediaThemeAssetUrlRedirectMiddleware
{
private readonly RequestDelegate _next;

public MediaThemeAssetUrlRedirectMiddleware(RequestDelegate next) =>
_next = next;
public MediaThemeAssetUrlRedirectMiddleware(RequestDelegate next) => _next = next;

public async Task InvokeAsync(
HttpContext context,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using Lombiq.Hosting.MediaTheme.Bridge.Constants;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.Extensions.Options;
using OrchardCore.FileStorage;
using OrchardCore.Media;
using OrchardCore.Mvc;
using System;

namespace Lombiq.Hosting.MediaTheme.Bridge.Services;

/// <summary>
/// Service to add a cache busting version key to the URL of static resources references from Media Theme, like it
/// happens for standard resources.
/// </summary>
/// <remarks>
/// <para>
/// The default <see cref="IFileVersionProvider"/>, <see cref="ShellFileVersionProvider"/>, works just fine, but we need
/// to translate /mediatheme URLs.
/// </para>
/// </remarks>
internal class FileVersionProviderDecorator : IFileVersionProvider
{
private readonly IFileVersionProvider _decorated;
private readonly IMediaFileStore _mediaFileStore;
private readonly IOptions<MediaOptions> _mediaOption;

public FileVersionProviderDecorator(
IFileVersionProvider decorated,
IMediaFileStore mediaFileStore,
IOptions<MediaOptions> mediaOptions)
{
_decorated = decorated;
_mediaFileStore = mediaFileStore;
_mediaOption = mediaOptions;
}

public string AddFileVersionToPath(PathString requestPathBase, string path)
{
var isMediaThemePath = path.StartsWithOrdinalIgnoreCase(Routes.MediaThemeAssets) ||
path.ContainsOrdinalIgnoreCase(Routes.MediaThemeAssets + "/");

if (isMediaThemePath)
{
var assetsSubPath = _mediaFileStore.Combine(
_mediaOption.Value.AssetsRequestPath, Paths.MediaThemeRootFolder, Paths.MediaThemeAssetsFolder);
path = path.Replace(Routes.MediaThemeAssets, assetsSubPath);
}

// Note that this will work all the time for local files. When a remote storage implementation is used to store
// Media files though (like Azure Blob Storage) then Media Cache will mirror the files locally. Since this only
// happens on the first request to the file, until then in the HTML output you'll see a URL without the cache
// busting parameter.
// This isn't an issue for real-life scenarios, just be mindful during development.
return _decorated.AddFileVersionToPath(requestPathBase, path);
}
}
6 changes: 5 additions & 1 deletion Lombiq.Hosting.MediaTheme.Bridge/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using Lombiq.Hosting.MediaTheme.Bridge.Deployment;
using Lombiq.HelpfulLibraries.OrchardCore.DependencyInjection;
using Lombiq.Hosting.MediaTheme.Bridge.Deployment;
using Lombiq.Hosting.MediaTheme.Bridge.Middlewares;
using Lombiq.Hosting.MediaTheme.Bridge.Navigation;
using Lombiq.Hosting.MediaTheme.Bridge.Permissions;
using Lombiq.Hosting.MediaTheme.Bridge.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using OrchardCore.Deployment;
Expand Down Expand Up @@ -38,6 +40,8 @@ public override void ConfigureServices(IServiceCollection services)
services.AddScoped<IDisplayDriver<DeploymentStep>, MediaThemeDeploymentStepDriver>();
services.AddScoped<IAuthorizationHandler, ManageMediaThemeFolderAuthorizationHandler>();
services.AddScoped<IMediaThemeCachingService, MediaThemeCachingService>();
services.AddOrchardServices();
services.Decorate<IFileVersionProvider, FileVersionProviderDecorator>();
}

public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider)
Expand Down
13 changes: 7 additions & 6 deletions Lombiq.Hosting.MediaTheme.Deployer/Constants/PathConstants.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
namespace Lombiq.Hosting.MediaTheme.Deployer.Constants;

public static class PathConstants
{
public const string MediaThemeRootDirectory = "_MediaTheme";
Expand All @@ -8,12 +9,12 @@ public static class PathConstants
public const string MediaThemeTemplatesDirectory = "Templates";
public const string MediaThemeAssetsDirectory = "Assets";

public const string MediaThemeAssetsWebPath = MediaThemeRootDirectory + "/" + MediaThemeAssetsDirectory;
public const string MediaThemeAssetsCopyDirectoryPath = "\\" + MediaThemeRootDirectory + "\\" + MediaThemeAssetsDirectory;
public const string RecipeFile = "Recipe.json";
public const string LiquidFileExtension = ".liquid";

public const string MediaThemeTemplatesWebPath = MediaThemeRootDirectory + "/" + MediaThemeTemplatesDirectory;
public const string MediaThemeTemplatesCopyDirectoryPath = "\\" + MediaThemeRootDirectory + "\\" + MediaThemeTemplatesDirectory;
public static readonly string MediaThemeAssetsCopyDirectoryPath =
Path.Combine(MediaThemeRootDirectory, MediaThemeAssetsDirectory);

public const string RecipeFile = "\\Recipe.json";
public const string LiquidFileExtension = ".liquid";
public static readonly string MediaThemeTemplatesCopyDirectoryPath =
Path.Combine(MediaThemeRootDirectory, MediaThemeTemplatesDirectory);
}
7 changes: 7 additions & 0 deletions Lombiq.Hosting.MediaTheme.Deployer/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using System.Diagnostics.CodeAnalysis;

[assembly: SuppressMessage(
"Globalization",
"CA1303:Do not pass literals as localized parameters",
Justification = "It's a developer console application, it doesn't need localization.",
Scope = "module")]
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.7.82" />
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>

<ItemGroup>
<None Include="..\.github\actions\deploy-media-theme\action.yml" Link=".github\action.yml" />
<None Include="..\.github\workflows\deploy-media-theme.yml" Link=".github\deploy-media-theme.yml" />
<None Include="License.md" Pack="true" PackagePath="" />
<None Include="NuGetIcon.png" Pack="true" PackagePath="" />
</ItemGroup>
Expand Down
Loading

0 comments on commit fd9b798

Please sign in to comment.