Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
- Implemented MigrationCategoryTests to validate migration categorization for startup, release, seed, and data migrations. - Added tests for edge cases, including null, empty, and whitespace migration names. - Created StartupMigrationHostTests to verify the behavior of the migration host with real PostgreSQL instances using Testcontainers. - Included tests for migration execution, schema creation, and handling of pending release migrations. - Added SQL migration files for testing: creating a test table, adding a column, a release migration, and seeding data.
127 lines
4.2 KiB
C#
127 lines
4.2 KiB
C#
using System.Globalization;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace StellaOps.Scanner.Analyzers.Lang.Node.Internal;
|
|
|
|
internal static class NodeEnvironmentScanner
|
|
{
|
|
private static readonly Regex EnvAssign = new(@"^\s*(ENV|ARG)\s+NODE_OPTIONS\s*(=|\s)(?<value>.+)$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
|
|
|
public static IReadOnlyList<LanguageComponentRecord> Scan(LanguageAnalyzerContext context, IReadOnlyList<string> sourceRoots, CancellationToken cancellationToken)
|
|
{
|
|
var warnings = new List<LanguageComponentRecord>();
|
|
|
|
foreach (var root in sourceRoots)
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
var dockerfile = Path.Combine(root, "Dockerfile");
|
|
if (File.Exists(dockerfile))
|
|
{
|
|
warnings.AddRange(ScanDockerfile(context, dockerfile));
|
|
}
|
|
|
|
var envFile = Path.Combine(root, ".env");
|
|
if (File.Exists(envFile))
|
|
{
|
|
warnings.AddRange(ScanEnvFile(context, envFile));
|
|
}
|
|
}
|
|
|
|
return warnings
|
|
.OrderBy(static r => r.ComponentKey, StringComparer.Ordinal)
|
|
.ToArray();
|
|
}
|
|
|
|
private static IEnumerable<LanguageComponentRecord> ScanDockerfile(LanguageAnalyzerContext context, string dockerfile)
|
|
{
|
|
var results = new List<LanguageComponentRecord>();
|
|
try
|
|
{
|
|
var lines = File.ReadAllLines(dockerfile);
|
|
for (var i = 0; i < lines.Length; i++)
|
|
{
|
|
var match = EnvAssign.Match(lines[i]);
|
|
if (!match.Success)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var value = match.Groups["value"].Value.Trim().Trim('"', '\'');
|
|
results.Add(BuildWarning(context, dockerfile, i + 1, value, source: "Dockerfile", reason: "NODE_OPTIONS"));
|
|
}
|
|
}
|
|
catch (IOException)
|
|
{
|
|
// Ignore IO errors
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
private static IEnumerable<LanguageComponentRecord> ScanEnvFile(LanguageAnalyzerContext context, string envFile)
|
|
{
|
|
var results = new List<LanguageComponentRecord>();
|
|
try
|
|
{
|
|
var lines = File.ReadAllLines(envFile);
|
|
for (var i = 0; i < lines.Length; i++)
|
|
{
|
|
var line = lines[i];
|
|
if (!line.Contains("NODE_OPTIONS", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var parts = line.Split('=', 2);
|
|
if (parts.Length != 2)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var value = parts[1].Trim().Trim('"', '\'');
|
|
results.Add(BuildWarning(context, envFile, i + 1, value, source: ".env", reason: "NODE_OPTIONS"));
|
|
}
|
|
}
|
|
catch (IOException)
|
|
{
|
|
// Ignore IO errors
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
private static LanguageComponentRecord BuildWarning(LanguageAnalyzerContext context, string filePath, int lineNumber, string value, string source, string reason)
|
|
{
|
|
var locator = context.GetRelativePath(filePath).Replace(Path.DirectorySeparatorChar, '/');
|
|
var metadata = new List<KeyValuePair<string, string?>>
|
|
{
|
|
new("source", source),
|
|
new("locator", string.Concat(locator, "#", lineNumber.ToString(CultureInfo.InvariantCulture))),
|
|
new("reason", reason),
|
|
new("value", value)
|
|
};
|
|
|
|
var evidence = new[]
|
|
{
|
|
new LanguageComponentEvidence(
|
|
LanguageEvidenceKind.Metadata,
|
|
"node.env",
|
|
string.Concat(locator, "#", lineNumber.ToString(CultureInfo.InvariantCulture)),
|
|
value,
|
|
null)
|
|
};
|
|
|
|
return LanguageComponentRecord.FromExplicitKey(
|
|
analyzerId: "node",
|
|
componentKey: string.Concat("warning:node-options:", locator, "#", lineNumber.ToString(CultureInfo.InvariantCulture)),
|
|
purl: null,
|
|
name: "NODE_OPTIONS warning",
|
|
version: null,
|
|
type: "node:warning",
|
|
metadata: metadata,
|
|
evidence: evidence,
|
|
usedByEntrypoint: false);
|
|
}
|
|
}
|