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

feat: GDrive File Scope implementation with file picker #86

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
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
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
# All files
[*]
indent_style = space

[*.csproj]
indent_size = 2
# Code files
[*.{cs,csx,vb,vbx}]
indent_size = 4
Expand Down
75 changes: 75 additions & 0 deletions .github/workflows/create_pre-release-on-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Create pre-release on PR

on: pull_request


jobs:
create-prerelease:
runs-on: windows-latest
permissions:
pull-requests: write

steps:
- uses: actions/checkout@v3

- uses: microsoft/setup-msbuild@v2

- name: publish
run: |
msbuild -t:restore,build -m -p:"Configuration=Release;Platform=Any Cpu" GoogleDriveSync.sln

# The publish needs to be run separately, since the PLGX build task seems to not run on first build
msbuild -t:publish -m -p:"Configuration=Release;Platform=Any Cpu" .\src\KPSyncForDrive.csproj `
-p:'CompileTimeConfig_ClientId=${{vars.GCPCLIENTID}}' -p:'CompileTimeConfig_GoogleDrivePickerAppId=${{vars.GDRIVEAPPID}}' `
-p:'CompileTimeConfig_DriveFilePickerPublicApiKey=${{vars.GDRIVEFILEPICKERAPIKEY}}' `
-p:'CompileTimeConfig_PublicClientSecret=${{vars.PublicClientSecret }}'


- name: zip results
env:
PR_NUMBER: ${{ github.event.number }}
shell: pwsh
run: |
$randString = -join ((48..57) + (97..122) | Get-Random -Count 10 | % {[char]$_})
mkdir ./dist
move-item "./src/bin/Any Cpu/Release/net48/*.plgx" -Destination ./dist/pr-$ENV:PR_NUMBER.$randString.plgx
Compress-Archive -Path "./src/bin/Any Cpu/Release/net48/publish/*" -DestinationPath ./dist/pr-$ENV:PR_NUMBER.$randString.zip -CompressionLevel Optimal -Force
[System.IO.FileSystemInfo[]]$files = Get-ChildItem ./dist/
Write-Host "$($files.Count) files found in dist directory:"
$files

- name: Upload plgx Artifact
uses: actions/upload-artifact@v4
id: plgx-upload
with:
name: plgx-artifact
retention-days: 15
path: ./dist/*.plgx
if-no-files-found: error

- name: Upload zipped Artifacts
uses: actions/upload-artifact@v4
id: zip-upload
with:
name: zip-artifact
retention-days: 15
path: ./dist/*.zip
if-no-files-found: error

- uses: actions/github-script@v6
env:
PR_NUMBER: ${{ github.event.number }}
PR_NOTES: |
Build artifacts (expire in 15 days):
| Name | Link |
|------|------|
| PLGX | ${{ steps.plgx-upload.outputs.artifact-url }} |
| zip | ${{ steps.zip-upload.outputs.artifact-url }} |
with:
script: |
github.rest.issues.createComment({
issue_number: process.env.PR_NUMBER,
owner: context.repo.owner,
repo: context.repo.repo,
body: process.env.PR_NOTES
})
89 changes: 89 additions & 0 deletions .github/workflows/publish-on-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
name: Publish artifacts on release

on:
release:
types:
- published

jobs:
build-and-publish:
runs-on: windows-latest
permissions:
id-token: write
contents: write
attestations: write

steps:
- uses: actions/checkout@v3

- uses: microsoft/setup-msbuild@v2

- name: publish
env:
VersionNumber: ${{github.event.release.name}}
run: |
msbuild -t:restore,build -m -p:"Configuration=Release;Platform=Any Cpu" GoogleDriveSync.sln

# The publish needs to be run separately, since the PLGX build task seems to not run on first build
msbuild -t:publish -m -p:"Configuration=Release;Platform=Any Cpu" .\src\KPSyncForDrive.csproj `
-p:'CompileTimeConfig_ClientId=${{vars.GCPCLIENTID}}' `
-p:'CompileTimeConfig_GoogleDrivePickerAppId=${{vars.GDRIVEAPPID}}' `
-p:'CompileTimeConfig_DriveFilePickerPublicApiKey=${{vars.GDRIVEFILEPICKERAPIKEY}}' `
-p:'CompileTimeConfig_PublicClientSecret=${{vars.PublicClientSecret }}' `
-p:Version=$Env:VersionNumber `
-p:'CompileTimeConfig_UpdateUrlPubKey=${{vars.UpdateUrlPubKey}}' `
-p:'CompileTimeConfig_UpdateUrl=https://github.com/${{github.repository}}/releases/latest/download/kpsync_final.txt'

- name: Create dist directory
run: mkdir ./dist

- name: Generate AutoUpdate file
run: |
"${{secrets.SIGNING_PRIVATEKEY_XML}}" | Set-Content .\lib\src\GenVerInfo\privateKey.xml -Force
msbuild -t:publish -p:Configuration=Release .\lib\src\GenVerInfo\GenVerInfo.csproj
& ".\lib\src\GenVerInfo\bin\Release\net48\GenVerInfo.exe" "./src/bin/Any Cpu/Release/net48/publish/KPSyncForDrive.dll" ./dist/kpsync_final.txt

- name: zip results
shell: pwsh
env:
VersionNumber: ${{github.event.release.name}}
run: |
move-item "./src/bin/Any Cpu/Release/net48/*.plgx" -Destination ./dist/KPSyncForDrive-$Env:VersionNumber.plgx
Compress-Archive -Path "./src/bin/Any Cpu/Release/net48/publish/*" -DestinationPath ./dist/KPSyncForDrive-$Env:VersionNumber.zip -CompressionLevel Optimal -Force
[System.IO.FileSystemInfo[]]$files = Get-ChildItem ./dist/
Write-Host "$($files.Count) files found in dist directory:"
$files

- name: Generate artifact attestation
uses: actions/attest-build-provenance@v1
with:
subject-path: './dist/*'

- uses: actions/github-script@v6
env:
ReleaseName: ${{github.event.release.name}}
with:
script: |
const { ReleaseName } = process.env
const fs = require('fs').promises;
await github.rest.repos.uploadReleaseAsset({
name: `KPSyncForDrive-${ReleaseName}.plgx`,
owner: context.repo.owner,
repo: context.repo.repo,
release_id: ${{ github.event.release.id }},
data: await fs.readFile(`./dist/KPSyncForDrive-${ReleaseName}.plgx`)
});
await github.rest.repos.uploadReleaseAsset({
name: `KPSyncForDrive-${ReleaseName}.zip`,
owner: context.repo.owner,
repo: context.repo.repo,
release_id: ${{ github.event.release.id }},
data: await fs.readFile(`./dist/KPSyncForDrive-${ReleaseName}.zip`)
});
await github.rest.repos.uploadReleaseAsset({
name: 'kpsync_final.txt',
owner: context.repo.owner,
repo: context.repo.repo,
release_id: ${{ github.event.release.id }},
data: await fs.readFile('./dist/kpsync_final.txt')
});
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,4 @@ kp/

# Local VS settings
/src/Properties/launchSettings.json
/.idea
2 changes: 1 addition & 1 deletion BuildMe.bat
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ set archname=KPSyncForDrive
set kp_version_manifest_name=kpsync_final
set versionPrefix=4.1.0
set versionSuffix=unstable
set netsdkver=net45
set netsdkver=net48

set sevenzip="%ProgramFiles%\7-Zip\7z.exe"
:: set dotnetPgm="%ProgramFiles%\dotnet\dotnet.exe"
Expand Down
35 changes: 22 additions & 13 deletions GoogleDriveSync.sln
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
VisualStudioVersion = 16.0.29920.165
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KPSyncForDrive", "src\KPSyncForDrive.csproj", "{4C1BB6F8-D2CD-49C2-9053-21705681356C}"
ProjectSection(ProjectDependencies) = postProject
{F7B92FBF-F5D8-45E0-B357-4CA8F05AD652} = {F7B92FBF-F5D8-45E0-B357-4CA8F05AD652}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GenClientId", "lib\src\GenClientId\GenClientId.csproj", "{F7B92FBF-F5D8-45E0-B357-4CA8F05AD652}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GenVerInfo", "lib\src\GenVerInfo\GenVerInfo.csproj", "{552F1DC6-E4B4-4766-B0B3-7A37276AB86B}"
EndProject
Expand All @@ -24,20 +19,18 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsControls", "lib\src\WindowsControls\WindowsControls.csproj", "{31D48296-6B88-4532-B0C3-6DDBF183499F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FilePicker", "lib\src\FilePicker\FilePicker.csproj", "{89B54C4A-00DF-49FD-BD57-4DA01AAF9710}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CompileTimeConfigGenerator", "lib\src\CompileTimeConfigGenerator\CompileTimeConfigGenerator.csproj", "{C9EABBC7-D089-46E8-996B-F34F3C6C8CBD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CompileTimeConfigPublicMembers", "lib\src\CompileTimeConfigPublicMembers\CompileTimeConfigPublicMembers.csproj", "{1960BE1C-5EB4-4679-9510-976F1A085CA3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4C1BB6F8-D2CD-49C2-9053-21705681356C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4C1BB6F8-D2CD-49C2-9053-21705681356C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4C1BB6F8-D2CD-49C2-9053-21705681356C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4C1BB6F8-D2CD-49C2-9053-21705681356C}.Release|Any CPU.Build.0 = Release|Any CPU
{F7B92FBF-F5D8-45E0-B357-4CA8F05AD652}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F7B92FBF-F5D8-45E0-B357-4CA8F05AD652}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F7B92FBF-F5D8-45E0-B357-4CA8F05AD652}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F7B92FBF-F5D8-45E0-B357-4CA8F05AD652}.Release|Any CPU.Build.0 = Release|Any CPU
{552F1DC6-E4B4-4766-B0B3-7A37276AB86B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{552F1DC6-E4B4-4766-B0B3-7A37276AB86B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{552F1DC6-E4B4-4766-B0B3-7A37276AB86B}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand All @@ -46,6 +39,22 @@ Global
{31D48296-6B88-4532-B0C3-6DDBF183499F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{31D48296-6B88-4532-B0C3-6DDBF183499F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{31D48296-6B88-4532-B0C3-6DDBF183499F}.Release|Any CPU.Build.0 = Release|Any CPU
{89B54C4A-00DF-49FD-BD57-4DA01AAF9710}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{89B54C4A-00DF-49FD-BD57-4DA01AAF9710}.Debug|Any CPU.Build.0 = Debug|Any CPU
{89B54C4A-00DF-49FD-BD57-4DA01AAF9710}.Release|Any CPU.ActiveCfg = Release|Any CPU
{89B54C4A-00DF-49FD-BD57-4DA01AAF9710}.Release|Any CPU.Build.0 = Release|Any CPU
{C9EABBC7-D089-46E8-996B-F34F3C6C8CBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C9EABBC7-D089-46E8-996B-F34F3C6C8CBD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C9EABBC7-D089-46E8-996B-F34F3C6C8CBD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C9EABBC7-D089-46E8-996B-F34F3C6C8CBD}.Release|Any CPU.Build.0 = Release|Any CPU
{1960BE1C-5EB4-4679-9510-976F1A085CA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1960BE1C-5EB4-4679-9510-976F1A085CA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1960BE1C-5EB4-4679-9510-976F1A085CA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1960BE1C-5EB4-4679-9510-976F1A085CA3}.Release|Any CPU.Build.0 = Release|Any CPU
{4C1BB6F8-D2CD-49C2-9053-21705681356C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4C1BB6F8-D2CD-49C2-9053-21705681356C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4C1BB6F8-D2CD-49C2-9053-21705681356C}.Release|Any CPU.ActiveCfg = Debug|Any CPU
{4C1BB6F8-D2CD-49C2-9053-21705681356C}.Release|Any CPU.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>12</LangVersion>
<Nullable>enable</Nullable>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<IncludeBuildOutput>false</IncludeBuildOutput>
<IsRoslynComponent>true</IsRoslynComponent>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" PrivateAssets="all" />
</ItemGroup>

<ItemGroup>
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true"
PackagePath="analyzers/dotnet/cs" Visible="false" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CompileTimeConfigPublicMembers\CompileTimeConfigPublicMembers.csproj" />
</ItemGroup>
</Project>
118 changes: 118 additions & 0 deletions lib/src/CompileTimeConfigGenerator/ConfigSourceGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;

namespace CompileTimeConfigGenerator;

public record MetadataOnAccessorConfigRecordsToGenerate
{
public string RecordFullClassName { get; set; } = "";
public List<string> Properties { get; set; } = [];
}

public record MetadataOnAccessorToGenerate
{
public List<MetadataOnAccessorConfigRecordsToGenerate> Records { get; set; } = [];
public string AccessorClassName { get; set; } = "";
public string AccessorNamespace { get; set; } = "";
}

[Generator]
public class ConfigSourceGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var metadataOnAccessorsToGenerate = context.SyntaxProvider
.ForAttributeWithMetadataName(
"CompileTimeConfigPublicMembers.GenerateConfigAccessorAttribute",
predicate: static (_, _) => true,
transform: (ctx, _) =>
{
if (ctx.SemanticModel.GetDeclaredSymbol(ctx.TargetNode) is not INamedTypeSymbol generatorSymbol)
return null;

var records = ctx.Attributes
.Select(attributeData => attributeData.ConstructorArguments[0].Value)
.OfType<ITypeSymbol>()
.Select(recordSymbol =>
{
var properties = recordSymbol.GetMembers()
.OfType<IPropertySymbol>()
.Where(x => x.SetMethod?.DeclaredAccessibility == Accessibility.Public &&
x.Type.Name == nameof(String));

return new MetadataOnAccessorConfigRecordsToGenerate
{
RecordFullClassName =
recordSymbol.ToDisplayString(
new SymbolDisplayFormat(SymbolDisplayGlobalNamespaceStyle.Included)),
Properties = properties.Select(x => x.Name).ToList()
};
}).ToList();


return new MetadataOnAccessorToGenerate
{
Records = records,
AccessorNamespace = generatorSymbol.ContainingNamespace.Name,
AccessorClassName = generatorSymbol.Name,
};
}).Collect();

var combine = metadataOnAccessorsToGenerate.Combine(context.AnalyzerConfigOptionsProvider);

context.RegisterSourceOutput(combine,
static (spc, tuple) =>
{
foreach (var metadata in tuple.Left)
{
if (metadata == null) continue;

var interfacesToImplement = metadata.Records.Select(CreateInterfaceString);
var accessorMethods = metadata.Records.Select(x => GenerateRecordAccessMethod(x, tuple.Right));

string generatorString =
$$"""
using CompileTimeConfigPublicMembers;

namespace {{metadata.AccessorNamespace}} {
public partial class {{metadata.AccessorClassName}}: {{string.Join(", ", interfacesToImplement)}} {
{{string.Join("\n", accessorMethods)}}
}
}
""";

spc.AddSource(
$"CompileTimeConfigAccessors.{metadata.AccessorClassName}.g.cs",
generatorString);
}
});
}

private static string? GetBuildParam(string paramName, AnalyzerConfigOptionsProvider context)
{
context.GlobalOptions.TryGetValue($"build_property.CompileTimeConfig_{paramName}", out string? value);
return value;
}

private static string CreateInterfaceString(MetadataOnAccessorConfigRecordsToGenerate record)
{
return $"ICompileTimeConfigAccessor<{record.RecordFullClassName}>";
}

private static string GenerateRecordAccessMethod(MetadataOnAccessorConfigRecordsToGenerate record,
AnalyzerConfigOptionsProvider configOptionsProvider)
{
return $$"""
{{record.RecordFullClassName}} {{CreateInterfaceString(record)}}.GetConfig() {
return new {{record.RecordFullClassName}} {
{{
string.Join("\n\t\t\t\t", record.Properties.Select(y => $"""{y} = "{GetBuildParam(y, configOptionsProvider)}","""))
}}
};
}
""";
}
}
Loading