diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 0000000..23b94ca --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,50 @@ +#---------------------------------# +# Build Image # +#---------------------------------# +image: Visual Studio 2022 + +#---------------------------------# +# Build Script # +#---------------------------------# +build_script: + - ps: .\build.ps1 -Target AppVeyor + +#---------------------------------# +# Tests +#---------------------------------# +test: off + +#---------------------------------# +# Pull Requests # +#---------------------------------# +pull_requests: + do_not_increment_build_number: true + +#---------------------------------# +# General # +#---------------------------------# +skip_branch_with_pr: true + +#---------------------------------# +# Branches to build # +#---------------------------------# +branches: + # Whitelist + only: + - develop + - master + - /release/.*/ + - /hotfix/.*/ + +#---------------------------------# +# Build Cache # +#---------------------------------# +cache: +- tools -> recipe.cake, tools/packages.config + +#---------------------------------# +# Skip builds for doc changes # +#---------------------------------# +skip_commits: + # Regex for matching commit message + message: /(doc).*/ diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1172014 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,23 @@ +; This file is for unifying the coding style for different editors and IDEs. +; More information at http://EditorConfig.org + +root = true + +[*] +end_of_line = CRLF + +[*.ps1] +indent_style = space +indent_size = 4 + +[*.cs] +indent_style = space +indent_size = 4 + +[*.cake] +indent_style = space +indent_size = 4 + +[*.js] +indent_style = tab +indent_size = 2 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.github/CODEOFCONDUCT.md b/.github/CODEOFCONDUCT.md new file mode 100644 index 0000000..66f199c --- /dev/null +++ b/.github/CODEOFCONDUCT.md @@ -0,0 +1,24 @@ +# Contributor Code of Conduct + +As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. + +We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery +- Personal attacks +- Trolling or insulting/derogatory comments +- Public or private harassment +- Publishing other's private information, such as physical or electronic addresses, without explicit permission +- Other unethical or unprofessional conduct + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at [abuse@gep13.co.uk](mailto:abuse@gep13.co.uk). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident. + +This Code of Conduct is adapted from the Contributor Covenant, version 1.3.0, available from http://contributor-covenant.org/version/1/3/0/ diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..adb265d --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,51 @@ +# How to contribute +Contributions to Cake.LibMan are highly encouraged and desired. Below are some guidelines that will help make the process as smooth as possible. + +# Getting Started +* Make sure you have a [GitHub account](https://github.com/signup/free) +* Submit a new issue, assuming one does not already exist. + * Clearly describe the issue including steps to reproduce when it is a bug. + * Make sure you fill in the earliest version that you know has the issue. +* Fork the repository on GitHub + +# Suggesting Enhancements +We want to know what you think is missing from Cake.LibMan and how it can be made better. +* When submitting an issue for an enhancement, please be as clear as possible about why you think the enhancement is needed and what the benefit of +it would be. + +# Making Changes +* From your fork of the repository, create a topic branch where work on your change will take place. +* To quickly create a topic branch based on develop; `git checkout -b my_contribution develop`. Please avoid working directly on the `develop` or `master` branch. +* Make commits of logical units. +* Check for unnecessary whitespace with `git diff --check` before committing. +* Please follow the prevailing code conventions in the repository. Differences in style make the code harder to understand for everyone. +* Make sure your commit messages are in the proper format. +```` + Add more cowbell to Get-Something + + The functionaly of Get-Something would be greatly improved if there was a little + more 'pizzazz' added to it. I propose a cowbell. Adding more cowbell has been + shown in studies to both increase one's mojo, and cement one's status + as a rock legend. +```` + +* Make sure you have added all the necessary unit tests for your changes. +* Run _all_ unit tests to assure nothing else was accidentally broken. + +# Documentation +We are infallible and as such the documenation needs no corectoin. In the highly +unlikely event that that is _not_ the case, commits to update or add documentation +are highly apprecaited. + +# Submitting Changes +* Push your changes to a topic branch in your fork of the repository. +* Submit a pull request to the main repository. +* Once the pull request has been reviewed and accepted, it will be merged with the master branch. +* Celebrate + +# Additional Resources +* [General GitHub documentation](https://help.github.com/) +* [GitHub forking documentation](https://guides.github.com/activities/forking/) +* [GitHub pull request documentation](https://help.github.com/send-pull-requests/) +* [GitHub Flow guide](https://guides.github.com/introduction/flow/) +* [GitHub's guide to contributing to open source projects](https://guides.github.com/activities/contributing-to-open-source/) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..8a48a49 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,30 @@ + + +## Expected Behavior + + + +## Current Behavior + + + +## Possible Solution + + + +## Steps to Reproduce (for bugs) + + +1. +2. +3. +4. + +## Context + + + +## Your Environment + +* Addin version used: +* Cake version used: diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..fab5004 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,36 @@ + + +## Description + + +## Related Issue + + + + + +## Motivation and Context + + +## How Has This Been Tested? + + + + +## Screenshots (if appropriate): + +## Types of changes + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to change) + +## Checklist: + + +- [ ] My code follows the code style of this project. +- [ ] My change requires a change to the documentation. +- [ ] I have updated the documentation accordingly. +- [ ] I have read the **CONTRIBUTING** document. +- [ ] I have added tests to cover my changes. +- [ ] All new and existing tests passed. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a9e78cf --- /dev/null +++ b/.gitignore @@ -0,0 +1,279 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Typescript v1 declaration files +typings/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +tools/** +!tools/packages.config +BuildArtifacts/ \ No newline at end of file diff --git a/GitReleaseManager.yaml b/GitReleaseManager.yaml new file mode 100644 index 0000000..721c1ba --- /dev/null +++ b/GitReleaseManager.yaml @@ -0,0 +1,12 @@ +issue-labels-include: +- Breaking change +- Feature +- Bug +- Improvement +- Documentation +issue-labels-exclude: +- Build +issue-labels-alias: + - name: Documentation + header: Documentation + plural: Documentation \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..50e9490 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2022 Cake Contributions Organization + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d983043 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +# Cake.CodeQL +CodeQL Scanning from GitHub is the analysis engine used by developers to automate security checks, and by security researchers to perform variant analysis. + +This plugin is a set of Cake aliases for [GitHub CodeQL CLI](https://docs.github.com/en/code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system/about-codeql-code-scanning-in-your-ci-system) (.NET Core or .NET6) used for scanning code hosted GitHub or GitHub Enterprise when GitHub Actions is not an option. + +> :exclamation: Please read the [GitHub CodeQL Terms and Conditions](https://github.com/github/codeql-cli-binaries/blob/main/LICENSE.md) before considering using this plugin. + +## Prerequisites + - [CodeQL CLI installed on CI agent host machine](https://docs.github.com/en/code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system/installing-codeql-cli-in-your-ci-system) + - Compliance with [GitHub CodeQL Terms and Conditions](https://github.com/github/codeql-cli-binaries/blob/main/LICENSE.md) + +## Using Cake Projects + +### Cake Script +```csharp +#addin "nuget:?package=Cake.CodeQL" +``` +### Project +```xml + +``` + +## Discussion + +If you have questions, search for an existing one, or create a new discussion on the Cake GitHub repository, using the `extension-q-a` category. + +[![Join in the discussion on the Cake repository](https://img.shields.io/badge/GitHub-Discussions-green?logo=github)](https://github.com/cake-build/cake/discussions) + +## License (this plugin only) + +[![License](http://img.shields.io/:license-mit-blue.svg)](http://cake-contrib.mit-license.org) \ No newline at end of file diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..4514a51 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,256 @@ +########################################################################## +# This is the Cake bootstrapper script for PowerShell. +# This file was downloaded from https://github.com/cake-build/resources +# Feel free to change this file to fit your needs. +########################################################################## + +<# + +.SYNOPSIS +This is a Powershell script to bootstrap a Cake build. + +.DESCRIPTION +This Powershell script will download NuGet if missing, restore NuGet tools (including Cake) +and execute your Cake build script with the parameters you provide. + +.PARAMETER Script +The build script to execute. +.PARAMETER Target +The build script target to run. +.PARAMETER Configuration +The build configuration to use. +.PARAMETER Verbosity +Specifies the amount of information to be displayed. +.PARAMETER ShowDescription +Shows description about tasks. +.PARAMETER DryRun +Performs a dry run. +.PARAMETER SkipToolPackageRestore +Skips restoring of packages. +.PARAMETER ScriptArgs +Remaining arguments are added here. + +.LINK +https://cakebuild.net + +#> + +[CmdletBinding()] +Param( + [string]$Script = "recipe.cake", + [string]$Target, + [string]$Configuration, + [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")] + [string]$Verbosity, + [switch]$ShowDescription, + [Alias("WhatIf", "Noop")] + [switch]$DryRun, + [switch]$SkipToolPackageRestore, + [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] + [string[]]$ScriptArgs +) + +# Attempt to set highest encryption available for SecurityProtocol. +# PowerShell will not set this by default (until maybe .NET 4.6.x). This +# will typically produce a message for PowerShell v2 (just an info +# message though) +try { + # Set TLS 1.2 (3072), then TLS 1.1 (768), then TLS 1.0 (192), finally SSL 3.0 (48) + # Use integers because the enumeration values for TLS 1.2 and TLS 1.1 won't + # exist in .NET 4.0, even though they are addressable if .NET 4.5+ is + # installed (.NET 4.5 is an in-place upgrade). + # PowerShell Core already has support for TLS 1.2 so we can skip this if running in that. + if (-not $IsCoreCLR) { + [System.Net.ServicePointManager]::SecurityProtocol = 3072 -bor 768 -bor 192 -bor 48 + } + } catch { + Write-Output 'Unable to set PowerShell to use TLS 1.2 and TLS 1.1 due to old .NET Framework installed. If you see underlying connection closed or trust errors, you may need to upgrade to .NET Framework 4.5+ and PowerShell v3' + } + +[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null +function MD5HashFile([string] $filePath) +{ + if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf)) + { + return $null + } + + [System.IO.Stream] $file = $null; + [System.Security.Cryptography.MD5] $md5 = $null; + try + { + $md5 = [System.Security.Cryptography.MD5]::Create() + $file = [System.IO.File]::OpenRead($filePath) + return [System.BitConverter]::ToString($md5.ComputeHash($file)) + } + finally + { + if ($file -ne $null) + { + $file.Dispose() + } + } +} + +function GetProxyEnabledWebClient +{ + $wc = New-Object System.Net.WebClient + $proxy = [System.Net.WebRequest]::GetSystemWebProxy() + $proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials + $wc.Proxy = $proxy + return $wc +} + +Write-Host "Preparing to run build script..." + +if(!$PSScriptRoot){ + $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent +} + +$TOOLS_DIR = Join-Path $PSScriptRoot "tools" +$ADDINS_DIR = Join-Path $TOOLS_DIR "Addins" +$MODULES_DIR = Join-Path $TOOLS_DIR "Modules" +$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe" +$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe" +$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" +$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config" +$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum" +$ADDINS_PACKAGES_CONFIG = Join-Path $ADDINS_DIR "packages.config" +$MODULES_PACKAGES_CONFIG = Join-Path $MODULES_DIR "packages.config" + +# Make sure tools folder exists +if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) { + Write-Verbose -Message "Creating tools directory..." + New-Item -Path $TOOLS_DIR -Type Directory | Out-Null +} + +# Make sure that packages.config exist. +if (!(Test-Path $PACKAGES_CONFIG)) { + Write-Verbose -Message "Downloading packages.config..." + try { + $wc = GetProxyEnabledWebClient + $wc.DownloadFile("https://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) + } catch { + Throw "Could not download packages.config." + } +} + +# Try find NuGet.exe in path if not exists +if (!(Test-Path $NUGET_EXE)) { + Write-Verbose -Message "Trying to find nuget.exe in PATH..." + $existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_ -PathType Container) } + $NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1 + if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) { + Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)." + $NUGET_EXE = $NUGET_EXE_IN_PATH.FullName + } +} + +# Try download NuGet.exe if not exists +if (!(Test-Path $NUGET_EXE)) { + Write-Verbose -Message "Downloading NuGet.exe..." + try { + $wc = GetProxyEnabledWebClient + $wc.DownloadFile($NUGET_URL, $NUGET_EXE) + } catch { + Throw "Could not download NuGet.exe." + } +} + +# Save nuget.exe path to environment to be available to child processed +$env:NUGET_EXE = $NUGET_EXE +$env:NUGET_EXE_INVOCATION = if ($IsLinux -or $IsMacOS) { + "mono `"$NUGET_EXE`"" +} else { + "`"$NUGET_EXE`"" +} + +# Restore tools from NuGet? +if(-Not $SkipToolPackageRestore.IsPresent) { + Push-Location + Set-Location $TOOLS_DIR + + # Check for changes in packages.config and remove installed tools if true. + [string] $md5Hash = MD5HashFile $PACKAGES_CONFIG + if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or + ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) { + Write-Verbose -Message "Missing or changed package.config hash..." + Get-ChildItem -Exclude packages.config,nuget.exe,Cake.Bakery | + Remove-Item -Recurse + } + + Write-Verbose -Message "Restoring tools from NuGet..." + + $NuGetOutput = Invoke-Expression "& $env:NUGET_EXE_INVOCATION install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`"" + + if ($LASTEXITCODE -ne 0) { + Throw "An error occurred while restoring NuGet tools." + } + else + { + $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII" + } + Write-Verbose -Message ($NuGetOutput | Out-String) + + Pop-Location +} + +# Restore addins from NuGet +if (Test-Path $ADDINS_PACKAGES_CONFIG) { + Push-Location + Set-Location $ADDINS_DIR + + Write-Verbose -Message "Restoring addins from NuGet..." + $NuGetOutput = Invoke-Expression "& $env:NUGET_EXE_INVOCATION install -ExcludeVersion -OutputDirectory `"$ADDINS_DIR`"" + + if ($LASTEXITCODE -ne 0) { + Throw "An error occurred while restoring NuGet addins." + } + + Write-Verbose -Message ($NuGetOutput | Out-String) + + Pop-Location +} + +# Restore modules from NuGet +if (Test-Path $MODULES_PACKAGES_CONFIG) { + Push-Location + Set-Location $MODULES_DIR + + Write-Verbose -Message "Restoring modules from NuGet..." + $NuGetOutput = Invoke-Expression "& $env:NUGET_EXE_INVOCATION install -ExcludeVersion -OutputDirectory `"$MODULES_DIR`"" + + if ($LASTEXITCODE -ne 0) { + Throw "An error occurred while restoring NuGet modules." + } + + Write-Verbose -Message ($NuGetOutput | Out-String) + + Pop-Location +} + +# Make sure that Cake has been installed. +if (!(Test-Path $CAKE_EXE)) { + Throw "Could not find Cake.exe at $CAKE_EXE" +} + +$CAKE_EXE_INVOCATION = if ($IsLinux -or $IsMacOS) { + "mono `"$CAKE_EXE`"" +} else { + "`"$CAKE_EXE`"" +} + + +# Build Cake arguments +$cakeArguments = @("$Script"); +if ($Target) { $cakeArguments += "-target=$Target" } +if ($Configuration) { $cakeArguments += "-configuration=$Configuration" } +if ($Verbosity) { $cakeArguments += "-verbosity=$Verbosity" } +if ($ShowDescription) { $cakeArguments += "-showdescription" } +if ($DryRun) { $cakeArguments += "-dryrun" } +$cakeArguments += $ScriptArgs + +# Start Cake +Write-Host "Running build script..." +Invoke-Expression "& $CAKE_EXE_INVOCATION $($cakeArguments -join " ")" +exit $LASTEXITCODE diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..7fc4599 --- /dev/null +++ b/build.sh @@ -0,0 +1,117 @@ +#!/usr/bin/env bash + +########################################################################## +# This is the Cake bootstrapper script for Linux and OS X. +# This file was downloaded from https://github.com/cake-build/resources +# Feel free to change this file to fit your needs. +########################################################################## + +# Define directories. +SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +TOOLS_DIR=$SCRIPT_DIR/tools +ADDINS_DIR=$TOOLS_DIR/Addins +MODULES_DIR=$TOOLS_DIR/Modules +NUGET_EXE=$TOOLS_DIR/nuget.exe +CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe +PACKAGES_CONFIG=$TOOLS_DIR/packages.config +PACKAGES_CONFIG_MD5=$TOOLS_DIR/packages.config.md5sum +ADDINS_PACKAGES_CONFIG=$ADDINS_DIR/packages.config +MODULES_PACKAGES_CONFIG=$MODULES_DIR/packages.config + +# Define md5sum or md5 depending on Linux/OSX +MD5_EXE= +if [[ "$(uname -s)" == "Darwin" ]]; then + MD5_EXE="md5 -r" +else + MD5_EXE="md5sum" +fi + +# Define default arguments. +SCRIPT="recipe.cake" +CAKE_ARGUMENTS=() + +# Parse arguments. +for i in "$@"; do + case $1 in + -s|--script) SCRIPT="$2"; shift ;; + --) shift; CAKE_ARGUMENTS+=("$@"); break ;; + *) CAKE_ARGUMENTS+=("$1") ;; + esac + shift +done + +# Make sure the tools folder exist. +if [ ! -d "$TOOLS_DIR" ]; then + mkdir "$TOOLS_DIR" +fi + +# Make sure that packages.config exist. +if [ ! -f "$TOOLS_DIR/packages.config" ]; then + echo "Downloading packages.config..." + curl -Lsfo "$TOOLS_DIR/packages.config" https://cakebuild.net/download/bootstrapper/packages + if [ $? -ne 0 ]; then + echo "An error occurred while downloading packages.config." + exit 1 + fi +fi + +# Download NuGet if it does not exist. +if [ ! -f "$NUGET_EXE" ]; then + echo "Downloading NuGet..." + curl -Lsfo "$NUGET_EXE" https://dist.nuget.org/win-x86-commandline/latest/nuget.exe + if [ $? -ne 0 ]; then + echo "An error occurred while downloading nuget.exe." + exit 1 + fi +fi + +# Restore tools from NuGet. +pushd "$TOOLS_DIR" >/dev/null +if [ ! -f "$PACKAGES_CONFIG_MD5" ] || [ "$( cat "$PACKAGES_CONFIG_MD5" | sed 's/\r$//' )" != "$( $MD5_EXE "$PACKAGES_CONFIG" | awk '{ print $1 }' )" ]; then + find . -type d ! -name . ! -name 'Cake.Bakery' | xargs rm -rf +fi + +mono "$NUGET_EXE" install -ExcludeVersion +if [ $? -ne 0 ]; then + echo "Could not restore NuGet tools." + exit 1 +fi + +$MD5_EXE "$PACKAGES_CONFIG" | awk '{ print $1 }' >| "$PACKAGES_CONFIG_MD5" + +popd >/dev/null + +# Restore addins from NuGet. +if [ -f "$ADDINS_PACKAGES_CONFIG" ]; then + pushd "$ADDINS_DIR" >/dev/null + + mono "$NUGET_EXE" install -ExcludeVersion + if [ $? -ne 0 ]; then + echo "Could not restore NuGet addins." + exit 1 + fi + + popd >/dev/null +fi + +# Restore modules from NuGet. +if [ -f "$MODULES_PACKAGES_CONFIG" ]; then + pushd "$MODULES_DIR" >/dev/null + + mono "$NUGET_EXE" install -ExcludeVersion + if [ $? -ne 0 ]; then + echo "Could not restore NuGet modules." + exit 1 + fi + + popd >/dev/null +fi + +# Make sure that Cake has been installed. +if [ ! -f "$CAKE_EXE" ]; then + echo "Could not find Cake.exe at '$CAKE_EXE'." + exit 1 +fi + +# Start Cake +exec mono "$CAKE_EXE" $SCRIPT "${CAKE_ARGUMENTS[@]}" diff --git a/recipe.cake b/recipe.cake new file mode 100644 index 0000000..bf115f2 --- /dev/null +++ b/recipe.cake @@ -0,0 +1,29 @@ +#load nuget:?package=Cake.Recipe&version=1.0.0 + +Environment.SetVariableNames(); + +BuildParameters.SetParameters( + context: Context, + buildSystem: BuildSystem, + sourceDirectoryPath: "./src", + title: "Cake.CodeQL", + repositoryOwner: "louisfischer", + repositoryName: "Cake.CodeQL", + appVeyorAccountName: "louisfischer", + shouldRunDupFinder: false, + shouldRunInspectCode: false, + shouldRunCodecov: false, + shouldDeployGraphDocumentation: false, + shouldRunGitVersion: true, + shouldRunDotNetCorePack: true); + +BuildParameters.PrintParameters(Context); + +ToolSettings.SetToolSettings( + context: Context, + dupFinderExcludePattern: new string[] { BuildParameters.RootDirectoryPath + "/src/Cake.CodeQL.Tests/**/*.cs" }, + testCoverageFilter: "+[*]* -[xunit.*]* -[Cake.Core]* -[Cake.Testing]* -[*.Tests]* -[Shouldly]*", + testCoverageExcludeByAttribute: "*.ExcludeFromCodeCoverage*", + testCoverageExcludeByFile: "*/*Designer.cs;*/*.g.cs;*/*.g.i.cs"); + +Build.RunDotNetCore(); diff --git a/src/Cake.CodeQL.Tests/Cake.EntityFrameworkCore.Tests.csproj b/src/Cake.CodeQL.Tests/Cake.EntityFrameworkCore.Tests.csproj new file mode 100644 index 0000000..823eb3a --- /dev/null +++ b/src/Cake.CodeQL.Tests/Cake.EntityFrameworkCore.Tests.csproj @@ -0,0 +1,30 @@ + + + + net5.0 + + false + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/src/Cake.CodeQL.Tests/Extensions/ExceptionAssertExtensions.cs b/src/Cake.CodeQL.Tests/Extensions/ExceptionAssertExtensions.cs new file mode 100644 index 0000000..f6969c2 --- /dev/null +++ b/src/Cake.CodeQL.Tests/Extensions/ExceptionAssertExtensions.cs @@ -0,0 +1,24 @@ +namespace Cake.EntityFrameworkCore.Tests +{ + using System; + using Xunit; + + public static class ExceptionAssertExtensions + { + public static void IsArgumentException(this Exception exception, string parameterName) + { + Assert.IsType(exception); + Assert.Equal(parameterName, ((ArgumentException)exception).ParamName); + } + + public static void IsArgumentNullException(this Exception exception, string parameterName) + { + Assert.IsType(exception); + Assert.Equal(parameterName, ((ArgumentNullException)exception).ParamName); + } + + public static void IsNotSupportException(this Exception exception) => Assert.IsType(exception); + + public static void IsUriFormatException(this Exception exception) => Assert.IsType(exception); + } +} diff --git a/src/Cake.CodeQL.Tests/Fixtures/EfCoreDatabaseUpdaterFixture.cs b/src/Cake.CodeQL.Tests/Fixtures/EfCoreDatabaseUpdaterFixture.cs new file mode 100644 index 0000000..cbf7ca2 --- /dev/null +++ b/src/Cake.CodeQL.Tests/Fixtures/EfCoreDatabaseUpdaterFixture.cs @@ -0,0 +1,13 @@ +using Cake.EntityFrameworkCore.Database; + +namespace Cake.EntityFrameworkCore.Tests.Database +{ + internal sealed class EfCoreDatabaseUpdaterFixture : EfCoreToolFixture + { + protected override void RunTool() + { + var tool = new EfCoreDatabaseUpdater(FileSystem, Environment, ProcessRunner, Tools, Log); + tool.Update(Settings); + } + } +} diff --git a/src/Cake.CodeQL.Tests/Fixtures/EfCoreToolFixture.cs b/src/Cake.CodeQL.Tests/Fixtures/EfCoreToolFixture.cs new file mode 100644 index 0000000..725baef --- /dev/null +++ b/src/Cake.CodeQL.Tests/Fixtures/EfCoreToolFixture.cs @@ -0,0 +1,22 @@ +using Cake.Core.Diagnostics; +using Cake.Core.IO; +using Cake.Testing; +using Cake.Testing.Fixtures; + +namespace Cake.EntityFrameworkCore.Tests +{ + internal abstract class EfCoreToolFixture : ToolFixture + where TSettings : EfCoreToolSettings, new() + { + protected EfCoreToolFixture() + : base("dotnet.exe") + { + ProcessRunner.Process.SetStandardOutput(new string[] { }); + Log.Verbosity = Verbosity.Normal; + } + + protected override ToolFixtureResult CreateResult(FilePath path, ProcessSettings process) => new ToolFixtureResult(path, process); + + protected ICakeLog Log { get; } = new FakeLog(); + } +} diff --git a/src/Cake.CodeQL.Tests/Unit/EfCoreDatabaseUpdateSettingsExtensionsTests.cs b/src/Cake.CodeQL.Tests/Unit/EfCoreDatabaseUpdateSettingsExtensionsTests.cs new file mode 100644 index 0000000..fd8a2fc --- /dev/null +++ b/src/Cake.CodeQL.Tests/Unit/EfCoreDatabaseUpdateSettingsExtensionsTests.cs @@ -0,0 +1,25 @@ +using Cake.EntityFrameworkCore.Database; +using Shouldly; +using Xunit; + +namespace Cake.EntityFrameworkCore.Tests +{ + public sealed class EfCoreDatabaseUpdateSettingsExtensionsTests + { + public sealed class TheSetTargetMigration + { + [Fact] + public void Should_Set_Migrations() + { + // Given + var settings = new EfCoreDatabaseUpdateSettings(); + + // When + settings.SetTargetMigration(@"20201221_MyTable_Change"); + + // Then + settings.Migration.ShouldBe(@"20201221_MyTable_Change"); + } + } + } +} diff --git a/src/Cake.CodeQL.Tests/Unit/EfCoreDatabaseUpdaterTests.cs b/src/Cake.CodeQL.Tests/Unit/EfCoreDatabaseUpdaterTests.cs new file mode 100644 index 0000000..84623f4 --- /dev/null +++ b/src/Cake.CodeQL.Tests/Unit/EfCoreDatabaseUpdaterTests.cs @@ -0,0 +1,51 @@ +using Cake.Core.IO; +using System; +using Xunit; + +namespace Cake.EntityFrameworkCore.Tests.Database +{ + public sealed class EfCoreDatabaseUpdaterTests + { + public sealed class TheUpdateMethod + { + [Fact] + public void Should_Throw_If_Settings_Are_Null() + { + // Given + var fixture = new EfCoreDatabaseUpdaterFixture(); + fixture.Settings = null; + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + result.IsArgumentNullException("settings"); + } + + [Fact] + public void Should_Update() + { + // Given + var fixture = new EfCoreDatabaseUpdaterFixture(); + + fixture.Tools.RegisterFile("c:/myproject/tools/Microsoft.EntityFrameworkCore.Tools.5.0.4/netcoreapp2.0/any/ef.dll"); + + fixture.Settings.WorkingDirectory = "c:/myproject"; + fixture.Settings.DbContextClassName = "MyDbContext"; + fixture.Settings.MigrationsNamespace = "My.Demo.Migrations"; + fixture.Settings.MigrationDll = "MyNamespace.Migrations.dll"; + fixture.Settings.StartupDll = "MyNamespace.WebUI.dll"; + fixture.Settings.Verbose = true; + fixture.Settings.Version = true; + + // When + var result = fixture.Run(); + + // Then + var expected = $"exec --depsfile \"c:/myproject/MyNamespace.WebUI.deps.json\" --additionalprobingpath \"{DirectoryPath.FromString(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile))}/.nuget/packages\" --runtimeconfig \"c:/myproject/MyNamespace.Migrations.runtimeconfig.json\" \"c:/myproject/tools/Microsoft.EntityFrameworkCore.Tools.5.0.4/netcoreapp2.0/any/ef.dll\" database update --assembly \"c:/myproject/MyNamespace.Migrations.dll\" --startup-assembly \"c:/myproject/MyNamespace.WebUI.dll\" --project-dir \"c:/myproject\" --data-dir \"c:/myproject\" --context \"MyDbContext\" --root-namespace \"My.Demo.Migrations\" --verbose"; + + Assert.Equal(expected, result.Args); + } + } + } +} diff --git a/src/Cake.CodeQL.Tests/Unit/EfCoreSettingsExtensionsTests.cs b/src/Cake.CodeQL.Tests/Unit/EfCoreSettingsExtensionsTests.cs new file mode 100644 index 0000000..eb8e3b7 --- /dev/null +++ b/src/Cake.CodeQL.Tests/Unit/EfCoreSettingsExtensionsTests.cs @@ -0,0 +1,231 @@ +using Shouldly; +using Xunit; + +namespace Cake.EntityFrameworkCore.Tests +{ + public sealed class EfCoreToolSettingsExtensionsTests + { + public sealed class TheSetVerboseMethod + { + [Fact] + public void Should_Throw_If_Settings_Are_Null() + { + // Given + EfCoreToolSettings settings = null; + + // When + var result = Record.Exception(() => settings.SetVerbose()); + + // Then + result.IsArgumentNullException(nameof(settings)); + } + + [Fact] + public void Should_Set_Verbose_To_True() + { + // Given + var settings = new EfCoreToolSettings(); + + // When + settings.SetVerbose(); + + // Then + settings.Verbose.ShouldBeTrue(); + } + } + + public sealed class TheSetNoColorMethod + { + [Fact] + public void Should_Throw_If_Settings_Are_Null() + { + // Given + EfCoreToolSettings settings = null; + + // When + var result = Record.Exception(() => settings.SetNoColor()); + + // Then + result.IsArgumentNullException(nameof(settings)); + } + + [Fact] + public void Should_Set_NoColor_To_True() + { + // Given + var settings = new EfCoreToolSettings(); + + // When + settings.SetNoColor(); + + // Then + settings.NoColor.ShouldBeTrue(); + } + } + + public sealed class TheSetPrefixOutputMethod + { + [Fact] + public void Should_Throw_If_Settings_Are_Null() + { + // Given + EfCoreToolSettings settings = null; + + // When + var result = Record.Exception(() => settings.SetPrefixOutput()); + + // Then + result.IsArgumentNullException(nameof(settings)); + } + + [Fact] + public void Should_Set_PrefixOutput_To_True() + { + // Given + var settings = new EfCoreToolSettings(); + + // When + settings.SetPrefixOutput(); + + // Then + settings.PrefixOutput.ShouldBeTrue(); + } + } + + public sealed class TheSetVersionMethod + { + [Fact] + public void Should_Throw_If_Settings_Are_Null() + { + // Given + EfCoreToolSettings settings = null; + + // When + var result = Record.Exception(() => settings.SetVersion()); + + // Then + result.IsArgumentNullException(nameof(settings)); + } + + [Fact] + public void Should_Set_Version_To_True() + { + // Given + var settings = new EfCoreToolSettings(); + + // When + settings.SetVersion(); + + // Then + settings.Version.ShouldBeTrue(); + } + + } + + public sealed class TheFromPathMethod + { + [Fact] + public void Should_Throw_If_Settings_Are_Null() + { + // Given + EfCoreToolSettings settings = null; + + // When + var result = Record.Exception(() => settings.FromPath(@"c:\temp")); + + // Then + result.IsArgumentNullException(nameof(settings)); + } + + [Fact] + public void Should_Throw_If_Path_Is_Null() + { + // Given + var settings = new EfCoreToolSettings(); + + // When + var result = Record.Exception(() => settings.FromPath(null)); + + // Then + result.IsArgumentNullException("path"); + } + + [Fact] + public void Should_Set_WorkingDirectory() + { + // Given + var settings = new EfCoreToolSettings(); + + // When + settings.FromPath(@"c:\temp"); + + // Then + settings.WorkingDirectory.ToString().ShouldBe(@"c:/temp"); + } + } + + public sealed class TheSetMigrationsDll + { + [Fact] + public void Should_Set_MigrationsDll() + { + // Given + var settings = new EfCoreToolSettings(); + + // When + settings.SetMigrationsDll(@"MyMigrations.dll"); + + // Then + settings.MigrationDll.ShouldBe(@"MyMigrations.dll"); + } + } + + public sealed class TheSetMigrationsNamespace + { + [Fact] + public void Should_Set_MigrationsNamespace() + { + // Given + var settings = new EfCoreToolSettings(); + + // When + settings.SetMigrationsNamespace("My.Demo.Migrations"); + + // Then + settings.MigrationsNamespace.ShouldBe("My.Demo.Migrations"); + } + } + + public sealed class TheSetStartupDll + { + [Fact] + public void Should_Set_StartupDll() + { + // Given + var settings = new EfCoreToolSettings(); + + // When + settings.SetStartupDll("MyWebUI.dll"); + + // Then + settings.StartupDll.ShouldBe("MyWebUI.dll"); + } + } + + public sealed class TheSetDbContextClass + { + [Fact] + public void Should_Set_DbContextClass() + { + // Given + var settings = new EfCoreToolSettings(); + + // When + settings.SetDbContextClass("MyDbContext"); + + // Then + settings.DbContextClassName.ShouldBe("MyDbContext"); + } + } + } +} diff --git a/src/Cake.CodeQL.sln b/src/Cake.CodeQL.sln new file mode 100644 index 0000000..41641af --- /dev/null +++ b/src/Cake.CodeQL.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32819.101 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cake.CodeQL", "Cake.CodeQL\Cake.CodeQL.csproj", "{F04A19AD-4F4C-488C-9D3C-022032FC2357}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{849370F8-B133-41C1-A0BF-B4027D16AFC0}" + ProjectSection(SolutionItems) = preProject + build.cake = build.cake + ..\README.md = ..\README.md + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F04A19AD-4F4C-488C-9D3C-022032FC2357}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F04A19AD-4F4C-488C-9D3C-022032FC2357}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F04A19AD-4F4C-488C-9D3C-022032FC2357}.Debug|x64.ActiveCfg = Debug|Any CPU + {F04A19AD-4F4C-488C-9D3C-022032FC2357}.Debug|x64.Build.0 = Debug|Any CPU + {F04A19AD-4F4C-488C-9D3C-022032FC2357}.Debug|x86.ActiveCfg = Debug|Any CPU + {F04A19AD-4F4C-488C-9D3C-022032FC2357}.Debug|x86.Build.0 = Debug|Any CPU + {F04A19AD-4F4C-488C-9D3C-022032FC2357}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F04A19AD-4F4C-488C-9D3C-022032FC2357}.Release|Any CPU.Build.0 = Release|Any CPU + {F04A19AD-4F4C-488C-9D3C-022032FC2357}.Release|x64.ActiveCfg = Release|Any CPU + {F04A19AD-4F4C-488C-9D3C-022032FC2357}.Release|x64.Build.0 = Release|Any CPU + {F04A19AD-4F4C-488C-9D3C-022032FC2357}.Release|x86.ActiveCfg = Release|Any CPU + {F04A19AD-4F4C-488C-9D3C-022032FC2357}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7D15F748-7D66-45A7-A2C5-3119C8652D48} + EndGlobalSection +EndGlobal diff --git a/src/Cake.CodeQL/Cake.CodeQL.csproj b/src/Cake.CodeQL/Cake.CodeQL.csproj new file mode 100644 index 0000000..87881bb --- /dev/null +++ b/src/Cake.CodeQL/Cake.CodeQL.csproj @@ -0,0 +1,46 @@ + + + Cake.CodeQL + netcoreapp3.1;net6.0 + true + true + true + 0 + bin\$(Configuration)\net6.0\$(AssemblyName).xml + true + full + true + false + + + 2.0.0 + Cake.CodeQL + Cake.CodeQL is a set of Cake aliases that use CodeQL Scanning code hosted GitHub or GitHub Enterprise when GitHub Actions is not an option. + louisfischer, Cake-Contrib + Cake-Contrib + icon.png + MIT + https://github.com/louisfischer/Cake.EntityFrameworkCore.git + Cake;codeql;scan;scanning; + $(PackageProjectUrl) + git + Copyright © 2022 - $([System.DateTime]::Now.Year) Cake Contributions Organization + $(TargetsForTfmSpecificContentInPackage);PackBuildOutputs + 2.0.0.0 + 2.0.0.0 + + + + + + + + + + + + lib\$(TargetFramework)\ + + + + diff --git a/src/Cake.CodeQL/Database/EFCoreDatabaseUpdateAliases.cs b/src/Cake.CodeQL/Database/EFCoreDatabaseUpdateAliases.cs new file mode 100644 index 0000000..9f12f7c --- /dev/null +++ b/src/Cake.CodeQL/Database/EFCoreDatabaseUpdateAliases.cs @@ -0,0 +1,95 @@ +using Cake.Core; +using Cake.Core.Annotations; +using Cake.EntityFrameworkCore; +using Cake.EntityFrameworkCore.Database; +using System; +using System.Runtime; + +namespace Cake.EntityFrameworkCore.Database +{ + /// + /// Entity Framework Core (ef.dll) Database Update aliases + /// + [CakeAliasCategory("EntityFrameworkCore")] + [CakeNamespaceImport("Cake.EntityFrameworkCore.Database")] + public static class EFCoreDatabaseUpdateAliases + { + /// + /// Applies any pending migrations to the database using the ef.dll migration tool. + /// + /// The context. + /// The settings configurator. + /// + /// Applies any pending migrations to the database using the ef.dll dotnet tool. ('dotnet ef database update') + /// + /// + /// { + /// settings + /// .FromPath(@"c:/myproject") + /// .SetDbContextClass("MyDbContext") + /// .SetMigrationsDll("MyMigrations.dll") + /// .SetMigrationsNamespace("My.Demo.Migrations") + /// .SetStartupDll("MyWebUI.dll") + /// .SetTargetMigration("20201221_MyTable_Change") + /// .SetVersion() + /// .SetNoColor() + /// .SetVerbose(); + /// }); + /// ]]> + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Database")] + public static void EfCoreDatabaseUpdate(this ICakeContext context, Action configurator) + { + if (context == null) + throw new ArgumentNullException(nameof(context)); + + if (configurator == null) + throw new ArgumentNullException(nameof(configurator)); + + var settings = new EfCoreDatabaseUpdateSettings(); + configurator(settings); + context.EfCoreDatabaseUpdate(settings); + } + + /// + /// Applies any pending migrations to the database using the ef.dll migration tool. + /// + /// The context. + /// The settings. + /// + /// Applies any pending migrations to the database using the ef.dll migration tool. ('dotnet ef database update') + /// + /// + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Database")] + public static void EfCoreDatabaseUpdate(this ICakeContext context, EfCoreDatabaseUpdateSettings settings) + { + if (context == null) + throw new ArgumentNullException(nameof(context)); + + if (settings == null) + throw new ArgumentNullException(nameof(settings)); + + EfCoreAddinInformation.LogVersionInformation(context.Log); + var tool = new EfCoreDatabaseUpdater(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools, context.Log); + tool.Update(settings); + } + } +} \ No newline at end of file diff --git a/src/Cake.CodeQL/Database/EfCoreDatabaseUpdateSettings.cs b/src/Cake.CodeQL/Database/EfCoreDatabaseUpdateSettings.cs new file mode 100644 index 0000000..ca98380 --- /dev/null +++ b/src/Cake.CodeQL/Database/EfCoreDatabaseUpdateSettings.cs @@ -0,0 +1,17 @@ +using Cake.Common.Tools.DotNetCore; +using Cake.Core; +using Cake.Core.IO; + +namespace Cake.EntityFrameworkCore.Database +{ + /// + /// Contains settings used by . + /// + public class EfCoreDatabaseUpdateSettings : EfCoreToolSettings + { + /// + /// The target migration. If '0', all migrations will be reverted. Defaults to the last migration. + /// + public string Migration { get; set; } + } +} diff --git a/src/Cake.CodeQL/Database/EfCoreDatabaseUpdateSettingsExtensions.cs b/src/Cake.CodeQL/Database/EfCoreDatabaseUpdateSettingsExtensions.cs new file mode 100644 index 0000000..af36324 --- /dev/null +++ b/src/Cake.CodeQL/Database/EfCoreDatabaseUpdateSettingsExtensions.cs @@ -0,0 +1,34 @@ +using Cake.Core; +using Cake.Core.Diagnostics; +using Cake.Core.IO; +using Cake.Core.Tooling; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Cake.EntityFrameworkCore.Database +{ + /// + /// Extensions for . + /// + public static class EfCoreDatabaseUpdateSettingsExtensions + { + /// + /// Sets a named target migration to migrate the database too. + /// + /// The settings. + /// The name of the migration to target + /// The instance with set to . + public static EfCoreDatabaseUpdateSettings SetTargetMigration(this EfCoreDatabaseUpdateSettings settings, string migration) + { + if (settings == null) + throw new ArgumentNullException(nameof(settings)); + + settings.Migration = migration; + + return settings; + } + } +} diff --git a/src/Cake.CodeQL/Database/EfCoreDatabaseUpdater.cs b/src/Cake.CodeQL/Database/EfCoreDatabaseUpdater.cs new file mode 100644 index 0000000..14283bf --- /dev/null +++ b/src/Cake.CodeQL/Database/EfCoreDatabaseUpdater.cs @@ -0,0 +1,57 @@ +using Cake.Common.Tools.DotNetCore; +using Cake.Core; +using Cake.Core.Diagnostics; +using Cake.Core.IO; +using Cake.Core.Tooling; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime; +using System.Text; +using System.Threading.Tasks; + +namespace Cake.EntityFrameworkCore.Database +{ + /// + /// .Net Ef Core Database Updater using Migrations + /// + public class EfCoreDatabaseUpdater : EfCoreTool + { + private readonly ICakeEnvironment _environment; + + /// + /// Initializes a new instance of the class. + /// + /// The file system. + /// The environment. + /// The process runner. + /// The tool locator. + public EfCoreDatabaseUpdater(IFileSystem fileSystem, ICakeEnvironment environment, IProcessRunner processRunner, IToolLocator tools, ICakeLog log) + : base(fileSystem, environment, processRunner, tools, log) + { } + + + /// + /// Updates the database to a specified migration. + /// + /// The target migration. If '0', all migrations will be reverted. Defaults to the last migration.. + /// The settings. + public void Update(EfCoreDatabaseUpdateSettings settings) + { + if (settings == null) + throw new ArgumentNullException(nameof(settings)); + + RunCommand(settings, GetArguments(settings)); + } + + protected override ProcessArgumentBuilder AppendToolArguments(ProcessArgumentBuilder builder, EfCoreDatabaseUpdateSettings settings) + { + builder.Append("database update"); + + if (!string.IsNullOrEmpty(settings.Migration)) + builder.Append(settings.Migration); + + return builder; + } + } +} \ No newline at end of file diff --git a/src/Cake.CodeQL/EfCoreAddinInformation.cs b/src/Cake.CodeQL/EfCoreAddinInformation.cs new file mode 100644 index 0000000..20632a2 --- /dev/null +++ b/src/Cake.CodeQL/EfCoreAddinInformation.cs @@ -0,0 +1,26 @@ +using Cake.Core.Diagnostics; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Cake.EntityFrameworkCore +{ + internal static class EfCoreAddinInformation + { + private static readonly string InformationalVersion = typeof(EfCoreAddinInformation).GetTypeInfo().Assembly.GetCustomAttribute()?.InformationalVersion; + private static readonly string AssemblyVersion = typeof(EfCoreAddinInformation).GetTypeInfo().Assembly.GetName().Version.ToString(); + private static readonly string AssemblyName = typeof(EfCoreAddinInformation).GetTypeInfo().Assembly.GetName().Name; + + /// + /// verbosely log addin version information + /// + /// + public static void LogVersionInformation(ICakeLog log) + { + log.Verbose(entry => entry("Using addin: {0} v{1} ({2})", AssemblyName, AssemblyVersion, InformationalVersion)); + } + } +} diff --git a/src/Cake.CodeQL/EfCoreTool.cs b/src/Cake.CodeQL/EfCoreTool.cs new file mode 100644 index 0000000..690067c --- /dev/null +++ b/src/Cake.CodeQL/EfCoreTool.cs @@ -0,0 +1,90 @@ +using Cake.Common.Tools.DotNetCore; +using Cake.Common.Tools.DotNetCore.Pack; +using Cake.Core; +using Cake.Core.Diagnostics; +using Cake.Core.IO; +using Cake.Core.Tooling; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Cake.EntityFrameworkCore +{ + /// + /// Base class for all efcore tools. + /// + /// The settings type. + public abstract class EfCoreTool : DotNetCoreTool + where TSettings : EfCoreToolSettings + { + protected readonly ICakeEnvironment _environment; + protected readonly ICakeLog _log; + private readonly IToolLocator _tools; + + /// + /// Initializes a new instance of the class. + /// + /// The file system. + /// The environment. + /// The process runner. + /// The tool locator. + protected EfCoreTool(IFileSystem fileSystem, ICakeEnvironment environment, IProcessRunner processRunner, IToolLocator tools, ICakeLog log) + : base(fileSystem, environment, processRunner, tools) + { + _environment = environment; + _log = log; + _tools = tools; + } + + /// + /// Adds specific tool commandline arguments. + /// + /// Process argument builder to update. + /// The settings. + /// Returns updated with common commandline arguments. + protected abstract ProcessArgumentBuilder AppendToolArguments(ProcessArgumentBuilder builder, TSettings settings); + + /// + /// Gets all the Arguments needed to run a ef command from a mgiration dll. + /// + /// The settings. + /// Returns updated with common commandline arguments. + protected ProcessArgumentBuilder GetArguments(TSettings settings) + { + var builder = base.CreateArgumentBuilder(settings); + + var migrationsDirectory = settings.WorkingDirectory.MakeAbsolute(_environment); + var migrationDllPath = settings.WorkingDirectory.CombineWithFilePath(settings.MigrationDll).MakeAbsolute(_environment); + var startupDllPath = settings.WorkingDirectory.CombineWithFilePath(settings.StartupDll).MakeAbsolute(_environment); + var runtimeConfigPath = settings.WorkingDirectory.CombineWithFilePath(System.IO.Path.GetFileNameWithoutExtension(settings.StartupDll)).AppendExtension(".runtimeconfig.json").MakeAbsolute(_environment).MakeAbsolute(_environment); + var depsJsonPath = settings.WorkingDirectory.CombineWithFilePath(System.IO.Path.GetFileNameWithoutExtension(settings.StartupDll)).AppendExtension(".deps.json").MakeAbsolute(_environment); + var pathToNuGetPackages = DirectoryPath.FromString(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)).Combine(".nuget/packages").MakeAbsolute(_environment); + var efDllPath = _tools.Resolve("ef.dll").MakeAbsolute(_environment); + + builder.Append("exec"); + builder.AppendSwitchQuoted("--depsfile", depsJsonPath.ToString()); + builder.AppendSwitchQuoted("--additionalprobingpath", pathToNuGetPackages.ToString()); + builder.AppendSwitchQuoted("--runtimeconfig", runtimeConfigPath.ToString()); + builder.AppendQuoted(efDllPath.ToString()); + + AppendToolArguments(builder, settings); + + builder.AppendSwitchQuoted("--assembly", migrationDllPath.ToString()); + builder.AppendSwitchQuoted("--startup-assembly", startupDllPath.ToString()); + builder.AppendSwitchQuoted("--project-dir", migrationsDirectory.ToString()); + builder.AppendSwitchQuoted("--data-dir", migrationsDirectory.ToString()); + builder.AppendSwitchQuoted("--context", settings.DbContextClassName); + + if (!string.IsNullOrWhiteSpace(settings.MigrationsNamespace)) + builder.AppendSwitchQuoted("--root-namespace", settings.MigrationsNamespace); + + if (settings.Verbose) + builder.Append("--verbose"); + + return builder; + + } + } +} \ No newline at end of file diff --git a/src/Cake.CodeQL/EfCoreToolSettings.cs b/src/Cake.CodeQL/EfCoreToolSettings.cs new file mode 100644 index 0000000..a06f633 --- /dev/null +++ b/src/Cake.CodeQL/EfCoreToolSettings.cs @@ -0,0 +1,63 @@ +using Cake.Common.Tools.DotNetCore; +using Cake.Common.Tools.DotNetCore.Tool; +using Cake.Core; +using Cake.Core.IO; +using Cake.Core.Tooling; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Cake.EntityFrameworkCore +{ + /// + /// Ef Core Tool Basic Settings + /// + public class EfCoreToolSettings : DotNetCoreSettings + { + /// + /// Filename of the DLL that contains your migrations. + /// + /// My.Demo123.Api.dll + public string MigrationDll { get; set; } + + /// + /// .NET namespace for the DbContext class. 'Benday.Demo123.Api.dll + /// + /// My.Demo123.Api + public string MigrationsNamespace { get; set; } + + /// + /// Filename of the DLL that is the startup DLL for this published application + /// + /// My.Demo123.WebUi.dll + public string StartupDll { get; set; } + + /// + /// Class name for the DbContext that controls the migrations to deploy + /// + /// MyDbContext + public string DbContextClassName { get; set; } + + /// + /// Gets or Sets whether to show Verbose output + /// + public bool Verbose { get; set; } + + /// + /// Gets or Sets whether to show the version of Entity Framework. + /// + public bool Version { get; set; } + + /// + /// Gets or Sets whether to colorize the output. + /// + public bool NoColor { get; set; } + + /// + /// Prefix output with level. + /// + public bool PrefixOutput { get; set; } + } +} diff --git a/src/Cake.CodeQL/EfCoreToolSettingsExtensions.cs b/src/Cake.CodeQL/EfCoreToolSettingsExtensions.cs new file mode 100644 index 0000000..b2f5451 --- /dev/null +++ b/src/Cake.CodeQL/EfCoreToolSettingsExtensions.cs @@ -0,0 +1,155 @@ +using Cake.Core; +using Cake.Core.Diagnostics; +using Cake.Core.IO; +using Cake.Core.Tooling; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Cake.EntityFrameworkCore +{ + /// + /// Extensions for . + /// + public static class EfCoreToolSettingsExtensions + { + /// + /// Sets the verbose output for Entity Framework output. (e.g. - Show verbose output). + /// + /// The settings. + /// The instance with set to true. + public static T SetVerbose(this T settings) + where T : EfCoreToolSettings + { + if (settings == null) + throw new ArgumentNullException(nameof(settings)); + + settings.Verbose = true; + + return settings; + } + + /// + /// Sets the no color output for Entity Framework output (e.g. - Don't colorize output). + /// + /// The settings. + /// The instance with set to true. + public static T SetNoColor(this T settings) + where T : EfCoreToolSettings + { + if (settings == null) + throw new ArgumentNullException(nameof(settings)); + + settings.NoColor = true; + + return settings; + } + + /// + /// Sets the Prefix Out with level for the ef.dll. (e.g. - Prefix output with level.). + /// + /// The settings. + /// The instance with set to true. + public static T SetPrefixOutput(this T settings) + where T : EfCoreToolSettings + { + if (settings == null) + throw new ArgumentNullException(nameof(settings)); + + settings.PrefixOutput = true; + + return settings; + } + + /// + /// Sets the to display version information in console output + /// + /// The settings. + /// The instance with set to true. + public static T SetVersion(this T settings) + where T : EfCoreToolSettings + { + if (settings == null) + throw new ArgumentNullException(nameof(settings)); + + settings.Version = true; + + return settings; + } + + /// + /// Sets the working directory which should be used to run the ef.dll command. + /// + /// The settings. + /// Working directory which should be used to run the ef.dll command. + /// The instance with set to . + public static T FromPath(this T settings, DirectoryPath path) + where T : EfCoreToolSettings + { + if (settings == null) + throw new ArgumentNullException(nameof(settings)); + + settings.WorkingDirectory = path ?? throw new ArgumentNullException(nameof(path)); + + return settings; + } + + /// + /// Sets the name of File of the DLL that contains your migrations + /// + /// The settings. + /// file name + /// The instance with + public static T SetMigrationsDll(this T settings, string fileName) + where T : EfCoreToolSettings + { + if (settings == null) throw new ArgumentNullException(nameof(settings)); + settings.MigrationDll = fileName ?? throw new ArgumentNullException(nameof(fileName)); + return settings; + } + + /// + /// Sets the migrations namespace that contains the DbContext + /// + /// The settings. + /// file name + /// The instance with set to . + public static T SetMigrationsNamespace(this T settings, string @namespace) + where T : EfCoreToolSettings + { + if (settings == null) throw new ArgumentNullException(nameof(settings)); + settings.MigrationsNamespace = @namespace ?? throw new ArgumentNullException(nameof(@namespace)); + return settings; + } + + /// + /// Sets the statup dll for the published application the publised application + /// + /// The settings. + /// file name. + /// The instance with set to . + public static T SetStartupDll(this T settings, string fileName) + where T : EfCoreToolSettings + { + if (settings == null) throw new ArgumentNullException(nameof(settings)); + settings.StartupDll = fileName ?? throw new ArgumentNullException(nameof(fileName)); + return settings; + } + + /// + /// Class name for the DbContext that controls the migrations to deploy + /// + /// The settings. + /// DbContext class name + /// The instance with set to . + public static T SetDbContextClass(this T settings, string name) + where T : EfCoreToolSettings + { + if (settings == null) throw new ArgumentNullException(nameof(settings)); + settings.DbContextClassName = name ?? throw new ArgumentNullException(nameof(name)); + return settings; + } + } +} diff --git a/src/Cake.CodeQL/Properties/InternalsVisibleInfo.cs b/src/Cake.CodeQL/Properties/InternalsVisibleInfo.cs new file mode 100644 index 0000000..3642492 --- /dev/null +++ b/src/Cake.CodeQL/Properties/InternalsVisibleInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Cake.EntityFrameworkCore.Tests")] \ No newline at end of file diff --git a/src/Cake.CodeQL/Properties/NamespaceDoc.cs b/src/Cake.CodeQL/Properties/NamespaceDoc.cs new file mode 100644 index 0000000..b378a82 --- /dev/null +++ b/src/Cake.CodeQL/Properties/NamespaceDoc.cs @@ -0,0 +1,22 @@ +using System.Runtime.CompilerServices; + +namespace Cake.EntityFrameworkCore +{ + /// + /// This namespace contain types used for operations using the EntityFrameworkCore tool wrapper. + /// + [CompilerGenerated] + internal class NamespaceDoc + { } +} + + +namespace Cake.EntityFrameworkCore.Database +{ + /// + /// This namespace contain types used for operations using the EntityFrameworkCore tool wrapper. + /// + [CompilerGenerated] + internal class NamespaceDoc + { } +} diff --git a/src/Cake.CodeQL/icon.png b/src/Cake.CodeQL/icon.png new file mode 100644 index 0000000..7524b13 Binary files /dev/null and b/src/Cake.CodeQL/icon.png differ diff --git a/src/build.cake b/src/build.cake new file mode 100644 index 0000000..32c50f8 --- /dev/null +++ b/src/build.cake @@ -0,0 +1,33 @@ +/////////////////////////////////////////////////////////////////////////////// +// ARGUMENTS +/////////////////////////////////////////////////////////////////////////////// + +var target = Argument("target", "Default"); +var configuration = Argument("configuration", "Release"); + +/////////////////////////////////////////////////////////////////////////////// +// SETUP / TEARDOWN +/////////////////////////////////////////////////////////////////////////////// + +Setup(ctx => +{ + // Executed BEFORE the first task. + Information("Running tasks..."); +}); + +Teardown(ctx => +{ + // Executed AFTER the last task. + Information("Finished running tasks."); +}); + +/////////////////////////////////////////////////////////////////////////////// +// TASKS +/////////////////////////////////////////////////////////////////////////////// + +Task("Default") +.Does(() => { + Information("Hello Cake!"); +}); + +RunTarget(target); \ No newline at end of file