{"id":26844653,"url":"https://github.com/dylanparsons/dotnet-installer-cicd","last_synced_at":"2026-02-13T15:07:41.096Z","repository":{"id":312669301,"uuid":"948169547","full_name":"dylanparsons/dotnet-installer-cicd","owner":"dylanparsons","description":"Automated Windows installer creation for .NET projects using GitLab CI/CD. Provides configurations and scripts for building C# applications and generating installers with Inno Setup or WiX Toolset.","archived":false,"fork":false,"pushed_at":"2025-03-13T21:50:26.000Z","size":14,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-01T10:13:12.172Z","etag":null,"topics":["dotnet","gitlab-ci","inno-setup","windows-installer","wix"],"latest_commit_sha":null,"homepage":"","language":"Inno Setup","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/dylanparsons.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-13T21:38:40.000Z","updated_at":"2025-07-12T03:02:32.000Z","dependencies_parsed_at":"2025-09-01T10:13:13.419Z","dependency_job_id":"b27ac5ef-8dec-406a-a626-fea265789ee7","html_url":"https://github.com/dylanparsons/dotnet-installer-cicd","commit_stats":null,"previous_names":["dylanparsons/dotnet-installer-cicd"],"tags_count":null,"template":true,"template_full_name":null,"purl":"pkg:github/dylanparsons/dotnet-installer-cicd","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dylanparsons%2Fdotnet-installer-cicd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dylanparsons%2Fdotnet-installer-cicd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dylanparsons%2Fdotnet-installer-cicd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dylanparsons%2Fdotnet-installer-cicd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dylanparsons","download_url":"https://codeload.github.com/dylanparsons/dotnet-installer-cicd/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dylanparsons%2Fdotnet-installer-cicd/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29411138,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-13T06:24:03.484Z","status":"ssl_error","status_checked_at":"2026-02-13T06:23:12.830Z","response_time":78,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["dotnet","gitlab-ci","inno-setup","windows-installer","wix"],"created_at":"2025-03-30T19:30:18.155Z","updated_at":"2026-02-13T15:07:41.075Z","avatar_url":"https://github.com/dylanparsons.png","language":"Inno Setup","funding_links":[],"categories":[],"sub_categories":[],"readme":"# .NET C# CI/CD Pipeline with Installer Automation on GitLab\n\nThis repository contains configurations and scripts to automate building .NET C# projects and creating Windows installers using Inno Setup or WiX Toolset within a GitLab CI/CD pipeline, even when running GitLab on Linux.\n\n## Overview\n\nThis setup helps you transition from Visual Studio Installer Projects (MSI installers) to Inno Setup or WiX, with automated builds through GitLab. The pipeline:\n\n1. Builds your .NET C# project\n2. Compiles an Inno Setup script to create a Windows installer\n3. Archives and publishes the installer as an artifact\n\n## Repository Structure\n\n```\n├── .gitlab-ci.yml        # GitLab CI/CD pipeline configuration\n├── installer/\n│   ├── inno/\n│   │   └── setup.iss     # Inno Setup script template\n│   └── wix/\n│       └── Product.wxs   # WiX Toolset script template\n├── src/                  # Your C# project source files\n└── README.md             # This file\n```\n\n## Setup Instructions\n\n### 1. Configure Your GitLab CI/CD Pipeline\n\nCopy the provided `.gitlab-ci.yml` file to your repository:\n\n```yaml\nstages:\n  - build\n  - package\n\nbuild_project:\n  stage: build\n  image: mcr.microsoft.com/dotnet/sdk:6.0\n  script:\n    - dotnet restore\n    - dotnet build --configuration Release\n    - dotnet publish --configuration Release --output ./publish\n  artifacts:\n    paths:\n      - ./publish/\n    expire_in: 1 day\n\ncreate_installer:\n  stage: package\n  image: mono:latest\n  dependencies:\n    - build_project\n  before_script:\n    - apt-get update \u0026\u0026 apt-get install -y wget unzip wine64\n    # Download Inno Setup\n    - wget https://files.jrsoftware.org/is/6/innosetup-6.2.1.exe\n    # Optional: Download icon editor tool if needed\n    - wget https://github.com/electron/rcedit/releases/download/v1.1.1/rcedit-x64.exe\n  script:\n    # Install innoextract to extract Inno Setup\n    - apt-get install -y innoextract\n    - mkdir -p /opt/innosetup\n    - innoextract innosetup-6.2.1.exe -d /opt/innosetup\n    # Use wine to compile the Inno Setup script\n    - cp -r ./publish /opt/innosetup/publish\n    - cp ./installer/inno/setup.iss /opt/innosetup/\n    - cd /opt/innosetup\n    - wine ISCC.exe setup.iss\n    # Copy the output back to the project\n    - mkdir -p $CI_PROJECT_DIR/Output\n    - cp -r Output/* $CI_PROJECT_DIR/Output/\n  artifacts:\n    paths:\n      - ./Output/*.exe\n    expire_in: 1 week\n```\n\n### 2. Choose and Configure Your Installer\n\n#### Option A: Inno Setup Script\n\nCreate a file named `installer/inno/setup.iss` in your repository:\n\n```\n[Setup]\n; NOTE: The value of AppId uniquely identifies this application\nAppId={{YOUR-GUID-HERE}\nAppName=MyApp\nAppVersion=1.0\nDefaultDirName={autopf}\\MyApp\nDefaultGroupName=MyApp\nOutputDir=Output\nOutputBaseFilename=MyAppSetup\nCompression=lzma\nSolidCompression=yes\nWizardStyle=modern\n\n[Languages]\nName: \"english\"; MessagesFile: \"compiler:Default.isl\"\n\n[Tasks]\nName: \"desktopicon\"; Description: \"{cm:CreateDesktopIcon}\"; GroupDescription: \"{cm:AdditionalIcons}\"; Flags: unchecked\n\n[Files]\nSource: \"publish\\*\"; DestDir: \"{app}\"; Flags: ignoreversion recursesubdirs\n\n[Icons]\nName: \"{autoprograms}\\MyApp\"; Filename: \"{app}\\MyApp.exe\"\nName: \"{autodesktop}\\MyApp\"; Filename: \"{app}\\MyApp.exe\"; Tasks: desktopicon\n\n[Run]\nFilename: \"{app}\\MyApp.exe\"; Description: \"{cm:LaunchProgram,MyApp}\"; Flags: nowait postinstall skipifsilent\n```\n\n#### Option B: WiX Toolset Script\n\nCreate a file named `installer/wix/Product.wxs` in your repository:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003cWix xmlns=\"http://schemas.microsoft.com/wix/2006/wi\" xmlns:ui=\"http://wixtoolset.org/schemas/v4/wxs/ui\"\u003e\n  \u003cProduct Id=\"*\" Name=\"MyApp\" Language=\"1033\" Version=\"1.0.0.0\" Manufacturer=\"Your Company\" UpgradeCode=\"PUT-GUID-HERE\"\u003e\n    \n    \u003cPackage InstallerVersion=\"200\" Compressed=\"yes\" InstallScope=\"perMachine\" /\u003e\n\n    \u003cMajorUpgrade DowngradeErrorMessage=\"A newer version of [ProductName] is already installed.\" /\u003e\n    \u003cMediaTemplate /\u003e\n\n    \u003cFeature Id=\"ProductFeature\" Title=\"MyApp\" Level=\"1\"\u003e\n      \u003cComponentGroupRef Id=\"ProductComponents\" /\u003e\n      \u003cComponentRef Id=\"ProgramMenuDir\"/\u003e\n    \u003c/Feature\u003e\n\n    \u003cUI\u003e\n      \u003cUIRef Id=\"WixUI_InstallDir\" /\u003e\n      \u003cProperty Id=\"WIXUI_INSTALLDIR\" Value=\"INSTALLFOLDER\" /\u003e\n    \u003c/UI\u003e\n    \n  \u003c/Product\u003e\n\n  \u003cFragment\u003e\n    \u003cDirectory Id=\"TARGETDIR\" Name=\"SourceDir\"\u003e\n      \u003cDirectory Id=\"ProgramFilesFolder\" Name=\"PFiles\"\u003e\n        \u003cDirectory Id=\"INSTALLFOLDER\" Name=\"MyApp\" /\u003e\n      \u003c/Directory\u003e\n      \u003cDirectory Id=\"ProgramMenuFolder\" Name=\"Programs\"\u003e\n        \u003cDirectory Id=\"ProgramMenuDir\" Name=\"MyApp\"\u003e\n          \u003cComponent Id=\"ProgramMenuDir\" Guid=\"PUT-GUID-HERE\"\u003e\n            \u003cRemoveFolder Id='ProgramMenuDir' On='uninstall' /\u003e\n            \u003cRegistryValue Root='HKCU' Key='Software\\[Manufacturer]\\[ProductName]' Type='string' Value='' KeyPath='yes' /\u003e\n          \u003c/Component\u003e\n        \u003c/Directory\u003e\n      \u003c/Directory\u003e\n      \u003cDirectory Id=\"DesktopFolder\" Name=\"Desktop\" /\u003e\n    \u003c/Directory\u003e\n  \u003c/Fragment\u003e\n\n  \u003cFragment\u003e\n    \u003cComponentGroup Id=\"ProductComponents\" Directory=\"INSTALLFOLDER\"\u003e\n      \u003c!-- Add components for each file in your application --\u003e\n      \u003cComponent Id=\"MainExecutable\" Guid=\"PUT-GUID-HERE\"\u003e\n        \u003cFile Id=\"MainExe\" Name=\"MyApp.exe\" Source=\"$(var.PublishDir)MyApp.exe\" KeyPath=\"yes\"\u003e\n          \u003cShortcut Id=\"StartMenuShortcut\" Directory=\"ProgramMenuDir\" Name=\"MyApp\" WorkingDirectory=\"INSTALLFOLDER\" Icon=\"icon.ico\" IconIndex=\"0\" Advertise=\"yes\" /\u003e\n          \u003cShortcut Id=\"DesktopShortcut\" Directory=\"DesktopFolder\" Name=\"MyApp\" WorkingDirectory=\"INSTALLFOLDER\" Icon=\"icon.ico\" IconIndex=\"0\" Advertise=\"yes\" /\u003e\n        \u003c/File\u003e\n      \u003c/Component\u003e\n      \u003c!-- Add additional components for other files --\u003e\n    \u003c/ComponentGroup\u003e\n  \u003c/Fragment\u003e\n\u003c/Wix\u003e\n```\n\nCustomize either script with your application details. Both formats support registry entries, shortcuts, and post-installation commands.\n\n## GitLab CI/CD Configuration Options\n\n### Option 1: Using Inno Setup with Linux Runner and Wine\n\nThis option uses Wine to compile Inno Setup scripts on Linux:\n\n```yaml\ncreate_inno_installer:\n  stage: package\n  image: mono:latest\n  dependencies:\n    - build_project\n  before_script:\n    - apt-get update \u0026\u0026 apt-get install -y wget unzip wine64 innoextract\n    - wget https://files.jrsoftware.org/is/6/innosetup-6.2.1.exe\n    - mkdir -p /opt/innosetup\n    - innoextract innosetup-6.2.1.exe -d /opt/innosetup\n  script:\n    - cp -r ./publish /opt/innosetup/publish\n    - cp ./installer/inno/setup.iss /opt/innosetup/\n    - cd /opt/innosetup\n    - wine ISCC.exe setup.iss\n    - mkdir -p $CI_PROJECT_DIR/Output\n    - cp -r Output/* $CI_PROJECT_DIR/Output/\n  artifacts:\n    paths:\n      - ./Output/*.exe\n    expire_in: 1 week\n```\n\n### Option 2: Using WiX with Linux Runner\n\nThis option uses WiX's Linux-compatible toolchain `wixl` for creating MSI installers:\n\n```yaml\ncreate_wix_installer:\n  stage: package\n  image: ubuntu:latest\n  dependencies:\n    - build_project\n  before_script:\n    - apt-get update \u0026\u0026 apt-get install -y msitools\n  script:\n    - mkdir -p ./Output\n    # Replace placeholder values with actual data\n    - sed -i 's/\\$\\(var\\.PublishDir\\)/\\.\\/publish\\//g' installer/wix/Product.wxs\n    - wixl -v installer/wix/Product.wxs -o ./Output/MyApp.msi\n  artifacts:\n    paths:\n      - ./Output/*.msi\n    expire_in: 1 week\n```\n\n### Option 3: Using a Windows Runner\n\nIf you have access to a Windows machine, you can register it as a GitLab runner to build both the C# project and the installer natively.\n\n1. Install the GitLab Runner on a Windows machine\n2. Register it with your GitLab instance\n3. Use tags in your `.gitlab-ci.yml` to target this runner\n\nExample addition to your `.gitlab-ci.yml`:\n\n```yaml\n# For Inno Setup\ncreate_installer_windows_inno:\n  stage: package\n  tags:\n    - windows\n  dependencies:\n    - build_project\n  script:\n    - iscc.exe installer/inno/setup.iss\n  artifacts:\n    paths:\n      - .\\Output\\*.exe\n    expire_in: 1 week\n\n# For WiX\ncreate_installer_windows_wix:\n  stage: package\n  tags:\n    - windows\n  dependencies:\n    - build_project\n  script:\n    - nuget install WiX\n    - .\\WiX.*\\tools\\candle.exe -ext WixUIExtension installer/wix/Product.wxs -dPublishDir=publish\\\n    - .\\WiX.*\\tools\\light.exe -ext WixUIExtension Product.wixobj -out .\\Output\\MyApp.msi\n  artifacts:\n    paths:\n      - .\\Output\\*.msi\n    expire_in: 1 week\n```\n\n## Advanced Configuration Tips\n\n### Versioning\n\n#### Inno Setup Versioning\n\nAutomatically update the installer version based on your CI/CD pipeline:\n\n```\n[Setup]\nAppName=MyApp\nAppVersion=$CI_COMMIT_TAG\n; ... other settings ...\n```\n\nYou can dynamically replace these values in your CI/CD pipeline:\n\n```yaml\nscript:\n  - sed -i \"s/#define MyAppVersion \\\".*\\\"/#define MyAppVersion \\\"$CI_COMMIT_TAG\\\"/g\" /opt/innosetup/setup.iss\n  - cd /opt/innosetup\n  - wine ISCC.exe setup.iss\n```\n\n#### WiX Versioning\n\nFor WiX, you can update the version in the CI/CD pipeline:\n\n```yaml\nscript:\n  - sed -i \"s/Version=\\\"[0-9.]*\\\"/Version=\\\"$CI_COMMIT_TAG.0\\\"/g\" installer/wix/Product.wxs\n  - wixl -v installer/wix/Product.wxs -o ./Output/MyApp.msi\n```\n\n### Code Signing\n\n#### Inno Setup Code Signing\n\n```yaml\ncreate_inno_installer:\n  # ... previous configuration ...\n  before_script:\n    # ... previous before_script commands ...\n    - mkdir -p /certs\n    - echo \"$CODE_SIGNING_CERT\" | base64 -d \u003e /certs/certificate.pfx\n  script:\n    # ... previous script commands ...\n    - cd /opt/innosetup\n    - wine ISCC.exe \"/SSigning=yes /F/certs/certificate.pfx /P$CODE_SIGNING_PASSWORD\" setup.iss\n```\n\n#### WiX Code Signing\n\nFor WiX, signing typically requires the Windows SignTool, which works best with a Windows runner:\n\n```yaml\ncreate_wix_installer_windows:\n  # ... previous configuration ...\n  script:\n    # ... build MSI ...\n    - '\u0026 \"C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.19041.0\\x64\\signtool.exe\" sign /f \"$env:CODE_SIGNING_CERT\" /p \"$env:CODE_SIGNING_PASSWORD\" /tr http://timestamp.digicert.com /td sha256 /fd sha256 \".\\Output\\MyApp.msi\"'\n```\n\n### Storing Build Artifacts\n\nConfigure your pipeline to store installers in GitLab's package registry:\n\n```yaml\ncreate_installer:\n  # ... previous configuration ...\n  script:\n    # ... previous script commands ...\n    - 'curl --header \"JOB-TOKEN: $CI_JOB_TOKEN\" --upload-file ./Output/*.exe \"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/my-app/${CI_COMMIT_TAG}/MyAppSetup.exe\"'\n```\n\nFor WiX-generated MSI files:\n\n```yaml\nscript:\n  # ... previous script commands ...\n  - 'curl --header \"JOB-TOKEN: $CI_JOB_TOKEN\" --upload-file ./Output/*.msi \"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/my-app/${CI_COMMIT_TAG}/MyApp.msi\"'\n```\n\n## Dealing with Complex Dependencies\n\nBoth example installer scripts you provided include large numbers of dependencies. Here are strategies to manage them:\n\n### For Inno Setup\n\nWhen your application has many DLLs (like in your example), streamline the `[Files]` section with wildcard patterns:\n\n```\n[Files]\n; Main executable and config files\nSource: \"publish\\*.exe\"; DestDir: \"{app}\"; Flags: ignoreversion\nSource: \"publish\\*.dll\"; DestDir: \"{app}\"; Flags: ignoreversion\nSource: \"publish\\*.config\"; DestDir: \"{app}\"; Flags: ignoreversion\nSource: \"publish\\*.json\"; DestDir: \"{app}\"; Flags: ignoreversion\nSource: \"publish\\*.pdb\"; DestDir: \"{app}\"; Flags: ignoreversion\n; Include all subdirectories\nSource: \"publish\\**\"; DestDir: \"{app}\"; Flags: ignoreversion recursesubdirs\n```\n\nOr generate the file list programmatically in your CI/CD pipeline:\n\n```yaml\nscript:\n  - echo \"[Files]\" \u003e file_list.iss\n  - find ./publish -type f -exec echo \"Source: \\\"{}\\\" ; DestDir: \\\"{app}\\\\$(dirname {} | sed 's/\\.\\\\/publish\\\\///')\\\"; Flags: ignoreversion\" \\; \u003e\u003e file_list.iss\n  - cat file_list.iss \u003e\u003e /opt/innosetup/setup.iss\n  - cd /opt/innosetup\n  - wine ISCC.exe setup.iss\n```\n\n### For WiX\n\nWhen using WiX with many files (like in your example), you can:\n\n1. Use a heat.exe command to automatically generate component lists:\n\n```yaml\nscript:\n  - .\\WiX.*\\tools\\heat.exe dir publish -cg ProductComponents -dr INSTALLFOLDER -ke -srd -gg -sfrag -template fragment -out Components.wxs\n  - .\\WiX.*\\tools\\candle.exe -ext WixUIExtension installer/wix/Product.wxs Components.wxs\n  - .\\WiX.*\\tools\\light.exe -ext WixUIExtension Product.wixobj Components.wixobj -out .\\Output\\MyApp.msi\n```\n\n2. For Linux-based CI/CD with `wixl`, you can generate components with a script:\n\n```yaml\nscript:\n  - mkdir -p ./Output\n  - cp installer/wix/Product.wxs ./Product.wxs\n  - echo \"\u003cWix xmlns=\\\"http://schemas.microsoft.com/wix/2006/wi\\\"\u003e\u003cFragment\u003e\u003cComponentGroup Id=\\\"ProductComponents\\\" Directory=\\\"INSTALLFOLDER\\\"\u003e\" \u003e Components.wxs\n  - find ./publish -type f | while read file; do\n      guid=$(uuidgen);\n      id=$(basename \"$file\" | sed 's/[^a-zA-Z0-9]//g');\n      echo \"\u003cComponent Id=\\\"$id\\\" Guid=\\\"$guid\\\" Win64=\\\"yes\\\"\u003e\u003cFile Id=\\\"${id}File\\\" Name=\\\"$(basename \"$file\")\\\" DiskId=\\\"1\\\" Source=\\\"$file\\\" KeyPath=\\\"yes\\\" /\u003e\u003c/Component\u003e\" \u003e\u003e Components.wxs;\n    done\n  - echo \"\u003c/ComponentGroup\u003e\u003c/Fragment\u003e\u003c/Wix\u003e\" \u003e\u003e Components.wxs\n  - wixl -v Product.wxs Components.wxs -o ./Output/MyApp.msi\n```\n\n## Troubleshooting\n\n- **Inno Setup Compilation Issues**: \n  - Running Inno Setup through Wine may have some limitations\n  - Make sure paths in your Inno Setup script are relative to the /opt/innosetup directory\n  - Test with a simplified script first to identify compatibility issues\n\n- **WiX Compilation Issues**:\n  - When using `wixl` on Linux, some Windows-specific features may not be supported\n  - GUIDs need to be generated for components and products\n  - Path separators should be consistent with the platform\n\n- **Path Issues**: \n  - Use forward slashes in scripts when running on Linux\n  - Use relative paths instead of absolute paths (like `C:\\Users\\...`)\n  - For absolute paths in Windows runners, use variables like `$(var.ProjectDir)`\n\n- **Mono Compatibility**:\n  - Some .NET features might not be fully supported in Mono, test thoroughly\n  - For .NET Core or .NET 5+ projects, use the .NET SDK Docker images\n\n## Resources\n\n- [Inno Setup Documentation](https://jrsoftware.org/ishelp/)\n- [WiX Toolset Documentation](https://wixtoolset.org/documentation/)\n- [GitLab CI/CD Documentation](https://docs.gitlab.com/ee/ci/)\n- [WiX Toolset on Linux (wixl)](https://gitlab.gnome.org/GNOME/msitools)\n- [innoextract](https://github.com/dscharrer/innoextract)\n- [Wine HQ](https://www.winehq.org/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdylanparsons%2Fdotnet-installer-cicd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdylanparsons%2Fdotnet-installer-cicd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdylanparsons%2Fdotnet-installer-cicd/lists"}