Sign or timestamp an unchanged tree's manifest in freshen (closes #190)
check / check (push) Waiting to run
check / check (push) Waiting to run
freshen skipped the write whenever no file was added, changed or removed, so --sign-key and --include-timestamps on an unchanged tree did nothing. It now skips only when the manifest would come out the same: nothing in the tree changed, the manifest is signed by the --sign-key key (unsigned without one), and it has a createdAt timestamp exactly when --include-timestamps asks for one. A file whose recorded mode is not what --include-permissions asks for already counts as changed. Deviation: the mfer package gains SecretKeyFingerprint and a loaded manifest's CreatedAt, which the comparison needs. Model: opus-5-5
This commit was merged in pull request #220.
This commit is contained in:
@@ -127,6 +127,53 @@ func TestFreshenSignedManifestNeedsSignKey(t *testing.T) {
|
||||
assert.Len(t, manifestFiles(t, fs, manifestPath), 2)
|
||||
}
|
||||
|
||||
// TestFreshenSignsUnchangedTree runs freshen with --sign-key on a tree that
|
||||
// has not changed since gen made its unsigned manifest. freshen must
|
||||
// rewrite the manifest signed by that key. Run again with the same key it
|
||||
// must leave the manifest as it is; with another key it must rewrite it
|
||||
// signed by that one.
|
||||
func TestFreshenSignsUnchangedTree(t *testing.T) {
|
||||
t.Setenv(envSignKeyPassphrase, "")
|
||||
|
||||
fs := afero.NewOsFs()
|
||||
_, manifestPath := setupFreshenDir(t, fs, map[string]string{testFileTxt: "hello"})
|
||||
|
||||
newKeyFile := func() (string, string) {
|
||||
secretKey, fingerprint := testSecretKey(t, nil, nil)
|
||||
keyFile := filepath.Join(t.TempDir(), "key.asc")
|
||||
require.NoError(t, afero.WriteFile(fs, keyFile, secretKey, 0o600))
|
||||
|
||||
return keyFile, fingerprint
|
||||
}
|
||||
|
||||
freshenAndCheckSignedBy := func(keyFile, fingerprint string) {
|
||||
opts := testOpts([]string{
|
||||
testApp, cmdFreshen, "-q", testFlagSignKey, keyFile, manifestPath,
|
||||
}, fs)
|
||||
require.Equal(t, 0, runCLI(opts), testStderr(t, opts))
|
||||
|
||||
opts = testOpts([]string{
|
||||
testApp, cmdCheck, "-q",
|
||||
"--" + flagRequireSignature, fingerprint, manifestPath,
|
||||
}, fs)
|
||||
require.Equal(t, 0, runCLI(opts), testStderr(t, opts))
|
||||
}
|
||||
|
||||
keyFile, fingerprint := newKeyFile()
|
||||
freshenAndCheckSignedBy(keyFile, fingerprint)
|
||||
|
||||
before, err := afero.ReadFile(fs, manifestPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
freshenAndCheckSignedBy(keyFile, fingerprint)
|
||||
|
||||
after, err := afero.ReadFile(fs, manifestPath)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, before, after, "manifest already signed by the key was rewritten")
|
||||
|
||||
freshenAndCheckSignedBy(newKeyFile())
|
||||
}
|
||||
|
||||
// TestSignWithProtectedKeyNeedsPassphrase runs gen with a protected key,
|
||||
// with MFER_SIGN_KEY_PASSPHRASE empty and no terminal to ask on. gen must
|
||||
// fail, naming the variable, and write no manifest.
|
||||
|
||||
Reference in New Issue
Block a user