Skip to content

Commit 82ee279

Browse files
authored
feat: add lifecycle hooks
1 parent 9290bb2 commit 82ee279

File tree

3 files changed

+289
-0
lines changed

3 files changed

+289
-0
lines changed

nitric/lifecycle/lifecycle.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copyright 2024, Nitric Technologies Pty Ltd.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package lifecycle
16+
17+
import (
18+
"fmt"
19+
"os"
20+
)
21+
22+
// LifecycleStage represents the different stages of Nitric execution
23+
type LifecycleStage string
24+
25+
const (
26+
// LocalRun represents local development run (using nitric run/start)
27+
LocalRun LifecycleStage = "run"
28+
// Build represents local development requirements building/collection (using nitric up)
29+
Build LifecycleStage = "build"
30+
// Cloud represents when the code is running in a deployed environment
31+
Cloud LifecycleStage = "cloud"
32+
)
33+
34+
const (
35+
// NITRIC_ENVIRONMENT is the environment variable key used to determine the current Nitric lifecycle
36+
NITRIC_ENVIRONMENT = "NITRIC_ENVIRONMENT"
37+
)
38+
39+
// GetCurrentLifecycle returns the current lifecycle stage
40+
func GetCurrentLifecycle() (LifecycleStage, error) {
41+
lifecycle := os.Getenv(NITRIC_ENVIRONMENT)
42+
if lifecycle == "" {
43+
return "", fmt.Errorf("unable to determine the current Nitric lifecycle, please ensure the %s environment variable is set", NITRIC_ENVIRONMENT)
44+
}
45+
46+
stage := LifecycleStage(lifecycle)
47+
switch stage {
48+
case LocalRun, Build, Cloud:
49+
return stage, nil
50+
default:
51+
return "", fmt.Errorf("invalid lifecycle stage: %s", lifecycle)
52+
}
53+
}
54+
55+
// IsInLifecycle checks if the current environment is one of the provided stages
56+
func IsInLifecycle(stages ...LifecycleStage) bool {
57+
currentStage, err := GetCurrentLifecycle()
58+
if err != nil {
59+
return false
60+
}
61+
62+
for _, stage := range stages {
63+
if currentStage == stage {
64+
return true
65+
}
66+
}
67+
return false
68+
}
69+
70+
// WhenInLifecycles executes the provided callback if the current environment is one of the provided stages
71+
func WhenInLifecycles[T any](stages []LifecycleStage, callback func() T) T {
72+
if IsInLifecycle(stages...) {
73+
return callback()
74+
}
75+
var zero T
76+
return zero
77+
}
78+
79+
// WhenRunning executes the provided callback if the current environment is running (LocalRun or Cloud)
80+
func WhenRunning[T any](callback func() T) T {
81+
return WhenInLifecycles([]LifecycleStage{LocalRun, Cloud}, callback)
82+
}
83+
84+
// WhenCollecting executes the provided callback if the current environment is collecting requirements (Build)
85+
func WhenCollecting[T any](callback func() T) T {
86+
return WhenInLifecycles([]LifecycleStage{Build}, callback)
87+
}
88+
89+
// IsRunning checks if the current lifecycle is running the app (LocalRun or Cloud)
90+
func IsRunning() bool {
91+
return IsInLifecycle(LocalRun, Cloud)
92+
}
93+
94+
// IsCollecting checks if the current lifecycle is collecting application requirements (Build)
95+
func IsCollecting() bool {
96+
return IsInLifecycle(Build)
97+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2024, Nitric Technologies Pty Ltd.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package lifecycle_test
16+
17+
import (
18+
"testing"
19+
20+
. "github.com/onsi/ginkgo"
21+
. "github.com/onsi/gomega"
22+
)
23+
24+
func TestLifecycle(t *testing.T) {
25+
RegisterFailHandler(Fail)
26+
RunSpecs(t, "Lifecycle Suite")
27+
}

nitric/lifecycle/lifecycle_test.go

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
// Copyright 2024, Nitric Technologies Pty Ltd.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package lifecycle_test
16+
17+
import (
18+
"os"
19+
20+
. "github.com/onsi/ginkgo"
21+
. "github.com/onsi/gomega"
22+
23+
"github.com/nitrictech/go-sdk/nitric/lifecycle"
24+
)
25+
26+
var _ = Describe("Lifecycle", func() {
27+
BeforeEach(func() {
28+
// Clear environment before each test
29+
os.Unsetenv(lifecycle.NITRIC_ENVIRONMENT)
30+
})
31+
32+
Describe("GetCurrentLifecycle", func() {
33+
Context("when environment variable is set to valid stages", func() {
34+
It("should return LocalRun stage", func() {
35+
os.Setenv(lifecycle.NITRIC_ENVIRONMENT, "run")
36+
stage, err := lifecycle.GetCurrentLifecycle()
37+
Expect(err).NotTo(HaveOccurred())
38+
Expect(stage).To(Equal(lifecycle.LocalRun))
39+
})
40+
41+
It("should return Build stage", func() {
42+
os.Setenv(lifecycle.NITRIC_ENVIRONMENT, "build")
43+
stage, err := lifecycle.GetCurrentLifecycle()
44+
Expect(err).NotTo(HaveOccurred())
45+
Expect(stage).To(Equal(lifecycle.Build))
46+
})
47+
48+
It("should return Cloud stage", func() {
49+
os.Setenv(lifecycle.NITRIC_ENVIRONMENT, "cloud")
50+
stage, err := lifecycle.GetCurrentLifecycle()
51+
Expect(err).NotTo(HaveOccurred())
52+
Expect(stage).To(Equal(lifecycle.Cloud))
53+
})
54+
})
55+
56+
Context("when environment variable is not set", func() {
57+
It("should return an error", func() {
58+
stage, err := lifecycle.GetCurrentLifecycle()
59+
Expect(err).To(HaveOccurred())
60+
Expect(stage).To(BeEmpty())
61+
})
62+
})
63+
64+
Context("when environment variable is set to invalid stage", func() {
65+
It("should return an error", func() {
66+
os.Setenv(lifecycle.NITRIC_ENVIRONMENT, "invalid")
67+
stage, err := lifecycle.GetCurrentLifecycle()
68+
Expect(err).To(HaveOccurred())
69+
Expect(stage).To(BeEmpty())
70+
})
71+
})
72+
})
73+
74+
Describe("IsInLifecycle", func() {
75+
Context("when current stage matches one of the provided stages", func() {
76+
It("should return true for LocalRun", func() {
77+
os.Setenv(lifecycle.NITRIC_ENVIRONMENT, "run")
78+
result := lifecycle.IsInLifecycle(lifecycle.LocalRun, lifecycle.Cloud)
79+
Expect(result).To(BeTrue())
80+
})
81+
82+
It("should return true for Cloud", func() {
83+
os.Setenv(lifecycle.NITRIC_ENVIRONMENT, "cloud")
84+
result := lifecycle.IsInLifecycle(lifecycle.LocalRun, lifecycle.Cloud)
85+
Expect(result).To(BeTrue())
86+
})
87+
})
88+
89+
Context("when current stage does not match any of the provided stages", func() {
90+
It("should return false", func() {
91+
os.Setenv(lifecycle.NITRIC_ENVIRONMENT, "build")
92+
result := lifecycle.IsInLifecycle(lifecycle.LocalRun, lifecycle.Cloud)
93+
Expect(result).To(BeFalse())
94+
})
95+
})
96+
})
97+
98+
Describe("WhenInLifecycles", func() {
99+
Context("when current stage matches one of the provided stages", func() {
100+
It("should execute the callback", func() {
101+
os.Setenv(lifecycle.NITRIC_ENVIRONMENT, "run")
102+
result := lifecycle.WhenInLifecycles([]lifecycle.LifecycleStage{lifecycle.LocalRun, lifecycle.Cloud}, func() string {
103+
return "executed"
104+
})
105+
Expect(result).To(Equal("executed"))
106+
})
107+
})
108+
109+
Context("when current stage does not match any of the provided stages", func() {
110+
It("should not execute the callback and return zero value", func() {
111+
os.Setenv(lifecycle.NITRIC_ENVIRONMENT, "build")
112+
result := lifecycle.WhenInLifecycles([]lifecycle.LifecycleStage{lifecycle.LocalRun, lifecycle.Cloud}, func() string {
113+
return "executed"
114+
})
115+
Expect(result).To(BeEmpty())
116+
})
117+
})
118+
})
119+
120+
Describe("IsRunning", func() {
121+
Context("when in LocalRun stage", func() {
122+
It("should return true", func() {
123+
os.Setenv(lifecycle.NITRIC_ENVIRONMENT, "run")
124+
Expect(lifecycle.IsRunning()).To(BeTrue())
125+
})
126+
})
127+
128+
Context("when in Cloud stage", func() {
129+
It("should return true", func() {
130+
os.Setenv(lifecycle.NITRIC_ENVIRONMENT, "cloud")
131+
Expect(lifecycle.IsRunning()).To(BeTrue())
132+
})
133+
})
134+
135+
Context("when in Build stage", func() {
136+
It("should return false", func() {
137+
os.Setenv(lifecycle.NITRIC_ENVIRONMENT, "build")
138+
Expect(lifecycle.IsRunning()).To(BeFalse())
139+
})
140+
})
141+
})
142+
143+
Describe("IsCollecting", func() {
144+
Context("when in Build stage", func() {
145+
It("should return true", func() {
146+
os.Setenv(lifecycle.NITRIC_ENVIRONMENT, "build")
147+
Expect(lifecycle.IsCollecting()).To(BeTrue())
148+
})
149+
})
150+
151+
Context("when in LocalRun stage", func() {
152+
It("should return false", func() {
153+
os.Setenv(lifecycle.NITRIC_ENVIRONMENT, "run")
154+
Expect(lifecycle.IsCollecting()).To(BeFalse())
155+
})
156+
})
157+
158+
Context("when in Cloud stage", func() {
159+
It("should return false", func() {
160+
os.Setenv(lifecycle.NITRIC_ENVIRONMENT, "cloud")
161+
Expect(lifecycle.IsCollecting()).To(BeFalse())
162+
})
163+
})
164+
})
165+
})

0 commit comments

Comments
 (0)