Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: tests and general improvements #1

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 1 addition & 22 deletions .github/workflows/ci.yml → .github/workflows/checks.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: CI
name: Checks
on:
push:
branches:
Expand Down Expand Up @@ -32,24 +32,3 @@ jobs:
go-version-file: go.mod
- run: make install-tools
- run: make test

release:
name: Release
runs-on: ubuntu-latest
needs: test
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: go-with-cache
uses: magnetikonline/action-golang-cache@v4
with:
go-version-file: go.mod
- run: make install-tools
- uses: go-semantic-release/action@v1
with:
bin: ./bin/semantic-release
hooks: goreleaser
allow-initial-development-versions: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30 changes: 30 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Release
on:
workflow_run:
workflows:
- Checks
branches:
- main
types:
- completed

jobs:
release:
name: Release
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: go-with-cache
uses: magnetikonline/action-golang-cache@v4
with:
go-version-file: go.mod
- run: make install-tools
- uses: go-semantic-release/action@v1
with:
bin: ./bin/semantic-release
hooks: goreleaser
allow-initial-development-versions: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
16 changes: 15 additions & 1 deletion cmd/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/fitz7/tfnew/internal/tfmodule"

Check failure on line 11 in cmd/module.go

View workflow job for this annotation

GitHub Actions / Lint

could not import github.com/fitz7/tfnew/internal/tfmodule (-: # github.com/fitz7/tfnew/internal/tfmodule

Check failure on line 11 in cmd/module.go

View workflow job for this annotation

GitHub Actions / Lint

could not import github.com/fitz7/tfnew/internal/tfmodule (-: # github.com/fitz7/tfnew/internal/tfmodule
)

// moduleCmd represents the module command
Expand Down Expand Up @@ -42,10 +42,24 @@
BackendType: backend,
}

err = tfmodule.CreateModule(createModuleOptions)
fullModulePath, err := tfmodule.CreateModuleDir(createModuleOptions)
if err != nil {
return err
}
defaultFiles, err := tfmodule.CreateDefaultModuleFiles(fullModulePath)
if err != nil {
return fmt.Errorf("error creating moduleName files: %w", err)
}
err = tfmodule.PopulateVersionsFile(defaultFiles[tfmodule.VersionsFile], createModuleOptions)
if err != nil {
return fmt.Errorf("error populating the versions.tf file: %w", err)
}

defer func() {
for _, file := range defaultFiles {
_ = file.Close()
}
}()
return nil
},
}
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ require (
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
github.com/pkg/errors v0.9.1 // indirect
Expand Down Expand Up @@ -380,7 +380,7 @@ require (
go.uber.org/zap v1.24.0 // indirect
gocloud.dev v0.34.0 // indirect
golang.org/x/crypto v0.16.0 // indirect
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect
golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/net v0.19.0 // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1075,8 +1075,8 @@ github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAv
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
Expand Down Expand Up @@ -1423,8 +1423,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8=
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 h1:qCEDpW1G+vcj3Y7Fy52pEM1AWm3abj8WimGYejI3SC4=
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 h1:jWGQJV4niP+CCmFW9ekjA9Zx8vYORzOUH2/Nl5WPuLQ=
Expand Down
37 changes: 33 additions & 4 deletions internal/releases/releases.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,42 @@
package releases

import (
"encoding/json"
"fmt"
)

func GetLatestProviderRelease(provider string) (map[string]interface{}, error) {
return makeGetRequest(fmt.Sprintf("https://registry.terraform.io/v1/providers/%s", provider))
type ProviderData struct {
Name string
Version string
}
type TerraformData struct {
Name string
Version string
}

func GetLatestProviderRelease(provider string) (*ProviderData, error) {
providerResponse, err := makeGetRequest(fmt.Sprintf("https://registry.terraform.io/v1/providers/%s", provider))
if err != nil {
return nil, err
}
var providerData ProviderData
err = json.Unmarshal(providerResponse, &providerData)
if err != nil {
return nil, err
}

return &providerData, nil
}

func GetLatestTerraformRelease() (map[string]interface{}, error) {
return makeGetRequest("https://api.releases.hashicorp.com/v1/releases/terraform/latest")
func GetLatestTerraformRelease() (*TerraformData, error) {
terraformResponse, err := makeGetRequest("https://api.releases.hashicorp.com/v1/releases/terraform/latest")
if err != nil {
return nil, err
}
var terraformData TerraformData
err = json.Unmarshal(terraformResponse, &terraformData)
if err != nil {
return nil, err
}
return &terraformData, nil
}
12 changes: 2 additions & 10 deletions internal/releases/util.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package releases

import (
"encoding/json"
"io"
"net/http"
)

func makeGetRequest(apiURL string) (map[string]interface{}, error) {
func makeGetRequest(apiURL string) ([]byte, error) {
req, err := http.NewRequest(http.MethodGet, apiURL, nil)
if err != nil {
return nil, err
Expand All @@ -28,12 +27,5 @@ func makeGetRequest(apiURL string) (map[string]interface{}, error) {
return nil, err
}

var response map[string]interface{}

err = json.Unmarshal(body, &response)
if err != nil {
return nil, err
}

return response, nil
return body, nil
}
62 changes: 21 additions & 41 deletions internal/tfmodule/tfmodule.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"errors"
"fmt"
"os"
"regexp"
"strings"

"github.com/hashicorp/hcl/v2/hclwrite"
Expand All @@ -14,9 +15,9 @@
"github.com/fitz7/tfnew/internal/releases"
)

const versionsFile = "versions.tf"
const VersionsFile = "versions.tf"

var defaultFilenames = []string{versionsFile, "variables.tf", "outputs.tf", "main.tf"}

Check failure on line 20 in internal/tfmodule/tfmodule.go

View workflow job for this annotation

GitHub Actions / Lint

undefined: versionsFile) (typecheck)

Check failure on line 20 in internal/tfmodule/tfmodule.go

View workflow job for this annotation

GitHub Actions / Lint

undefined: versionsFile (typecheck)

Check failure on line 20 in internal/tfmodule/tfmodule.go

View workflow job for this annotation

GitHub Actions / Lint

undefined: versionsFile) (typecheck)

Check failure on line 20 in internal/tfmodule/tfmodule.go

View workflow job for this annotation

GitHub Actions / Lint

undefined: versionsFile (typecheck)

type CreateModuleOptions struct {
Name string
Expand All @@ -26,34 +27,18 @@
BackendType string
}

func CreateModule(cmo CreateModuleOptions) error {
func CreateModuleDir(cmo CreateModuleOptions) (string, error) {
fullPathWithModuleName := fmt.Sprintf("%s/%s", fsutils.FindProjectRootDir(), cmo.Name)

err := os.Mkdir(fullPathWithModuleName, 0o755)
if err != nil {
return fmt.Errorf("error creating directory: %w", err)
return "", fmt.Errorf("error creating directory: %w", err)
}

defaultFiles, err := createDefaultModuleFiles(fullPathWithModuleName)
if err != nil {
return fmt.Errorf("error creating moduleName files: %w", err)
}

defer func() {
for _, file := range defaultFiles {
_ = file.Close()
}
}()

err = populateVersionsFile(defaultFiles[versionsFile], cmo)
if err != nil {
return fmt.Errorf("error populating the versions.tf file: %w", err)
}

return nil
return fullPathWithModuleName, nil
}

func createDefaultModuleFiles(path string) (map[string]*os.File, error) {
func CreateDefaultModuleFiles(path string) (map[string]*os.File, error) {
defaultFiles := make(map[string]*os.File)

for _, filename := range defaultFilenames {
Expand All @@ -68,7 +53,7 @@
return defaultFiles, nil
}

func populateVersionsFile(versionsFile *os.File, cmo CreateModuleOptions) error {
func PopulateVersionsFile(versionsFile *os.File, cmo CreateModuleOptions) error {
f := hclwrite.NewEmptyFile()
body := f.Body()

Expand Down Expand Up @@ -176,24 +161,17 @@
requiredProvidersBody := body.AppendNewBlock("required_providers", []string{}).Body()

for _, provider := range cmo.RequiredProviders {
latestProviderRelease, err := releases.GetLatestProviderRelease(provider)
latestProviderData, err := releases.GetLatestProviderRelease(provider)
if err != nil {
return err
}

providerName, ok := latestProviderRelease["name"].(string)
if !ok {
return fmt.Errorf("could not find name for provider: %s", provider)
}

latestProviderVersion, ok := latestProviderRelease["version"].(string)
if !ok {
return fmt.Errorf("could not find version for provider: %s", provider)
minorProviderVersion, err := truncatePatchVersion(latestProviderData.Version)
if err != nil {
return fmt.Errorf("%s provider version for: %s", latestProviderData.Name, err.Error())
}

minorProviderVersion := truncatePatchVersion(latestProviderVersion)

requiredProvidersBody.SetAttributeValue(providerName, cty.ObjectVal(map[string]cty.Value{
requiredProvidersBody.SetAttributeValue(latestProviderData.Name, cty.ObjectVal(map[string]cty.Value{
"source": cty.StringVal(provider),
"version": cty.StringVal(fmt.Sprintf("~> %s", minorProviderVersion)),
}))
Expand All @@ -214,19 +192,21 @@
return "", errors.New("failed to fetch terraform version")
}

latestTerraformVersion, ok := latestTerraformRelease["version"].(string)
if !ok {
return "", err
minorTerraformVersion, err := truncatePatchVersion(latestTerraformRelease.Version)
if err != nil {
return "", fmt.Errorf("terraform %s", err.Error())
}

minorTerraformVersion := truncatePatchVersion(latestTerraformVersion)

terraformVersion = fmt.Sprintf("~> %s", minorTerraformVersion)
}

return terraformVersion, nil
}

func truncatePatchVersion(version string) string {
return strings.Join(strings.Split(version, ".")[:2], ".")
func truncatePatchVersion(version string) (string, error) {
versionMatch := regexp.MustCompile(`^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
if !versionMatch.MatchString(version) {
return "", errors.New("version returned is not valid semver")
}
return strings.Join(strings.Split(version, ".")[:2], "."), nil
}
60 changes: 60 additions & 0 deletions internal/tfmodule/tfmodule_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package tfmodule

import (
"testing"
)

func Test_truncatePatchVersion(t *testing.T) {
type args struct {
version string
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{
name: "regular version",
args: args{version: "1.2.3"},
want: "1.2",
wantErr: false,
},
{
name: "minor only version",
args: args{version: "1.2"},
want: "",
wantErr: true,
},
{
name: "major only version",
args: args{version: "1"},
want: "",
wantErr: true,
},
{
name: "regular big",
args: args{version: "12.34.56"},
want: "12.34",
wantErr: false,
},
{
name: "bad version",
args: args{version: "02.34.56"},
want: "",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := truncatePatchVersion(tt.args.version)
if (err != nil) != tt.wantErr {
t.Errorf("truncatePatchVersion() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("truncatePatchVersion() = %v, want %v", got, tt.want)
}
})
}
}
Loading