Warning This is a test repository to play around with and perform the Validators Exercise with. For the real Validator and real contributions please use: https://github.com/SkylineCommunications/Skyline.DataMiner.CICD.Validators
In this tutorial, you will explore collaborative software development and DevOps with a focus on adding new checks to the validator (which is also incorporated in DataMiner Integration Studio (DIS)) and on CI/CD. You will learn how to navigate the validator source code, add a new check, and create a pull request. With a hands-on exercise using fake Validator source code, you will get to utilize GitHub to create a fork, a clone, and a pull request with your changes so that you will be ready to contribute to the actual Validator.
The only difference between the tutorial and actual contributions lies in the fork used in step 2:
-
In the tutorial, you will fork https://github.com/SkylineCommunications/Skyline.DataMiner.CICD.ValidatorsExercise
-
For real validator contributions, you will fork https://github.com/SkylineCommunications/Skyline.DataMiner.CICD.Validators
The missing test: When adding the option "datetime" to the Measurement.Type tag, check if the Display tag contains a <Decimals>8</Decimals>
tag.
Expected duration: 15 minutes.
Note
This tutorial requires Microsoft .NET 6.0 SDK.
Warning
After installing .NET 6.0 SDK and updating Visual Studio, you may need to reboot your computer.
-
Go to https://github.com/SkylineCommunications/Skyline.DataMiner.CICD.ValidatorsExercise
-
In the top right corner, click Fork.
-
Follow the wizard to create a fork of the repository under your own account.
On the page of your GitHub fork (e.g. https://github.com/YourGitHubHandle/Skyline.DataMiner.CICD.ValidatorsExercise
), click the Code button and select Open in Visual Studio.
Note
In some cases, the Open in Visual Studio option may not be available. In that case, you will need to use GitHub Desktop instead to make the clone. Make sure you have GitHub Desktop installed. Then click the Code button on your fork page and select the option Open with GitHub Desktop instead.
-
In the Solution Explorer, right-click the Validator Management Tool, and select Set as Startup Project.
This will turn Validator Management Tool bold, and Validator Management Tool will appear at the top next to the Play button.
-
Click the Play button.
You should now see the following screen:
-
In the Validator Management Tool, click the Add Check... button.
A new window will open.
-
In the new window, do the following:
-
Category: Choose the top-level category for the check.
Use
Param
. -
Namespace: Define the "path" of the tag/attribute. If it is a new namespace, use the Add new Namespace... button.
In this exercise, we want to check the correctness of the Display tag. So we should add a new namespace for Protocol.Params.Param.Display.Decimals.
Select the newly created
Protocol.Params.Param.Display.Decimals
namespace. -
Check Name: Specify the name of the class to be generated.
In this exercise, we want to check the validity of the content of this tag. We should add a new check named CheckDecimalsTag.
Select the newly created
CheckDecimalsTag
. -
Error Message Name: Enter the name of the error message. A method with that same name will be created during code generation.
Use
InvalidTagForDateTime
. -
Description: Provide a description with placeholders.
Open the selection box and select the
Missing tag '{0}' with expected value '{1}' for {2} '{3}'.
template. -
Description Parameters: List the placeholders from the description.
For this exercise, we can already add some fixed data:
- tagName: Display/Decimals
- expectedValue: 8
- itemKind: Param
We can also rename "itemId" to "paramId" to make our code more readable later on.
-
Source: Indicate whether the source is "Validator" (Validate) or "MajorChangeChecker" (Compare).
Use
Validator
. -
Severity: Specify the severity level. To choose the correct severity, you can follow the following guide:
-
Critical: This type of error will have a critical impact on the system or will fully prevent the driver from working. It may also draw your attention to something that needs to be fixed for administrative reasons.
-
Major: This type of error will prevent part of the driver from working as expected. Example: A specific driver feature will not work.
-
Minor: This type of error will not prevent the driver from working, but will have some impact. It may draw your attention to something that was not implemented according to the best practice guidelines. Example: Bad performance, Not user-friendly, etc.
-
Warning: This type of error reveals something that will not have any impact. Example: Unused XML elements or attributes.
Use
Major
. -
-
Certainty: Specify the certainty level.
-
Certain: An error has been detected and needs to be fixed.
-
Uncertain: A possible error has been detected and needs to be fixed once verified.
Use
Certain
. -
-
Fix Impact: Determine if there is a breaking change.
Use
NonBreaking
. -
Has Code Fix: Indicate if an automatic fix is possible.
Though an automatic fix is possible, we will deal with automatic fixes in a different tutorial. Do not select the checkbox.
-
How To Fix: Optionally describe the steps to fix the issue.
We can write the following:
Add a Protocol/Params/Param/Display/Decimals tag with value 8.
-
Example Code: Optionally provide the correct syntax.
We can write the following:
<Display> <RTDisplay>true</RTDisplay> <Decimals>8</Decimals> </Display> <Measurement> <Type options="datetime">number</Type> </Measurement>
-
Details: Extra information about the error. This is important as it will be visible in the DIS UI.
We can write the following:
By default, only 6 decimals are saved in memory. Parameters holding datetime values need at least 8 decimals to be accurate. Otherwise, there might be rounding issues when retrieving the parameter from an external source like an Automation script.
-
Click Add to list the error message. If necessary, add more messages or modify existing ones.
[!IMPORTANT] Wait for the indication
The XML is outdated!
. -
Click Save to save all changes to the XML file containing all error messages. Then, click Generate Code to generate the C# files.
-
Close the window.
-
In the Git Changes window, you can see what was added by the code generation.
We will now write our tests. This will ensure we can develop until no tests are failing.
-
Open the Valid.xml file, and create XML code that represents the expected correct XML code:
<Protocol xmlns="http://www.skyline.be/validatorProtocolUnitTest"> <Params> <Param id="10"> <Display> <RTDisplay>true</RTDisplay> <Decimals>8</Decimals> </Display> <Measurement> <Type options="datetime">number</Type> </Measurement> </Param> </Params> </Protocol>
-
Open the InvalidTagForDateTime.xml, and create an example of an incorrect situation:
<Protocol xmlns="http://www.skyline.be/validatorProtocolUnitTest"> <Params> <Param id="10"> <Display> <RTDisplay>true</RTDisplay> </Display> <Measurement> <Type options="datetime">number</Type> </Measurement> </Param> </Params> </Protocol>
-
Go to ProtocolTests\Protocol\Params\Param\Display\Decimals\CheckDecimalTag, open the CheckDecimalTag.cs file, and remove all the
Ignore
attributes. -
Uncomment the
Error.InvalidTagForDateTime(...
line, and change it to what we expect to get.You can press F12 on the static method to see the expected description format:
Missing tag '{0}' with expected value '{1}' for {2} '{3}'.
Error.InvalidTagForDateTime(null, null, null, "paramId"),
-
Right-click the first line of the file, and select Run Tests.
At this point, you should see 3 failing tests.
-
In the Git Changes window, you can see what was added by the code generation.
-
Go to Tests\Protocol\Params\Display\Decimals, and open the CheckDecimalTag.cs file.
-
Make sure to check the documentation of the tag to find out what syntax options exist.
-
Uncomment the following attribute:
//[Test(CheckId.CheckDecimalTag, Category.Param)]
-
Comment out
ICodeFix
andICompare
. We will only useIValidate
. -
Most of your validation will need to loop over several items to validate. In this case, we need every parameter: context.EachParamWithValidId.
You can use the following code:
public List<IValidationResult> Validate(ValidatorContext context) { List<IValidationResult> results = new List<IValidationResult>(); foreach (var param in context.EachParamWithValidId()) { // Early Return pattern. Only check number types. if (!param.IsNumber()) continue; // Only check if there are options. var allOptions = param.Measurement?.Type?.Options?.Value?.Split(';'); if (allOptions == null) continue; // Is there an option involving date or datetime? List<string> possibleLowerCaseDateSyntax = new List<string>() { "date", "datetime", "datetime:minute" }; bool foundDateTime = Array.Exists(allOptions, option => possibleLowerCaseDateSyntax.Contains(option.ToLower())); // Verify valid decimals. var decimalsTag = param.Display?.Decimals; if (foundDateTime && decimalsTag?.Value != 8) { results.Add(Error.InvalidTagForDateTime(this, param, decimalsTag, param.Id.RawValue)); } } return results; }
-
Run your new tests. Check whether all tests pass.
-
Run the entire test battery to check for any regression. This can take several minutes.
In order to share your changes with the original owner, you will need to create a pull request.
-
If you are using Visual Studio 2022, you can do this from within Visual Studio. It will detect that you performed a commit and push to a forked repository, and it will suggest making a pull request.
-
You can also do this from GitHub by navigating to the Pull requests tab of your fork page and then clicking the New pull request button.
This will inform the owners that you suggested additions and changes. Those can then be reviewed, merged and released.
For this exercise, this will trigger an automatic pipeline that closes your pull request and forwards the results to Skyline.
Note
Skyline will review your submission. Upon successful review, you will be awarded the appropriate DevOps points as a token of your accomplishment.