cc-os/plugins/os-adr/bin/adr-new

59 lines
1.9 KiB
Plaintext
Raw Permalink Normal View History

#!/usr/bin/env ruby
# Create a templated, numbered, indexed ADR in one invocation.
#
# Usage: echo '{"title": "...", ...}' | adr-new [--root DIR]
#
# JSON input fields:
# title (required) decision title
# status (optional) default "Accepted"
# date (optional) ISO date, default today
# supersedes (optional) 4-digit ID of the ADR this one supersedes
# affected_paths, affected_components (optional) arrays
# context, decision, consequences, alternatives (optional) section bodies
#
# Prints the created file path. Also mechanically sets superseded-by + status
# on the superseded ADR and regenerates the index.
require "json"
require "date"
require_relative "../lib/adr"
root = Dir.pwd
ARGV.each_with_index { |arg, i| root = ARGV[i + 1] if arg == "--root" }
input = JSON.parse($stdin.read)
title = input["title"].to_s.strip
abort "adr-new: 'title' is required" if title.empty?
repo = Adr::Repository.new(root: root)
abort "adr-new: #{repo.dir} is not initialized (run adr-init first)" unless Dir.exist?(repo.dir)
id = repo.next_id
template = Adr::Template.new(path: File.expand_path("../templates/adr.md", __dir__))
content = template.render(
id: id,
title: title,
date: input["date"] || Date.today.iso8601,
status: input["status"] || "Accepted",
supersedes: input["supersedes"] ? %("#{input['supersedes']}") : nil,
affected_paths: input["affected_paths"] || [],
affected_components: input["affected_components"] || [],
context: input["context"],
decision: input["decision"],
consequences: input["consequences"],
alternatives: input["alternatives"]
)
path = File.join(repo.dir, "#{id}-#{Adr.slugify(title)}.md")
File.write(path, content)
if (old_id = input["supersedes"])
entry = repo.find(old_id.to_s)
abort "adr-new: superseded ADR #{old_id} not found" unless entry
entry.record.supersede_with(id)
repo.write_entry(entry)
end
Adr::Index.new(repository: repo).regenerate!
puts path