Skip to content

Commit adc17bf

Browse files
authored
Merge pull request #2321 from ActiveState/DX-1456
Error out when deprecated fields are found in activestate.yaml
2 parents f71302d + 80e0e6e commit adc17bf

6 files changed

Lines changed: 150 additions & 20 deletions

File tree

internal/locale/locales/en-us.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,3 +2022,11 @@ warning_macos_bash:
20222022
operating_message:
20232023
other: |
20242024
Operating on project [ACTIONABLE]{{.V0}}[/RESET], located at [ACTIONABLE]{{.V1}}[/RESET].
2025+
pjfile_deprecation_msg:
2026+
other: |
2027+
Your activestate.yaml located at [ACTIONABLE]{{.V0}}[/RESET] appears to be using deprecated keys. Please update the following keys:
2028+
{{.V1}}
2029+
To find out how to update these please read the deprecation information at:
2030+
[ACTIONABLE]{{.V2}}[/RESET]
2031+
pjfile_deprecation_entry:
2032+
other: " - '[ACTIONABLE]{{.V0}}[/RESET]' located at byte [ACTIONABLE]{{.V1}}[/RESET]"

internal/testhelpers/e2e/session.go

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,12 @@ import (
2929
"github.com/ActiveState/cli/pkg/platform/api/mono/mono_models"
3030
"github.com/ActiveState/cli/pkg/platform/authentication"
3131
"github.com/ActiveState/cli/pkg/project"
32-
"github.com/ActiveState/cli/pkg/projectfile"
3332
"github.com/ActiveState/termtest"
3433
"github.com/ActiveState/termtest/expect"
3534
"github.com/go-openapi/strfmt"
3635
"github.com/google/uuid"
3736
"github.com/phayes/permbits"
3837
"github.com/stretchr/testify/require"
39-
"gopkg.in/yaml.v2"
4038
)
4139

4240
// Session represents an end-to-end testing session during which several console process can be spawned and tested
@@ -293,21 +291,7 @@ func (s *Session) SpawnCmdWithOpts(exe string, opts ...SpawnOptions) *termtest.C
293291
// provided contents and saves the output to an as.y file within the named
294292
// directory.
295293
func (s *Session) PrepareActiveStateYAML(contents string) {
296-
msg := "cannot setup activestate.yaml file"
297-
298-
contents = strings.TrimSpace(contents)
299-
projectFile := &projectfile.Project{}
300-
301-
err := yaml.Unmarshal([]byte(contents), projectFile)
302-
require.NoError(s.t, err, msg)
303-
304-
cfg, err := config.New()
305-
require.NoError(s.t, err)
306-
defer func() { require.NoError(s.t, cfg.Close()) }()
307-
308-
projectFile.SetPath(filepath.Join(s.Dirs.Work, "activestate.yaml"))
309-
err = projectFile.Save(cfg)
310-
require.NoError(s.t, err, msg)
294+
require.NoError(s.t, fileutils.WriteFile(filepath.Join(s.Dirs.Work, "activestate.yaml"), []byte(contents)))
311295
}
312296

313297
// PrepareFile writes a file to path with contents, expecting no error

internal/testhelpers/tagsuite/tagsuite.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ const (
5050
Platforms = "platforms"
5151
Prepare = "prepare"
5252
Projects = "projects"
53+
Projectfile = "projectfile"
5354
Pull = "pull"
5455
Push = "push"
5556
Python = "python"

pkg/projectfile/projectfile.go

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"path/filepath"
1010
"regexp"
1111
"runtime"
12+
"strconv"
1213
"strings"
1314
"sync"
1415
"time"
@@ -47,6 +48,8 @@ var (
4748
ProjectURLRe = regexp.MustCompile(urlProjectRegexStr)
4849
// CommitURLRe Regex used to validate commit info /commit/someUUID
4950
CommitURLRe = regexp.MustCompile(urlCommitRegexStr)
51+
// deprecatedRegex covers the deprecated fields in the project file
52+
deprecatedRegex = regexp.MustCompile(`\s*(?:constraints|platforms|languages):`)
5053
)
5154

5255
type ErrorParseProject struct{ *locale.LocalizedError }
@@ -443,12 +446,16 @@ func parse(configFilepath string) (*Project, error) {
443446
return nil, errs.Wrap(err, "ioutil.ReadFile %s failure", configFilepath)
444447
}
445448

449+
if err := detectDeprecations(dat, configFilepath); err != nil {
450+
return nil, errs.Wrap(err, "deprecations found")
451+
}
452+
446453
project := Project{}
447-
err = yaml.Unmarshal([]byte(dat), &project)
454+
err2 := yaml.Unmarshal(dat, &project)
448455
project.path = configFilepath
449456

450-
if err != nil {
451-
return nil, &ErrorParseProject{locale.NewError(
457+
if err2 != nil {
458+
return nil, &ErrorParseProject{locale.NewInputError(
452459
"err_project_parsed",
453460
"Project file `{{.V1}}` could not be parsed, the parser produced the following error: {{.V0}}", err.Error(), configFilepath),
454461
}
@@ -457,6 +464,22 @@ func parse(configFilepath string) (*Project, error) {
457464
return &project, nil
458465
}
459466

467+
func detectDeprecations(dat []byte, configFilepath string) error {
468+
deprecations := deprecatedRegex.FindAllIndex(dat, -1)
469+
if len(deprecations) == 0 {
470+
return nil
471+
}
472+
deplist := []string{}
473+
for _, depIdxs := range deprecations {
474+
dep := strings.TrimSpace(strings.TrimSuffix(string(dat[depIdxs[0]:depIdxs[1]]), ":"))
475+
deplist = append(deplist, locale.Tr("pjfile_deprecation_entry", dep, strconv.Itoa(depIdxs[0])))
476+
}
477+
return &ErrorParseProject{locale.NewInputError(
478+
"pjfile_deprecation_msg",
479+
"", configFilepath, strings.Join(deplist, "\n"), constants.DocumentationURL+"config/#deprecation"),
480+
}
481+
}
482+
460483
// Owner returns the project namespace's organization
461484
func (p *Project) Owner() string {
462485
return p.parsedURL.Owner

pkg/projectfile/projectfile_test.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"strings"
99
"testing"
1010

11+
"github.com/ActiveState/cli/internal/locale"
1112
"github.com/stretchr/testify/assert"
1213
"github.com/stretchr/testify/require"
1314
"gopkg.in/yaml.v2"
@@ -418,3 +419,75 @@ func TestProject_Init(t *testing.T) {
418419
})
419420
}
420421
}
422+
423+
func Test_detectDeprecations(t *testing.T) {
424+
tests := []struct {
425+
name string
426+
dat string
427+
wantMatchError []string
428+
}{
429+
{
430+
"Constraints",
431+
`constraints: 0`,
432+
[]string{
433+
locale.Tr("pjfile_deprecation_entry", "constraints", "0"),
434+
},
435+
},
436+
{
437+
"Platforms",
438+
`platforms: 0"`,
439+
[]string{
440+
locale.Tr("pjfile_deprecation_entry", "platforms", "0"),
441+
},
442+
},
443+
{
444+
"Languages",
445+
`languages: 0`,
446+
[]string{
447+
locale.Tr("pjfile_deprecation_entry", "languages", "0"),
448+
},
449+
},
450+
{
451+
"Mixed",
452+
"foo: 0\nconstraints: 0\nbar: 0\nlanguages: 0, platforms: 0",
453+
[]string{
454+
locale.Tr("pjfile_deprecation_entry", "constraints", "6"),
455+
locale.Tr("pjfile_deprecation_entry", "languages", "28"),
456+
locale.Tr("pjfile_deprecation_entry", "platforms", "42"),
457+
},
458+
},
459+
{
460+
"Real world",
461+
`project: https://platform.activestate.com/ActiveState-CLI/test?commitID=9090c128-e948-4388-8f7f-96e2c1e00d98
462+
platforms:
463+
- name: Linux64Label
464+
languages:
465+
- name: Go
466+
constraints:
467+
platform: Windows10Label,Linux64Label`,
468+
[]string{
469+
locale.Tr("pjfile_deprecation_entry", "platforms", "108"),
470+
locale.Tr("pjfile_deprecation_entry", "languages", "142"),
471+
locale.Tr("pjfile_deprecation_entry", "constraints", "166"),
472+
},
473+
},
474+
{
475+
"Valid",
476+
"foo: 0\nbar: 0",
477+
[]string{},
478+
},
479+
}
480+
for _, tt := range tests {
481+
t.Run(tt.name, func(t *testing.T) {
482+
err := detectDeprecations([]byte(tt.dat), "activestate.yaml")
483+
if len(tt.wantMatchError) == 0 {
484+
assert.NoError(t, err)
485+
return
486+
}
487+
require.Error(t, err)
488+
for _, want := range tt.wantMatchError {
489+
assert.Contains(t, err.Error(), want)
490+
}
491+
})
492+
}
493+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package integration
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
"github.com/stretchr/testify/suite"
8+
9+
"github.com/ActiveState/cli/internal/testhelpers/e2e"
10+
"github.com/ActiveState/cli/internal/testhelpers/tagsuite"
11+
)
12+
13+
type PjFileIntegrationTestSuite struct {
14+
tagsuite.Suite
15+
}
16+
17+
func (suite *PjFileIntegrationTestSuite) TestDeprecation() {
18+
suite.OnlyRunForTags(tagsuite.Projects)
19+
ts := e2e.New(suite.T(), false)
20+
defer ts.Close()
21+
22+
ts.PrepareActiveStateYAML(strings.TrimSpace(`
23+
project: https://platform.activestate.com/ActiveState-CLI/test?commitID=1090c128-e948-4388-8f7f-96e2c1e00d98
24+
platforms:
25+
- name: Linux64Label
26+
languages:
27+
- name: Go
28+
constraints:
29+
platform: Windows10Label,Linux64Label
30+
`))
31+
32+
cp := ts.SpawnWithOpts(
33+
e2e.WithArgs("scripts"),
34+
e2e.AppendEnv("VERBOSE=true"),
35+
)
36+
cp.ExpectExitCode(1)
37+
}
38+
39+
func TestPjFileIntegrationTestSuite(t *testing.T) {
40+
suite.Run(t, new(PjFileIntegrationTestSuite))
41+
}

0 commit comments

Comments
 (0)