Class: Kamal::Lint::Checks::KamalSecretsNotGitignored

Inherits:
Kamal::Lint::Check show all
Defined in:
lib/kamal/lint/checks/kamal_secrets_not_gitignored.rb

Instance Attribute Summary

Attributes inherited from Kamal::Lint::Check

#context

Instance Method Summary collapse

Methods inherited from Kamal::Lint::Check

applies_to?, autofixable, id, #initialize, severity, since, title, until_version

Constructor Details

This class inherits a constructor from Kamal::Lint::Check

Instance Method Details

#apply_fix(ctx) ⇒ Object



42
43
44
45
46
47
48
49
50
# File 'lib/kamal/lint/checks/kamal_secrets_not_gitignored.rb', line 42

def apply_fix(ctx)
  path = ctx.gitignore_path
  existing = File.exist?(path) ? File.read(path) : ""
  existing = existing + "\n" unless existing.empty? || existing.end_with?("\n")
  File.write(path, "#{existing}.kamal/secrets\n")
  true
rescue => _e
  false
end

#callObject

We only flag when:

- a .kamal/secrets file exists (so there's something to leak), AND
- it is NOT covered by .gitignore (or .gitignore is missing).


16
17
18
19
20
21
22
23
24
25
# File 'lib/kamal/lint/checks/kamal_secrets_not_gitignored.rb', line 16

def call
  return [] unless File.exist?(context.secrets_path)
  return [] if gitignored?

  [ finding(
    message: ".kamal/secrets exists but isn't ignored by .gitignore; you risk committing real secrets",
    line: 1,
    autofix: method(:apply_fix)
  ) ]
end

#gitignored?Boolean

Returns:

  • (Boolean)


27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/kamal/lint/checks/kamal_secrets_not_gitignored.rb', line 27

def gitignored?
  return false unless File.exist?(context.gitignore_path)

  File.foreach(context.gitignore_path).any? do |line|
    stripped = line.strip
    next false if stripped.empty? || stripped.start_with?("#")

    stripped == ".kamal/secrets" ||
      stripped == "/.kamal/secrets" ||
      stripped == ".kamal/*" ||
      stripped == ".kamal/" ||
      stripped == ".kamal"
  end
end