Git Product home page Git Product logo

github-actions-for-desktop-apps's Introduction

DevOps for Windows Desktop Apps Using GitHub Actions

Create CI/CD workflows for WPF and Windows Forms Applications built on .NET Core 3.x

This repo contains a sample application to demonstrate how to create CI/CD pipelines using GitHub Actions.

With GitHub Actions, you can quickly and easily automate your software workflows with CI/CD.

  • Integrate code changes directly into GitHub to speed up development cycles
  • Trigger builds to quickly identify breaking changes and create testable debug builds
  • Continuously run tests to identify and eliminate bugs, improving code quality
  • Automatically build, sign, package and deploy branches that pass CI

Build, test, and deploy your code entirely within GitHub.

Workflow Status
WPF - CI ci
WPF - CD cd
WPF - CI (.NET 6 experimental) NET 6.0 CI (temporary)

Workflows

To take advantage of GitHub Actions, workflows are defined in YAML files that are in the .github/workflows folder. In the project, there are two workflows defined:

  • .github/workflows/ci.yml
  • .github/workflows/cd.yml

The ci.yml file defines the continuous integration workflow which is used to build, test, and create a package every time a developer pushes code to the repo.

The benefits of kicking off a CI run on every push are multi-fold:

  • Quickly identify breaking changes
  • Create a testable debug build
  • Continuously run tests to identify and eliminate bugs, improving code quality
  • Keep workflow relatively lightweight by only testing configurations necessary to ensure good quality

The cd.yml file defines our continuous delivery workflow used to build, sign, package and archive release assets for every configuration that is planned for release.

ci.yml: Build, test, package, and save package artifacts.

The CI workflow defines the Package.Identity.Name in the Windows Application Packaging project’s Package.appxmanifest to identify the application as "MyWPFApp.DevOpsDemo.Local." By suffixing the application name with ".Local," developers are able to install it side by side with other channels of the app.

  <Identity
    Name="MyWPFApp.DevOpsDemo.Local"
    Publisher="CN=GitHubActionsDemo"
    Version="0.0.1.0" />

On every push to the repo, take advantage of the setup-dotnet GitHub Action and install the dotnet core cli environment. Then add MSBuild to the PATH and execute unit tests using the dotnet test runner console application.

    - name: Install .NET Core
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: 3.1.100

    # Add  MsBuild to the PATH: https://github.com/microsoft/setup-msbuild
    - name: Setup MSBuild.exe
      uses: microsoft/[email protected]
      
    # Test
    - name: Execute Unit Tests
      run: dotnet test $env:Test_Project_Path

As mentioned above, you can target multiple platforms by authoring the workflow file to define a build matrix, a set of different configurations that are each run in a fresh instance of a virtual environment by the GitHub-hosted runner.

In the continuous integration workflow, create a release build for x86 and x64 that runs on the latest windows OS installed on the GitHub-hosted runners. Then, define environment variables that are common to all the runs in the matrix such as the signing certificate name, the relative path to the solution file and the Windows Application Packaging project name.

    strategy:
      matrix:
        targetplatform: [x86, x64]

    runs-on: windows-latest

    env:
      SigningCertificate: GitHubActionsDemo.pfx
      Solution_Path: MyWpfApp.sln
      Test_Project_Path: MyWpfApp.Tests\MyWpfApp.Tests.csproj
      Wpf_Project_Path: MyWpfApp\MyWpfApp.csproj
      Wap_Project_Directory: MyWpfApp.Package
      Wap_Project_Name: MyWpfApp.Package.wapproj

Next, execute the unit tests in MYWPFApp.Tests by calling ‘donet test’.

    # Test
    - name: Execute Unit Tests
      run: dotnet test $env:Test_Project_Path

After executing the tests, restore the application while passing in the RuntimeIdentifier parameter in order to populate the obj folder with the appropriate platform dependencies for use during build.

    # Restore the application
    - name:  Restore the Wpf application to populate the obj folder
      run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier
      env:
        Configuration: Debug
        RuntimeIdentifier: win-${{ matrix.targetplatform }}

Once the application has been restored, build and create the MSIX. Rather than build each project separately, simply build the solution, making sure to pass the target platform, configuration, build mode, whether to produce an app bundle, the signing certificate, and certificate password as parameters.

    # Build the Windows Application Packaging project
    - name: Build the Windows Application Packaging Project (wapproj) 
      run: msbuild $env:Solution_Path /p:Platform=$env:TargetPlatform /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:BuildMode /p:AppxBundle=$env:AppxBundle /p:PackageCertificateKeyFile=$env:SigningCertificate /p:PackageCertificatePassword=${{ secrets.Pfx_Key }}
      env:
        AppxBundle: Never
        BuildMode: SideLoadOnly
        Configuration: Release
        TargetPlatform: ${{ matrix.targetplatform }}

Once the app package has been created, take advantage of the upload-artifact GitHub Action to save the artifact. You have the option to download the artifact to test the build or upload the artifact to a website or file share to distribute the application.

    # Upload the MSIX package: https://github.com/marketplace/actions/upload-artifact
    - name: Upload build artifacts
      uses: actions/upload-artifact@v1
      with:
        name: MSIX Package
        path: MyWpfApp.Package\AppPackages\

To find the artifact, navigate to "Actions," select the workflow, then download the artifact on the right side of the window.

cd.yml: Build, package, and create a GitHub release for multiple channels

In the CD workflow, you can build, package and distribute code built for multiple channels such as “Dev”, “Prod_Sideload” and “Prod_Store.” During every workflow run, the applications’ Package.Identity.Name, Package.Identity.Version and Package.Properties.DisplayName are changed according to which channel of the build matrix will be built. We use a Powershell script to overwrite these values in the Windows Application Packaging project's Package.appxmanifest. By doing so, we change the identity of the application to MyWPFApp.DevOpsDemo.Dev, MyWPFApp.DevOpsDemo.ProdSideload, or MyWPFApp.DevOpsDemo.ProdStore depending on which matrix channel is built, thus enabling multiple channels of the application.

    # Update the appxmanifest before build by setting the per-channel values set in the matrix.
    - name: Update manifest version
      run: |
        [xml]$manifest = get-content ".\$env:Wap_Project_Directory\Package.appxmanifest"
        $manifest.Package.Identity.Version = "$env:NBGV_SimpleVersion.0"
        $manifest.Package.Identity.Name = "${{ matrix.MsixPackageId }}"
        $manifest.Package.Identity.Publisher = "${{ matrix.MsixPublisherId }}"
        $manifest.Package.Properties.DisplayName = "${{ matrix.MsixPackageDisplayName }}"
        $manifest.Package.Applications.Application.VisualElements.DisplayName = "${{ matrix.MsixPackageDisplayName }}"
        $manifest.save(".\$env:Wap_Project_Directory\Package.appxmanifest")

On every push to the repo with a tag matching the pattern *, the workflow will build the solution, create a release and upload the release asset. For more information on how to configure a workflow to run on specific branches or tags, see GitHub Workflow syntax for GitHub Actions - on.<push | pull_request>.<branches | tags>.

on: 
  push:
    tags:
      - '*'

To create a git tag, run the following commands on the branch you wish to release:

git tag 1.0.0.0
git push origin --tags

The above commands will add the tag "1.0.0.0" and then push the branch and tag to the repo. Learn more about Git Tagging.

Channels and environment variables used during the run are defined in the build matrix and will build and create app packages for development (Dev), production sideload (Prod_Sideload), and also production for the Microsoft Store (Prod_Store). In this example, each channel is built for two configurations: x86 and x64. However, arm or arm64 are valid configurations as well.

A build matrix can be created to execute jobs across multiple operating systems, build configurations or different supported versions of a programming language. With GitHub Actions, you can define incredibly complex build matrices that can generate up to 256 builds per run! Learn how to configure a build matrix.

jobs:

  build:

    strategy:
      matrix:
        channel: [Dev, Prod_Sideload, Prod_Store]
        targetPlatform: [x86, x64]
        include:
          
          # includes the following variables for the matrix leg matching Dev
          - channel: Dev
            ChannelName: Dev
            Configuration: Debug
            DistributionUrl: https://microsoft.github.io/github-actions-for-desktop-apps-distribution-dev
            MsixPackageId: MyWPFApp.DevOpsDemo.Dev
            MsixPublisherId: CN=GitHubActionsDemo
            MsixPackageDisplayName: MyWPFApp (Dev)

          # includes the following variables for the matrix leg matching Prod_Sideload
          - channel: Prod_Sideload
            Configuration: Release
            ChannelName: Prod_Sideload
            DistributionUrl: https://microsoft.github.io/github-actions-for-desktop-apps-distribution-prod
            MsixPackageId: MyWPFApp.DevOpsDemo.ProdSideload
            MsixPublisherId: CN=GitHubActionsDemo
            MsixPackageDisplayName: MyWPFApp (ProdSideload)

          # includes the following variables for the matrix leg matching Prod_Store
          - channel: Prod_Store
            Configuration: Release
            ChannelName: Prod_Store
            DistributionUrl: 
            MsixPackageId: MyWPFApp.DevOpsDemo.ProdStore
            MsixPublisherId: CN=GitHubActionsDemo
            MsixPackageDisplayName: MyWPFApp (ProdStore)

Just like the CI workflow, restore the solution.

    # Restore the application
    - name:  Restore the Wpf application to populate the obj folder
      run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier
      env:
        Configuration: Debug
        RuntimeIdentifier: win-${{ matrix.targetplatform }}

This time, however, use GitHub’s if conditional to build and package the MSIX for Dev and Prod_Sideload (which requires an AppInstaller Uri and Signing Certificate) or for Prod_Store. We pass different parameters depending on which channel we are building for.

    # Build the Windows Application Packaging project for Dev and Prod_Sideload
    - name: Build the Windows Application Packaging Project (wapproj) for ${{ matrix.ChannelName }}
      run: msbuild $env:Solution_Path /p:Platform=$env:TargetPlatform /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:BuildMode /p:AppxBundle=$env:AppxBundle /p:PackageCertificateKeyFile=$env:SigningCertificate /p:PackageCertificatePassword=${{ secrets.Pfx_Key }}
      if: matrix.ChannelName != 'Prod_Store'
      env:
        AppxBundle: Never
        AppInstallerUri: ${{ matrix.DistributionUrl }}
        BuildMode: SideLoadOnly
        Configuration: ${{ matrix.Configuration }}
        GenerateAppInstallerFile: True
        TargetPlatform: ${{ matrix.targetplatform }}
        
    # Build the Windows Application Packaging project for Prod_Store
    - name: Build the Windows Application Packaging Project (wapproj) for ${{ matrix.ChannelName }}
      run: msbuild $env:Solution_Path /p:Platform=$env:TargetPlatform /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:BuildMode /p:AppxBundle=$env:AppxBundle /p:GenerateAppInstallerFile=$env:GenerateAppInstallerFile /p:AppxPackageSigningEnabled=$env:AppxPackageSigningEnabled
      if: matrix.ChannelName == 'Prod_Store'
      env:
        AppxBundle: Never
        AppxPackageSigningEnabled: False
        BuildMode: StoreOnly
        Configuration: ${{ matrix.Configuration }}
        GenerateAppInstallerFile: False
        TargetPlatform: ${{ matrix.targetplatform }}

Once the MSIX is created for each channel, the agent archives the AppPackages folder then creates a Release with the specified git release tag. The archive is uploaded to the release as an asset for storage or distribution. It’s important to note that release names must be unique or an error will be generated. This is why tag_name and release_name include the github reference, channel name and target platform.

    # Create the release:  https://github.com/actions/create-release
    - name: Create release
      id: create_release
      uses: actions/create-release@v1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
      with:
        tag_name: ${{ github.ref}}.${{matrix.ChannelName}}.${{ matrix.targetplatform }}
        release_name:  ${{ github.ref }}.${{ matrix.ChannelName }}.${{ matrix.targetplatform }}
        draft: false
        prerelease: false

    # Upload release asset:   https://github.com/actions/upload-release-asset
    - name: Update release asset
      id: upload-release-asset
      uses: actions/upload-release-asset@v1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        upload_url: ${{ steps.create_release.outputs.upload_url }}  # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 
        asset_path: MyWpfApp.Package\AppPackages\AppPackages.zip
        asset_name: AppPackages.zip
        asset_content_type: application/zip

To find the Release artifacts, navigate to the "Releases" link in the repo.

Find the release and asset location.

Creating channels for the application is a powerful way to create multiple distributions of an application in the same CD pipeline.

Versioning

In both workflows, one of the first things to do is create a version and store version information as environment variables. Having a different version for every push is especially important when a release is created as each release must have a unique release_name.

The Nerdbank.GitVersioning GitHub Action sets the build version based on a combination of the included version.json file, and the git height of the version.

    # Use Nerdbank.GitVersioning to set version variables: https://github.com/AArnott/nbgv
    - name: Use Nerdbank.GitVersioning to set version variables
      uses: aarnott/[email protected]
      with:
        setAllVars: true

Once the action runs, a number of environment variables are available for use, such as:

  • NBGV_Version (e.g. 1.1.159.47562)
  • NBGV_SimpleVersion (e.g. 1.1.159)
  • NBGV_NuGetPackageVersion (e.g. 1.1.159-gcab9873dd7)
  • NBGV_ChocolateyPackageVersion
  • NBGV_NpmPackageVersion

A list of all the environment variables available to use in the run are shown below. Environment variables set by NBGV.

See the Nerdbank.GitVersioning package for more information.

Signing

Avoid submitting certificates to the repo if at all possible to ensure security best practices. (Git ignores them by default.) To manage the safe handling of sensitive files like certificates, take advantage of GitHub secrets, which allow the storage of sensitive information in the repository.

First, generate a signing certificate in the Windows Application Packaging Project or add an existing signing certificate to the project. Next, use PowerShell to encode the .pfx file using Base64 encoding by running the following Powershell script to generate the output file.

$pfx_cert = Get-Content '.\GitHubActionsDemo.pfx' -Encoding Byte
[System.Convert]::ToBase64String($pfx_cert) | Out-File 'SigningCertificate_Encoded.txt'

Open the output file, SigningCertificate_Encoded.txt, and copy the string inside. Finally, add the string to the repo as a GitHub secret and name it Base64_Encoded_Pfx. Learn how to add a secret to the workflow. In the workflow, add a step to decode the secret, save the .pfx to the build agent, and package the application with the Windows Application Packaging project.

    # Decode the Base64 encoded Pfx
    - name: Decode the Pfx
      run: |
        $pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.Base64_Encoded_Pfx }}")
        $currentDirectory = Get-Location
        $certificatePath = Join-Path -Path $currentDirectory -ChildPath $env:Wap_Project_Directory -AdditionalChildPath $env:SigningCertificate
        [IO.File]::WriteAllBytes("$certificatePath", $pfx_cert_byte)

Once the certificate is decoded and saved to the Windows Application Packaging Project, use it to sign the package during packaging making sure to pass the signing certificate's password, stored as a GitHub secret, to MSBuild as a parameter.

    # Build the Windows Application Packaging project for Dev and Prod_Sideload
    - name: Build the Windows Application Packaging Project (wapproj) for ${{ matrix.ChannelName }}
      run: msbuild $env:Wap_Project_Directory/$env:Wap_Project_Name /p:Platform=$env:TargetPlatform /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:BuildMode /p:GenerateAppInstallerFile=$env:GenerateAppInstallerFile /p:AppInstallerUri=$env:AppInstallerUri /p:PackageCertificateKeyFile=$env:SigningCertificate /p:PackageCertificatePassword=${{ secrets.Pfx_Key }}
      if: ${{ matrix.ChannelName }} != Prod_Store
      env:
        AppInstallerUri: ${{ matrix.DistributionUrl }}
        BuildMode: SideLoadOnly
        Configuration: ${{ matrix.Configuration }}
        GenerateAppInstallerFile: True
        TargetPlatform: ${{ matrix.TargetPlatform }}

Finally, to ensure the certificate doesn’t stay on the build machine, delete the .pfx.

    # Remove the .pfx
    - name: Remove the .pfx
      run: Remove-Item -path $env:Wap_Project_Directory/$env:SigningCertificate
      if: ${{ matrix.ChannelName }} != Prod_Store

Publisher Profiles

Publisher Profiles allow developers to store publishing information on their WPF application such as the configuration, target runtime, and deployment mode (whether the application is self contained or framework dependent). These profiles can be easily referenced by the Windows Application Packaging project and used during build and packaging.

To add a Publisher Profile to the WPF application, right-click the Wpf application and select “Publish.” In the Publish dialog, select 'New.' In the "Pick a publish target" dialog, choose the folder or file share to publish the app to and "Create Profile."

In the Publish dialog, click "Edit" to customize the profile settings.

Select the configuration, framework and runtime to target, then select whether the deployment mode should be "Framework Dependent" or "Self-contained."

Edit the profile name to reflect the settings by clicking "Rename" in the Publish dialog.

Finally, in the Windows Application Packaging project, add a reference to the Publish Profile. In the Solution Explorer, open MyWPFApp.Package and navigate to Applications. Click on MyWFPApp and, in the properties window, select Publishing Profile. The dropdown should be populated with the recently-created profile.

To ensure the settings were added correctly to MyWPFApp.Package, double click on the project to open the .wapproj file and scroll to the bottom to find the PublishProfile elements.

Conclusion

GitHub workflows that leverage GitHub Actions are a great way for developers to create and customize continuous integration and continuous deployment pipelines to build, test, package, publish and distribute their application from start to finish entirely in GitHub.

To learn more about other GitHub Actions that you can add to your pipelines, take a look at the GitHub Marketplace. For more information on GitHub Actions, check out the GitHub Actions home page.

We are always open to your feedback. Please feel free to email us at [email protected].

Our repo is open source and welcomes contributions and suggestions. Please see Contributing.md for more information on how to submit a PR to the repo.

github-actions-for-desktop-apps's People

Contributors

aarnott avatar ashikpaul avatar edwardskrod avatar lancemccarthy avatar microsoftopensource avatar timheuer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

github-actions-for-desktop-apps's Issues

Difficulty creating a new repository

Good Morning
I would like a help please
My name and Thiago Sales thank you.

How to solve?

This message appears below

This directory appears to be a Git repository. Would you like to add this repository instead?

image

Continuous integration Deployment - Code sign Failed

Recommended by Microsoft Q&A HuiLiu-MSFT

I'm trying to code sign my application using GitHub Actions cd-net6-temp.yml from Lance branch and latest updated notes from Readme.md for codes signing.

From the workflow run, the following error are:

error : Certificate could not be opened: …..
error : The specified network password is not correct….
error : [D:\a\MPC-MassPropertiesCalculator\MPC-MassPropertiesCalculator\MPC-MassPropertiesCalculator.Installer\MPC-MassPropertiesCalculator.Installer.wapproj]

Can you confirm that's an issue or error created by me in my CD-dotnet6.0-desktop.yml

Here my latest workflow run link

Could not find file "GitHubActionsWorkflow.pfx"

I've been figuring this workflow out for hours. My current roadblock is to do with supplying the msbuild command with the correct PFX. I used the provided template and followed the instructions to a tee.

It appears that msbuild is trying to find the locally generated certificate, the one that is generated through the Project Properties, but is not committed (I conveniently named it GitHubActionsWorkflow.pfx). For some reason, it's not picking up the supplied file along with the supplied secret key.

C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(3326,5): error MSB3322: Unable to get MD5 checksum for the key file "..\GitHubActionsWorkflow.pfx". Could not find file 'D:\a\my-project\my-project\GitHubActionsWorkflow.pfx'. [D:\a\my-project\my-project\project1\project1.csproj]
Done Building Project "D:\a\my-project\my-project\project1\project1.csproj" (build target(s)) -- FAILED.
C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\DesktopBridge\Microsoft.DesktopBridge.targets(498,5): error MSB4181: The "MSBuild" task returned false but did not log an error. [D:\a\my-project\my-project\WindowsAppPackaging\WindowsAppPackaging.wapproj]
Done Building Project "D:\a\my-project\my-project\WindowsAppPackaging\WindowsAppPackaging.wapproj" (default targets) -- FAILED.

Build FAILED.

I tried un-checking the Sign the Assembly option and it successfully built the solution. However, attempting to run install.ps1 resulted in the following:

Found bundle: D:\Medallyon\Desktop\WindowsAppPackaging_1.0.0.0_Test\WindowsAppPackaging_1.0.0.0_x86.appxbundle
Error: The package or bundle is not digitally signed or its signature is corrupted.
Press Enter to continue...:

Am I supposed to un-check the Sign the Assembly option after uploading my encoded certificate? If so, what use does supplying msbuild with a decoded certificate file have if the assembly is not signed? And, most importantly, how do I fix this?
image

Replace Hard-coded Paths with Already Existing Variable

Problematic

At the end of the YAML for the continuous integration example, the upload-artifact step path uses a hard coded folder path:

path: MyWpfApp.Package\AppPackages\

Recommended

I believe this should be using the Wap_Project_Directory variable plus "AppPackages" subfolder instead.

Snippet

# Upload the MSIX package: https://github.com/marketplace/actions/upload-artifact
- name: Upload build artifacts
  uses: actions/upload-artifact@v1
  with:
    name: MSIX Package
    path: '$env:Wap_Project_Directory\AppPackages\'

[Edit] - Added the subfolder name to the variable. I'm not sure that's how to concatenate the variable with a string in GitHub actions yet, but you get the point

Unnecessary PropertyGroups for PlatformTarget?

Are all these really necessary?

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>

It seems if defining these is necessary can't it be done in one step?

<PlatformTarget>$(Platform)</PlatformTarget> 

But I'd be surprised if that behavior isn't the default.

.NET 6 Update

There have been a lot of changes since .NET Core 3 for WPF and packaging projects. .NET 5/6 have many improvements and has a different project style and structure.

This enhancement is to migrate the existing .NET Core 3 project type to .NET 5 and use the improved interconnect in Project Reunion (aka Windows App SDK), SDK contracts and CsWinRT.

@edwardskrod
These changes have been implemented in the lance/net5-update branch. Can you review for initial approval? If it looks good to you, I will write a new temporary workflow to start CI-CD improvements.

Wpf Net5 and MSIX

Hello, I'm trying to setup a Continuous Integration action, based on the ci.yaml provided in this repository.
I'm using net5 for my Wpf application, and visual studio 2019 preview.
Locally I'm able to build and deploy without problems, but on the github action I receive this error

D:\a\weekly_diet_organizer\weekly_diet_organizer\DietOrganizer.Wap\DietOrganizer.Wap.wapproj : error NU1201: Project DietOrganizer is not compatible with uap10.0.16299 (UAP,Version=v10.0.16299). Project DietOrganizer supports: net5.0-windows7.0 (.NETCoreApp,Version=v5.0) [D:\a\weekly_diet_organizer\weekly_diet_organizer\DietOrganizer.sln]

this is my workflow file
` name: ci

on:
  push:
    branches: [ master ]

jobs:
  build:
    strategy:
      matrix:
        targetplatform: [x64]

    runs-on: windows-latest

    env:
      App_Packages_Directory: AppPackages
      Solution_Name: DietOrganizer.sln
      Test_Project_Path: DietOrganizer.Tests\DietOrganizer.Tests.csproj
      Wpf_Project_Path: DietOrganizer\DietOrganizer.csproj
      Wap_Project_Directory: DietOrganizer.Wap
      Wap_Project_Name: DietOrganizer.Wap.wapproj
  
    steps:
    - name: Checkout
      uses: actions/checkout@v2
      with:
        fetch-depth: 0
    
# Use Nerdbank.GitVersioning to set version variables: https://github.com/AArnott/nbgv
- name: Use Nerdbank.GitVersioning to set version variables
  uses: aarnott/nbgv@master
  with:
    setAllVars: true

# Install the .NET Core workload
- name: Install .NET Core
  uses: actions/setup-dotnet@v1
  with:
    dotnet-version: 5.0.x

# Add  MSBuild to the PATH
- name: Setup MSBuild.exe
  uses: microsoft/setup-msbuild@v1
  
# Update the version before build
- name: Update manifest version
  run: |
    [xml]$manifest = get-content ".\$env:Wap_Project_Directory\Package.appxmanifest"
    $manifest.Package.Identity.Version = "$env:NBGV_SimpleVersion.0"
    $manifest.save(".\$env:Wap_Project_Directory\Package.appxmanifest")

# Execute unit tests
- name: Execute unit tests
  run: dotnet test $env:Test_Project_Path

# Restore the application to populate the obj folder with RuntimeIdentifiers
- name: Restore the application
  run: msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier
  env:
    Configuration: Debug
    RuntimeIdentifier: win-${{ matrix.targetplatform }}
    
# Decode the Base64 encoded Pfx
- name: Decode the Pfx
  run: |
    $pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.Base64_Encoded_Pfx }}")
    $currentDirectory = Get-Location
    $certificatePath = Join-Path -Path $currentDirectory -ChildPath $env:Wap_Project_Directory -AdditionalChildPath $env:SigningCertificate
    [IO.File]::WriteAllBytes("$certificatePath", $pfx_cert_byte)

# Build the Windows Application Packaging project
- name: Build the Windows Application Packaging Project (wapproj)
  run: msbuild $env:Solution_Path /p:Platform=$env:TargetPlatform /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:BuildMode /p:AppxBundle=$env:AppxBundle /p:PackageCertificateKeyFile=$env:SigningCertificate /p:PackageCertificatePassword=${{ secrets.Pfx_Key }}
  env:
    AppxBundle: Never
    BuildMode: SideloadOnly
    Configuration: Debug
    TargetPlatform: ${{ matrix.targetplatform }}

# Remove the .pfx
- name: Remove the .pfx
  run: Remove-Item -path $env:Wap_Project_Directory\$env:SigningCertificate

# Upload the MSIX package: https://github.com/marketplace/actions/upload-artifact
- name: Upload build artifacts
  uses: actions/upload-artifact@v1
  with:
    name: MSIX Package
    path: ${{ env.Wap_Project_Directory }}\${{ env.App_Packages_Directory }}`

Can someone help me?
Is there something I can do to make it work?

Thank you in advance

Letter of thank

After three hours, with the help of your documentation, I successfully passed the CI build, see https://github.com/dotnet-campus/TranslationTool/actions

I just want to share you what my mistake.

  1. As #17 say, I should change the Upload build artifacts path
  2. I forget to add the start project. And how to solve it, see dotnet-campus/TranslationTool@2caac99
  3. I forget to set the AppxBundlePlatforms in TranslationTool.Package.wapproj. And how to solve it, see dotnet-campus/TranslationTool@107e6fd
  4. I forgot to remove the SigningCertificate code because my pfx has no keys. See dotnet-campus/TranslationTool@58e47f7
  5. I forget to add the PublishProfiles files and which will cause the following errors to build. And how to solve it, see dotnet-campus/TranslationTool@1650f7a
(ResolveAssemblyReferences target) ->   
C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(2106,5): error MSB3270: There was a mismatch between the processor architecture of the project being built "AMD64" and the processor architecture of the reference "D:\a\TranslationTool\TranslationTool\Code\TranslationTool.WPF\bin\x86\Debug\netcoreapp3.1\win-x86\TranslationTool.WPF.dll", "x86". This mismatch may cause runtime failures. Please consider changing the targeted processor architecture of your project through the Configuration Manager so as to align the processor architectures between your project and references, or take a dependency on references with a processor architecture that matches the targeted processor architecture of your project. [D:\a\TranslationTool\TranslationTool\Code\TranslationTool.Package\TranslationTool.Package.wapproj]

Thank you

Unable to fix error on CI workflow

I am trying to set-up the CI workflow for an app that I develop with a friend, but I simply cannot pass the "Restore the application" step, I keep getting the following error.

_Run msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration
Microsoft (R) Build Engine version 16.8.3+39993bd9d for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.

MSBUILD : error MSB1003: Specify a project or solution file. The current working directory does not contain a project or solution file.
Error: Process completed with exit code 1._

I made a test repo where I tried again to set up but I get the same error.
The test repo is: https://github.com/CiucurDaniel/TestCorectAppWithCI

error_log
file_structure

msbuild command for wapproj doesn't work locally via cli

Hi.

Thanks for the example. It's really helpful!

I would like to clarify some moment:
I study your ci.yml file and try to repeat all basics command locally on my machine.
So I've got a situation when I can build wapproject via visual studio, but it doesn't build via cli.

Environment:

➜ dotnet --version
3.1.201
➜ dotnet msbuild
Microsoft (R) Build Engine version 16.5.0+d4cbfca49 for .NET Core

➜ Get-ComputerInfo -Property @("OsVersion", "WindowsVersion", "CsSystemType")

OsVersion  WindowsVersion CsSystemType
---------  -------------- ------------
10.0.18363 1909           x64-based PC

As I've already mentioned I can build wapproject via visual studio (2019 community Version 16.5.3),
but

➜ dotnet build
Microsoft (R) Build Engine version 16.5.0+d4cbfca49 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

.wapproj(51,3): error MSB4019: The imported project "C:\Program Files\dotnet\sdk\3.1.201\Microsoft\DesktopBridge\Microsoft.DesktopBridge.props" was not found. Confirm that t
he expression in the Import declaration "C:\Program Files\dotnet\sdk\3.1.201\\Microsoft\DesktopBridge\\Microsoft.DesktopBridge.props" is correct, and that the file exists on disk.

Build FAILED.

Compiler complains on this row:

  <PropertyGroup>
    <WapProjPath Condition="'$(WapProjPath)'==''">$(MSBuildExtensionsPath)\Microsoft\DesktopBridge\</WapProjPath>
  </PropertyGroup>
  <Import Project="$(WapProjPath)\Microsoft.DesktopBridge.props" />

How I understood my .net core sdk doesn't have DesktopBridge.

With dotnet msbuild and all parameters like platform, UapAppxPackageBuildMode and so on the result will be the same.

Do you have any idea how to solve it and it possible in principle I mean pack win exe to appx via .net core sdk?

Thanks and good luck!

CI-CD Builds Fail Due to AddPath being Deprecated

Problem

When running any of the workflows, they will fail due to new restrictions implemented on GitHub Actions Runners. See GitHub runner Deprecating AddPath and SetEnv.

In this case, NerdBankVersioning will hit the error first, but there are other steps that have issues, too.

The `add-path` command is disabled. Please upgrade to using Environment Files or opt into unsecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_COMMANDS` environment variable to `true`. For more information see: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/

Solution Options

  1. Add an environment variable to the top of the pipeline to allow these variables to be set (easiest)
  2. Investigate all the GH Actions being used in the workflow and see if they have an update available that addresses the restriction.

Option 1 is recommended to get the pipeline working again ASAP. Then you can work on moving to Option 2 over time as you find updated Actions to migrate to.

I will open a Pull Request to get Option 1 implemented. for option 2 will take a little more time, but I wil work on it and open a follow up Pull Request once it's working w/out Option 1

YML file to build WPF application targeted to .NET core 3.1

I’ve a WPF application targeted to .NET core 3.1 and I’m trying to build and publish it with below YML file in GitHub Action

https://github.com/PramodKumarHK89/MicrosoftIdentityPlatformEditor/blob/5d882caa5c220c846645ddcde0d0252ea6e9a01a/.github/workflows/dotnet-desktop.yml

However, build fails with below errors.

Warning: C:\Users\runneradmin\AppData\Local\Microsoft\dotnet\sdk\3.1.417\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.DefaultItems.targets(349,5): warning NETSDK1107: Microsoft.NET.Sdk.WindowsDesktop is required to build Windows desktop applications. 'UseWpf' and 'UseWindowsForms' are not supported by the current SDK. [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
14CSC : warning CS8032: An instance of analyzer System.Text.Json.SourceGeneration.JsonSourceGenerator cannot be created from C:\Users\runneradmin.nuget\packages\system.text.json\6.0.2\analyzers\dotnet\roslyn3.11\cs\System.Text.Json.SourceGeneration.dll : Could not load file or assembly 'Microsoft.CodeAnalysis, Version=3.11.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified.. [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
15CSC : warning CS8032: An instance of analyzer System.Text.Json.SourceGeneration.JsonSourceGenerator cannot be created from C:\Users\runneradmin.nuget\packages\system.text.json\6.0.2\analyzers\dotnet\roslyn4.0\cs\System.Text.Json.SourceGeneration.dll : Could not load file or assembly 'Microsoft.CodeAnalysis, Version=3.11.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified.. [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
16Error: AssemblyInfo.cs(3,12): error CS0246: The type or namespace name 'ThemeInfoAttribute' could not be found (are you missing a using directive or an assembly reference?) [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
17Error: AssemblyInfo.cs(3,12): error CS0246: The type or namespace name 'ThemeInfo' could not be found (are you missing a using directive or an assembly reference?) [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
18Error: AssemblyInfo.cs(4,5): error CS0103: The name 'ResourceDictionaryLocation' does not exist in the current context [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
19Error: AssemblyInfo.cs(7,5): error CS0103: The name 'ResourceDictionaryLocation' does not exist in the current context [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
20Error: MainWindow.xaml.cs(7,22): error CS0234: The type or namespace name 'Controls' does not exist in the namespace 'System.Windows' (are you missing an assembly reference?) [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
21Error: MainWindow.xaml.cs(8,22): error CS0234: The type or namespace name 'Data' does not exist in the namespace 'System.Windows' (are you missing an assembly reference?) [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
22Error: MainWindow.xaml.cs(9,22): error CS0234: The type or namespace name 'Documents' does not exist in the namespace 'System.Windows' (are you missing an assembly reference?) [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
23Error: MainWindow.xaml.cs(11,22): error CS0234: The type or namespace name 'Media' does not exist in the namespace 'System.Windows' (are you missing an assembly reference?) [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
24Error: MainWindow.xaml.cs(12,22): error CS0234: The type or namespace name 'Media' does not exist in the namespace 'System.Windows' (are you missing an assembly reference?) [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
25Error: MainWindow.xaml.cs(13,22): error CS0234: The type or namespace name 'Navigation' does not exist in the namespace 'System.Windows' (are you missing an assembly reference?) [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
26Error: MainWindow.xaml.cs(14,22): error CS0234: The type or namespace name 'Shapes' does not exist in the namespace 'System.Windows' (are you missing an assembly reference?) [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
27Error: MainWindow.xaml.cs(18,22): error CS0234: The type or namespace name 'Interop' does not exist in the namespace 'System.Windows' (are you missing an assembly reference?) [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
28Error: MainWindow.xaml.cs(29,39): error CS0246: The type or namespace name 'Window' could not be found (are you missing a using directive or an assembly reference?) [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
29Error: App.xaml.cs(16,32): error CS0246: The type or namespace name 'Application' could not be found (are you missing a using directive or an assembly reference?) [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
30Error: MainWindow.xaml.cs(43,56): error CS0246: The type or namespace name 'RoutedEventArgs' could not be found (are you missing a using directive or an assembly reference?) [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]
31Error: MainWindow.xaml.cs(126,58): error CS0246: The type or namespace name 'RoutedEventArgs' could not be found (are you missing a using directive or an assembly reference?) [D:\a\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor\MicrosoftIdentityPlatformEditor.csproj]

I’m not sure whats wrong with the YML. When I build it locally with VS 2022, build succeeds. Does anyone has a YAML file which I can use it in the GitHub Action to build WPF application targeted to .NET core 3.1

Here is my project
https://github.com/PramodKumarHK89/MicrosoftIdentityPlatformEditor/tree/5d882caa5c220c846645ddcde0d0252ea6e9a01a

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.