mirror of
https://github.com/roleypoly/roleypoly.git
synced 2025-04-24 19:39:11 +00:00
initial port to cfworkers i guess
This commit is contained in:
parent
ab9fe30b42
commit
9eeb946389
37 changed files with 367 additions and 1098 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -3,3 +3,5 @@ node_modules
|
|||
*.log
|
||||
storybook-static
|
||||
.next
|
||||
worker
|
||||
wrangler.toml
|
||||
|
|
11
package.json
11
package.json
|
@ -34,10 +34,12 @@
|
|||
"react-icons": "^4.1.0",
|
||||
"react-is": "^17.0.1",
|
||||
"react-tooltip": "^4.2.11",
|
||||
"styled-components": "^5.2.1"
|
||||
"styled-components": "^5.2.1",
|
||||
"uuid": "^8.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.9",
|
||||
"@cloudflare/workers-types": "^2.1.0",
|
||||
"@storybook/addon-actions": "^6.1.9",
|
||||
"@storybook/addon-essentials": "^6.1.9",
|
||||
"@storybook/addon-links": "^6.1.9",
|
||||
|
@ -54,6 +56,7 @@
|
|||
"@types/react-custom-scrollbars": "^4.0.7",
|
||||
"@types/react-dom": "^17.0.0",
|
||||
"@types/styled-components": "^5.1.4",
|
||||
"@types/uuid": "^8.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.9.0",
|
||||
"@typescript-eslint/eslint-plugin-tslint": "^4.9.0",
|
||||
"@typescript-eslint/parser": "^4.9.0",
|
||||
|
@ -86,7 +89,9 @@
|
|||
"stylelint-prettier": "^1.1.2",
|
||||
"stylelint-processor-styled-components": "^1.10.0",
|
||||
"ts-jest": "^26.4.4",
|
||||
"ts-loader": "^8.0.11",
|
||||
"tsconfig-paths-webpack-plugin": "^3.3.0",
|
||||
"typescript": "^4.1.2"
|
||||
"typescript": "^4.1.2",
|
||||
"webpack": "^5.9.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
1
src/backend-worker/.gitignore
vendored
Normal file
1
src/backend-worker/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
dist
|
10
src/backend-worker/bindings.d.ts
vendored
Normal file
10
src/backend-worker/bindings.d.ts
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
export {};
|
||||
|
||||
declare global {
|
||||
const BOT_CLIENT_ID: string;
|
||||
const BOT_CLIENT_SECRET: string;
|
||||
const UI_PUBLIC_URI: string;
|
||||
const API_PUBLIC_URI: string;
|
||||
const ROOT_USERS: string;
|
||||
const KV_PREFIX: string;
|
||||
}
|
35
src/backend-worker/handlers/bot-join.ts
Normal file
35
src/backend-worker/handlers/bot-join.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { Bounce } from '../utils/bounce';
|
||||
|
||||
const validGuildID = /^[0-9]+$/;
|
||||
|
||||
type URLParams = {
|
||||
clientID: string;
|
||||
permissions: number;
|
||||
guildID?: string;
|
||||
};
|
||||
|
||||
const buildURL = (params: URLParams) => {
|
||||
let url = `https://discord.com/api/oauth2/authorize?client_id=${params.clientID}&scope=bot&permissions=${params.permissions}`;
|
||||
|
||||
if (params.guildID) {
|
||||
url += `&guild_id=${params.guildID}&disable_guild_select=true`;
|
||||
}
|
||||
|
||||
return url;
|
||||
};
|
||||
|
||||
export const BotJoin = (request: Request): Response => {
|
||||
let guildID = new URL(request.url).searchParams.get('guild') || '';
|
||||
|
||||
if (guildID && !validGuildID.test(guildID)) {
|
||||
guildID = '';
|
||||
}
|
||||
|
||||
return Bounce(
|
||||
buildURL({
|
||||
clientID: BOT_CLIENT_ID,
|
||||
permissions: 268435456,
|
||||
guildID,
|
||||
})
|
||||
);
|
||||
};
|
23
src/backend-worker/handlers/login-bounce.ts
Normal file
23
src/backend-worker/handlers/login-bounce.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { Bounce } from '../utils/bounce';
|
||||
|
||||
type URLParams = {
|
||||
clientID: string;
|
||||
redirectURI: string;
|
||||
state: string;
|
||||
};
|
||||
|
||||
const buildURL = (params: URLParams) =>
|
||||
`https://discord.com/api/oauth2/authorize?client_id=${
|
||||
params.clientID
|
||||
}&response_type=code&scope=identify%20guilds&redirect_uri=${encodeURIComponent(
|
||||
params.redirectURI
|
||||
)}&state=${params.state}`;
|
||||
|
||||
export const LoginBounce = (request: Request): Response => {
|
||||
const state = uuidv4();
|
||||
const redirectURI = `${API_PUBLIC_URI}/login-callback`;
|
||||
const clientID = BOT_CLIENT_ID;
|
||||
|
||||
return Bounce(buildURL({ state, redirectURI, clientID }));
|
||||
};
|
3
src/backend-worker/handlers/login-callback.ts
Normal file
3
src/backend-worker/handlers/login-callback.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export const LoginCallback = (request: Request): Response => {
|
||||
return new Response('login-callback!');
|
||||
};
|
14
src/backend-worker/index.ts
Normal file
14
src/backend-worker/index.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { BotJoin } from './handlers/bot-join';
|
||||
import { LoginBounce } from './handlers/login-bounce';
|
||||
import { LoginCallback } from './handlers/login-callback';
|
||||
import { Router } from './router';
|
||||
|
||||
const router = new Router();
|
||||
|
||||
router.add('GET', 'bot-join', BotJoin);
|
||||
router.add('GET', 'login-bounce', LoginBounce);
|
||||
router.add('GET', 'login-callback', LoginCallback);
|
||||
|
||||
addEventListener('fetch', (event: FetchEvent) => {
|
||||
event.respondWith(router.handle(event.request));
|
||||
});
|
73
src/backend-worker/router.ts
Normal file
73
src/backend-worker/router.ts
Normal file
|
@ -0,0 +1,73 @@
|
|||
export type Handler = (request: Request) => Promise<Response> | Response;
|
||||
|
||||
type RoutingTree = {
|
||||
[method: string]: {
|
||||
[path: string]: Handler;
|
||||
};
|
||||
};
|
||||
|
||||
type Fallbacks = {
|
||||
root: Handler;
|
||||
404: Handler;
|
||||
500: Handler;
|
||||
};
|
||||
|
||||
export class Router {
|
||||
private routingTree: RoutingTree = {};
|
||||
private fallbacks: Fallbacks = {
|
||||
root: this.respondToRoot,
|
||||
404: this.notFound,
|
||||
500: this.serverError,
|
||||
};
|
||||
|
||||
addFallback(which: keyof Fallbacks, handler: Handler) {
|
||||
this.fallbacks[which] = handler;
|
||||
}
|
||||
|
||||
add(method: string, rootPath: string, handler: Handler) {
|
||||
const lowerMethod = method.toLowerCase();
|
||||
|
||||
if (!this.routingTree[lowerMethod]) {
|
||||
this.routingTree[lowerMethod] = {};
|
||||
}
|
||||
|
||||
this.routingTree[lowerMethod][rootPath] = handler;
|
||||
}
|
||||
|
||||
handle(request: Request): Promise<Response> | Response {
|
||||
if (request.url === '/') {
|
||||
return this.fallbacks.root(request);
|
||||
}
|
||||
const lowerMethod = request.method.toLowerCase();
|
||||
const url = new URL(request.url);
|
||||
const rootPath = url.pathname.split('/')[1];
|
||||
const handler = this.routingTree[lowerMethod]?.[rootPath];
|
||||
|
||||
if (handler) {
|
||||
try {
|
||||
return handler(request);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return this.fallbacks[500](request);
|
||||
}
|
||||
}
|
||||
|
||||
return this.fallbacks[404](request);
|
||||
}
|
||||
|
||||
private respondToRoot(): Response {
|
||||
return new Response('Hi there!');
|
||||
}
|
||||
|
||||
private notFound(): Response {
|
||||
return new Response(JSON.stringify({ error: 'not_found' }), {
|
||||
status: 404,
|
||||
});
|
||||
}
|
||||
|
||||
private serverError(): Response {
|
||||
return new Response(JSON.stringify({ error: 'internal_server_error' }), {
|
||||
status: 500,
|
||||
});
|
||||
}
|
||||
}
|
14
src/backend-worker/tsconfig.json
Normal file
14
src/backend-worker/tsconfig.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"lib": ["esnext", "webworker"],
|
||||
"types": ["@cloudflare/workers-types"]
|
||||
},
|
||||
"include": [
|
||||
"./*.ts",
|
||||
"./**/*.ts",
|
||||
"../../node_modules/@cloudflare/workers-types/index.d.ts"
|
||||
],
|
||||
"exclude": ["./**/*.spec.ts"],
|
||||
"extends": "../../tsconfig.json"
|
||||
}
|
7
src/backend-worker/utils/bounce.ts
Normal file
7
src/backend-worker/utils/bounce.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
export const Bounce = (url: string): Response =>
|
||||
new Response(null, {
|
||||
status: 303,
|
||||
headers: {
|
||||
location: url,
|
||||
},
|
||||
});
|
29
src/backend-worker/webpack.config.js
Normal file
29
src/backend-worker/webpack.config.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
const path = require('path');
|
||||
|
||||
const mode = process.env.NODE_ENV || 'production';
|
||||
|
||||
module.exports = {
|
||||
target: 'webworker',
|
||||
entry: path.join(__dirname, 'index.ts'),
|
||||
output: {
|
||||
filename: `worker.${mode}.js`,
|
||||
path: path.join(__dirname, 'dist'),
|
||||
},
|
||||
mode,
|
||||
resolve: {
|
||||
extensions: ['.ts', '.tsx', '.js'],
|
||||
plugins: [],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
transpileOnly: true,
|
||||
configFile: path.join(__dirname, 'tsconfig.json'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
0
src/functions/hello-world/helloworld.ts
Normal file
0
src/functions/hello-world/helloworld.ts
Normal file
|
@ -1,156 +0,0 @@
|
|||
// Package redisbreaker provides a go-redis v8 instance designed for resilient caching via circuit breakers.
|
||||
// tl;dr: If redis is lost, it can either cache objects in memory using sync.Map or dropping gracefully.
|
||||
// As a side benefit, it means we don't need a redis server to develop locally, unless we want one :)
|
||||
package redisbreaker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/sony/gobreaker"
|
||||
)
|
||||
|
||||
type RedisBreaker struct {
|
||||
redisClient *redis.Client
|
||||
breaker *gobreaker.CircuitBreaker
|
||||
|
||||
config *RedisBreakerConfig
|
||||
inMemoryCache sync.Map
|
||||
}
|
||||
|
||||
type RedisBreakerConfig struct {
|
||||
Redis *redis.Options
|
||||
Breaker gobreaker.Settings
|
||||
UseInMemoryCache bool
|
||||
DefaultTTL time.Duration
|
||||
}
|
||||
|
||||
type inmemoryCacheObject struct {
|
||||
expiresAt time.Time
|
||||
object []byte
|
||||
}
|
||||
|
||||
func NewRedisBreaker(config *RedisBreakerConfig) *RedisBreaker {
|
||||
if config == nil {
|
||||
config = &RedisBreakerConfig{
|
||||
UseInMemoryCache: true,
|
||||
}
|
||||
}
|
||||
|
||||
if config.DefaultTTL == 0 {
|
||||
config.DefaultTTL = 2 * time.Minute
|
||||
}
|
||||
|
||||
breaker := &RedisBreaker{
|
||||
config: config,
|
||||
redisClient: redis.NewClient(config.Redis),
|
||||
breaker: gobreaker.NewCircuitBreaker(config.Breaker),
|
||||
}
|
||||
|
||||
return breaker
|
||||
}
|
||||
|
||||
func (rb *RedisBreaker) doOr(
|
||||
ctx context.Context,
|
||||
func1 func(context.Context, string, interface{}) (interface{}, error),
|
||||
func2 func(context.Context, string, interface{}) (interface{}, error),
|
||||
key string,
|
||||
object interface{},
|
||||
) (interface{}, error) {
|
||||
val, err := rb.breaker.Execute(func() (interface{}, error) {
|
||||
return func1(ctx, key, object)
|
||||
})
|
||||
if err == gobreaker.ErrOpenState || err == gobreaker.ErrTooManyRequests {
|
||||
return func2(ctx, key, object)
|
||||
}
|
||||
|
||||
return val, err
|
||||
}
|
||||
|
||||
// Set pushes an object into the cache with the specified default TTL, using SetEX
|
||||
func (rb *RedisBreaker) Set(ctx context.Context, key string, object interface{}) error {
|
||||
_, err := rb.doOr(ctx, rb.setRedis, rb.setInmemory, key, object)
|
||||
return err
|
||||
}
|
||||
|
||||
func (rb *RedisBreaker) setRedis(ctx context.Context, key string, object interface{}) (interface{}, error) {
|
||||
objectJSON, err := json.Marshal(object)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rb.redisClient.SetEX(ctx, key, objectJSON, rb.config.DefaultTTL).Result()
|
||||
}
|
||||
|
||||
func (rb *RedisBreaker) setInmemory(ctx context.Context, key string, object interface{}) (interface{}, error) {
|
||||
if rb.config.UseInMemoryCache {
|
||||
objectJSON, err := json.Marshal(object)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rb.inMemoryCache.Store(key, inmemoryCacheObject{
|
||||
expiresAt: time.Now().Add(rb.config.DefaultTTL),
|
||||
object: objectJSON,
|
||||
})
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Get pulls an object from cache, returning ok = true if it succeeded.
|
||||
func (rb *RedisBreaker) Get(ctx context.Context, key string, object interface{}) (bool, error) {
|
||||
ok, err := rb.doOr(ctx, rb.getRedis, rb.getInmemory, key, object)
|
||||
|
||||
return ok.(bool), err
|
||||
}
|
||||
|
||||
func (rb *RedisBreaker) getRedis(ctx context.Context, key string, object interface{}) (interface{}, error) {
|
||||
result := rb.redisClient.Get(ctx, key)
|
||||
if result.Err() != nil {
|
||||
if result.Err() == redis.Nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return false, result.Err()
|
||||
}
|
||||
|
||||
objectJSON, err := result.Bytes()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(objectJSON, object)
|
||||
|
||||
return true, err
|
||||
}
|
||||
|
||||
func (rb *RedisBreaker) getInmemory(ctx context.Context, key string, object interface{}) (interface{}, error) {
|
||||
if !rb.config.UseInMemoryCache {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
cacheObjIntf, ok := rb.inMemoryCache.Load(key)
|
||||
if !ok {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
cacheObj, ok := cacheObjIntf.(inmemoryCacheObject)
|
||||
if !ok {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if time.Now().After(cacheObj.expiresAt) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
err := json.Unmarshal(cacheObj.object, object)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
package redisbreaker_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/alicebob/miniredis/v2"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/onsi/gomega"
|
||||
"github.com/sony/gobreaker"
|
||||
|
||||
redisbreaker "github.com/roleypoly/roleypoly/src/redis-breaker"
|
||||
)
|
||||
|
||||
func getBreaker(breakerOpen bool) (*redisbreaker.RedisBreaker, *miniredis.Miniredis) {
|
||||
redisServer, err := miniredis.Run()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
config := &redisbreaker.RedisBreakerConfig{
|
||||
Redis: &redis.Options{
|
||||
Addr: redisServer.Addr(),
|
||||
},
|
||||
UseInMemoryCache: true,
|
||||
DefaultTTL: 1 * time.Second,
|
||||
}
|
||||
|
||||
if breakerOpen {
|
||||
config.Breaker.ReadyToTrip = func(gobreaker.Counts) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
redisServer.Close()
|
||||
}
|
||||
|
||||
rb := redisbreaker.NewRedisBreaker(config)
|
||||
|
||||
if breakerOpen {
|
||||
// forcibly open the breaker
|
||||
rb.Set(context.Background(), "@@@breaker@@@", nil)
|
||||
}
|
||||
|
||||
return rb, redisServer
|
||||
}
|
||||
|
||||
type TestData struct {
|
||||
IAmAField1 string
|
||||
IAmAField2 int
|
||||
IAmAField3 map[string]interface{}
|
||||
}
|
||||
|
||||
var testData = TestData{
|
||||
IAmAField1: "hello world!",
|
||||
IAmAField2: 420 * 69,
|
||||
IAmAField3: map[string]interface{}{
|
||||
"foxes": "are so heckin cute",
|
||||
},
|
||||
}
|
||||
|
||||
func getSet(t *testing.T, openCircuit bool) {
|
||||
g := gomega.NewGomegaWithT(t)
|
||||
rb, rds := getBreaker(openCircuit)
|
||||
defer rds.Close()
|
||||
|
||||
err := rb.Set(context.Background(), "test-data", testData)
|
||||
g.Expect(err).To(gomega.BeNil())
|
||||
|
||||
output := TestData{}
|
||||
ok, err := rb.Get(context.Background(), "test-data", &output)
|
||||
g.Expect(err).To(gomega.BeNil())
|
||||
|
||||
g.Expect(ok).To(gomega.BeTrue(), "ok should be true")
|
||||
g.Expect(output).To(gomega.Equal(testData), "testData should match output data")
|
||||
}
|
||||
|
||||
func TestGetSet(t *testing.T) {
|
||||
getSet(t, false)
|
||||
}
|
||||
|
||||
func TestGetSetOpenCircuit(t *testing.T) {
|
||||
getSet(t, true)
|
||||
}
|
||||
|
||||
func getNotInCache(t *testing.T, openCircuit bool) {
|
||||
g := gomega.NewGomegaWithT(t)
|
||||
rb, rds := getBreaker(openCircuit)
|
||||
defer rds.Close()
|
||||
|
||||
output := TestData{}
|
||||
ok, err := rb.Get(context.Background(), "not-test-data", &output)
|
||||
g.Expect(err).To(gomega.BeNil())
|
||||
|
||||
g.Expect(ok).To(gomega.BeFalse(), "ok should be false")
|
||||
g.Expect(output).To(gomega.BeZero(), "output should be 'zero'")
|
||||
}
|
||||
|
||||
func TestGetNotInCache(t *testing.T) {
|
||||
getNotInCache(t, false)
|
||||
}
|
||||
|
||||
func TestGetNotInCacheOpenCircuit(t *testing.T) {
|
||||
getNotInCache(t, true)
|
||||
}
|
||||
|
||||
func getAfterTTL(t *testing.T, openCircuit bool) {
|
||||
g := gomega.NewGomegaWithT(t)
|
||||
rb, rds := getBreaker(openCircuit)
|
||||
defer rds.Close()
|
||||
|
||||
err := rb.Set(context.Background(), "test-expired", testData)
|
||||
g.Expect(err).To(gomega.BeNil())
|
||||
|
||||
rds.FastForward(1 * time.Second)
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
output := TestData{}
|
||||
ok, err := rb.Get(context.Background(), "test-expired", &output)
|
||||
g.Expect(ok).To(gomega.BeFalse(), "ok should be false")
|
||||
g.Expect(output).To(gomega.BeZero(), "output should be 'zero'")
|
||||
}
|
||||
|
||||
func TestGetAfterTTL(t *testing.T) {
|
||||
getAfterTTL(t, false)
|
||||
}
|
||||
|
||||
func TestGetAfterTTLOpenCircuit(t *testing.T) {
|
||||
getAfterTTL(t, true)
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
locals {
|
||||
discord_labels = {
|
||||
"app.kubernetes.io/name" = "discord"
|
||||
"app.kubernetes.io/part-of" = "roleypoly"
|
||||
"roleypoly/environment" = var.environment_tag
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_deployment" "discord" {
|
||||
metadata {
|
||||
name = "discord"
|
||||
namespace = local.ns
|
||||
labels = local.discord_labels
|
||||
}
|
||||
|
||||
spec {
|
||||
replicas = 1
|
||||
|
||||
selector {
|
||||
match_labels = local.discord_labels
|
||||
}
|
||||
|
||||
template {
|
||||
metadata {
|
||||
labels = local.discord_labels
|
||||
}
|
||||
|
||||
spec {
|
||||
container {
|
||||
image = "roleypoly/discord:${local.tags.discord}"
|
||||
name = "discord"
|
||||
|
||||
liveness_probe {
|
||||
http_get {
|
||||
path = "/"
|
||||
port = 16777
|
||||
}
|
||||
|
||||
initial_delay_seconds = 3
|
||||
period_seconds = 3
|
||||
}
|
||||
|
||||
readiness_probe {
|
||||
http_get {
|
||||
path = "/"
|
||||
port = 16777
|
||||
}
|
||||
|
||||
initial_delay_seconds = 3
|
||||
period_seconds = 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
terraform {
|
||||
required_version = ">=0.12.6"
|
||||
|
||||
backend "remote" {
|
||||
organization = "Roleypoly"
|
||||
|
||||
workspaces {
|
||||
prefix = "roleypoly-app-"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
variable "k8s_endpoint" { type = string }
|
||||
variable "k8s_token" { type = string }
|
||||
variable "k8s_cert" { type = string }
|
||||
variable "k8s_namespace" { type = string }
|
||||
provider "kubernetes" {
|
||||
load_config_file = false
|
||||
token = var.k8s_token
|
||||
host = var.k8s_endpoint
|
||||
cluster_ca_certificate = var.k8s_cert
|
||||
}
|
||||
|
||||
locals {
|
||||
ns = var.k8s_namespace
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"deployment_env": {
|
||||
"production": {},
|
||||
"staging": {}
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
variable "deployment_env" {
|
||||
type = map(map(string))
|
||||
}
|
||||
|
||||
variable "environment_tag" {
|
||||
type = string
|
||||
description = "One of: production, staging, test"
|
||||
}
|
||||
|
||||
locals {
|
||||
tags = var.deployment_env[var.environment_tag]
|
||||
}
|
20
terraform/functions/.terraform.lock.hcl
generated
20
terraform/functions/.terraform.lock.hcl
generated
|
@ -1,20 +0,0 @@
|
|||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/google" {
|
||||
version = "3.49.0"
|
||||
constraints = ">= 3.49.0"
|
||||
hashes = [
|
||||
"h1:MgihBNqO052m2jthWBu00wWYkz+eNrETwLqBfWmvMMY=",
|
||||
"zh:00ea68b3a3b6e11ea469f47ee949c7f8f5751f935a3366152f9d3c6660c27e9b",
|
||||
"zh:1ef3efc2e81fa31ceb04e39ae25acd0f061629f104827e127bdb4345e95f37d0",
|
||||
"zh:6bf00943baa776adef0bbc914886359cf95c505b0494f3936cedac5cd1e01a00",
|
||||
"zh:7d2cce5a9be476d8eee67435d854d094f82b5814a0e34964d10f28c1e88a2c8f",
|
||||
"zh:841d074e3fb06f0df7c930bc0c4a9733ce0c5f1a19d6af98632a7931d2ca6a59",
|
||||
"zh:8920ccd27c8904fcf5d701d71baee4f64d9d6f1383e66c4673909d9c53895057",
|
||||
"zh:91d4479d2d461ad582d127d47aa7094bd74a1278cc8d78ad36a1c4f31301f4f0",
|
||||
"zh:a97c19cdb42b5f7e4e297183d60eaa45843ee7b0adde1120e47026c4cae456c1",
|
||||
"zh:cbd862cc4d21866bb832e3e7fe4e6ed959f5e5363bcf3d74e476b42fec716efe",
|
||||
"zh:ec3c63ba6db74b353fafff6aedbb30e3eb1a4e5c856b4920c7ffa10d7081cbbd",
|
||||
]
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
|
||||
resource "google_cloudfunctions_function" "function" {
|
||||
name = "roleypoly-test-hello-world"
|
||||
description = "Roleypoly FaaS: /hello-world"
|
||||
runtime = "go113"
|
||||
|
||||
available_memory_mb = 128
|
||||
source_repository {
|
||||
url = "https://source.cloud.google.com/projects/roleypoly/repos/github_roleypoly_roleypoly/moveable-alias/gcf/paths/src/functions/hello-world"
|
||||
}
|
||||
trigger_http = true
|
||||
entry_point = "helloGET"
|
||||
}
|
||||
|
||||
# IAM entry for all users to invoke the function
|
||||
resource "google_cloudfunctions_function_iam_member" "invoker" {
|
||||
project = google_cloudfunctions_function.function.project
|
||||
region = google_cloudfunctions_function.function.region
|
||||
cloud_function = google_cloudfunctions_function.function.name
|
||||
|
||||
role = "roles/cloudfunctions.invoker"
|
||||
member = "allUsers"
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
terraform {
|
||||
required_version = ">=0.14"
|
||||
required_providers {
|
||||
google = {
|
||||
source = "hashicorp/google"
|
||||
version = ">=3.49.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Google Cloud
|
||||
*/
|
||||
# variable "gcs_token" { type = string }
|
||||
# variable "gcs_region" { type = string }
|
||||
# variable "gcs_project" { type = string }
|
||||
provider "google" {
|
||||
# project = var.gcs_project
|
||||
# region = var.gcs_region
|
||||
# credentials = var.gcs_token
|
||||
|
||||
scopes = [
|
||||
"https://www.googleapis.com/auth/devstorage.full_control",
|
||||
"https://www.googleapis.com/auth/cloud-platform",
|
||||
]
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
# Primary cluster hostname
|
||||
resource "cloudflare_record" "cluster" {
|
||||
zone_id = var.cloudflare-zone-id
|
||||
name = var.record-name
|
||||
value = var.ingress-endpoint
|
||||
type = "A"
|
||||
proxied = true
|
||||
}
|
||||
|
||||
# PRD & STG records for direct FQDN usage
|
||||
# Long term, these will also be CNAME'd to
|
||||
# - prd == roleypoly.com
|
||||
# - stg == beta.roleypoly.com
|
||||
resource "cloudflare_record" "prd" {
|
||||
zone_id = var.cloudflare-zone-id
|
||||
name = "prd.${var.record-name}"
|
||||
value = cloudflare_record.cluster.hostname
|
||||
type = "CNAME"
|
||||
proxied = true
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "stg" {
|
||||
zone_id = var.cloudflare-zone-id
|
||||
name = "stg.${var.record-name}"
|
||||
value = cloudflare_record.cluster.hostname
|
||||
type = "CNAME"
|
||||
proxied = true
|
||||
}
|
||||
|
||||
# Origin CA Cert
|
||||
resource "tls_private_key" "origin-ca-key" {
|
||||
algorithm = "ECDSA"
|
||||
}
|
||||
|
||||
resource "tls_cert_request" "origin-ca-csr" {
|
||||
key_algorithm = tls_private_key.origin-ca-key.algorithm
|
||||
private_key_pem = tls_private_key.origin-ca-key.private_key_pem
|
||||
|
||||
subject {
|
||||
common_name = "roleypoly.com"
|
||||
organization = "Roleypoly"
|
||||
}
|
||||
}
|
||||
|
||||
resource "cloudflare_origin_ca_certificate" "origin-ca-cert" {
|
||||
csr = tls_cert_request.origin-ca-csr.cert_request_pem
|
||||
hostnames = [
|
||||
cloudflare_record.cluster.hostname,
|
||||
cloudflare_record.prd.hostname,
|
||||
cloudflare_record.stg.hostname
|
||||
]
|
||||
request_type = "origin-ecc"
|
||||
requested_validity = 1095 # 3 years
|
||||
}
|
||||
|
||||
resource "kubernetes_secret" "cloudflare-origin" {
|
||||
type = "kubernetes.io/tls"
|
||||
metadata {
|
||||
name = "cloudflare-origin"
|
||||
namespace = "default"
|
||||
}
|
||||
data = {
|
||||
"tls.crt" = base64encode(cloudflare_origin_ca_certificate.origin-ca-cert.certificate),
|
||||
"tls.key" = base64encode(tls_private_key.origin-ca-key.private_key_pem)
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
variable "ingress-name" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "ingress-namespace" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "ingress-endpoint" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "cloudflare-zone-id" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "record-name" {
|
||||
type = string
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
terraform {
|
||||
required_version = ">=0.12"
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
locals {
|
||||
ns = "${var.app_name}-${var.environment_tag}"
|
||||
labels = {
|
||||
"app.kubernetes.io/name" = var.app_name
|
||||
"app.kubernetes.io/part-of" = var.app_name
|
||||
"roleypoly/environment" = var.environment_tag
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_namespace" "ns" {
|
||||
metadata {
|
||||
name = local.ns
|
||||
labels = local.labels
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_service_account" "sa" {
|
||||
metadata {
|
||||
name = "${local.ns}-sa-tf"
|
||||
namespace = local.ns
|
||||
labels = local.labels
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_secret" "sa-key" {
|
||||
metadata {
|
||||
name = "${local.ns}-sa-tf-key"
|
||||
namespace = local.ns
|
||||
labels = local.labels
|
||||
annotations = {
|
||||
"kubernetes.io/service-account.name" = kubernetes_service_account.sa.metadata.0.name
|
||||
}
|
||||
}
|
||||
|
||||
type = "kubernetes.io/service-account-token"
|
||||
}
|
||||
|
||||
resource "kubernetes_role_binding" "sa-admin-rb" {
|
||||
metadata {
|
||||
name = "${local.ns}-sa-admin-binding"
|
||||
namespace = local.ns
|
||||
labels = local.labels
|
||||
}
|
||||
|
||||
subject {
|
||||
kind = "ServiceAccount"
|
||||
name = kubernetes_service_account.sa.metadata.0.name
|
||||
namespace = local.ns
|
||||
}
|
||||
|
||||
role_ref {
|
||||
kind = "ClusterRole"
|
||||
name = "admin"
|
||||
api_group = "rbac.authorization.k8s.io"
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
output "service_account_token" {
|
||||
value = lookup(kubernetes_secret.sa-key, "data.token", "")
|
||||
}
|
||||
|
||||
output "namespace" {
|
||||
value = local.ns
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
variable "environment_tag" {
|
||||
type = string
|
||||
default = "main"
|
||||
}
|
||||
|
||||
variable "app_name" {
|
||||
type = string
|
||||
}
|
||||
|
|
@ -1,331 +0,0 @@
|
|||
locals {
|
||||
ns = kubernetes_namespace.ns.metadata.0.name
|
||||
labels = {
|
||||
"app.kubernetes.io/name" = "ingress-nginx"
|
||||
"app.kubernetes.io/part-of" = "ingress-nginx"
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_namespace" "ns" {
|
||||
metadata {
|
||||
name = "ingress-nginx"
|
||||
labels = local.labels
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_config_map" "cm-nginx" {
|
||||
metadata {
|
||||
name = "nginx-configuration"
|
||||
namespace = local.ns
|
||||
labels = local.labels
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_config_map" "cm-tcp" {
|
||||
metadata {
|
||||
name = "tcp-services"
|
||||
namespace = local.ns
|
||||
labels = local.labels
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_config_map" "cm-udp" {
|
||||
metadata {
|
||||
name = "udp-services"
|
||||
namespace = local.ns
|
||||
labels = local.labels
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_service_account" "sa" {
|
||||
metadata {
|
||||
name = "nginx-ingress-serviceaccount"
|
||||
namespace = local.ns
|
||||
labels = local.labels
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_cluster_role" "cr" {
|
||||
metadata {
|
||||
name = "nginx-ingress-clusterrole"
|
||||
labels = local.labels
|
||||
}
|
||||
rule {
|
||||
api_groups = [""]
|
||||
resources = ["configmaps", "endpoints", "nodes", "pods", "secrets"]
|
||||
verbs = ["list", "watch"]
|
||||
}
|
||||
rule {
|
||||
api_groups = [""]
|
||||
resources = ["nodes"]
|
||||
verbs = ["get"]
|
||||
}
|
||||
rule {
|
||||
api_groups = [""]
|
||||
resources = ["services"]
|
||||
verbs = ["get", "list", "watch"]
|
||||
}
|
||||
rule {
|
||||
api_groups = [""]
|
||||
resources = ["events"]
|
||||
verbs = ["create", "patch"]
|
||||
}
|
||||
rule {
|
||||
api_groups = ["extensions", "networking.k8s.io"]
|
||||
resources = ["ingresses"]
|
||||
verbs = ["get", "list", "watch"]
|
||||
}
|
||||
rule {
|
||||
api_groups = ["extensions", "networking.k8s.io"]
|
||||
resources = ["ingresses/status"]
|
||||
verbs = ["update"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_role" "role" {
|
||||
metadata {
|
||||
name = "nginx-ingress-role"
|
||||
namespace = local.ns
|
||||
labels = local.labels
|
||||
}
|
||||
|
||||
rule {
|
||||
api_groups = [""]
|
||||
resources = ["configmaps", "pods", "secrets", "namespaces"]
|
||||
verbs = ["get"]
|
||||
}
|
||||
|
||||
rule {
|
||||
api_groups = [""]
|
||||
resources = ["configmaps"]
|
||||
resource_names = ["ingress-controller-leader-nginx"]
|
||||
verbs = ["get", "update"]
|
||||
}
|
||||
|
||||
rule {
|
||||
api_groups = [""]
|
||||
resources = ["configmaps"]
|
||||
verbs = ["create"]
|
||||
}
|
||||
|
||||
rule {
|
||||
api_groups = [""]
|
||||
resources = ["endpoints"]
|
||||
verbs = ["get"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_role_binding" "rb" {
|
||||
metadata {
|
||||
name = "nginx-ingress-role-nisa-binding"
|
||||
namespace = local.ns
|
||||
labels = local.labels
|
||||
}
|
||||
|
||||
role_ref {
|
||||
api_group = "rbac.authorization.k8s.io"
|
||||
kind = "Role"
|
||||
name = kubernetes_role.role.metadata.0.name
|
||||
}
|
||||
|
||||
subject {
|
||||
kind = "ServiceAccount"
|
||||
name = kubernetes_service_account.sa.metadata.0.name
|
||||
namespace = local.ns
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_cluster_role_binding" "crb" {
|
||||
metadata {
|
||||
name = "nginx-ingress-clusterrole-nisa-binding"
|
||||
labels = local.labels
|
||||
}
|
||||
|
||||
role_ref {
|
||||
api_group = "rbac.authorization.k8s.io"
|
||||
kind = "ClusterRole"
|
||||
name = kubernetes_cluster_role.cr.metadata.0.name
|
||||
}
|
||||
|
||||
subject {
|
||||
kind = "ServiceAccount"
|
||||
name = kubernetes_service_account.sa.metadata.0.name
|
||||
namespace = local.ns
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_deployment" "deployment" {
|
||||
metadata {
|
||||
name = "nginx-ingress-controller"
|
||||
namespace = local.ns
|
||||
labels = local.labels
|
||||
}
|
||||
|
||||
spec {
|
||||
replicas = 3
|
||||
|
||||
selector {
|
||||
match_labels = local.labels
|
||||
}
|
||||
|
||||
template {
|
||||
metadata {
|
||||
labels = local.labels
|
||||
annotations = {
|
||||
"prometheus.io/port" = "10254"
|
||||
"prometheus.io/scrape" = "true"
|
||||
}
|
||||
}
|
||||
|
||||
spec {
|
||||
automount_service_account_token = true
|
||||
termination_grace_period_seconds = 300
|
||||
service_account_name = kubernetes_service_account.sa.metadata.0.name
|
||||
node_selector = {
|
||||
"kubernetes.io/os" = "linux"
|
||||
node_type = "static"
|
||||
}
|
||||
|
||||
container {
|
||||
name = "nginx-ingress-controller"
|
||||
image = "quay.io/kubernetes-ingress-controller/nginx-ingress-controller:${var.nginx-ingress-version}"
|
||||
args = [
|
||||
"/nginx-ingress-controller",
|
||||
"--configmap=${local.ns}/${kubernetes_config_map.cm-nginx.metadata.0.name}",
|
||||
"--tcp-services-configmap=${local.ns}/${kubernetes_config_map.cm-tcp.metadata.0.name}",
|
||||
"--udp-services-configmap=${local.ns}/${kubernetes_config_map.cm-udp.metadata.0.name}",
|
||||
"--publish-service=${local.ns}/ingress-nginx",
|
||||
"--annotations-prefix=nginx.ingress.kubernetes.io",
|
||||
]
|
||||
security_context {
|
||||
allow_privilege_escalation = true
|
||||
capabilities {
|
||||
drop = ["ALL"]
|
||||
add = ["NET_BIND_SERVICE"]
|
||||
}
|
||||
run_as_user = 101
|
||||
}
|
||||
|
||||
env {
|
||||
name = "POD_NAME"
|
||||
value_from {
|
||||
field_ref {
|
||||
field_path = "metadata.name"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
env {
|
||||
name = "POD_NAMESPACE"
|
||||
value_from {
|
||||
field_ref {
|
||||
field_path = "metadata.namespace"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
port {
|
||||
name = "http"
|
||||
container_port = 80
|
||||
protocol = "TCP"
|
||||
}
|
||||
|
||||
port {
|
||||
name = "https"
|
||||
container_port = 443
|
||||
protocol = "TCP"
|
||||
}
|
||||
|
||||
liveness_probe {
|
||||
http_get {
|
||||
path = "/healthz"
|
||||
port = 10254
|
||||
scheme = "HTTP"
|
||||
}
|
||||
failure_threshold = 3
|
||||
initial_delay_seconds = 10
|
||||
period_seconds = 10
|
||||
success_threshold = 1
|
||||
timeout_seconds = 10
|
||||
}
|
||||
|
||||
readiness_probe {
|
||||
http_get {
|
||||
path = "/healthz"
|
||||
port = 10254
|
||||
scheme = "HTTP"
|
||||
}
|
||||
failure_threshold = 3
|
||||
initial_delay_seconds = 10
|
||||
period_seconds = 10
|
||||
success_threshold = 1
|
||||
timeout_seconds = 10
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
pre_stop {
|
||||
exec {
|
||||
command = ["/wait-shutdown"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_limit_range" "lr" {
|
||||
metadata {
|
||||
name = "ingress-nginx"
|
||||
namespace = local.ns
|
||||
labels = local.labels
|
||||
}
|
||||
|
||||
spec {
|
||||
limit {
|
||||
min = {
|
||||
memory = "90Mi"
|
||||
cpu = "100m"
|
||||
}
|
||||
|
||||
type = "Container"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Specific service related to Google Cloud
|
||||
resource "kubernetes_service" "svc" {
|
||||
metadata {
|
||||
name = "ingress-nginx"
|
||||
namespace = local.ns
|
||||
labels = local.labels
|
||||
}
|
||||
|
||||
spec {
|
||||
external_traffic_policy = "Local"
|
||||
type = "LoadBalancer"
|
||||
selector = local.labels
|
||||
|
||||
port {
|
||||
name = "http"
|
||||
port = 80
|
||||
protocol = "TCP"
|
||||
target_port = "http"
|
||||
}
|
||||
|
||||
port {
|
||||
name = "https"
|
||||
port = 443
|
||||
protocol = "TCP"
|
||||
target_port = "https"
|
||||
}
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [
|
||||
// We add no annotations, but DO adds some.
|
||||
metadata[0].annotations,
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
output "service-name" {
|
||||
value = kubernetes_service.svc.metadata.0.name
|
||||
}
|
||||
|
||||
output "service-namespace" {
|
||||
value = kubernetes_service.svc.metadata.0.namespace
|
||||
}
|
||||
|
||||
output "service-endpoint" {
|
||||
value = kubernetes_service.svc.load_balancer_ingress.0.ip
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
variable "nginx-ingress-version" {
|
||||
type = string
|
||||
default = "0.30.0"
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
terraform {
|
||||
required_version = ">=0.12"
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
locals {
|
||||
dependentModulesPathed = formatlist("terraform/modules/%s", var.dependent_modules)
|
||||
variableDescription = "Terraform-owned variable"
|
||||
}
|
||||
|
||||
resource "tfe_workspace" "ws" {
|
||||
name = var.workspace-name
|
||||
organization = var.tfc_org
|
||||
auto_apply = var.auto_apply
|
||||
trigger_prefixes = concat([var.directory], local.dependentModulesPathed)
|
||||
working_directory = var.directory
|
||||
|
||||
vcs_repo {
|
||||
identifier = var.repo
|
||||
branch = var.branch
|
||||
oauth_token_id = var.tfc_oauth_token_id
|
||||
}
|
||||
}
|
||||
|
||||
resource "tfe_notification_configuration" "webhook" {
|
||||
name = "${var.workspace-name}-webhook"
|
||||
enabled = true
|
||||
destination_type = "slack"
|
||||
triggers = ["run:created", "run:planning", "run:needs_attention", "run:applying", "run:completed", "run:errored"]
|
||||
url = var.tfc_webhook_url
|
||||
workspace_id = tfe_workspace.ws.id
|
||||
}
|
||||
|
||||
resource "tfe_variable" "vars" {
|
||||
for_each = var.vars
|
||||
|
||||
key = each.key
|
||||
value = each.value
|
||||
category = "terraform"
|
||||
workspace_id = tfe_workspace.ws.id
|
||||
sensitive = false
|
||||
}
|
||||
|
||||
resource "tfe_variable" "sensitive" {
|
||||
for_each = var.secret-vars
|
||||
|
||||
key = each.key
|
||||
value = each.value
|
||||
category = "terraform"
|
||||
workspace_id = tfe_workspace.ws.id
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
resource "tfe_variable" "env" {
|
||||
for_each = var.env-vars
|
||||
|
||||
key = each.key
|
||||
value = each.value
|
||||
category = "env"
|
||||
workspace_id = tfe_workspace.ws.id
|
||||
sensitive = true
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
output "workspace" {
|
||||
value = tfe_workspace.ws[*]
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
variable "workspace-name" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "secret-vars" {
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "vars" {
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "env-vars" {
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "repo" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "directory" {
|
||||
type = string
|
||||
default = "/"
|
||||
}
|
||||
|
||||
variable "branch" {
|
||||
type = string
|
||||
default = "master"
|
||||
}
|
||||
|
||||
variable "auto_apply" {
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "dependent_modules" {
|
||||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "tfc_oauth_token_id" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "tfc_org" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "tfc_webhook_url" {
|
||||
type = string
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
terraform {
|
||||
required_version = ">=0.12.6"
|
||||
}
|
||||
|
||||
provider "tfe" {
|
||||
version = ">=0.15.0"
|
||||
}
|
157
yarn.lock
157
yarn.lock
|
@ -1081,6 +1081,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@cloudflare/workers-types@^2.1.0":
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@cloudflare/workers-types/-/workers-types-2.1.0.tgz#6e4f07567f4c914ad811c2d7a6172d0ae834c7f6"
|
||||
integrity sha512-VmXaHTq0lt6Xre4aK1hUK25hjZjuEUkHtdUEt0FJamv+NzQO54Gwp6Zr5Cfu6SP5EQ/tTmTMP/tK9npA8zhcCg==
|
||||
|
||||
"@cnakazawa/watch@^1.0.3":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a"
|
||||
|
@ -2280,6 +2285,27 @@
|
|||
"@types/cheerio" "*"
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/eslint-scope@^3.7.0":
|
||||
version "3.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.0.tgz#4792816e31119ebd506902a482caec4951fabd86"
|
||||
integrity sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw==
|
||||
dependencies:
|
||||
"@types/eslint" "*"
|
||||
"@types/estree" "*"
|
||||
|
||||
"@types/eslint@*":
|
||||
version "7.2.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.6.tgz#5e9aff555a975596c03a98b59ecd103decc70c3c"
|
||||
integrity sha512-I+1sYH+NPQ3/tVqCeUSBwTE/0heyvtXqpIopUUArlBm0Kpocb8FbMa3AZ/ASKIFpN3rnEx932TTXDbt9OXsNDw==
|
||||
dependencies:
|
||||
"@types/estree" "*"
|
||||
"@types/json-schema" "*"
|
||||
|
||||
"@types/estree@*", "@types/estree@^0.0.45":
|
||||
version "0.0.45"
|
||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884"
|
||||
integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==
|
||||
|
||||
"@types/glob-base@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/glob-base/-/glob-base-0.3.0.tgz#a581d688347e10e50dd7c17d6f2880a10354319d"
|
||||
|
@ -2365,7 +2391,7 @@
|
|||
jest-diff "^26.0.0"
|
||||
pretty-format "^26.0.0"
|
||||
|
||||
"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6":
|
||||
"@types/json-schema@*", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6":
|
||||
version "7.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0"
|
||||
integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==
|
||||
|
@ -2560,6 +2586,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
|
||||
integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==
|
||||
|
||||
"@types/uuid@^8.3.0":
|
||||
version "8.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.0.tgz#215c231dff736d5ba92410e6d602050cce7e273f"
|
||||
integrity sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==
|
||||
|
||||
"@types/webpack-env@^1.15.3":
|
||||
version "1.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.16.0.tgz#8c0a9435dfa7b3b1be76562f3070efb3f92637b4"
|
||||
|
@ -2916,6 +2947,11 @@ acorn@^7.1.0, acorn@^7.1.1, acorn@^7.4.0:
|
|||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
|
||||
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
|
||||
|
||||
acorn@^8.0.4:
|
||||
version "8.0.4"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.0.4.tgz#7a3ae4191466a6984eee0fe3407a4f3aa9db8354"
|
||||
integrity sha512-XNP0PqF1XD19ZlLKvB7cMmnZswW4C/03pRHgirB30uSJTaS3A3V1/P4sS3HPvFmjoriPCJQs+JDSbm4bL1TxGQ==
|
||||
|
||||
add-px-to-style@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/add-px-to-style/-/add-px-to-style-1.0.0.tgz#d0c135441fa8014a8137904531096f67f28f263a"
|
||||
|
@ -5654,6 +5690,14 @@ enhanced-resolve@^4.0.0, enhanced-resolve@^4.3.0:
|
|||
memory-fs "^0.5.0"
|
||||
tapable "^1.0.0"
|
||||
|
||||
enhanced-resolve@^5.3.1:
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.4.0.tgz#a8bcf23b00affac9455cf71efd80844f4054f4dc"
|
||||
integrity sha512-ZmqfWURB2lConOBM1JdCVfPyMRv5RdKWktLXO6123p97ovVm2CLBgw9t5MBj3jJWA6eHyOeIws9iJQoGFR4euQ==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.4"
|
||||
tapable "^2.0.0"
|
||||
|
||||
enquirer@^2.3.5:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
|
||||
|
@ -6104,7 +6148,7 @@ event-target-shim@^5.0.0:
|
|||
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
|
||||
integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
|
||||
|
||||
events@^3.0.0:
|
||||
events@^3.0.0, events@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379"
|
||||
integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==
|
||||
|
@ -8541,7 +8585,7 @@ jest-worker@24.9.0, jest-worker@^24.9.0:
|
|||
merge-stream "^2.0.0"
|
||||
supports-color "^6.1.0"
|
||||
|
||||
jest-worker@^26.2.1, jest-worker@^26.6.2:
|
||||
jest-worker@^26.2.1, jest-worker@^26.6.1, jest-worker@^26.6.2:
|
||||
version "26.6.2"
|
||||
resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed"
|
||||
integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==
|
||||
|
@ -8870,6 +8914,11 @@ loader-runner@^2.4.0:
|
|||
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
|
||||
integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
|
||||
|
||||
loader-runner@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.1.0.tgz#f70bc0c29edbabdf2043e7ee73ccc3fe1c96b42d"
|
||||
integrity sha512-oR4lB4WvwFoC70ocraKhn5nkKSs23t57h9udUgw8o0iH8hMXeEoRuUgfcvgUwAJ1ZpRqBvcou4N2SMvM1DwMrA==
|
||||
|
||||
loader-utils@1.2.3:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7"
|
||||
|
@ -8888,7 +8937,7 @@ loader-utils@2.0.0, loader-utils@^2.0.0:
|
|||
emojis-list "^3.0.0"
|
||||
json5 "^2.1.2"
|
||||
|
||||
loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0:
|
||||
loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
|
||||
integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==
|
||||
|
@ -9334,7 +9383,7 @@ micromatch@^3.1.10, micromatch@^3.1.4:
|
|||
snapdragon "^0.8.1"
|
||||
to-regex "^3.0.2"
|
||||
|
||||
micromatch@^4.0.2:
|
||||
micromatch@^4.0.0, micromatch@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259"
|
||||
integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==
|
||||
|
@ -11957,6 +12006,13 @@ serialize-javascript@^4.0.0:
|
|||
dependencies:
|
||||
randombytes "^2.1.0"
|
||||
|
||||
serialize-javascript@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4"
|
||||
integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==
|
||||
dependencies:
|
||||
randombytes "^2.1.0"
|
||||
|
||||
serve-favicon@^2.5.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.5.0.tgz#935d240cdfe0f5805307fdfe967d88942a2cbcf0"
|
||||
|
@ -12202,7 +12258,7 @@ sort-package-json@1.48.0:
|
|||
is-plain-obj "2.1.0"
|
||||
sort-object-keys "^1.1.3"
|
||||
|
||||
source-list-map@^2.0.0:
|
||||
source-list-map@^2.0.0, source-list-map@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
|
||||
integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
|
||||
|
@ -12218,7 +12274,7 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
|
|||
source-map-url "^0.4.0"
|
||||
urix "^0.1.0"
|
||||
|
||||
source-map-support@^0.5.16, source-map-support@^0.5.6, source-map-support@~0.5.12:
|
||||
source-map-support@^0.5.16, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.19:
|
||||
version "0.5.19"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
|
||||
integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
|
||||
|
@ -12236,7 +12292,7 @@ source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, sourc
|
|||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
source-map@0.7.3, source-map@^0.7.3:
|
||||
source-map@0.7.3, source-map@^0.7.3, source-map@~0.7.2:
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
||||
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
|
||||
|
@ -12859,6 +12915,11 @@ tapable@^1.0.0, tapable@^1.1.3:
|
|||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
|
||||
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
|
||||
|
||||
tapable@^2.0.0, tapable@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.1.1.tgz#b01cc1902d42a7bb30514e320ce21c456f72fd3f"
|
||||
integrity sha512-Wib1S8m2wdpLbmQz0RBEVosIyvb/ykfKXf3ZIDqvWoMg/zTNm6G/tDSuUM61J1kNCDXWJrLHGSFeMhAG+gAGpQ==
|
||||
|
||||
tar-fs@^2.0.0, tar-fs@^2.1.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784"
|
||||
|
@ -12949,6 +13010,18 @@ terser-webpack-plugin@^3.0.0:
|
|||
terser "^4.8.0"
|
||||
webpack-sources "^1.4.3"
|
||||
|
||||
terser-webpack-plugin@^5.0.3:
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.0.3.tgz#ec60542db2421f45735c719d2e17dabfbb2e3e42"
|
||||
integrity sha512-zFdGk8Lh9ZJGPxxPE6jwysOlATWB8GMW8HcfGULWA/nPal+3VdATflQvSBSLQJRCmYZnfFJl6vkRTiwJGNgPiQ==
|
||||
dependencies:
|
||||
jest-worker "^26.6.1"
|
||||
p-limit "^3.0.2"
|
||||
schema-utils "^3.0.0"
|
||||
serialize-javascript "^5.0.1"
|
||||
source-map "^0.6.1"
|
||||
terser "^5.3.8"
|
||||
|
||||
terser@5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-5.1.0.tgz#1f4ab81c8619654fdded51f3157b001e1747281d"
|
||||
|
@ -12967,6 +13040,15 @@ terser@^4.1.2, terser@^4.6.3, terser@^4.8.0:
|
|||
source-map "~0.6.1"
|
||||
source-map-support "~0.5.12"
|
||||
|
||||
terser@^5.3.8:
|
||||
version "5.5.1"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-5.5.1.tgz#540caa25139d6f496fdea056e414284886fb2289"
|
||||
integrity sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==
|
||||
dependencies:
|
||||
commander "^2.20.0"
|
||||
source-map "~0.7.2"
|
||||
source-map-support "~0.5.19"
|
||||
|
||||
test-exclude@^5.2.3:
|
||||
version "5.2.3"
|
||||
resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0"
|
||||
|
@ -13197,6 +13279,17 @@ ts-jest@^26.4.4:
|
|||
semver "7.x"
|
||||
yargs-parser "20.x"
|
||||
|
||||
ts-loader@^8.0.11:
|
||||
version "8.0.11"
|
||||
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.11.tgz#35d58a65932caacb120426eea59eca841786c899"
|
||||
integrity sha512-06X+mWA2JXoXJHYAesUUL4mHFYhnmyoCdQVMXofXF552Lzd4wNwSGg7unJpttqUP7ziaruM8d7u8LUB6I1sgzA==
|
||||
dependencies:
|
||||
chalk "^2.3.0"
|
||||
enhanced-resolve "^4.0.0"
|
||||
loader-utils "^1.0.2"
|
||||
micromatch "^4.0.0"
|
||||
semver "^6.0.0"
|
||||
|
||||
ts-pnp@^1.1.6:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"
|
||||
|
@ -13626,7 +13719,7 @@ uuid@^7.0.3:
|
|||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b"
|
||||
integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==
|
||||
|
||||
uuid@^8.0.0, uuid@^8.3.0:
|
||||
uuid@^8.0.0, uuid@^8.3.0, uuid@^8.3.1:
|
||||
version "8.3.1"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31"
|
||||
integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==
|
||||
|
@ -13750,6 +13843,14 @@ watchpack@^1.7.4:
|
|||
chokidar "^3.4.1"
|
||||
watchpack-chokidar2 "^2.0.1"
|
||||
|
||||
watchpack@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.0.1.tgz#2f2192c542c82a3bcde76acd3411470c120426a8"
|
||||
integrity sha512-vO8AKGX22ZRo6PiOFM9dC0re8IcKh8Kd/aH2zeqUc6w4/jBGlTy2P7fTC6ekT0NjVeGjgU2dGC5rNstKkeLEQg==
|
||||
dependencies:
|
||||
glob-to-regexp "^0.4.1"
|
||||
graceful-fs "^4.1.2"
|
||||
|
||||
web-namespaces@^1.0.0:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec"
|
||||
|
@ -13822,6 +13923,14 @@ webpack-sources@1.4.3, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-s
|
|||
source-list-map "^2.0.0"
|
||||
source-map "~0.6.1"
|
||||
|
||||
webpack-sources@^2.1.1:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.2.0.tgz#058926f39e3d443193b6c31547229806ffd02bac"
|
||||
integrity sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w==
|
||||
dependencies:
|
||||
source-list-map "^2.0.1"
|
||||
source-map "^0.6.1"
|
||||
|
||||
webpack-virtual-modules@^0.2.2:
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.2.2.tgz#20863dc3cb6bb2104729fff951fbe14b18bd0299"
|
||||
|
@ -13887,6 +13996,36 @@ webpack@^4.44.2:
|
|||
watchpack "^1.7.4"
|
||||
webpack-sources "^1.4.1"
|
||||
|
||||
webpack@^5.9.0:
|
||||
version "5.9.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.9.0.tgz#af2e9cf9d6c7867cdcf214ea3bb5eb77aece6895"
|
||||
integrity sha512-YnnqIV/uAS5ZrNpctSv378qV7HmbJ74DL+XfvMxzbX1bV9e7eeT6eEWU4wuUw33CNr/HspBh7R/xQlVjTEyAeA==
|
||||
dependencies:
|
||||
"@types/eslint-scope" "^3.7.0"
|
||||
"@types/estree" "^0.0.45"
|
||||
"@webassemblyjs/ast" "1.9.0"
|
||||
"@webassemblyjs/helper-module-context" "1.9.0"
|
||||
"@webassemblyjs/wasm-edit" "1.9.0"
|
||||
"@webassemblyjs/wasm-parser" "1.9.0"
|
||||
acorn "^8.0.4"
|
||||
browserslist "^4.14.5"
|
||||
chrome-trace-event "^1.0.2"
|
||||
enhanced-resolve "^5.3.1"
|
||||
eslint-scope "^5.1.1"
|
||||
events "^3.2.0"
|
||||
glob-to-regexp "^0.4.1"
|
||||
graceful-fs "^4.2.4"
|
||||
json-parse-better-errors "^1.0.2"
|
||||
loader-runner "^4.1.0"
|
||||
mime-types "^2.1.27"
|
||||
neo-async "^2.6.2"
|
||||
pkg-dir "^4.2.0"
|
||||
schema-utils "^3.0.0"
|
||||
tapable "^2.1.1"
|
||||
terser-webpack-plugin "^5.0.3"
|
||||
watchpack "^2.0.0"
|
||||
webpack-sources "^2.1.1"
|
||||
|
||||
whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3, whatwg-encoding@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
|
||||
|
|
Loading…
Add table
Reference in a new issue