{"id":386235,"date":"2024-06-29T06:35:14","date_gmt":"2024-06-29T06:35:14","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=386235"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=386235","title":{"rendered":"<span>Analysis of merge requests in GitLab using PVS-Studio for C#<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/d7c\/ae5\/987\/d7cae5987aa9787abd00f829cd2d0d55.png\" alt=\"image1.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/d7c\/ae5\/987\/d7cae5987aa9787abd00f829cd2d0d55.png\"\/><\/div>\n<p>  Do you like GitLab and don&#8217;t like bugs? Do you want to improve the quality of your source code? Then you&#8217;ve come to the right place. Today we will tell you how to configure the PVS-Studio C# analyzer for checking merge requests. Enjoy the reading and have a nice unicorn mood.<br \/>  <a name=\"habracut\"><\/a><br \/>  <a href=\"https:\/\/www.viva64.com\/en\/pvs-studio\/\">PVS-Studio<\/a> is a tool designed to detect errors and potential vulnerabilities in the source code of programs, written in C, C++, C#, and Java. Works in 64-bit systems on Windows, Linux and macOS. Can analyze the code meant for 32-bit, 64-bit and embedded ARM platforms.<\/p>\n<p>  By the way, we&#8217;ve released PVS-Studio 7.08, which was full of new sapid <a href=\"https:\/\/www.viva64.com\/en\/b\/0745\/\">features<\/a>. For example:<\/p>\n<ul>\n<li>C# analyzer under Linux and macOS;<\/li>\n<li>plugin for Rider;<\/li>\n<li>new mode for checking a list of files.<\/li>\n<\/ul>\n<p>  <\/p>\n<h2>Mode of checking a list of files<\/h2>\n<p>  Previously, in order to check certain files, one had to pass .xml to the analyzer with a list of files. But since this is not very convenient, we have added the ability to pass .txt, which makes life much simpler.<\/p>\n<p>  To check certain files, specify the <i>&#8212;sourceFiles<\/i> (<i>-f<\/i>) flag and pass .txt with the list of files. It looks like this:<\/p>\n<pre><code class=\"cpp\">pvs-studio-dotnet -t path\/to\/solution.sln -f fileList.txt -o project.json<\/code><\/pre>\n<p>  If you are interested in configuring checks of commits or pull requests, you can also do this using this mode. The difference will be in getting a list of files for analysis and will depend on which systems you are using.<\/p>\n<h2>Principle of checking merge requests<\/h2>\n<p>  The main point of checking is to make sure that problems detected by the analyzer do not make it into the <i>master<\/i> branch when merging. We also don&#8217;t want to analyze the entire project every time. Moreover, when merging branches, we have a list of changed files. Therefore, I suggest adding a merge request check.<\/p>\n<p>  This is how a merge request looks like before introducing a static analyzer:<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/b36\/dd4\/c38\/b36dd4c384db25073c72a20109bd32ba.png\" alt=\"image2.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/b36\/dd4\/c38\/b36dd4c384db25073c72a20109bd32ba.png\"\/><\/div>\n<p>  In other words, all errors in the <i>changes<\/i> branch will get to the master branch. Since we wouldn&#8217;t like this, we add the analysis, and now the scheme looks as follows:<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/75b\/ce2\/539\/75bce2539363d98423b6b6e1274b6188.png\" alt=\"image3.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/75b\/ce2\/539\/75bce2539363d98423b6b6e1274b6188.png\"\/><\/div>\n<p>  We analyze <i>changes2<\/i> and, if there are no errors, we accept the merge request, otherwise reject it.<\/p>\n<p>  By the way, if you are interested in analyzing commits and pull requests for C\/C++, you are welcome to read about it <a href=\"https:\/\/www.viva64.com\/en\/b\/0679\/\">here<\/a>.<\/p>\n<h2>GitLab<\/h2>\n<p>  <a href=\"https:\/\/gitlab.com\/\">GitLab<\/a> is an open source DevOps lifecycle web tool that provides a code repository management system for Git with its own wiki, bug tracking system, CI\/CD pipeline, and other features.<\/p>\n<p>  Before you start implementing the merge request analysis, you need to register and upload your project. If you do not know how to do this, then I suggest an <a href=\"https:\/\/www.viva64.com\/en\/b\/0686\/\">article<\/a> by my colleague.<\/p>\n<p>  <b>Note<\/b>. One of the possible ways to configure the environment is described below. The point is to show the steps for configuring the environment needed for analyzing and running the analyzer. In your case, it may be better to separate the stages of environment preparation (adding repositories, installing the analyzer) and analysis. For example, preparing Docker instances with the necessary environment and their usage, or some other method.<\/p>\n<p>  In order to get a better understanding of what is going to happen next, I suggest taking a look at the following scheme:<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/255\/520\/613\/255520613b3ce5b52c933349c78d0b28.png\" alt=\"image4.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/255\/520\/613\/255520613b3ce5b52c933349c78d0b28.png\"\/><\/div>\n<p>  The analyzer needs .NET Core SDK 3 for proper operation from which the necessary dependencies for the analyzer will be installed. Adding Microsoft repositories for various Linux distributions is <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/core\/install\/linux-ubuntu\">described in the relevant document<\/a>.<\/p>\n<p>  To install PVS-Studio via the package manager, you will also need to add PVS-Studio repositories. Adding repositories for various distributions is described in more detail in the <a href=\"https:\/\/www.viva64.com\/en\/m\/0051\/\">relevant section of the documentation<\/a>.<\/p>\n<p>  The analyzer needs a license key to operate. You can get a trial license on the <a href=\"https:\/\/www.viva64.com\/en\/pvs-studio-download\/\">analyzer download page<\/a>.<\/p>\n<p>  <b>Note<\/b>. Please note that the described operating mode (merge requests analysis) requires an Enterprise license. Therefore, if you would like to try this mode of operation, don&#8217;t forget to specify that you need an Enterprise license in the &#171;Message&#187; field.<\/p>\n<p>  If a merge request occurs, we only need to analyze the list of changed files, otherwise we analyze all files. After the analysis, we need to convert the logs to the format we need.<\/p>\n<p>  Now, with the algorithm in front of your eyes, you can proceed to writing the script. To do this, we need to change the <i>.gitlab-ci.yml<\/i> file or, if there is no such file, create one. To create it, click on the name of your project -> <i>Set up CI\/CD<\/i>.<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/7a2\/692\/ac7\/7a2692ac79bb8cd18942526db1c948e2.png\" alt=\"image5.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/7a2\/692\/ac7\/7a2692ac79bb8cd18942526db1c948e2.png\"\/><\/div>\n<p>  Now we are ready to write the script. Let&#8217;s first write the code that will install the analyzer and enter the license:<\/p>\n<pre><code class=\"cpp\">before_script:   - apt-get update &amp;&amp; apt-get -y install wget gnupg     - apt-get -y install git   - wget https:\/\/packages.microsoft.com\/config\/debian\/10\/ packages-microsoft-prod.deb -O packages-microsoft-prod.deb   - dpkg -i packages-microsoft-prod.deb   - apt-get update   - apt-get install apt-transport-https   - apt-get update      - wget -q -O - https:\/\/files.viva64.com\/etc\/pubkey.txt | apt-key add -   - wget -O \/etc\/apt\/sources.list.d\/viva64.list https:\/\/files.viva64.com\/etc\/viva64.list   - apt-get update   - apt-get -y install pvs-studio-dotnet    - pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY   - dotnet restore \"$CI_PROJECT_DIR\"\/Test\/Test.sln<\/code><\/pre>\n<p>  Since installation and activation must occur before all other scripts, we use a special <i>before_script<\/i> label. Let me be clear on this fragment.<\/p>\n<p>  Preparation for the analyzer installation:<\/p>\n<pre><code class=\"cpp\">  - wget https:\/\/packages.microsoft.com\/config\/debian\/10\/ packages-microsoft-prod.deb -O packages-microsoft-prod.deb   - dpkg -i packages-microsoft-prod.deb   - apt-get update   - apt-get install apt-transport-https   - apt-get update<\/code><\/pre>\n<p>  Adding PVS-Studio repositories and the analyzer:<\/p>\n<pre><code class=\"cpp\">  - wget -q -O - https:\/\/files.viva64.com\/etc\/pubkey.txt | apt-key add -   - wget -O \/etc\/apt\/sources.list.d\/viva64.list https:\/\/files.viva64.com\/etc\/viva64.list   - apt-get update   - apt-get -y install pvs-studio-dotnet<\/code><\/pre>\n<p>  License activation:<\/p>\n<pre><code class=\"cpp\">  - pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY<\/code><\/pre>\n<p>  <i>$PVS_NAME<\/i> \u2014 user name.<\/p>\n<p>  <i>$PVS_KEY<\/i> \u2014 product key. <\/p>\n<p>  Restoration of project dependencies, where <i>$CI_PROJECT_DIR<\/i> is the full path to the project directory:<\/p>\n<pre><code class=\"cpp\">  - dotnet restore \"$CI_PROJECT_DIR\"\/Path\/To\/Solution.sln<\/code><\/pre>\n<p>  For correct analysis, the project must be successfully built, and its dependencies must be restored (for example, the necessary NuGet packages must be loaded).<\/p>\n<p>  You can set environment variables containing license information by clicking on <i>Setting<\/i>, and then on<i> CI \/ CD<\/i>.<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/ef9\/969\/9e7\/ef99699e71329a999acb143c8d519e6a.png\" alt=\"image6.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/ef9\/969\/9e7\/ef99699e71329a999acb143c8d519e6a.png\"\/><\/div>\n<p>  In the opening window, find the item <i>Variables<\/i>, click <i>Expand<\/i> on the right and add variables. The result should be the following:<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/b8c\/765\/6ce\/b8c7656ce7dc5e8956a5d83fc80343ce.png\" alt=\"image7.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/b8c\/765\/6ce\/b8c7656ce7dc5e8956a5d83fc80343ce.png\"\/><\/div>\n<p>  Now we can proceed to the analysis. First, we will add a script for full analysis. In the<i> -t<\/i> flag, we pass the path to solution, and in the <i>-o<\/i> flag, we write the path to the file where the analysis results will be written. Also the return code is of interest for us here. In this case, we&#8217;d like the analysis to continue when an exit code signals that warnings were issued during the analysis. Here&#8217;s how this fragment looks like:<\/p>\n<pre><code class=\"cpp\">job:   script:   - exit_code=0   - pvs-studio-dotnet -t \"$CI_PROJECT_DIR\"\/Test\/Test.sln -o  PVS-Studio.json || exit_code=$?   - exit_code=$((($exit_code &amp; 8)\/8))   - if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi<\/code><\/pre>\n<p>  Exit codes work as bit masks. For example, if warnings were issued as a result of the analysis, the exit code will be equal to 8. If the license expires within a month, the exit code will be 4. If errors were found during the analysis, and the license expires within a month, both values will be written to the exit code: the numbers add up and we get the final exit code \u2014 8+4=12. Thus, by checking the corresponding bits, you can get information about various states during analysis. Exit codes are described in more detail in the section &#171;Pvs-studio-dotnet exit codes (Linux \/ macOS)&#187;of the document &#171;<a href=\"https:\/\/www.viva64.com\/en\/m\/0035\/\">Analyzing Visual Studio \/ MSBuild \/ .NET Core projects from the command line using PVS-Studio<\/a>&#171;.<\/p>\n<p>  In this case, we are interested in all exit codes where 8 appears.<\/p>\n<pre><code class=\"cpp\">  - exit_code=$((($exit_code &amp; 8)\/8))<\/code><\/pre>\n<p>  We get 1 when the exit code has the bit we are interested in set, otherwise we get 0.<\/p>\n<p>  Now it is time to add the analysis of the merge request. Before doing this, let&#8217;s get some space for the script. We want it to be executed only when a merge request occurs. This looks as follows:<\/p>\n<pre><code class=\"cpp\">merge:   script:   only:   - merge_requests<\/code><\/pre>\n<p>  Let&#8217;s move on to the script itself. I stumbled upon the issue that the virtual machine knows nothing about <i>origin\/master<\/i>. So we&#8217;ll lend it a hand:<\/p>\n<pre><code class=\"cpp\">  - git fetch origin<\/code><\/pre>\n<p>  Now we get the difference between branches and save the result to a <i>txt<\/i> file:<\/p>\n<pre><code class=\"cpp\">  - git diff --name-only origin\/master $CI_COMMIT_SHA > pvs-fl.txt<\/code><\/pre>\n<p>  Where <i>$CI_COMMIT_SH<\/i>A is the hash of the last commit.<\/p>\n<p>  Next, we run analysis of the list of files by using the <i>-f<\/i> flag. We pass the previously received .txt file to it. By analogy with the full analysis, we check out the exit codes:<\/p>\n<pre><code class=\"cpp\">  - exit_code=0   - pvs-studio-dotnet -t \"$CI_PROJECT_DIR\"\/Test\/Test.sln -f  pvs-fl.txt -o PVS-Studio.json || exit_code=$?   - exit_code=$((($exit_code &amp; 8)\/8))   - if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi<\/code><\/pre>\n<p>  Full script for checking merge request will look like this:<\/p>\n<pre><code class=\"cpp\">merge:   script:   - git fetch origin   - git diff --name-only origin\/master $CI_COMMIT_SHA > pvs-fl.txt   - exit_code=0   - pvs-studio-dotnet -t \"$CI_PROJECT_DIR\"\/Test\/Test.sln -f  pvs-fl.txt -o PVS-Studio.json || exit_code=$?   - exit_code=$((($exit_code &amp; 8)\/8))   - if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi   only:   - merge_requests<\/code><\/pre>\n<p>  It only remains to add the log conversion after all the scripts have worked. We use the <i>after_script<\/i> label and the <i>plog-converter<\/i> utility:<\/p>\n<pre><code class=\"cpp\">after_script:   - plog-converter -t html -o eLog .\/PVS-Studio.json<\/code><\/pre>\n<p>  The <a href=\"https:\/\/github.com\/viva64\/plog-converter\">plog-converter<\/a> utility is an open source project that is used to convert the analyzer error report into various forms, such as HTML. For a more detailed description of the utility, see the section &#171;Plog Converter Utility&#187; in the <a href=\"https:\/\/www.viva64.com\/en\/m\/0036\/\">relevant documentation section<\/a>.<\/p>\n<p>  By the way, if you&#8217;d like to conveniently work with a .json report locally from the IDE, then I recommend our <a href=\"https:\/\/plugins.jetbrains.com\/plugin\/14480-pvs-studio-for-rider\">plugin<\/a> for IDE Rider. For more information about its use, see the <a href=\"https:\/\/www.viva64.com\/en\/m\/0052\/\">special document<\/a>. <\/p>\n<p>  For convenience, here is the entire<i>.gitlab-ci.yml<\/i>:<\/p>\n<pre><code class=\"cpp\">image: debian  before_script:   - apt-get update &amp;&amp; apt-get -y install wget gnupg     - apt-get -y install git   - wget https:\/\/packages.microsoft.com\/config\/debian\/10\/ packages-microsoft-prod.deb -O packages-microsoft-prod.deb   - dpkg -i packages-microsoft-prod.deb   - apt-get update   - apt-get install apt-transport-https   - apt-get update      - wget -q -O - https:\/\/files.viva64.com\/etc\/pubkey.txt | apt-key add -   - wget -O \/etc\/apt\/sources.list.d\/viva64.list https:\/\/files.viva64.com\/etc\/viva64.list   - apt-get update   - apt-get -y install pvs-studio-dotnet    - pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY   - dotnet restore \"$CI_PROJECT_DIR\"\/Test\/Test.sln  merge:   script:   - git fetch origin   - git diff --name-only origin\/master $CI_COMMIT_SHA > pvs-fl.txt   - exit_code=0   - pvs-studio-dotnet -t \"$CI_PROJECT_DIR\"\/Test\/Test.sln -f  pvs-fl.txt -o PVS-Studio.json || exit_code=$?   - exit_code=$((($exit_code &amp; 8)\/8))   - if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi   only:   - merge_requests  job:   script:   - exit_code=0   - pvs-studio-dotnet -t \"$CI_PROJECT_DIR\"\/Test\/Test.sln -o  PVS-Studio.json || exit_code=$?   - exit_code=$((($exit_code &amp; 8)\/8))   - if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi    after_script:   - plog-converter -t html -o eLog .\/PVS-Studio.json<\/code><\/pre>\n<p>  As soon as we&#8217;ve added everything to the file, click on <i>Commit changes<\/i>. To make sure that everything is correct, go to <i>CI\/CD<\/i> \u2014 > <i>Pipelines<\/i> -> <i>Running<\/i>. It opens the virtual machine window at the end of which should be the following:<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/cef\/150\/825\/cef150825e4521ab8aab29ef452d655e.png\" alt=\"image8.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/cef\/150\/825\/cef150825e4521ab8aab29ef452d655e.png\"\/><\/div>\n<p>  Once you get <i>Job succeeded<\/i> \u2014 it&#8217;s ok, profit. Now you can test what you&#8217;ve done.<\/p>\n<h2>Examples of working<\/h2>\n<p>  As an example, we will create a simple project (in <i>master<\/i>) that will contain several files. After that, we will change only one file in another branch and try to make a merge request. <\/p>\n<p>  Let&#8217;s look at two cases: when the modified file contains an error, and when it doesn&#8217;t. First, we&#8217;ll consider an example with an error.<\/p>\n<p>  Let&#8217;s say there is a <i>Program.cs<\/i> file in the master branch that doesn&#8217;t contain errors, and in another branch the developer added erroneous code and wants to make a merge request. What kind of mistake they made is not so important, the main thing is that it is there. For example, they forgot the <i>throw<\/i> operator (yes, <a href=\"https:\/\/www.viva64.com\/en\/examples\/v3006\/\">people make such mistakes<\/a>):<\/p>\n<pre><code class=\"cpp\">void MyAwesomeMethod(String name) {   if (name == null)     new ArgumentNullException(....);   \/\/ do something   .... }<\/code><\/pre>\n<p>  Let&#8217;s look at the analysis result for the example with an error. Also, to make sure that only one file was analyzed, I added the <i>-r<\/i> flag to the pvs-studio-dotnet command line: <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/baf\/3d2\/0fa\/baf3d20fab753a627149a8a877aba083.png\" alt=\"image9.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/baf\/3d2\/0fa\/baf3d20fab753a627149a8a877aba083.png\"\/><\/div>\n<p>  As we can see, the analyzer found an error and didn&#8217;t allow merging branches.<\/p>\n<p>  Now let&#8217;s check the example without an error. Fixed code:<\/p>\n<pre><code class=\"cpp\">void MyAwesomeMethod(String name) {   if (name == null)     throw new ArgumentNullException(....);   \/\/ do something   .... }<\/code><\/pre>\n<p>  Analysis results of merge request:<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/07c\/aca\/037\/07caca03738a4310e6414880ad714e74.png\" alt=\"image10.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/07c\/aca\/037\/07caca03738a4310e6414880ad714e74.png\"\/><\/div>\n<p>  As we can see, no errors were found, and the task was completed successfully, which is what we wanted to check.<\/p>\n<h2>Conclusion<\/h2>\n<p>  Filtering out bad code before merging branches is very convenient and pleasant. So if you are using CI\/CD, try embedding a static analyzer to check it. Especially since it can be done very simply. <\/p>\n<p>  Thank you for your attention.<\/p><\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/512294\/\"> https:\/\/habr.com\/ru\/articles\/512294\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/d7c\/ae5\/987\/d7cae5987aa9787abd00f829cd2d0d55.png\" alt=\"image1.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/d7c\/ae5\/987\/d7cae5987aa9787abd00f829cd2d0d55.png\"\/><\/div>\n<p>  Do you like GitLab and don&#8217;t like bugs? Do you want to improve the quality of your source code? Then you&#8217;ve come to the right place. Today we will tell you how to configure the PVS-Studio C# analyzer for checking merge requests. Enjoy the reading and have a nice unicorn mood.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-386235","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/386235","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=386235"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/386235\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=386235"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=386235"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=386235"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}