#!/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