{"id":13677131,"url":"https://github.com/microsoft/github-actions-for-desktop-apps","last_synced_at":"2025-04-29T10:32:04.026Z","repository":{"id":43670584,"uuid":"236312612","full_name":"microsoft/github-actions-for-desktop-apps","owner":"microsoft","description":"This repo contains a sample WPF application to demonstrate how to create CI/CD pipelines using GitHub Actions.","archived":true,"fork":false,"pushed_at":"2022-10-06T17:53:05.000Z","size":817,"stargazers_count":353,"open_issues_count":0,"forks_count":109,"subscribers_count":21,"default_branch":"main","last_synced_at":"2024-11-11T19:39:42.973Z","etag":null,"topics":["continuous-deployment","continuous-integration","continuous-testing","githubactions","wpf"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/microsoft.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null}},"created_at":"2020-01-26T12:59:55.000Z","updated_at":"2024-11-11T05:47:52.000Z","dependencies_parsed_at":"2023-01-19T12:45:15.306Z","dependency_job_id":null,"html_url":"https://github.com/microsoft/github-actions-for-desktop-apps","commit_stats":null,"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microsoft%2Fgithub-actions-for-desktop-apps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microsoft%2Fgithub-actions-for-desktop-apps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microsoft%2Fgithub-actions-for-desktop-apps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microsoft%2Fgithub-actions-for-desktop-apps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/microsoft","download_url":"https://codeload.github.com/microsoft/github-actions-for-desktop-apps/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251483996,"owners_count":21596637,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["continuous-deployment","continuous-integration","continuous-testing","githubactions","wpf"],"created_at":"2024-08-02T13:00:37.406Z","updated_at":"2025-04-29T10:31:59.014Z","avatar_url":"https://github.com/microsoft.png","language":"C#","readme":"# DevOps for Windows Desktop Apps Using GitHub Actions\n\n### Create CI/CD workflows for WPF and Windows Forms Applications built on .NET Core 3.x\n\nThis repo contains a sample application to demonstrate how to create CI/CD pipelines using [GitHub Actions](https://github.com/features/actions \"GitHub Actions page\"). \n\nWith GitHub Actions, you can quickly and easily automate your software workflows with CI/CD.\n* Integrate code changes directly into GitHub to speed up development cycles\n* Trigger builds to quickly identify breaking changes and create testable debug builds\n* Continuously run tests to identify and eliminate bugs, improving code quality \n* Automatically build, sign, package and deploy branches that pass CI \n\nBuild, test, and deploy your code entirely within GitHub.\n\n| Workflow | Status |\n|----------|--------|\n| WPF - CI | ![ci](https://github.com/microsoft/github-actions-for-desktop-apps/workflows/Wpf%20Continuous%20Integration/badge.svg) |\n| WPF - CD | ![cd](https://github.com/microsoft/github-actions-for-desktop-apps/workflows/Wpf%20Continuous%20Delivery/badge.svg) |\n| WPF - CI (.NET 6 experimental) | [![NET 6.0 CI (temporary)](https://github.com/microsoft/github-actions-for-desktop-apps/actions/workflows/ci-net6-temp.yml/badge.svg)](https://github.com/microsoft/github-actions-for-desktop-apps/actions/workflows/ci-net6-temp.yml) |\n\n## Workflows\n\nTo take advantage of GitHub Actions, workflows are defined in YAML files that are in the .github/workflows folder. \nIn the project, there are two workflows defined:\n\n* .github/workflows/ci.yml\n* .github/workflows/cd.yml\n\nThe 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.\n\nThe benefits of kicking off a CI run on every push are multi-fold:\n* Quickly identify breaking changes\n* Create a testable debug build\n* Continuously run tests to identify and eliminate bugs, improving code quality\n* Keep workflow relatively lightweight by only testing configurations necessary to ensure good quality\n\nThe 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.\n\n\n### ci.yml: Build, test, package, and save package artifacts.\n\nThe 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.\n```yaml\n  \u003cIdentity\n    Name=\"MyWPFApp.DevOpsDemo.Local\"\n    Publisher=\"CN=GitHubActionsDemo\"\n    Version=\"0.0.1.0\" /\u003e\n```\n\nOn every push to the repo, take advantage of the [setup-dotnet](https://github.com/actions/setup-dotnet \"Setup dotnet GitHub Action\") GitHub Action and install the [dotnet core cli](https://github.com/dotnet/cli \"DotNet Core CLI page\") environment. Then add [MSBuild](https://github.com/microsoft/setup-msbuild \"MSBuild GitHub Action page\") to the PATH and execute unit tests using the [dotnet test](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-test \"DotNet test page\") runner console application.\n```yaml\n    - name: Install .NET Core\n      uses: actions/setup-dotnet@v1\n      with:\n        dotnet-version: 3.1.100\n\n    # Add  MsBuild to the PATH: https://github.com/microsoft/setup-msbuild\n    - name: Setup MSBuild.exe\n      uses: microsoft/setup-msbuild@v1.0.0\n      \n    # Test\n    - name: Execute Unit Tests\n      run: dotnet test $env:Test_Project_Path\n```\n\nAs 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](https://help.github.com/en/actions/getting-started-with-github-actions/core-concepts-for-github-actions#github-hosted-runner \"GitHub Hosted Runner page\").\n\nIn 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](https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables \"Configuring and Managing Workflows Using Environment Variables page\") 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.\n```yaml\n    strategy:\n      matrix:\n        targetplatform: [x86, x64]\n\n    runs-on: windows-latest\n\n    env:\n      SigningCertificate: GitHubActionsDemo.pfx\n      Solution_Path: MyWpfApp.sln\n      Test_Project_Path: MyWpfApp.Tests\\MyWpfApp.Tests.csproj\n      Wpf_Project_Path: MyWpfApp\\MyWpfApp.csproj\n      Wap_Project_Directory: MyWpfApp.Package\n      Wap_Project_Name: MyWpfApp.Package.wapproj\n```\n\nNext, execute the unit tests in MYWPFApp.Tests by calling ‘donet test’.\n```yaml\n    # Test\n    - name: Execute Unit Tests\n      run: dotnet test $env:Test_Project_Path\n```\n\nAfter 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.\n```yaml\n    # Restore the application\n    - name:  Restore the Wpf application to populate the obj folder\n      run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier\n      env:\n        Configuration: Debug\n        RuntimeIdentifier: win-${{ matrix.targetplatform }}\n```\n\nOnce 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.\n```yaml\n    # Build the Windows Application Packaging project\n    - name: Build the Windows Application Packaging Project (wapproj) \n      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 }}\n      env:\n        AppxBundle: Never\n        BuildMode: SideLoadOnly\n        Configuration: Release\n        TargetPlatform: ${{ matrix.targetplatform }}\n```\n\nOnce the app package has been created, take advantage of the [upload-artifact](https://github.com/marketplace/actions/upload-artifact \"upload-artifact GitHub Action page\") 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. \n```yaml\n    # Upload the MSIX package: https://github.com/marketplace/actions/upload-artifact\n    - name: Upload build artifacts\n      uses: actions/upload-artifact@v1\n      with:\n        name: MSIX Package\n        path: MyWpfApp.Package\\AppPackages\\\n```\n\nTo find the artifact, navigate to \"Actions,\" select the workflow, then download the artifact on the right side of the window.\n![](doc/images/findArtifact.png)\n\n\n### cd.yml: Build, package, and create a GitHub release for multiple channels\n\nIn 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.\nWe 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.\n```yaml\n    # Update the appxmanifest before build by setting the per-channel values set in the matrix.\n    - name: Update manifest version\n      run: |\n        [xml]$manifest = get-content \".\\$env:Wap_Project_Directory\\Package.appxmanifest\"\n        $manifest.Package.Identity.Version = \"$env:NBGV_SimpleVersion.0\"\n        $manifest.Package.Identity.Name = \"${{ matrix.MsixPackageId }}\"\n        $manifest.Package.Identity.Publisher = \"${{ matrix.MsixPublisherId }}\"\n        $manifest.Package.Properties.DisplayName = \"${{ matrix.MsixPackageDisplayName }}\"\n        $manifest.Package.Applications.Application.VisualElements.DisplayName = \"${{ matrix.MsixPackageDisplayName }}\"\n        $manifest.save(\".\\$env:Wap_Project_Directory\\Package.appxmanifest\")\n```\n\nOn 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.\u003cpush | pull_request\u003e.\u003cbranches | tags\u003e](https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#onpushpull_requestbranchestags \"GitHub Workflow Syntax for GitHub Actions\").\n```yaml\non: \n  push:\n    tags:\n      - '*'\n```\n\nTo create a git `tag`, run the following commands on the branch you wish to release:\n```cmd\ngit tag 1.0.0.0\ngit push origin --tags\n```\n\nThe 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.](https://git-scm.com/book/en/v2/Git-Basics-Tagging \"Basics of Git Tagging\")\n\nChannels 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](https://www.microsoft.com/en-us/store/apps/windows \"Microsoft Store home page\") (Prod_Store). In this example, each channel is built for two configurations: x86 and x64.  However, arm or arm64 are valid configurations as well.\n\nA 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.](https://help.github.com/en/actions/configuring-and-managing-workflows/configuring-a-workflow#configuring-a-build-matrix \"Learn how to configure a build matrix page\")\n```yaml\njobs:\n\n  build:\n\n    strategy:\n      matrix:\n        channel: [Dev, Prod_Sideload, Prod_Store]\n        targetPlatform: [x86, x64]\n        include:\n          \n          # includes the following variables for the matrix leg matching Dev\n          - channel: Dev\n            ChannelName: Dev\n            Configuration: Debug\n            DistributionUrl: https://microsoft.github.io/github-actions-for-desktop-apps-distribution-dev\n            MsixPackageId: MyWPFApp.DevOpsDemo.Dev\n            MsixPublisherId: CN=GitHubActionsDemo\n            MsixPackageDisplayName: MyWPFApp (Dev)\n\n          # includes the following variables for the matrix leg matching Prod_Sideload\n          - channel: Prod_Sideload\n            Configuration: Release\n            ChannelName: Prod_Sideload\n            DistributionUrl: https://microsoft.github.io/github-actions-for-desktop-apps-distribution-prod\n            MsixPackageId: MyWPFApp.DevOpsDemo.ProdSideload\n            MsixPublisherId: CN=GitHubActionsDemo\n            MsixPackageDisplayName: MyWPFApp (ProdSideload)\n\n          # includes the following variables for the matrix leg matching Prod_Store\n          - channel: Prod_Store\n            Configuration: Release\n            ChannelName: Prod_Store\n            DistributionUrl: \n            MsixPackageId: MyWPFApp.DevOpsDemo.ProdStore\n            MsixPublisherId: CN=GitHubActionsDemo\n            MsixPackageDisplayName: MyWPFApp (ProdStore)\n```\nJust like the CI workflow, restore the solution.\n```yaml\n    # Restore the application\n    - name:  Restore the Wpf application to populate the obj folder\n      run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier\n      env:\n        Configuration: Debug\n        RuntimeIdentifier: win-${{ matrix.targetplatform }}\n```\n\nThis 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. \nWe pass different parameters depending on which channel we are building for.\n```yaml\n    # Build the Windows Application Packaging project for Dev and Prod_Sideload\n    - name: Build the Windows Application Packaging Project (wapproj) for ${{ matrix.ChannelName }}\n      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 }}\n      if: matrix.ChannelName != 'Prod_Store'\n      env:\n        AppxBundle: Never\n        AppInstallerUri: ${{ matrix.DistributionUrl }}\n        BuildMode: SideLoadOnly\n        Configuration: ${{ matrix.Configuration }}\n        GenerateAppInstallerFile: True\n        TargetPlatform: ${{ matrix.targetplatform }}\n        \n    # Build the Windows Application Packaging project for Prod_Store\n    - name: Build the Windows Application Packaging Project (wapproj) for ${{ matrix.ChannelName }}\n      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\n      if: matrix.ChannelName == 'Prod_Store'\n      env:\n        AppxBundle: Never\n        AppxPackageSigningEnabled: False\n        BuildMode: StoreOnly\n        Configuration: ${{ matrix.Configuration }}\n        GenerateAppInstallerFile: False\n        TargetPlatform: ${{ matrix.targetplatform }}\n```\n\nOnce 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. \nIt’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.\n```yaml\n    # Create the release:  https://github.com/actions/create-release\n    - name: Create release\n      id: create_release\n      uses: actions/create-release@v1\n      env:\n        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token\n      with:\n        tag_name: ${{ github.ref}}.${{matrix.ChannelName}}.${{ matrix.targetplatform }}\n        release_name:  ${{ github.ref }}.${{ matrix.ChannelName }}.${{ matrix.targetplatform }}\n        draft: false\n        prerelease: false\n\n    # Upload release asset:   https://github.com/actions/upload-release-asset\n    - name: Update release asset\n      id: upload-release-asset\n      uses: actions/upload-release-asset@v1\n      env:\n        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n      with:\n        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 \n        asset_path: MyWpfApp.Package\\AppPackages\\AppPackages.zip\n        asset_name: AppPackages.zip\n        asset_content_type: application/zip\n\n```\n\nTo find the Release artifacts, navigate to the \"Releases\" link in the repo.\n![](doc/images/releases.png)\n\nFind the release and asset location.\n![](doc/images/releaseAssetLocation.png)\n\nCreating channels for the application is a powerful way to create multiple distributions of an application in the same CD pipeline.\n\n\n### Versioning\n\nIn 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.\n\nThe [Nerdbank.GitVersioning GitHub Action](https://github.com/AArnott/nbgv \"Nerbank.GitVersioning GitHub Action page\") sets the build version based on a combination of the included version.json file, and the git height of the version. \n```yaml\n    # Use Nerdbank.GitVersioning to set version variables: https://github.com/AArnott/nbgv\n    - name: Use Nerdbank.GitVersioning to set version variables\n      uses: aarnott/nbgv@v0.3\n      with:\n        setAllVars: true\n ```\n\n Once the action runs, a number of environment variables are available for use, such as:\n* NBGV_Version (e.g. 1.1.159.47562)\n* NBGV_SimpleVersion (e.g. 1.1.159)\n* NBGV_NuGetPackageVersion (e.g. 1.1.159-gcab9873dd7)\n* NBGV_ChocolateyPackageVersion \n* NBGV_NpmPackageVersion\n\nA list of all the environment variables available to use in the run are shown below.\n![Environment variables set by NBGV.](doc/images/versionEnvironmentVariables.png)\n\nSee the [Nerdbank.GitVersioning](https://github.com/aarnott/nerdbank.gitversioning \"Nerdbank.GitVersioning page\") package for more information.\n\n\n### Signing\nAvoid 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](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets \"GitHub Secrets page\"), which allow the storage of sensitive information in the repository.\n\nFirst, 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.\n```pwsh\n$pfx_cert = Get-Content '.\\GitHubActionsDemo.pfx' -Encoding Byte\n[System.Convert]::ToBase64String($pfx_cert) | Out-File 'SigningCertificate_Encoded.txt'\n```\n\nOpen 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.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners#creating-and-using-secrets-encrypted-variables \"Creating and using secrets page\")\nIn 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.\n```yaml\n    # Decode the Base64 encoded Pfx\n    - name: Decode the Pfx\n      run: |\n        $pfx_cert_byte = [System.Convert]::FromBase64String(\"${{ secrets.Base64_Encoded_Pfx }}\")\n        $currentDirectory = Get-Location\n        $certificatePath = Join-Path -Path $currentDirectory -ChildPath $env:Wap_Project_Directory -AdditionalChildPath $env:SigningCertificate\n        [IO.File]::WriteAllBytes(\"$certificatePath\", $pfx_cert_byte)\n```\n\nOnce 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.\n```yaml\n    # Build the Windows Application Packaging project for Dev and Prod_Sideload\n    - name: Build the Windows Application Packaging Project (wapproj) for ${{ matrix.ChannelName }}\n      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 }}\n      if: ${{ matrix.ChannelName }} != Prod_Store\n      env:\n        AppInstallerUri: ${{ matrix.DistributionUrl }}\n        BuildMode: SideLoadOnly\n        Configuration: ${{ matrix.Configuration }}\n        GenerateAppInstallerFile: True\n        TargetPlatform: ${{ matrix.TargetPlatform }}\n```\n\nFinally, to ensure the certificate doesn’t stay on the build machine, delete the .pfx.\n```yaml\n    # Remove the .pfx\n    - name: Remove the .pfx\n      run: Remove-Item -path $env:Wap_Project_Directory/$env:SigningCertificate\n      if: ${{ matrix.ChannelName }} != Prod_Store\n```\n\n### Publisher Profiles\nPublisher 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.\n\nTo 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.\"\n![](doc/images/pickAPublishTarget.png)\n\nIn the Publish dialog, click \"Edit\" to customize the profile settings.\n![](doc/images/editToCustomizeSettings.png)\n\nSelect the configuration, framework and runtime to target, then select whether the deployment mode should be \"Framework Dependent\" or \"Self-contained.\"\n![](doc/images/profileSettings.png)\n\nEdit the profile name to reflect the settings by clicking \"Rename\" in the Publish dialog.\n![](doc/images/renameProfile.png)\n\nFinally, in the Windows Application Packaging project, add a reference to the Publish Profile. \nIn 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.\n![](doc/images/myWpfApp.Package.Properties.png)\n\nTo 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.\n![](doc/images/publishProfileComplete.png)\n\n# Conclusion\nGitHub 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.\n\nTo learn more about other GitHub Actions that you can add to your pipelines, take a look at the [GitHub Marketplace](https://github.com/marketplace?type=actions \"GitHub Marketplace page\").  For more information on GitHub Actions, check out the [GitHub Actions](https://github.com/features/actions \"GitHub Actions home page\") home page.\n\nWe are always open to your feedback.  Please feel free to email us at [devdeploymenttools@microsoft.com](mailto:devdeploymenttools@microsoft.com \"Email us at devdeploymenttools at Microsoft.com\").\n\nOur repo is open source and welcomes contributions and suggestions.  Please see [Contributing.md](https://github.com/microsoft/github-actions-for-desktop-apps/blob/master/CONTRIBUTING.md \"Contributing.md page\") for more information on how to submit a PR to the repo.\n","funding_links":[],"categories":["C#"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicrosoft%2Fgithub-actions-for-desktop-apps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmicrosoft%2Fgithub-actions-for-desktop-apps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicrosoft%2Fgithub-actions-for-desktop-apps/lists"}