Repository: goreleaser/nfpm
Pull request #240 (2020-11-02 18:20:17)

feat: add support for deb templates
Add support for `templates` file inside `DEBIAN` that is needed for `debconf` to be able to ask question user during installation. More on subject [here](http://www.fifi.org/doc/debconf-doc/tutorial.html) and [here](https://manpages.debian.org/testing/debconf-doc/debconf-devel.7.en.html)

vercel[bot]: This pull request is being automatically deployed with Vercel ([learn more](https://vercel.link/github-learn-more)).  
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: [https://vercel.com/goreleaser/nfpm/kuzoakcpb](https://vercel.com/goreleaser/nfpm/kuzoakcpb)  
✅ Preview: *In Progress*


djgilcrease: Is there a reason this cannot just be handled with the normal files process?
vandot: @djgilcrease `templates` file needs to be inside `DEBIAN` folder, maybe I missed something but with `files` and `conffiles` files are placed in relative installation path 
codecov[bot]: # [Codecov](https://codecov.io/gh/goreleaser/nfpm/pull/240?src=pr&el=h1) Report
> Merging [#240](https://codecov.io/gh/goreleaser/nfpm/pull/240?src=pr&el=desc) into [master](https://codecov.io/gh/goreleaser/nfpm/commit/0e2c2844bbf34472793220baefea43b9cd0294c1?el=desc) will **increase** coverage by `0.52%`.
> The diff coverage is `96.15%`.

[![Impacted file tree graph](https://codecov.io/gh/goreleaser/nfpm/pull/240/graphs/tree.svg?width=650&height=150&src=pr&token=9QKGIxn7wg)](https://codecov.io/gh/goreleaser/nfpm/pull/240?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #240      +/-   ##
==========================================
+ Coverage   66.33%   66.86%   +0.52%     
==========================================
  Files           9        9              
  Lines        1007     1023      +16     
==========================================
+ Hits          668      684      +16     
  Misses        204      204              
  Partials      135      135              
```


| [Impacted Files](https://codecov.io/gh/goreleaser/nfpm/pull/240?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [nfpm.go](https://codecov.io/gh/goreleaser/nfpm/pull/240/diff?src=pr&el=tree#diff-bmZwbS5nbw==) | `78.04% <ø> (ø)` | |
| [deb/deb.go](https://codecov.io/gh/goreleaser/nfpm/pull/240/diff?src=pr&el=tree#diff-ZGViL2RlYi5nbw==) | `68.56% <96.15%> (+1.77%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/goreleaser/nfpm/pull/240?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/goreleaser/nfpm/pull/240?src=pr&el=footer). Last update [0e2c284...1534e68](https://codecov.io/gh/goreleaser/nfpm/pull/240?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

vandot: Done, added to the docs.

Patch:
diff --git a/deb/deb.go b/deb/deb.go
index 9fc0b85..33d9cb5 100644
--- a/deb/deb.go
+++ b/deb/deb.go
@@ -410,15 +410,40 @@ func createControl(instSize int64, md5sums []byte, info *nfpm.Info) (controlTarG
 		}
 	}
 
-	for script, dest := range map[string]string{
-		info.Scripts.PreInstall:             "preinst",
-		info.Scripts.PostInstall:            "postinst",
-		info.Scripts.PreRemove:              "prerm",
-		info.Scripts.PostRemove:             "postrm",
-		info.Overridables.Deb.Scripts.Rules: "rules",
-	} {
-		if script != "" {
-			if err := newScriptInsideTarGz(out, script, dest); err != nil {
+	type fileAndMode struct {
+		fileName string
+		mode     int64
+	}
+
+	var specialFiles = map[string]*fileAndMode{}
+	specialFiles[info.Scripts.PreInstall] = &fileAndMode{
+		fileName: "preinst",
+		mode:     0755,
+	}
+	specialFiles[info.Scripts.PostInstall] = &fileAndMode{
+		fileName: "postinst",
+		mode:     0755,
+	}
+	specialFiles[info.Scripts.PreRemove] = &fileAndMode{
+		fileName: "prerm",
+		mode:     0755,
+	}
+	specialFiles[info.Scripts.PostRemove] = &fileAndMode{
+		fileName: "postrm",
+		mode:     0755,
+	}
+	specialFiles[info.Overridables.Deb.Scripts.Rules] = &fileAndMode{
+		fileName: "rules",
+		mode:     0755,
+	}
+	specialFiles[info.Overridables.Deb.Scripts.Templates] = &fileAndMode{
+		fileName: "templates",
+		mode:     0644,
+	}
+
+	for path, destMode := range specialFiles {
+		if path != "" {
+			if err := newFilePathInsideTarGz(out, path, destMode.fileName, destMode.mode); err != nil {
 				return nil, err
 			}
 		}
@@ -454,13 +479,7 @@ func newFileInsideTarGz(out *tar.Writer, name string, content []byte) error {
 	})
 }
 
-// normalizePath returns a path separated by slashes, all relative path items
-// resolved and relative to the current directory (so it starts with "./").
-func normalizePath(src string) string {
-	return "." + filepath.ToSlash(filepath.Clean(filepath.Join("/", src)))
-}
-
-func newScriptInsideTarGz(out *tar.Writer, path, dest string) error {
+func newFilePathInsideTarGz(out *tar.Writer, path, dest string, mode int64) error {
 	file, err := os.Open(path) //nolint:gosec
 	if err != nil {
 		return err
@@ -472,13 +491,19 @@ func newScriptInsideTarGz(out *tar.Writer, path, dest string) error {
 	return newItemInsideTarGz(out, content, &tar.Header{
 		Name:     normalizePath(dest),
 		Size:     int64(len(content)),
-		Mode:     0755,
+		Mode:     mode,
 		ModTime:  time.Now(),
 		Typeflag: tar.TypeReg,
 		Format:   tar.FormatGNU,
 	})
 }
 
+// normalizePath returns a path separated by slashes, all relative path items
+// resolved and relative to the current directory (so it starts with "./").
+func normalizePath(src string) string {
+	return "." + filepath.ToSlash(filepath.Clean(filepath.Join("/", src)))
+}
+
 // this is needed because the data.tar.gz file should have the empty folders
 // as well, so we walk through the dst and create all subfolders.
 func createTree(tarw *tar.Writer, dst string, created map[string]bool) error {
diff --git a/nfpm.go b/nfpm.go
index a03048e..9f0e3bc 100644
--- a/nfpm.go
+++ b/nfpm.go
@@ -232,7 +232,8 @@ type DebTriggers struct {
 
 // DebScripts is scripts only available on deb packages.
 type DebScripts struct {
-	Rules string `yaml:"rules,omitempty"`
+	Rules     string `yaml:"rules,omitempty"`
+	Templates string `yaml:"templates,omitempty"`
 }
 
 // Scripts contains information about maintainer scripts for packages.
diff --git a/www/docs/configuration.md b/www/docs/configuration.md
index 7fa0a71..97cbc2b 100644
--- a/www/docs/configuration.md
+++ b/www/docs/configuration.md
@@ -152,11 +152,14 @@ rpm:
     # to #NFPM_PASSPHRASE.
     key_file: key.gpg
 
-# Custon configuration applied only to the Deb packager.
+# Custom configuration applied only to the Deb packager.
 deb:
-  # Custom deb rules script.
+  # Custom deb special files.
   scripts:
+    # Deb rules script.
     rules: foo.sh
+    # Deb templates file, when using debconf.
+    templates: templates
 
   # Custom deb triggers
   triggers:


Test patch:
diff --git a/deb/deb_test.go b/deb/deb_test.go
index ed59f5e..2995497 100644
--- a/deb/deb_test.go
+++ b/deb/deb_test.go
@@ -197,17 +197,17 @@ func TestControl(t *testing.T) {
 	assert.Equal(t, string(bts), w.String())
 }
 
-func TestScripts(t *testing.T) {
+func TestSpecialFiles(t *testing.T) {
 	var w bytes.Buffer
 	var out = tar.NewWriter(&w)
-	filePath := "../testdata/scripts/preinstall.sh"
-	assert.Error(t, newScriptInsideTarGz(out, "doesnotexit", "preinst"))
-	require.NoError(t, newScriptInsideTarGz(out, filePath, "preinst"))
+	filePath := "testdata/templates.golden"
+	assert.Error(t, newFilePathInsideTarGz(out, "doesnotexit", "templates", 0644))
+	require.NoError(t, newFilePathInsideTarGz(out, filePath, "templates", 0644))
 	var in = tar.NewReader(&w)
 	header, err := in.Next()
 	require.NoError(t, err)
-	assert.Equal(t, "preinst", header.FileInfo().Name())
-	mode, err := strconv.ParseInt("0755", 8, 64)
+	assert.Equal(t, "templates", header.FileInfo().Name())
+	mode, err := strconv.ParseInt("0644", 8, 64)
 	require.NoError(t, err)
 	assert.Equal(t, int64(header.FileInfo().Mode()), mode)
 	data, err := ioutil.ReadAll(in)
diff --git a/deb/testdata/templates.golden b/deb/testdata/templates.golden
new file mode 100644
index 0000000..2bb149b
--- /dev/null
+++ b/deb/testdata/templates.golden
@@ -0,0 +1,4 @@
+Template: templates/lala
+Type: string
+Description: Set lala for templates.
+ For the test purpose this templates.golden is created.