Repository: theupdateframework/go-tuf
Pull request #240 (2022-03-26 22:43:19)

use int64 instead of int for metadata version
Release Notes: Metadata version now uses int64

**Types of changes**:
- [x] Breaking change (fix or feature that would cause existing functionality to not work as expected)

**Description of the changes being introduced by the pull request**:

We have a high write throughput on our TUF repositories and there's a good chance we'll reach 2B+ snapshots versions in the future which would break our clients on 32bit archs. Let's standardize to `int64` to avoid any surprises.

coveralls: ## Pull Request Test Coverage Report for [Build 2045946320](https://coveralls.io/builds/47720574)

* **14** of **21**   **(66.67%)**  changed or added relevant lines in **5** files are covered.
* **1** unchanged line in **1** file lost coverage.
* Overall coverage remained the same at **71.277%**

---

|  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
| :-----|--------------|--------|---: |
| [verify/verify.go](https://coveralls.io/builds/47720574/source?filename=verify%2Fverify.go#L139) | 3 | 4 | 75.0%
| [repo.go](https://coveralls.io/builds/47720574/source?filename=repo.go#L205) | 6 | 9 | 66.67%
| [util/util.go](https://coveralls.io/builds/47720574/source?filename=util%2Futil.go#L189) | 1 | 4 | 25.0%
<!-- | **Total:** | **14** | **21** | **66.67%** | -->

|  Files with Coverage Reduction | New Missed Lines | % |
| :-----|--------------|--: |
| [util/util.go](https://coveralls.io/builds/47720574/source?filename=util%2Futil.go#L258) | 1 | 40.84% |
<!-- | **Total:** | **1** |  | -->

|  Totals | [![Coverage Status](https://coveralls.io/builds/47720574/badge)](https://coveralls.io/builds/47720574) |
| :-- | --: |
| Change from base [Build 2029695489](https://coveralls.io/builds/47625270): |  0.0% |
| Covered Lines: | 2278 |
| Relevant Lines: | 3196 |

---
##### 💛  - [Coveralls](https://coveralls.io)


Patch:
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index b2b5771..a1423f0 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,7 +1,32 @@
 version: 2
 updates:
-- package-ecosystem: "gomod"
-  directory: "/"
-  schedule:
-    interval: "daily"
-  open-pull-requests-limit: 10
+  # Monitor Go dependencies
+  - package-ecosystem: "gomod"
+    directory: "/"
+    schedule:
+      interval: "daily"
+      time: "10:00"
+    commit-message:
+      prefix: "chore"
+      include: "scope"
+    open-pull-requests-limit: 10
+  # Monitor Github Actions
+  - package-ecosystem: "github-actions"
+    directory: "/"
+    schedule:
+      interval: "daily"
+      time: "10:00"
+    commit-message:
+      prefix: "chore"
+      include: "scope"
+    open-pull-requests-limit: 10
+  # Monitor Python test dependencies
+  - package-ecosystem: "pip"
+    directory: "/"
+    schedule:
+      interval: "daily"
+      time: "10:00"
+    commit-message:
+      prefix: "chore"
+      include: "scope"
+    open-pull-requests-limit: 10
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
deleted file mode 100644
index d1a2160..0000000
--- a/.github/workflows/build.yml
+++ /dev/null
@@ -1,41 +0,0 @@
-on: [push, pull_request]
-name: build
-jobs:
-  test:
-    strategy:
-      matrix:
-        go-version: [1.16.x, 1.17.x]
-        os: [ubuntu-latest, macos-latest]
-    runs-on: ${{ matrix.os }}
-    steps:
-    - name: Install Go
-      uses: actions/setup-go@v2
-      with:
-        go-version: ${{ matrix.go-version }}
-    - name: Setup Python
-      uses: actions/setup-python@v2
-      with:
-        python-version: 3.6
-    - name: Checkout code
-      uses: actions/checkout@v2
-    - name: Install Python dependencies
-      run: |
-        python -m pip install --upgrade iso8601 requests securesystemslib six tuf
-    - name: Format Unix
-      if: runner.os == 'Linux'
-      run: test -z $(go fmt ./...)
-    - name: Test
-      run: go test -race -covermode atomic -coverprofile='profile.cov' ./...
-    - name: Send coverage
-      if: runner.os == 'Linux'
-      env:
-        COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-      run: |
-        GO111MODULE=off go get github.com/mattn/goveralls
-        $(go env GOPATH)/bin/goveralls -coverprofile=profile.cov -service=github
-    - name: Vet
-      run: go vet ./...
-    - name: Install staticcheck
-      run: "go install honnef.co/go/tools/cmd/staticcheck@v0.2.2"
-    - name: Run staticcheck
-      run: staticcheck ./...
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..6de8931
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,23 @@
+on:
+  pull_request:
+  push:
+    branches:
+      - "master"
+    tags:
+      - "v*"
+name: CI
+jobs:
+  tests:
+    uses: ./.github/workflows/tests.yml
+  tuf:
+    needs: tests
+    if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
+    uses: ./.github/workflows/release.yml
+    with:
+      cli-name: tuf
+  tuf-client:
+    needs: tests
+    if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
+    uses: ./.github/workflows/release.yml
+    with:
+      cli-name: tuf-client
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..ac54755
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,34 @@
+on:
+  workflow_call:
+    inputs:
+      cli-name:
+        required: true
+        type: string
+name: Release
+jobs:
+  release:
+    permissions:
+      contents: write
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
+        with:
+          fetch-depth: 0
+      - name: Get Go version
+        uses: arnested/go-version-action@d44f8fbecf1ac5ea61d81603e99dfec9833f592f
+        id: go-version
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      - name: Set up Go
+        uses: actions/setup-go@f6164bd8c8acb4a71fb2791a8b6c4024ff038dab
+        with:
+          go-version: ${{ steps.go-version.outputs.minimal }}
+      - name: Run GoReleaser
+        uses: goreleaser/goreleaser-action@b953231f81b8dfd023c58e0854a721e35037f28b
+        with:
+          distribution: goreleaser
+          version: "v1.7.0"
+          args: release --config ./.goreleaser/${{ inputs.cli-name }}.yml --rm-dist
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.golangci.yml b/.golangci.yml
new file mode 100644
index 0000000..4d86052
--- /dev/null
+++ b/.golangci.yml
@@ -0,0 +1,11 @@
+linters:
+  disable-all: true
+  enable:
+    - staticcheck
+    - gofmt
+    - govet
+    - gosimple
+    - structcheck
+    - varcheck
+    - unused
+    - typecheck
diff --git a/.goreleaser/tuf-client.yml b/.goreleaser/tuf-client.yml
new file mode 100644
index 0000000..36a46ae
--- /dev/null
+++ b/.goreleaser/tuf-client.yml
@@ -0,0 +1,39 @@
+project_name: tuf-client
+builds:
+  - ldflags:
+      - "-s -w"
+      - "-extldflags=-zrelro"
+      - "-extldflags=-znow"
+    env:
+      - "CGO_ENABLED=0"
+      - "GO111MODULE=on"
+    flags:
+      - -mod=readonly
+      - -trimpath
+    goos:
+      - linux
+      - darwin
+      - windows
+    goarch:
+      - amd64
+    main: ./cmd/tuf-client/
+source:
+  enabled: true
+changelog:
+  use: github
+  groups:
+    - title: "Breaking changes"
+      regexp: "^.*BREAKING CHANGE[(\\w)]*:+.*$"
+      order: 0
+    - title: Features
+      regexp: "^.*feat[(\\w)]*:+.*$"
+      order: 1
+    - title: "Bug fixes"
+      regexp: "^.*fix[(\\w)]*:+.*$"
+      order: 2
+    - title: Others
+      order: 999
+release:
+  # If set to auto, will mark the release as not ready for production
+  # in case there is an indicator for this in the tag e.g. v1.0.0-rc1
+  prerelease: auto
diff --git a/.goreleaser/tuf.yml b/.goreleaser/tuf.yml
new file mode 100644
index 0000000..eaa45c7
--- /dev/null
+++ b/.goreleaser/tuf.yml
@@ -0,0 +1,39 @@
+project_name: tuf
+builds:
+  - ldflags:
+      - "-s -w"
+      - "-extldflags=-zrelro"
+      - "-extldflags=-znow"
+    env:
+      - "CGO_ENABLED=0"
+      - "GO111MODULE=on"
+    flags:
+      - -mod=readonly
+      - -trimpath
+    goos:
+      - linux
+      - darwin
+      - windows
+    goarch:
+      - amd64
+    main: ./cmd/tuf/
+source:
+  enabled: true
+changelog:
+  use: github
+  groups:
+    - title: "Breaking changes"
+      regexp: "^.*BREAKING CHANGE[(\\w)]*:+.*$"
+      order: 0
+    - title: Features
+      regexp: "^.*feat[(\\w)]*:+.*$"
+      order: 1
+    - title: "Bug fixes"
+      regexp: "^.*fix[(\\w)]*:+.*$"
+      order: 2
+    - title: Others
+      order: 999
+release:
+  # If set to auto, will mark the release as not ready for production
+  # in case there is an indicator for this in the tag e.g. v1.0.0-rc1
+  prerelease: auto
diff --git a/client/client.go b/client/client.go
index 893e161..bf22041 100644
--- a/client/client.go
+++ b/client/client.go
@@ -69,10 +69,10 @@ type Client struct {
 
 	// The following four fields represent the versions of metatdata either
 	// from local storage or from recently downloaded metadata
-	rootVer      int
-	targetsVer   int
-	snapshotVer  int
-	timestampVer int
+	rootVer      int64
+	targetsVer   int64
+	snapshotVer  int64
+	timestampVer int64
 
 	// targets is the list of available targets, either from local storage
 	// or from recently downloaded targets metadata
@@ -612,7 +612,7 @@ func (c *Client) downloadTarget(file string, get remoteGetFunc, hashes data.Hash
 
 // downloadVersionedMeta downloads top-level metadata from remote storage and
 // verifies it using the given file metadata.
-func (c *Client) downloadMeta(name string, version int, m data.FileMeta) ([]byte, error) {
+func (c *Client) downloadMeta(name string, version int64, m data.FileMeta) ([]byte, error) {
 	r, size, err := func() (io.ReadCloser, int64, error) {
 		if c.consistentSnapshot {
 			path := util.VersionedPath(name, version)
diff --git a/client/errors.go b/client/errors.go
index 4806ba4..44a36d2 100644
--- a/client/errors.go
+++ b/client/errors.go
@@ -42,7 +42,7 @@ func (e ErrDecodeFailed) Error() string {
 type ErrMaxDelegations struct {
 	Target          string
 	MaxDelegations  int
-	SnapshotVersion int
+	SnapshotVersion int64
 }
 
 func (e ErrMaxDelegations) Error() string {
@@ -87,7 +87,7 @@ func (e ErrWrongSize) Error() string {
 }
 
 type ErrLatestSnapshot struct {
-	Version int
+	Version int64
 }
 
 func (e ErrLatestSnapshot) Error() string {
@@ -101,7 +101,7 @@ func IsLatestSnapshot(err error) bool {
 
 type ErrUnknownTarget struct {
 	Name            string
-	SnapshotVersion int
+	SnapshotVersion int64
 }
 
 func (e ErrUnknownTarget) Error() string {
@@ -128,7 +128,7 @@ func (e ErrInvalidURL) Error() string {
 
 type ErrRoleNotInSnapshot struct {
 	Role            string
-	SnapshotVersion int
+	SnapshotVersion int64
 }
 
 func (e ErrRoleNotInSnapshot) Error() string {
diff --git a/data/types.go b/data/types.go
index db60c16..6ec2fc3 100644
--- a/data/types.go
+++ b/data/types.go
@@ -96,7 +96,7 @@ func DefaultExpires(role string) time.Time {
 type Root struct {
 	Type        string                `json:"_type"`
 	SpecVersion string                `json:"spec_version"`
-	Version     int                   `json:"version"`
+	Version     int64                 `json:"version"`
 	Expires     time.Time             `json:"expires"`
 	Keys        map[string]*PublicKey `json:"keys"`
 	Roles       map[string]*Role      `json:"roles"`
@@ -167,7 +167,7 @@ func (f FileMeta) HashAlgorithms() []string {
 
 type SnapshotFileMeta struct {
 	FileMeta
-	Version int `json:"version"`
+	Version int64 `json:"version"`
 }
 
 type SnapshotFiles map[string]SnapshotFileMeta
@@ -175,7 +175,7 @@ type SnapshotFiles map[string]SnapshotFileMeta
 type Snapshot struct {
 	Type        string           `json:"_type"`
 	SpecVersion string           `json:"spec_version"`
-	Version     int              `json:"version"`
+	Version     int64            `json:"version"`
 	Expires     time.Time        `json:"expires"`
 	Meta        SnapshotFiles    `json:"meta"`
 	Custom      *json.RawMessage `json:"custom,omitempty"`
@@ -203,7 +203,7 @@ func (f TargetFileMeta) HashAlgorithms() []string {
 type Targets struct {
 	Type        string           `json:"_type"`
 	SpecVersion string           `json:"spec_version"`
-	Version     int              `json:"version"`
+	Version     int64            `json:"version"`
 	Expires     time.Time        `json:"expires"`
 	Targets     TargetFiles      `json:"targets"`
 	Delegations *Delegations     `json:"delegations,omitempty"`
@@ -302,7 +302,7 @@ func NewTargets() *Targets {
 
 type TimestampFileMeta struct {
 	FileMeta
-	Version int `json:"version"`
+	Version int64 `json:"version"`
 }
 
 type TimestampFiles map[string]TimestampFileMeta
@@ -310,7 +310,7 @@ type TimestampFiles map[string]TimestampFileMeta
 type Timestamp struct {
 	Type        string           `json:"_type"`
 	SpecVersion string           `json:"spec_version"`
-	Version     int              `json:"version"`
+	Version     int64            `json:"version"`
 	Expires     time.Time        `json:"expires"`
 	Meta        TimestampFiles   `json:"meta"`
 	Custom      *json.RawMessage `json:"custom,omitempty"`
diff --git a/local_store.go b/local_store.go
index 86eceef..9456016 100644
--- a/local_store.go
+++ b/local_store.go
@@ -40,7 +40,7 @@ type LocalStore interface {
 	// This will also reset the staged meta to signal incrementing version numbers.
 	// TUF 1.0 requires that the root metadata version numbers in the repository does not
 	// gaps. To avoid this, we will only increment the number once until we commit.
-	Commit(bool, map[string]int, map[string]data.Hashes) error
+	Commit(bool, map[string]int64, map[string]data.Hashes) error
 
 	// GetSigners return a list of signers for a role.
 	GetSigners(role string) ([]keys.Signer, error)
@@ -125,7 +125,7 @@ func (m *memoryStore) WalkStagedTargets(paths []string, targetsFn TargetsWalkFun
 	return nil
 }
 
-func (m *memoryStore) Commit(consistentSnapshot bool, versions map[string]int, hashes map[string]data.Hashes) error {
+func (m *memoryStore) Commit(consistentSnapshot bool, versions map[string]int64, hashes map[string]data.Hashes) error {
 	for name, meta := range m.stagedMeta {
 		paths := computeMetadataPaths(consistentSnapshot, name, versions)
 		for _, path := range paths {
@@ -369,7 +369,7 @@ func (f *fileSystemStore) createRepoFile(path string) (*os.File, error) {
 	return os.Create(dst)
 }
 
-func (f *fileSystemStore) Commit(consistentSnapshot bool, versions map[string]int, hashes map[string]data.Hashes) error {
+func (f *fileSystemStore) Commit(consistentSnapshot bool, versions map[string]int64, hashes map[string]data.Hashes) error {
 	isTarget := func(path string) bool {
 		return strings.HasPrefix(path, "targets/")
 	}
@@ -410,6 +410,7 @@ func (f *fileSystemStore) Commit(consistentSnapshot bool, versions map[string]in
 		}
 		return nil
 	}
+	// Checks if target file should be deleted
 	needsRemoval := func(path string) bool {
 		if consistentSnapshot {
 			// strip out the hash
@@ -422,6 +423,16 @@ func (f *fileSystemStore) Commit(consistentSnapshot bool, versions map[string]in
 		_, ok := hashes[path]
 		return !ok
 	}
+	// Checks if folder is empty
+	folderNeedsRemoval := func(path string) bool {
+		f, err := os.Open(path)
+		if err != nil {
+			return false
+		}
+		defer f.Close()
+		_, err = f.Readdirnames(1)
+		return err == io.EOF
+	}
 	removeFile := func(path string, info os.FileInfo, err error) error {
 		if err != nil {
 			return err
@@ -431,11 +442,17 @@ func (f *fileSystemStore) Commit(consistentSnapshot bool, versions map[string]in
 			return err
 		}
 		if !info.IsDir() && isTarget(rel) && needsRemoval(rel) {
-			//lint:ignore SA9003 empty branch
+			// Delete the target file
 			if err := os.Remove(path); err != nil {
-				// TODO: log / handle error
+				return err
+			}
+			// Delete the target folder too if it's empty
+			targetFolder := filepath.Dir(path)
+			if folderNeedsRemoval(targetFolder) {
+				if err := os.Remove(targetFolder); err != nil {
+					return err
+				}
 			}
-			// TODO: remove empty directory
 		}
 		return nil
 	}
@@ -683,7 +700,7 @@ func computeTargetPaths(consistentSnapshot bool, name string, hashes map[string]
 	}
 }
 
-func computeMetadataPaths(consistentSnapshot bool, name string, versions map[string]int) []string {
+func computeMetadataPaths(consistentSnapshot bool, name string, versions map[string]int64) []string {
 	copyVersion := false
 
 	switch name {
diff --git a/internal/targets/hash_bins.go b/pkg/targets/hash_bins.go
similarity index 100%
rename from internal/targets/hash_bins.go
rename to pkg/targets/hash_bins.go
diff --git a/internal/targets/hash_bins_test.go b/pkg/targets/hash_bins_test.go
similarity index 100%
rename from internal/targets/hash_bins_test.go
rename to pkg/targets/hash_bins_test.go
diff --git a/repo.go b/repo.go
index 53a65a7..1f513ec 100644
--- a/repo.go
+++ b/repo.go
@@ -143,7 +143,7 @@ func (r *Repo) snapshot() (*data.Snapshot, error) {
 	return snapshot, nil
 }
 
-func (r *Repo) RootVersion() (int, error) {
+func (r *Repo) RootVersion() (int64, error) {
 	root, err := r.root()
 	if err != nil {
 		return -1, err
@@ -202,7 +202,7 @@ func (r *Repo) Targets() (data.TargetFiles, error) {
 	return targets.Targets, nil
 }
 
-func (r *Repo) SetTargetsVersion(v int) error {
+func (r *Repo) SetTargetsVersion(v int64) error {
 	t, err := r.topLevelTargets()
 	if err != nil {
 		return err
@@ -211,7 +211,7 @@ func (r *Repo) SetTargetsVersion(v int) error {
 	return r.setTopLevelMeta("targets.json", t)
 }
 
-func (r *Repo) TargetsVersion() (int, error) {
+func (r *Repo) TargetsVersion() (int64, error) {
 	t, err := r.topLevelTargets()
 	if err != nil {
 		return -1, err
@@ -219,7 +219,7 @@ func (r *Repo) TargetsVersion() (int, error) {
 	return t.Version, nil
 }
 
-func (r *Repo) SetTimestampVersion(v int) error {
+func (r *Repo) SetTimestampVersion(v int64) error {
 	ts, err := r.timestamp()
 	if err != nil {
 		return err
@@ -228,7 +228,7 @@ func (r *Repo) SetTimestampVersion(v int) error {
 	return r.setTopLevelMeta("timestamp.json", ts)
 }
 
-func (r *Repo) TimestampVersion() (int, error) {
+func (r *Repo) TimestampVersion() (int64, error) {
 	ts, err := r.timestamp()
 	if err != nil {
 		return -1, err
@@ -236,7 +236,7 @@ func (r *Repo) TimestampVersion() (int, error) {
 	return ts.Version, nil
 }
 
-func (r *Repo) SetSnapshotVersion(v int) error {
+func (r *Repo) SetSnapshotVersion(v int64) error {
 	s, err := r.snapshot()
 	if err != nil {
 		return err
@@ -246,7 +246,7 @@ func (r *Repo) SetSnapshotVersion(v int) error {
 	return r.setTopLevelMeta("snapshot.json", s)
 }
 
-func (r *Repo) SnapshotVersion() (int, error) {
+func (r *Repo) SnapshotVersion() (int64, error) {
 	s, err := r.snapshot()
 	if err != nil {
 		return -1, err
@@ -903,7 +903,7 @@ func (r *Repo) TimestampWithExpires(expires time.Time) error {
 	return err
 }
 
-func (r *Repo) fileVersions() (map[string]int, error) {
+func (r *Repo) fileVersions() (map[string]int64, error) {
 	root, err := r.root()
 	if err != nil {
 		return nil, err
@@ -916,7 +916,7 @@ func (r *Repo) fileVersions() (map[string]int, error) {
 	if err != nil {
 		return nil, err
 	}
-	versions := make(map[string]int)
+	versions := make(map[string]int64)
 	versions["root.json"] = root.Version
 	versions["targets.json"] = targets.Version
 	versions["snapshot.json"] = snapshot.Version
diff --git a/util/util.go b/util/util.go
index ac86761..b6bf9cf 100644
--- a/util/util.go
+++ b/util/util.go
@@ -30,8 +30,8 @@ func (e ErrWrongLength) Error() string {
 }
 
 type ErrWrongVersion struct {
-	Expected int
-	Actual   int
+	Expected int64
+	Actual   int64
 }
 
 func (e ErrWrongVersion) Error() string {
@@ -102,7 +102,7 @@ func hashEqual(actual data.Hashes, expected data.Hashes) error {
 	return nil
 }
 
-func versionEqual(actual int, expected int) error {
+func versionEqual(actual int64, expected int64) error {
 	if actual != expected {
 		return ErrWrongVersion{expected, actual}
 	}
@@ -183,10 +183,10 @@ func GenerateFileMeta(r io.Reader, hashAlgorithms ...string) (data.FileMeta, err
 }
 
 type versionedMeta struct {
-	Version int `json:"version"`
+	Version int64 `json:"version"`
 }
 
-func generateVersionedFileMeta(r io.Reader, hashAlgorithms ...string) (data.FileMeta, int, error) {
+func generateVersionedFileMeta(r io.Reader, hashAlgorithms ...string) (data.FileMeta, int64, error) {
 	b, err := ioutil.ReadAll(r)
 	if err != nil {
 		return data.FileMeta{}, 0, err
@@ -253,8 +253,8 @@ func NormalizeTarget(p string) string {
 	return strings.TrimPrefix(path.Join("/", p), "/")
 }
 
-func VersionedPath(p string, version int) string {
-	return path.Join(path.Dir(p), strconv.Itoa(version)+"."+path.Base(p))
+func VersionedPath(p string, version int64) string {
+	return path.Join(path.Dir(p), strconv.FormatInt(version, 10)+"."+path.Base(p))
 }
 
 func HashedPaths(p string, hashes data.Hashes) []string {
diff --git a/verify/errors.go b/verify/errors.go
index c84f216..11dfa14 100644
--- a/verify/errors.go
+++ b/verify/errors.go
@@ -43,8 +43,8 @@ func (e ErrExpired) Error() string {
 }
 
 type ErrLowVersion struct {
-	Actual  int
-	Current int
+	Actual  int64
+	Current int64
 }
 
 func (e ErrLowVersion) Error() string {
@@ -52,8 +52,8 @@ func (e ErrLowVersion) Error() string {
 }
 
 type ErrWrongVersion struct {
-	Given    int
-	Expected int
+	Given    int64
+	Expected int64
 }
 
 func (e ErrWrongVersion) Error() string {
diff --git a/verify/verify.go b/verify/verify.go
index 2586a60..7b6726f 100644
--- a/verify/verify.go
+++ b/verify/verify.go
@@ -13,10 +13,10 @@ import (
 type signedMeta struct {
 	Type    string    `json:"_type"`
 	Expires time.Time `json:"expires"`
-	Version int       `json:"version"`
+	Version int64     `json:"version"`
 }
 
-func (db *DB) VerifyIgnoreExpiredCheck(s *data.Signed, role string, minVersion int) error {
+func (db *DB) VerifyIgnoreExpiredCheck(s *data.Signed, role string, minVersion int64) error {
 	if err := db.VerifySignatures(s, role); err != nil {
 		return err
 	}
@@ -46,7 +46,7 @@ func (db *DB) VerifyIgnoreExpiredCheck(s *data.Signed, role string, minVersion i
 	return nil
 }
 
-func (db *DB) Verify(s *data.Signed, role string, minVersion int) error {
+func (db *DB) Verify(s *data.Signed, role string, minVersion int64) error {
 
 	err := db.VerifyIgnoreExpiredCheck(s, role, minVersion)
 
@@ -124,7 +124,7 @@ func (db *DB) VerifySignatures(s *data.Signed, role string) error {
 	return nil
 }
 
-func (db *DB) Unmarshal(b []byte, v interface{}, role string, minVersion int) error {
+func (db *DB) Unmarshal(b []byte, v interface{}, role string, minVersion int64) error {
 	s := &data.Signed{}
 	if err := json.Unmarshal(b, s); err != nil {
 		return err
@@ -136,7 +136,7 @@ func (db *DB) Unmarshal(b []byte, v interface{}, role string, minVersion int) er
 }
 
 // UnmarshalExpired is exactly like Unmarshal except ignores expired timestamp error.
-func (db *DB) UnmarshalIgnoreExpired(b []byte, v interface{}, role string, minVersion int) error {
+func (db *DB) UnmarshalIgnoreExpired(b []byte, v interface{}, role string, minVersion int64) error {
 	s := &data.Signed{}
 	if err := json.Unmarshal(b, s); err != nil {
 		return err


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 0000000..a55d5ae
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,78 @@
+on:
+  workflow_call:
+name: Tests
+jobs:
+  get-go-versions:
+    name: Collect available Go versions
+    runs-on: ubuntu-latest
+    outputs:
+      matrix: ${{ steps.versions.outputs.matrix }}
+    steps:
+      - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
+      - uses: arnested/go-version-action@d44f8fbecf1ac5ea61d81603e99dfec9833f592f
+        id: versions
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+  run:
+    strategy:
+      matrix:
+        os: [ubuntu-latest, macos-latest]
+        go-version: ${{ fromJSON(needs.get-go-versions.outputs.matrix) }}
+    runs-on: ${{ matrix.os }}
+    needs: get-go-versions
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
+
+      - name: Setup - Go ${{ matrix.go-version }}
+        uses: actions/setup-go@f6164bd8c8acb4a71fb2791a8b6c4024ff038dab
+        with:
+          go-version: ${{ matrix.go-version }}
+
+      - name: Setup - Python
+        uses: actions/setup-python@7f80679172b057fc5e90d70d197929d454754a5a
+        with:
+          python-version: 3.6
+          cache: "pip"
+          cache-dependency-path: "requirements-test.txt"
+
+      - name: Install Python dependencies
+        run: |
+          python3 -m pip install --upgrade pip
+          python3 -m pip install --upgrade -r requirements-test.txt
+
+      - name: Run tests
+        run: go test -race -covermode atomic -coverprofile='profile.cov' ./...
+
+      - name: Send coverage
+        uses: shogo82148/actions-goveralls@31ee804b8576ae49f6dc3caa22591bc5080e7920
+        with:
+          path-to-profile: profile.cov
+          flag-name: Go-${{ matrix.go-version }}
+          parallel: true
+
+  golangci:
+    strategy:
+      matrix:
+        go-version: ${{ fromJSON(needs.get-go-versions.outputs.matrix) }}
+        os: [ubuntu-latest, macos-latest]
+    runs-on: ${{ matrix.os }}
+    needs: get-go-versions
+    steps:
+      - uses: actions/setup-go@f6164bd8c8acb4a71fb2791a8b6c4024ff038dab
+      - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
+      - name: golangci-lint
+        uses: golangci/golangci-lint-action@5c56cd6c9dc07901af25baab6f2b0d9f3b7c3018
+        with:
+          version: v1.45.2
+
+  conventional-commits-lint-check:
+    runs-on: "ubuntu-latest"
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
+        with:
+          fetch-depth: 0
+      - name: Commitsar Action
+        uses: aevea/commitsar@159cec82966ca402a09ae3c185524a5256affa22
diff --git a/client/client_test.go b/client/client_test.go
index 5ad38b3..85fa57e 100644
--- a/client/client_test.go
+++ b/client/client_test.go
@@ -456,39 +456,39 @@ func (s *ClientSuite) TestUpdateRoots(c *C) {
 	var tests = []struct {
 		fixturePath      string
 		expectedError    error
-		expectedVersions map[string]int
+		expectedVersions map[string]int64
 	}{
 		// Succeeds when there is no root update.
-		{"testdata/Published1Time", nil, map[string]int{"root": 1, "timestamp": 1, "snapshot": 1, "targets": 1}},
+		{"testdata/Published1Time", nil, map[string]int64{"root": 1, "timestamp": 1, "snapshot": 1, "targets": 1}},
 		// Succeeds when client only has root.json
-		{"testdata/Published1Time_client_root_only", nil, map[string]int{"root": 1, "timestamp": 1, "snapshot": 1, "targets": 1}},
+		{"testdata/Published1Time_client_root_only", nil, map[string]int64{"root": 1, "timestamp": 1, "snapshot": 1, "targets": 1}},
 		// Succeeds updating root from version 1 to version 2.
-		{"testdata/Published2Times_keyrotated", nil, map[string]int{"root": 2, "timestamp": 1, "snapshot": 1, "targets": 1}},
+		{"testdata/Published2Times_keyrotated", nil, map[string]int64{"root": 2, "timestamp": 1, "snapshot": 1, "targets": 1}},
 		// Succeeds updating root from version 1 to version 2 when the client's initial root version is expired.
-		{"testdata/Published2Times_keyrotated_initialrootexpired", nil, map[string]int{"root": 2, "timestamp": 1, "snapshot": 1, "targets": 1}},
+		{"testdata/Published2Times_keyrotated_initialrootexpired", nil, map[string]int64{"root": 2, "timestamp": 1, "snapshot": 1, "targets": 1}},
 		// Succeeds updating root from version 1 to version 3 when versions 1 and 2 are expired.
-		{"testdata/Published3Times_keyrotated_initialrootsexpired", nil, map[string]int{"root": 3, "timestamp": 1, "snapshot": 1, "targets": 1}},
+		{"testdata/Published3Times_keyrotated_initialrootsexpired", nil, map[string]int64{"root": 3, "timestamp": 1, "snapshot": 1, "targets": 1}},
 		// Succeeds updating root from version 2 to version 3.
-		{"testdata/Published3Times_keyrotated_initialrootsexpired_clientversionis2", nil, map[string]int{"root": 3, "timestamp": 1, "snapshot": 1, "targets": 1}},
+		{"testdata/Published3Times_keyrotated_initialrootsexpired_clientversionis2", nil, map[string]int64{"root": 3, "timestamp": 1, "snapshot": 1, "targets": 1}},
 		// Fails updating root from version 1 to version 3 when versions 1 and 3 are expired but version 2 is not expired.
-		{"testdata/Published3Times_keyrotated_latestrootexpired", ErrDecodeFailed{File: "root.json", Err: verify.ErrExpired{}}, map[string]int{"root": 2, "timestamp": 1, "snapshot": 1, "targets": 1}},
+		{"testdata/Published3Times_keyrotated_latestrootexpired", ErrDecodeFailed{File: "root.json", Err: verify.ErrExpired{}}, map[string]int64{"root": 2, "timestamp": 1, "snapshot": 1, "targets": 1}},
 		// Fails updating root from version 1 to version 2 when old root 1 did not sign off on it (nth root didn't sign off n+1).
-		{"testdata/Published2Times_keyrotated_invalidOldRootSignature", errors.New("tuf: signature verification failed"), map[string]int{}},
+		{"testdata/Published2Times_keyrotated_invalidOldRootSignature", errors.New("tuf: signature verification failed"), map[string]int64{}},
 		// Fails updating root from version 1 to version 2 when the new root 2 did not sign itself (n+1th root didn't sign off n+1)
-		{"testdata/Published2Times_keyrotated_invalidNewRootSignature", errors.New("tuf: signature verification failed"), map[string]int{}},
+		{"testdata/Published2Times_keyrotated_invalidNewRootSignature", errors.New("tuf: signature verification failed"), map[string]int64{}},
 		// Fails updating root to 2.root.json when the value of the version field inside it is 1 (rollback attack prevention).
-		{"testdata/Published1Time_backwardRootVersion", verify.ErrWrongVersion(verify.ErrWrongVersion{Given: 1, Expected: 2}), map[string]int{}},
+		{"testdata/Published1Time_backwardRootVersion", verify.ErrWrongVersion(verify.ErrWrongVersion{Given: 1, Expected: 2}), map[string]int64{}},
 		// Fails updating root to 2.root.json when the value of the version field inside it is 3 (rollforward attack prevention).
-		{"testdata/Published3Times_keyrotated_forwardRootVersion", verify.ErrWrongVersion(verify.ErrWrongVersion{Given: 3, Expected: 2}), map[string]int{}},
+		{"testdata/Published3Times_keyrotated_forwardRootVersion", verify.ErrWrongVersion(verify.ErrWrongVersion{Given: 3, Expected: 2}), map[string]int64{}},
 		// Fails updating when there is no local trusted root.
-		{"testdata/Published1Time_client_no_root", errors.New("tuf: no root keys found in local meta store"), map[string]int{}},
+		{"testdata/Published1Time_client_no_root", errors.New("tuf: no root keys found in local meta store"), map[string]int64{}},
 
 		// snapshot role key rotation increase the snapshot and timestamp.
-		{"testdata/Published2Times_snapshot_keyrotated", nil, map[string]int{"root": 2, "timestamp": 2, "snapshot": 2, "targets": 1}},
+		{"testdata/Published2Times_snapshot_keyrotated", nil, map[string]int64{"root": 2, "timestamp": 2, "snapshot": 2, "targets": 1}},
 		// targets role key rotation increase the snapshot, timestamp, and targets.
-		{"testdata/Published2Times_targets_keyrotated", nil, map[string]int{"root": 2, "timestamp": 2, "snapshot": 2, "targets": 2}},
+		{"testdata/Published2Times_targets_keyrotated", nil, map[string]int64{"root": 2, "timestamp": 2, "snapshot": 2, "targets": 2}},
 		// timestamp role key rotation increase the timestamp.
-		{"testdata/Published2Times_timestamp_keyrotated", nil, map[string]int{"root": 2, "timestamp": 2, "snapshot": 1, "targets": 1}},
+		{"testdata/Published2Times_timestamp_keyrotated", nil, map[string]int64{"root": 2, "timestamp": 2, "snapshot": 1, "targets": 1}},
 	}
 
 	for _, test := range tests {
@@ -498,7 +498,7 @@ func (s *ClientSuite) TestUpdateRoots(c *C) {
 			c.Assert(err, IsNil)
 			// Check if the root.json is being saved in non-volatile storage.
 			tufClient.getLocalMeta()
-			versionMethods := map[string]int{"root": tufClient.rootVer,
+			versionMethods := map[string]int64{"root": tufClient.rootVer,
 				"timestamp": tufClient.timestampVer,
 				"snapshot":  tufClient.snapshotVer,
 				"targets":   tufClient.targetsVer}
@@ -800,7 +800,7 @@ func (s *ClientSuite) TestUpdateLocalRootExpired(c *C) {
 	c.Assert(s.repo.Commit(), IsNil)
 	s.syncRemote(c)
 
-	const expectedRootVersion = 3
+	const expectedRootVersion = int64(3)
 
 	// check the update downloads the non expired remote root.json and
 	// restarts itself, thus successfully updating
diff --git a/client/delegations_test.go b/client/delegations_test.go
index fe1d72b..c7303ac 100644
--- a/client/delegations_test.go
+++ b/client/delegations_test.go
@@ -129,7 +129,7 @@ func TestPersistedMeta(t *testing.T) {
 
 	type expectedTargets struct {
 		name    string
-		version int
+		version int64
 	}
 	var persistedTests = []struct {
 		file          string
@@ -241,7 +241,7 @@ func TestPersistedMeta(t *testing.T) {
 	}
 }
 
-func versionOfStoredTargets(name string, store map[string]json.RawMessage) (int, error) {
+func versionOfStoredTargets(name string, store map[string]json.RawMessage) (int64, error) {
 	rawTargets, ok := store[name]
 	if !ok {
 		return 0, nil
diff --git a/repo_test.go b/repo_test.go
index 3364373..a021ac0 100644
--- a/repo_test.go
+++ b/repo_test.go
@@ -123,28 +123,28 @@ func testNewRepo(c *C, newRepo func(local LocalStore, hashAlgorithms ...string)
 	root, err := r.root()
 	c.Assert(err, IsNil)
 	c.Assert(root.Type, Equals, "root")
-	c.Assert(root.Version, Equals, 1)
+	c.Assert(root.Version, Equals, int64(1))
 	c.Assert(root.Keys, NotNil)
 	c.Assert(root.Keys, HasLen, 0)
 
 	targets, err := r.topLevelTargets()
 	c.Assert(err, IsNil)
 	c.Assert(targets.Type, Equals, "targets")
-	c.Assert(targets.Version, Equals, 1)
+	c.Assert(targets.Version, Equals, int64(1))
 	c.Assert(targets.Targets, NotNil)
 	c.Assert(targets.Targets, HasLen, 0)
 
 	snapshot, err := r.snapshot()
 	c.Assert(err, IsNil)
 	c.Assert(snapshot.Type, Equals, "snapshot")
-	c.Assert(snapshot.Version, Equals, 1)
+	c.Assert(snapshot.Version, Equals, int64(1))
 	c.Assert(snapshot.Meta, NotNil)
 	c.Assert(snapshot.Meta, HasLen, 0)
 
 	timestamp, err := r.timestamp()
 	c.Assert(err, IsNil)
 	c.Assert(timestamp.Type, Equals, "timestamp")
-	c.Assert(timestamp.Version, Equals, 1)
+	c.Assert(timestamp.Version, Equals, int64(1))
 	c.Assert(timestamp.Meta, NotNil)
 	c.Assert(timestamp.Meta, HasLen, 0)
 }
@@ -354,7 +354,7 @@ func (rs *RepoSuite) TestAddPrivateKey(c *C) {
 	// check root metadata is correct
 	root, err := r.root()
 	c.Assert(err, IsNil)
-	c.Assert(root.Version, Equals, 1)
+	c.Assert(root.Version, Equals, int64(1))
 	c.Assert(root.Roles, NotNil)
 	c.Assert(root.Roles, HasLen, 1)
 	rs.assertNumUniqueKeys(c, root, "root", 1)
@@ -768,19 +768,19 @@ func (rs *RepoSuite) TestCommitVersions(c *C) {
 	// on initial commit everything should be at version 1.
 	rootVersion, err := r.RootVersion()
 	c.Assert(err, IsNil)
-	c.Assert(rootVersion, Equals, 1)
+	c.Assert(rootVersion, Equals, int64(1))
 
 	targetsVersion, err := r.TargetsVersion()
 	c.Assert(err, IsNil)
-	c.Assert(targetsVersion, Equals, 1)
+	c.Assert(targetsVersion, Equals, int64(1))
 
 	snapshotVersion, err := r.SnapshotVersion()
 	c.Assert(err, IsNil)
-	c.Assert(snapshotVersion, Equals, 1)
+	c.Assert(snapshotVersion, Equals, int64(1))
 
 	timestampVersion, err := r.SnapshotVersion()
 	c.Assert(err, IsNil)
-	c.Assert(timestampVersion, Equals, 1)
+	c.Assert(timestampVersion, Equals, int64(1))
 
 	// taking a snapshot should only increment snapshot and timestamp.
 	c.Assert(r.Snapshot(), IsNil)
@@ -789,19 +789,19 @@ func (rs *RepoSuite) TestCommitVersions(c *C) {
 
 	rootVersion, err = r.RootVersion()
 	c.Assert(err, IsNil)
-	c.Assert(rootVersion, Equals, 1)
+	c.Assert(rootVersion, Equals, int64(1))
 
 	targetsVersion, err = r.TargetsVersion()
 	c.Assert(err, IsNil)
-	c.Assert(targetsVersion, Equals, 1)
+	c.Assert(targetsVersion, Equals, int64(1))
 
 	snapshotVersion, err = r.SnapshotVersion()
 	c.Assert(err, IsNil)
-	c.Assert(snapshotVersion, Equals, 2)
+	c.Assert(snapshotVersion, Equals, int64(2))
 
 	timestampVersion, err = r.SnapshotVersion()
 	c.Assert(err, IsNil)
-	c.Assert(timestampVersion, Equals, 2)
+	c.Assert(timestampVersion, Equals, int64(2))
 
 	// rotating multiple keys should increment the root once.
 	genKey(c, r, "targets")
@@ -813,19 +813,19 @@ func (rs *RepoSuite) TestCommitVersions(c *C) {
 
 	rootVersion, err = r.RootVersion()
 	c.Assert(err, IsNil)
-	c.Assert(rootVersion, Equals, 2)
+	c.Assert(rootVersion, Equals, int64(2))
 
 	targetsVersion, err = r.TargetsVersion()
 	c.Assert(err, IsNil)
-	c.Assert(targetsVersion, Equals, 1)
+	c.Assert(targetsVersion, Equals, int64(1))
 
 	snapshotVersion, err = r.SnapshotVersion()
 	c.Assert(err, IsNil)
-	c.Assert(snapshotVersion, Equals, 3)
+	c.Assert(snapshotVersion, Equals, int64(3))
 
 	timestampVersion, err = r.TimestampVersion()
 	c.Assert(err, IsNil)
-	c.Assert(timestampVersion, Equals, 3)
+	c.Assert(timestampVersion, Equals, int64(3))
 }
 
 type tmpDir struct {
@@ -862,11 +862,11 @@ func (t *tmpDir) assertHashedFilesNotExist(path string, hashes data.Hashes) {
 	}
 }
 
-func (t *tmpDir) assertVersionedFileExist(path string, version int) {
+func (t *tmpDir) assertVersionedFileExist(path string, version int64) {
 	t.assertExists(util.VersionedPath(path, version))
 }
 
-func (t *tmpDir) assertVersionedFileNotExist(path string, version int) {
+func (t *tmpDir) assertVersionedFileNotExist(path string, version int64) {
 	t.assertNotExist(util.VersionedPath(path, version))
 }
 
@@ -1034,9 +1034,9 @@ func (rs *RepoSuite) TestConsistentSnapshot(c *C) {
 
 	versions, err := r.fileVersions()
 	c.Assert(err, IsNil)
-	c.Assert(versions["root.json"], Equals, 1)
-	c.Assert(versions["targets.json"], Equals, 1)
-	c.Assert(versions["snapshot.json"], Equals, 1)
+	c.Assert(versions["root.json"], Equals, int64(1))
+	c.Assert(versions["targets.json"], Equals, int64(1))
+	c.Assert(versions["snapshot.json"], Equals, int64(1))
 
 	hashes, err := r.fileHashes()
 	c.Assert(err, IsNil)
@@ -1072,9 +1072,9 @@ func (rs *RepoSuite) TestConsistentSnapshot(c *C) {
 
 	versions, err = r.fileVersions()
 	c.Assert(err, IsNil)
-	c.Assert(versions["root.json"], Equals, 1)
-	c.Assert(versions["targets.json"], Equals, 2)
-	c.Assert(versions["snapshot.json"], Equals, 2)
+	c.Assert(versions["root.json"], Equals, int64(1))
+	c.Assert(versions["targets.json"], Equals, int64(2))
+	c.Assert(versions["snapshot.json"], Equals, int64(2))
 
 	// Save the old hashes for foo.txt to make sure we can assert it doesn't exist later.
 	fooHashes := hashes["targets/foo.txt"]
@@ -1136,7 +1136,7 @@ func (rs *RepoSuite) TestExpiresAndVersion(c *C) {
 
 	root, err := r.root()
 	c.Assert(err, IsNil)
-	c.Assert(root.Version, Equals, 1)
+	c.Assert(root.Version, Equals, int64(1))
 
 	expires := time.Now().Add(24 * time.Hour)
 	_, err = r.GenKeyWithExpires("root", expires)
@@ -1147,7 +1147,7 @@ func (rs *RepoSuite) TestExpiresAndVersion(c *C) {
 	root, err = r.root()
 	c.Assert(err, IsNil)
 	c.Assert(root.Expires.Unix(), DeepEquals, expires.Round(time.Second).Unix())
-	c.Assert(root.Version, Equals, 2)
+	c.Assert(root.Version, Equals, int64(2))
 
 	expires = time.Now().Add(12 * time.Hour)
 	role, ok := root.Roles["root"]
@@ -1162,7 +1162,7 @@ func (rs *RepoSuite) TestExpiresAndVersion(c *C) {
 	root, err = r.root()
 	c.Assert(err, IsNil)
 	c.Assert(root.Expires.Unix(), DeepEquals, expires.Round(time.Second).Unix())
-	c.Assert(root.Version, Equals, 3)
+	c.Assert(root.Version, Equals, int64(3))
 
 	expires = time.Now().Add(6 * time.Hour)
 	c.Assert(r.AddTargetWithExpires("foo.txt", nil, expires), IsNil)
@@ -1172,7 +1172,7 @@ func (rs *RepoSuite) TestExpiresAndVersion(c *C) {
 	targets, err := r.topLevelTargets()
 	c.Assert(err, IsNil)
 	c.Assert(targets.Expires.Unix(), Equals, expires.Round(time.Second).Unix())
-	c.Assert(targets.Version, Equals, 2)
+	c.Assert(targets.Version, Equals, int64(2))
 
 	expires = time.Now().Add(2 * time.Hour)
 	c.Assert(r.RemoveTargetWithExpires("foo.txt", expires), IsNil)
@@ -1182,7 +1182,7 @@ func (rs *RepoSuite) TestExpiresAndVersion(c *C) {
 	targets, err = r.topLevelTargets()
 	c.Assert(err, IsNil)
 	c.Assert(targets.Expires.Unix(), Equals, expires.Round(time.Second).Unix())
-	c.Assert(targets.Version, Equals, 3)
+	c.Assert(targets.Version, Equals, int64(3))
 
 	expires = time.Now().Add(time.Hour)
 	c.Assert(r.SnapshotWithExpires(expires), IsNil)
@@ -1191,7 +1191,7 @@ func (rs *RepoSuite) TestExpiresAndVersion(c *C) {
 	snapshot, err := r.snapshot()
 	c.Assert(err, IsNil)
 	c.Assert(snapshot.Expires.Unix(), Equals, expires.Round(time.Second).Unix())
-	c.Assert(snapshot.Version, Equals, 6)
+	c.Assert(snapshot.Version, Equals, int64(6))
 
 	_, snapshotHasRoot := snapshot.Meta["root.json"]
 	c.Assert(snapshotHasRoot, Equals, false)
@@ -1202,7 +1202,7 @@ func (rs *RepoSuite) TestExpiresAndVersion(c *C) {
 	c.Assert(r.Commit(), IsNil)
 	snapshot, err = r.snapshot()
 	c.Assert(err, IsNil)
-	c.Assert(snapshot.Version, Equals, 7)
+	c.Assert(snapshot.Version, Equals, int64(7))
 
 	expires = time.Now().Add(10 * time.Minute)
 	c.Assert(r.TimestampWithExpires(expires), IsNil)
@@ -1210,13 +1210,13 @@ func (rs *RepoSuite) TestExpiresAndVersion(c *C) {
 	timestamp, err := r.timestamp()
 	c.Assert(err, IsNil)
 	c.Assert(timestamp.Expires.Unix(), Equals, expires.Round(time.Second).Unix())
-	c.Assert(timestamp.Version, Equals, 8)
+	c.Assert(timestamp.Version, Equals, int64(8))
 
 	c.Assert(r.Timestamp(), IsNil)
 	c.Assert(r.Commit(), IsNil)
 	timestamp, err = r.timestamp()
 	c.Assert(err, IsNil)
-	c.Assert(timestamp.Version, Equals, 9)
+	c.Assert(timestamp.Version, Equals, int64(9))
 	c.Assert(timestamp.Meta["snapshot.json"].Version, Equals, snapshot.Version)
 }
 
@@ -1490,7 +1490,7 @@ func (rs *RepoSuite) TestManageMultipleTargets(c *C) {
 	c.Assert(r.Snapshot(), IsNil)
 	c.Assert(r.Timestamp(), IsNil)
 	c.Assert(r.Commit(), IsNil)
-	tmp.assertEmpty("repository/targets")
+	tmp.assertNotExist("repository/targets")
 	t, err := r.topLevelTargets()
 	c.Assert(err, IsNil)
 	c.Assert(t.Targets, HasLen, 0)
@@ -1550,7 +1550,7 @@ func (rs *RepoSuite) TestUnknownKeyIDs(c *C) {
 
 	root, err := r.root()
 	c.Assert(err, IsNil)
-	c.Assert(root.Version, Equals, 1)
+	c.Assert(root.Version, Equals, int64(1))
 
 	root.Keys["unknown-key-id"] = signer.PublicData()
 	r.setTopLevelMeta("root.json", root)
@@ -1574,7 +1574,7 @@ func (rs *RepoSuite) TestUnknownKeyIDs(c *C) {
 		Signatures []data.Signature `json:"signatures"`
 	}
 	c.Assert(json.Unmarshal(rootJSON, &signedRoot), IsNil)
-	c.Assert(signedRoot.Signed.Version, Equals, 1)
+	c.Assert(signedRoot.Signed.Version, Equals, int64(1))
 
 	unknownKey, ok := signedRoot.Signed.Keys["unknown-key-id"]
 	c.Assert(ok, Equals, true)
@@ -1597,7 +1597,7 @@ func (rs *RepoSuite) TestUnknownKeyIDs(c *C) {
 	c.Assert(ok, Equals, true)
 
 	c.Assert(json.Unmarshal(rootJSON, &signedRoot), IsNil)
-	c.Assert(signedRoot.Signed.Version, Equals, 2)
+	c.Assert(signedRoot.Signed.Version, Equals, int64(2))
 
 	unknownKey, ok = signedRoot.Signed.Keys["unknown-key-id"]
 	c.Assert(ok, Equals, true)
@@ -1651,19 +1651,19 @@ func (rs *RepoSuite) TestThreshold(c *C) {
 	// Check versions updated
 	rootVersion, err := r.RootVersion()
 	c.Assert(err, IsNil)
-	c.Assert(rootVersion, Equals, 2)
+	c.Assert(rootVersion, Equals, int64(2))
 
 	targetsVersion, err := r.TargetsVersion()
 	c.Assert(err, IsNil)
-	c.Assert(targetsVersion, Equals, 1)
+	c.Assert(targetsVersion, Equals, int64(1))
 
 	snapshotVersion, err := r.SnapshotVersion()
 	c.Assert(err, IsNil)
-	c.Assert(snapshotVersion, Equals, 2)
+	c.Assert(snapshotVersion, Equals, int64(2))
 
 	timestampVersion, err := r.TimestampVersion()
 	c.Assert(err, IsNil)
-	c.Assert(timestampVersion, Equals, 2)
+	c.Assert(timestampVersion, Equals, int64(2))
 }
 
 func (rs *RepoSuite) TestAddOrUpdateSignatures(c *C) {
diff --git a/requirements-test.txt b/requirements-test.txt
new file mode 100644
index 0000000..e29d3f9
--- /dev/null
+++ b/requirements-test.txt
@@ -0,0 +1,5 @@
+iso8601==1.0.2
+requests==2.27.1
+securesystemslib==0.21.0
+six==1.16.0
+tuf==0.20.0
\ No newline at end of file
diff --git a/util/util_test.go b/util/util_test.go
index ba924f8..4ee4894 100644
--- a/util/util_test.go
+++ b/util/util_test.go
@@ -113,7 +113,7 @@ func (UtilSuite) TestSnapshotFileMetaEqual(c *C) {
 		err      func(test) error
 	}
 
-	fileMeta := func(version int, length int64, hashes map[string]string) data.SnapshotFileMeta {
+	fileMeta := func(version int64, length int64, hashes map[string]string) data.SnapshotFileMeta {
 		return data.SnapshotFileMeta{
 			FileMeta: data.FileMeta{
 				Length: length,
diff --git a/verify/db_test.go b/verify/db_test.go
index e4bab0a..84031ff 100644
--- a/verify/db_test.go
+++ b/verify/db_test.go
@@ -36,7 +36,7 @@ func TestDelegationsDB(t *testing.T) {
 		{
 			testName: "invalid keys",
 			delegations: &data.Delegations{Keys: map[string]*data.PublicKey{
-				"a": &data.PublicKey{Type: data.KeySchemeEd25519},
+				"a": {Type: data.KeySchemeEd25519},
 			}},
 			initErr: ErrWrongID{},
 		},
diff --git a/verify/verify_test.go b/verify/verify_test.go
index 648db32..4d9d379 100644
--- a/verify/verify_test.go
+++ b/verify/verify_test.go
@@ -68,7 +68,7 @@ func (VerifySuite) Test(c *C) {
 		keys  []*data.PublicKey
 		roles map[string]*data.Role
 		s     *data.Signed
-		ver   int
+		ver   int64
 		exp   *time.Time
 		typ   string
 		role  string
@@ -77,7 +77,7 @@ func (VerifySuite) Test(c *C) {
 	}
 
 	expiredTime := time.Now().Add(-time.Hour)
-	minVer := 10
+	minVer := int64(10)
 	tests := []test{
 		{
 			name: "no signatures",
@@ -255,7 +255,7 @@ func (VerifySuite) Test(c *C) {
 }
 
 func (VerifySuite) TestVerifyIgnoreExpired(c *C) {
-	minVer := 10
+	minVer := int64(10)
 	role := "root"
 	k, _ := keys.GenerateEd25519Key()
 	s, _ := sign.Marshal(&signedMeta{Type: role, Version: minVer, Expires: time.Now().Add(-time.Hour)}, k)