@vaharoni/devops 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/{chunk-N2NFRGJO.js → chunk-JQGPJAPS.js} +1 -1
  2. package/dist/{chunk-OFUEFG64.js → chunk-STUOTOGE.js} +1 -1
  3. package/dist/{chunk-HXGGJIAS.js → chunk-VZ6XNNUH.js} +1 -0
  4. package/dist/devops.js +21 -24
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.js +2 -2
  7. package/dist/plugins.js +2 -2
  8. package/dist/src/target-templates/infra-variants/digitalocean/.github/workflows/k8s-build.yaml +13 -13
  9. package/dist/src/target-templates/infra-variants/gcloud/.github/workflows/k8s-build.yaml +15 -15
  10. package/dist/src/target-templates/infra-variants/hetzner/.devops/config/constants.yaml +4 -0
  11. package/dist/src/target-templates/infra-variants/hetzner/.github/workflows/k8s-build.yaml +13 -13
  12. package/dist/src/target-templates/lang-variants-common/typescript/.github/actions/registry/connect-to-artifact-registry-with-oidc@v1/action.yaml +29 -0
  13. package/{src/target-templates/lang-variants-common/typescript/.github/actions/registry/connect-to-artifact-registry@v1 → dist/src/target-templates/lang-variants-common/typescript/.github/actions/registry/connect-to-artifact-registry-with-sa@v1}/action.yaml +2 -2
  14. package/package.json +1 -1
  15. package/src/cli/core/namespace.ts +5 -5
  16. package/src/libs/{hetzner/reg-secret.ts → registry/image-pull-secret.ts} +13 -15
  17. package/src/target-templates/infra-variants/digitalocean/.github/workflows/k8s-build.yaml +13 -13
  18. package/src/target-templates/infra-variants/gcloud/.github/workflows/k8s-build.yaml +15 -15
  19. package/src/target-templates/infra-variants/hetzner/.devops/config/constants.yaml +4 -0
  20. package/src/target-templates/infra-variants/hetzner/.github/workflows/k8s-build.yaml +13 -13
  21. package/src/target-templates/lang-variants-common/typescript/.github/actions/registry/connect-to-artifact-registry-with-oidc@v1/action.yaml +29 -0
  22. package/{dist/src/target-templates/lang-variants-common/typescript/.github/actions/registry/connect-to-artifact-registry@v1 → src/target-templates/lang-variants-common/typescript/.github/actions/registry/connect-to-artifact-registry-with-sa@v1}/action.yaml +2 -2
  23. package/src/types/index.ts +1 -0
  24. /package/dist/src/target-templates/lang-variants-common/typescript/.github/actions/{build-image@v1 → common/build-image@v1}/action.yaml +0 -0
  25. /package/dist/src/target-templates/lang-variants-common/typescript/.github/actions/{db-migrate@v1 → common/db-migrate@v1}/action.yaml +0 -0
  26. /package/dist/src/target-templates/lang-variants-common/typescript/.github/actions/{deploy-image-cloudrun@v1 → common/deploy-image-cloudrun@v1}/action.yaml +0 -0
  27. /package/dist/src/target-templates/lang-variants-common/typescript/.github/actions/{deploy-image-k8s@v1 → common/deploy-image-k8s@v1}/action.yaml +0 -0
  28. /package/dist/src/target-templates/lang-variants-common/typescript/.github/actions/{setup-prereq@v1 → common/setup-prereq@v1}/action.yaml +0 -0
  29. /package/src/target-templates/lang-variants-common/typescript/.github/actions/{build-image@v1 → common/build-image@v1}/action.yaml +0 -0
  30. /package/src/target-templates/lang-variants-common/typescript/.github/actions/{db-migrate@v1 → common/db-migrate@v1}/action.yaml +0 -0
  31. /package/src/target-templates/lang-variants-common/typescript/.github/actions/{deploy-image-cloudrun@v1 → common/deploy-image-cloudrun@v1}/action.yaml +0 -0
  32. /package/src/target-templates/lang-variants-common/typescript/.github/actions/{deploy-image-k8s@v1 → common/deploy-image-k8s@v1}/action.yaml +0 -0
  33. /package/src/target-templates/lang-variants-common/typescript/.github/actions/{setup-prereq@v1 → common/setup-prereq@v1}/action.yaml +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getConst
3
- } from "./chunk-HXGGJIAS.js";
3
+ } from "./chunk-VZ6XNNUH.js";
4
4
 
5
5
  // src/app-support/crypto/aes.ts
6
6
  import crypto from "crypto";
@@ -2,7 +2,7 @@ import {
2
2
  getConst,
3
3
  getImageData,
4
4
  globEnvYamlFiles
5
- } from "./chunk-HXGGJIAS.js";
5
+ } from "./chunk-VZ6XNNUH.js";
6
6
 
7
7
  // src/cli/common.ts
8
8
  import chalk from "chalk";
@@ -10,6 +10,7 @@ var SUPPORTED_LANGUAGES = ["python", "node"];
10
10
  var constFileSchema = z.object({
11
11
  "project-name": z.string(),
12
12
  "registry-infra": z.enum(["digitalocean", "gcp", "harbor"]),
13
+ "image-pull-secret-name": z.string().optional(),
13
14
  "image-versions-to-keep": z.number().optional(),
14
15
  "registry-base-url": z.string(),
15
16
  "registry-image-path-prefix": z.string().optional(),
package/dist/devops.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bun
2
2
  import {
3
3
  InternalToken
4
- } from "./chunk-N2NFRGJO.js";
4
+ } from "./chunk-JQGPJAPS.js";
5
5
  import {
6
6
  CLICommandParser,
7
7
  CommandExecutor,
@@ -24,7 +24,7 @@ import {
24
24
  printUsageAndExit,
25
25
  secretName,
26
26
  upsertConfigMapCommand
27
- } from "./chunk-OFUEFG64.js";
27
+ } from "./chunk-STUOTOGE.js";
28
28
  import {
29
29
  IGNORED_PATHS,
30
30
  __export,
@@ -36,7 +36,7 @@ import {
36
36
  getWorkspace,
37
37
  globEnvYamlFiles,
38
38
  workspaceDirectoryForLanguage
39
- } from "./chunk-HXGGJIAS.js";
39
+ } from "./chunk-VZ6XNNUH.js";
40
40
 
41
41
  // src/devops.ts
42
42
  import { globSync as globSync2 } from "glob";
@@ -386,8 +386,8 @@ function setWorkspaceScale(monorepoEnv, image2, workspaceName, replicaCount) {
386
386
  }
387
387
  const { scale: _scale, ...rest } = getImageConfigMap(monorepoEnv, image2);
388
388
  const parsedScale = deserializeImageConfigMapKey(monorepoEnv, image2, "scale");
389
- const isApplicable2 = setK8sScale(monorepoEnv, workspaceName, replicaCount);
390
- if (!isApplicable2) return;
389
+ const isApplicable = setK8sScale(monorepoEnv, workspaceName, replicaCount);
390
+ if (!isApplicable) return;
391
391
  updateImageConfigMap(monorepoEnv, image2, {
392
392
  ...rest,
393
393
  scale: JSON.stringify({
@@ -2067,22 +2067,18 @@ function run11(cmdObj) {
2067
2067
  }
2068
2068
  var job = { oneLiner: oneLiner11, keyExamples: keyExamples11, run: run11 };
2069
2069
 
2070
- // src/libs/hetzner/reg-secret.ts
2071
- function isApplicable() {
2072
- const registryInfra = getConst("registry-infra");
2073
- if (registryInfra !== "harbor") {
2074
- console.warn(
2075
- "Setting up registry permissions is only needed for Harbor in a Hetzner setup"
2076
- );
2077
- return false;
2078
- }
2079
- return true;
2070
+ // src/libs/registry/image-pull-secret.ts
2071
+ var SOURCE_NAMESPACE = "default";
2072
+ function getSecretName() {
2073
+ const secretName2 = getConst("image-pull-secret-name");
2074
+ return secretName2 || null;
2080
2075
  }
2081
- function copySecretHarborToNamespace(monorepoEnv) {
2082
- if (!isApplicable()) return;
2083
- const cmd = kubectlCommand("get secret harbor-registry-secret -o json", {
2076
+ function copyRegistrySecretToNamespace(monorepoEnv) {
2077
+ const secretName2 = getSecretName();
2078
+ if (!secretName2) return;
2079
+ const cmd = kubectlCommand(`get secret ${secretName2} -o json`, {
2084
2080
  monorepoEnv,
2085
- namespace: "harbor"
2081
+ namespace: SOURCE_NAMESPACE
2086
2082
  });
2087
2083
  const secretStr = new CommandExecutor(cmd, { quiet: true }).exec();
2088
2084
  const secretJson = JSON.parse(secretStr);
@@ -2104,9 +2100,10 @@ function copySecretHarborToNamespace(monorepoEnv) {
2104
2100
  new CommandExecutor(copyCmd, { quiet: true }).exec();
2105
2101
  }
2106
2102
  function patchServiceAccountImagePullSecret(monorepoEnv) {
2107
- if (!isApplicable()) return;
2103
+ const secretName2 = getSecretName();
2104
+ if (!secretName2) return;
2108
2105
  const cmd = kubectlCommand(
2109
- `patch serviceaccount default -p '{"imagePullSecrets": [{"name": "harbor-registry-secret"}]}'`,
2106
+ `patch serviceaccount default -p '{"imagePullSecrets": [{"name": "${secretName2}"}]}'`,
2110
2107
  { monorepoEnv }
2111
2108
  );
2112
2109
  new CommandExecutor(cmd, { quiet: true }).exec();
@@ -2127,8 +2124,8 @@ GENERAL USAGE
2127
2124
 
2128
2125
  'create' does the following:
2129
2126
  1. Creates the namepace
2130
- 2. Creates a secret to hold environment variables (used by devops env) and the base cryptographic secret
2131
- 3. On Hetzner, copies the Harbor secret to the namespace and patches the default service account to use it
2127
+ 2. Creates a secret to hold environment variables (used by devops env) and the base cryptographic secret
2128
+ 3. If use-image-pull-secret is true, copies the external-registry-secret to the namespace and patches the default service account to use it
2132
2129
 
2133
2130
  'delete' removes the namespace in kubernetes, which deletes all entities within it.
2134
2131
 
@@ -2143,7 +2140,7 @@ var handlers4 = {
2143
2140
  createNamespace(env2);
2144
2141
  createEmptyEnvSecret(env2);
2145
2142
  patchBaseSecret(env2);
2146
- copySecretHarborToNamespace(env2);
2143
+ copyRegistrySecretToNamespace(env2);
2147
2144
  patchServiceAccountImagePullSecret(env2);
2148
2145
  },
2149
2146
  delete(opts) {
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ type SupportedLanguages = typeof SUPPORTED_LANGUAGES[number];
5
5
  declare const constFileSchema: z.ZodObject<{
6
6
  "project-name": z.ZodString;
7
7
  "registry-infra": z.ZodEnum<["digitalocean", "gcp", "harbor"]>;
8
+ "image-pull-secret-name": z.ZodOptional<z.ZodString>;
8
9
  "image-versions-to-keep": z.ZodOptional<z.ZodNumber>;
9
10
  "registry-base-url": z.ZodString;
10
11
  "registry-image-path-prefix": z.ZodOptional<z.ZodString>;
@@ -18,6 +19,7 @@ declare const constFileSchema: z.ZodObject<{
18
19
  "registry-base-url": string;
19
20
  "extra-remote-environments": string[];
20
21
  "extra-local-environments": string[];
22
+ "image-pull-secret-name"?: string | undefined;
21
23
  "image-versions-to-keep"?: number | undefined;
22
24
  "registry-image-path-prefix"?: string | undefined;
23
25
  "cloudrun-artifact-registry-repo-path"?: string | undefined;
@@ -28,6 +30,7 @@ declare const constFileSchema: z.ZodObject<{
28
30
  "registry-base-url": string;
29
31
  "extra-remote-environments": string[];
30
32
  "extra-local-environments": string[];
33
+ "image-pull-secret-name"?: string | undefined;
31
34
  "image-versions-to-keep"?: number | undefined;
32
35
  "registry-image-path-prefix"?: string | undefined;
33
36
  "cloudrun-artifact-registry-repo-path"?: string | undefined;
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  InternalToken,
3
3
  decryptAes256Gcm,
4
4
  encryptAes256Gcm
5
- } from "./chunk-N2NFRGJO.js";
5
+ } from "./chunk-JQGPJAPS.js";
6
6
  import {
7
7
  SUPPORTED_LANGUAGES,
8
8
  constFileSchema,
@@ -10,7 +10,7 @@ import {
10
10
  packageFileNodeSchema,
11
11
  packageFilePythonSchema,
12
12
  workspaces
13
- } from "./chunk-HXGGJIAS.js";
13
+ } from "./chunk-VZ6XNNUH.js";
14
14
 
15
15
  // src/app-support/discovery/dev-discovery-loader.ts
16
16
  var _portLookupByServiceName = null;
package/dist/plugins.js CHANGED
@@ -5,8 +5,8 @@ import {
5
5
  kubectlCommand,
6
6
  pkgRoot,
7
7
  printUsageAndExit
8
- } from "./chunk-OFUEFG64.js";
9
- import "./chunk-HXGGJIAS.js";
8
+ } from "./chunk-STUOTOGE.js";
9
+ import "./chunk-VZ6XNNUH.js";
10
10
 
11
11
  // src/plugins.ts
12
12
  import path from "path";
@@ -9,7 +9,7 @@ on:
9
9
  permissions:
10
10
  contents: read
11
11
  packages: read
12
- # For deploying images to Cloud Run
12
+ # For OIDC authentication to GCP
13
13
  # id-token: write
14
14
 
15
15
  jobs:
@@ -29,7 +29,7 @@ jobs:
29
29
  fetch-depth: 50
30
30
 
31
31
  - name: Setup prerequesites
32
- uses: ./.github/actions/setup-prereq@v1
32
+ uses: ./.github/actions/common/setup-prereq@v1
33
33
 
34
34
  - name: Connect to DigitalOcean K8s
35
35
  uses: ./.github/actions/k8s/connect-to-digitalocean-k8s@v1
@@ -42,16 +42,16 @@ jobs:
42
42
  with:
43
43
  access_token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
44
44
 
45
- # For deploying images to Cloud Run
46
- # - name: Connect to Cloud Run
47
- # uses: ./.github/actions/connect-to-cloud-run@v1
45
+ # For GCP Artifact Registry with OIDC (alternative to DOCR)
46
+ # - name: Connect to Artifact Registry with OIDC
47
+ # uses: ./.github/actions/registry/connect-to-artifact-registry-with-oidc@v1
48
48
  # with:
49
49
  # project_id: ${{ vars.GCP_PROJECT_ID }}
50
50
  # project_number: ${{ vars.GCP_PROJECT_NUMBER }}
51
51
  # region: ${{ vars.GCP_ARTIFACT_REGISTRY_REGION }}
52
52
 
53
53
  - name: Build image
54
- uses: ./.github/actions/build-image@v1
54
+ uses: ./.github/actions/common/build-image@v1
55
55
  with:
56
56
  image_name: ${{ matrix.image_name }}
57
57
  cache_path: ${{ matrix.cache_path || '/root/.bun/install/cache' }}
@@ -67,7 +67,7 @@ jobs:
67
67
  fetch-depth: 50
68
68
 
69
69
  - name: Setup prerequesites
70
- uses: ./.github/actions/setup-prereq@v1
70
+ uses: ./.github/actions/common/setup-prereq@v1
71
71
 
72
72
  - name: Connect to DigitalOcean K8s
73
73
  uses: ./.github/actions/k8s/connect-to-digitalocean-k8s@v1
@@ -80,22 +80,22 @@ jobs:
80
80
  with:
81
81
  access_token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
82
82
 
83
- # For deploying images to Cloud Run
84
- # - name: Connect to Cloud Run
85
- # uses: ./.github/actions/connect-to-cloud-run@v1
83
+ # For GCP Artifact Registry with OIDC (alternative to DOCR)
84
+ # - name: Connect to Artifact Registry with OIDC
85
+ # uses: ./.github/actions/registry/connect-to-artifact-registry-with-oidc@v1
86
86
  # with:
87
87
  # project_id: ${{ vars.GCP_PROJECT_ID }}
88
88
  # project_number: ${{ vars.GCP_PROJECT_NUMBER }}
89
89
  # region: ${{ vars.GCP_ARTIFACT_REGISTRY_REGION }}
90
90
 
91
91
  - name: Run DB Migrate
92
- uses: ./.github/actions/db-migrate@v1
92
+ uses: ./.github/actions/common/db-migrate@v1
93
93
 
94
94
  # Repeat per image (it checks if the image is affected and deploys it if it is)
95
95
  - name: Deploy main node
96
- uses: ./.github/actions/deploy-image-k8s@v1
96
+ uses: ./.github/actions/common/deploy-image-k8s@v1
97
97
  with: { "image_name": "main-node" }
98
98
 
99
99
  - name: Deploy main python
100
- uses: ./.github/actions/deploy-image-k8s@v1
100
+ uses: ./.github/actions/common/deploy-image-k8s@v1
101
101
  with: { "image_name": "main-python" }
@@ -9,7 +9,7 @@ on:
9
9
  permissions:
10
10
  contents: read
11
11
  packages: read
12
- # For deploying images to Cloud Run
12
+ # For OIDC authentication to GCP
13
13
  # id-token: write
14
14
 
15
15
  jobs:
@@ -29,7 +29,7 @@ jobs:
29
29
  fetch-depth: 50
30
30
 
31
31
  - name: Setup prerequesites
32
- uses: ./.github/actions/setup-prereq@v1
32
+ uses: ./.github/actions/common/setup-prereq@v1
33
33
 
34
34
  - name: Connect to GKE
35
35
  uses: ./.github/actions/k8s/connect-to-gke@v1
@@ -40,22 +40,22 @@ jobs:
40
40
  service_account_key: ${{ secrets.GCLOUD_SA_KEY }}
41
41
 
42
42
  - name: Connect to Artifact Registry
43
- uses: ./.github/actions/registry/connect-to-artifact-registry@v1
43
+ uses: ./.github/actions/registry/connect-to-artifact-registry-with-sa@v1
44
44
  with:
45
45
  service_account_key: ${{ secrets.GCLOUD_SA_KEY }}
46
46
  project_id: ${{ secrets.GCLOUD_PROJECT_ID }}
47
47
  region: ${{ secrets.GCLOUD_ARTIFACT_REGISTRY_REGION }}
48
48
 
49
- # For deploying images to Cloud Run
50
- # - name: Connect to Cloud Run
51
- # uses: ./.github/actions/connect-to-cloud-run@v1
49
+ # For GCP Artifact Registry with OIDC (alternative to service account key)
50
+ # - name: Connect to Artifact Registry with OIDC
51
+ # uses: ./.github/actions/registry/connect-to-artifact-registry-with-oidc@v1
52
52
  # with:
53
53
  # project_id: ${{ vars.GCP_PROJECT_ID }}
54
54
  # project_number: ${{ vars.GCP_PROJECT_NUMBER }}
55
55
  # region: ${{ vars.GCP_ARTIFACT_REGISTRY_REGION }}
56
56
 
57
57
  - name: Build image
58
- uses: ./.github/actions/build-image@v1
58
+ uses: ./.github/actions/common/build-image@v1
59
59
  with:
60
60
  image_name: ${{ matrix.image_name }}
61
61
  cache_path: ${{ matrix.cache_path || '/root/.bun/install/cache' }}
@@ -71,7 +71,7 @@ jobs:
71
71
  fetch-depth: 50
72
72
 
73
73
  - name: Setup prerequesites
74
- uses: ./.github/actions/setup-prereq@v1
74
+ uses: ./.github/actions/common/setup-prereq@v1
75
75
 
76
76
  - name: Connect to GKE
77
77
  uses: ./.github/actions/k8s/connect-to-gke@v1
@@ -82,28 +82,28 @@ jobs:
82
82
  service_account_key: ${{ secrets.GCLOUD_SA_KEY }}
83
83
 
84
84
  - name: Connect to Artifact Registry
85
- uses: ./.github/actions/registry/connect-to-artifact-registry@v1
85
+ uses: ./.github/actions/registry/connect-to-artifact-registry-with-sa@v1
86
86
  with:
87
87
  service_account_key: ${{ secrets.GCLOUD_SA_KEY }}
88
88
  project_id: ${{ secrets.GCLOUD_PROJECT_ID }}
89
89
  region: ${{ secrets.GCLOUD_ARTIFACT_REGISTRY_REGION }}
90
90
 
91
- # For deploying images to Cloud Run
92
- # - name: Connect to Cloud Run
93
- # uses: ./.github/actions/connect-to-cloud-run@v1
91
+ # For GCP Artifact Registry with OIDC (alternative to service account key)
92
+ # - name: Connect to Artifact Registry with OIDC
93
+ # uses: ./.github/actions/registry/connect-to-artifact-registry-with-oidc@v1
94
94
  # with:
95
95
  # project_id: ${{ vars.GCP_PROJECT_ID }}
96
96
  # project_number: ${{ vars.GCP_PROJECT_NUMBER }}
97
97
  # region: ${{ vars.GCP_ARTIFACT_REGISTRY_REGION }}
98
98
 
99
99
  - name: Run DB Migrate
100
- uses: ./.github/actions/db-migrate@v1
100
+ uses: ./.github/actions/common/db-migrate@v1
101
101
 
102
102
  # Repeat per image (it checks if the image is affected and deploys it if it is)
103
103
  - name: Deploy main node
104
- uses: ./.github/actions/deploy-image-k8s@v1
104
+ uses: ./.github/actions/common/deploy-image-k8s@v1
105
105
  with: { "image_name": "main-node" }
106
106
 
107
107
  - name: Deploy main python
108
- uses: ./.github/actions/deploy-image-k8s@v1
108
+ uses: ./.github/actions/common/deploy-image-k8s@v1
109
109
  with: { "image_name": "main-python" }
@@ -4,6 +4,10 @@ project-name: $PROJECT_NAME
4
4
  # Registry infrastructure: digitalocean, gcp, or harbor
5
5
  registry-infra: harbor
6
6
 
7
+ # When set, devops namespace create will copy this secret from default namespace
8
+ # and patch the default service account to use it. See docs/infra/RegistrySetup.md for details.
9
+ image-pull-secret-name: $PROJECT_NAME-registry-secret
10
+
7
11
  # Only relevant for Digital Ocean. Determines the number of versions to keep for each docker image.
8
12
  image-versions-to-keep: 5
9
13
 
@@ -9,7 +9,7 @@ on:
9
9
  permissions:
10
10
  contents: read
11
11
  packages: read
12
- # For deploying images to Cloud Run
12
+ # For OIDC authentication to GCP
13
13
  # id-token: write
14
14
 
15
15
  jobs:
@@ -29,7 +29,7 @@ jobs:
29
29
  fetch-depth: 50
30
30
 
31
31
  - name: Setup prerequesites
32
- uses: ./.github/actions/setup-prereq@v1
32
+ uses: ./.github/actions/common/setup-prereq@v1
33
33
 
34
34
  - name: Connect to Hetzner K8s
35
35
  uses: ./.github/actions/k8s/connect-to-hetzner-k8s@v1
@@ -42,16 +42,16 @@ jobs:
42
42
  harbor_user: ${{ secrets.HARBOR_USER }}
43
43
  harbor_password: ${{ secrets.HARBOR_PASSWORD }}
44
44
 
45
- # For deploying images to Cloud Run
46
- # - name: Connect to Cloud Run
47
- # uses: ./.github/actions/connect-to-cloud-run@v1
45
+ # For GCP Artifact Registry with OIDC (alternative to Harbor)
46
+ # - name: Connect to Artifact Registry with OIDC
47
+ # uses: ./.github/actions/registry/connect-to-artifact-registry-with-oidc@v1
48
48
  # with:
49
49
  # project_id: ${{ vars.GCP_PROJECT_ID }}
50
50
  # project_number: ${{ vars.GCP_PROJECT_NUMBER }}
51
51
  # region: ${{ vars.GCP_ARTIFACT_REGISTRY_REGION }}
52
52
 
53
53
  - name: Build image
54
- uses: ./.github/actions/build-image@v1
54
+ uses: ./.github/actions/common/build-image@v1
55
55
  with:
56
56
  image_name: ${{ matrix.image_name }}
57
57
  cache_path: ${{ matrix.cache_path || '/root/.bun/install/cache' }}
@@ -67,7 +67,7 @@ jobs:
67
67
  fetch-depth: 50
68
68
 
69
69
  - name: Setup prerequesites
70
- uses: ./.github/actions/setup-prereq@v1
70
+ uses: ./.github/actions/common/setup-prereq@v1
71
71
 
72
72
  - name: Connect to Hetzner K8s
73
73
  uses: ./.github/actions/k8s/connect-to-hetzner-k8s@v1
@@ -80,22 +80,22 @@ jobs:
80
80
  harbor_user: ${{ secrets.HARBOR_USER }}
81
81
  harbor_password: ${{ secrets.HARBOR_PASSWORD }}
82
82
 
83
- # For deploying images to Cloud Run
84
- # - name: Connect to Cloud Run
85
- # uses: ./.github/actions/connect-to-cloud-run@v1
83
+ # For GCP Artifact Registry with OIDC (alternative to Harbor)
84
+ # - name: Connect to Artifact Registry with OIDC
85
+ # uses: ./.github/actions/registry/connect-to-artifact-registry-with-oidc@v1
86
86
  # with:
87
87
  # project_id: ${{ vars.GCP_PROJECT_ID }}
88
88
  # project_number: ${{ vars.GCP_PROJECT_NUMBER }}
89
89
  # region: ${{ vars.GCP_ARTIFACT_REGISTRY_REGION }}
90
90
 
91
91
  - name: Run DB Migrate
92
- uses: ./.github/actions/db-migrate@v1
92
+ uses: ./.github/actions/common/db-migrate@v1
93
93
 
94
94
  # Repeat per image (it checks if the image is affected and deploys it if it is)
95
95
  - name: Deploy main node
96
- uses: ./.github/actions/deploy-image-k8s@v1
96
+ uses: ./.github/actions/common/deploy-image-k8s@v1
97
97
  with: { "image_name": "main-node" }
98
98
 
99
99
  - name: Deploy main python
100
- uses: ./.github/actions/deploy-image-k8s@v1
100
+ uses: ./.github/actions/common/deploy-image-k8s@v1
101
101
  with: { "image_name": "main-python" }
@@ -0,0 +1,29 @@
1
+ name: "Connect to Artifact Registry with OIDC"
2
+ description: "Authenticates to Google Artifact Registry using Workload Identity Federation (OIDC)"
3
+ inputs:
4
+ project_id:
5
+ description: "Google Cloud project ID"
6
+ required: true
7
+ project_number:
8
+ description: "Google Cloud project number"
9
+ required: true
10
+ region:
11
+ description: "Google Cloud region where the Artifact Registry is located"
12
+ required: true
13
+ runs:
14
+ using: "composite"
15
+ steps:
16
+ - name: Auth to GCP via OIDC
17
+ uses: google-github-actions/auth@v2
18
+ with:
19
+ workload_identity_provider: projects/${{ inputs.project_number }}/locations/global/workloadIdentityPools/github/providers/github-oidc
20
+ service_account: gha-deployer@${{ inputs.project_id }}.iam.gserviceaccount.com
21
+ project_id: ${{ inputs.project_id }}
22
+
23
+ - name: Setup gcloud
24
+ uses: google-github-actions/setup-gcloud@v2
25
+
26
+ - name: Configure docker to use Artifact Registry
27
+ shell: bash
28
+ run: gcloud auth configure-docker ${{ inputs.region }}-docker.pkg.dev --quiet
29
+
@@ -1,5 +1,5 @@
1
- name: "Connect to Artifact Registry"
2
- description: "Authenticates to Google Artifact Registry"
1
+ name: "Connect to Artifact Registry with Service Account"
2
+ description: "Authenticates to Google Artifact Registry using a service account JSON key"
3
3
  inputs:
4
4
  service_account_key:
5
5
  description: "Google Cloud service account key in JSON format"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vaharoni/devops",
3
3
  "type": "module",
4
- "version": "1.3.0",
4
+ "version": "1.3.2",
5
5
  "description": "Devops utility",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -1,8 +1,8 @@
1
1
  import { CLICommandParser, printUsageAndExit, StrongParams } from "../../../src/cli/common";
2
2
  import {
3
- copySecretHarborToNamespace,
3
+ copyRegistrySecretToNamespace,
4
4
  patchServiceAccountImagePullSecret,
5
- } from "../../../src/libs/hetzner/reg-secret";
5
+ } from "../../../src/libs/registry/image-pull-secret";
6
6
  import { checkEnvSetup, createEmptyEnvSecret, createNamespace, deleteNamespace, patchBaseSecret } from "../../libs/k8s-namespace";
7
7
 
8
8
  const oneLiner = "Creates the basic prerequisites for a monorepo";
@@ -20,8 +20,8 @@ GENERAL USAGE
20
20
 
21
21
  'create' does the following:
22
22
  1. Creates the namepace
23
- 2. Creates a secret to hold environment variables (used by devops env) and the base cryptographic secret
24
- 3. On Hetzner, copies the Harbor secret to the namespace and patches the default service account to use it
23
+ 2. Creates a secret to hold environment variables (used by devops env) and the base cryptographic secret
24
+ 3. If use-image-pull-secret is true, copies the external-registry-secret to the namespace and patches the default service account to use it
25
25
 
26
26
  'delete' removes the namespace in kubernetes, which deletes all entities within it.
27
27
 
@@ -37,7 +37,7 @@ const handlers = {
37
37
  createNamespace(env);
38
38
  createEmptyEnvSecret(env);
39
39
  patchBaseSecret(env);
40
- copySecretHarborToNamespace(env);
40
+ copyRegistrySecretToNamespace(env);
41
41
  patchServiceAccountImagePullSecret(env);
42
42
  },
43
43
  delete (opts: StrongParams) {
@@ -3,23 +3,20 @@ import { getConst } from "../config";
3
3
  import { envToNamespace } from "../k8s-constants";
4
4
  import { kubectlCommand } from "../k8s-helpers";
5
5
 
6
- function isApplicable() {
7
- const registryInfra = getConst("registry-infra");
8
- if (registryInfra !== "harbor") {
9
- console.warn(
10
- "Setting up registry permissions is only needed for Harbor in a Hetzner setup"
11
- );
12
- return false;
13
- }
14
- return true;
6
+ const SOURCE_NAMESPACE = "default";
7
+
8
+ function getSecretName(): string | null {
9
+ const secretName = getConst("image-pull-secret-name");
10
+ return secretName || null;
15
11
  }
16
12
 
17
- export function copySecretHarborToNamespace(monorepoEnv: string) {
18
- if (!isApplicable()) return;
13
+ export function copyRegistrySecretToNamespace(monorepoEnv: string) {
14
+ const secretName = getSecretName();
15
+ if (!secretName) return;
19
16
 
20
- const cmd = kubectlCommand("get secret harbor-registry-secret -o json", {
17
+ const cmd = kubectlCommand(`get secret ${secretName} -o json`, {
21
18
  monorepoEnv,
22
- namespace: "harbor",
19
+ namespace: SOURCE_NAMESPACE,
23
20
  });
24
21
  const secretStr = new CommandExecutor(cmd, { quiet: true }).exec();
25
22
  const secretJson = JSON.parse(secretStr);
@@ -44,10 +41,11 @@ export function copySecretHarborToNamespace(monorepoEnv: string) {
44
41
  }
45
42
 
46
43
  export function patchServiceAccountImagePullSecret(monorepoEnv: string) {
47
- if (!isApplicable()) return;
44
+ const secretName = getSecretName();
45
+ if (!secretName) return;
48
46
 
49
47
  const cmd = kubectlCommand(
50
- `patch serviceaccount default -p '{"imagePullSecrets": [{"name": "harbor-registry-secret"}]}'`,
48
+ `patch serviceaccount default -p '{"imagePullSecrets": [{"name": "${secretName}"}]}'`,
51
49
  { monorepoEnv }
52
50
  );
53
51
  new CommandExecutor(cmd, { quiet: true }).exec();
@@ -9,7 +9,7 @@ on:
9
9
  permissions:
10
10
  contents: read
11
11
  packages: read
12
- # For deploying images to Cloud Run
12
+ # For OIDC authentication to GCP
13
13
  # id-token: write
14
14
 
15
15
  jobs:
@@ -29,7 +29,7 @@ jobs:
29
29
  fetch-depth: 50
30
30
 
31
31
  - name: Setup prerequesites
32
- uses: ./.github/actions/setup-prereq@v1
32
+ uses: ./.github/actions/common/setup-prereq@v1
33
33
 
34
34
  - name: Connect to DigitalOcean K8s
35
35
  uses: ./.github/actions/k8s/connect-to-digitalocean-k8s@v1
@@ -42,16 +42,16 @@ jobs:
42
42
  with:
43
43
  access_token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
44
44
 
45
- # For deploying images to Cloud Run
46
- # - name: Connect to Cloud Run
47
- # uses: ./.github/actions/connect-to-cloud-run@v1
45
+ # For GCP Artifact Registry with OIDC (alternative to DOCR)
46
+ # - name: Connect to Artifact Registry with OIDC
47
+ # uses: ./.github/actions/registry/connect-to-artifact-registry-with-oidc@v1
48
48
  # with:
49
49
  # project_id: ${{ vars.GCP_PROJECT_ID }}
50
50
  # project_number: ${{ vars.GCP_PROJECT_NUMBER }}
51
51
  # region: ${{ vars.GCP_ARTIFACT_REGISTRY_REGION }}
52
52
 
53
53
  - name: Build image
54
- uses: ./.github/actions/build-image@v1
54
+ uses: ./.github/actions/common/build-image@v1
55
55
  with:
56
56
  image_name: ${{ matrix.image_name }}
57
57
  cache_path: ${{ matrix.cache_path || '/root/.bun/install/cache' }}
@@ -67,7 +67,7 @@ jobs:
67
67
  fetch-depth: 50
68
68
 
69
69
  - name: Setup prerequesites
70
- uses: ./.github/actions/setup-prereq@v1
70
+ uses: ./.github/actions/common/setup-prereq@v1
71
71
 
72
72
  - name: Connect to DigitalOcean K8s
73
73
  uses: ./.github/actions/k8s/connect-to-digitalocean-k8s@v1
@@ -80,22 +80,22 @@ jobs:
80
80
  with:
81
81
  access_token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
82
82
 
83
- # For deploying images to Cloud Run
84
- # - name: Connect to Cloud Run
85
- # uses: ./.github/actions/connect-to-cloud-run@v1
83
+ # For GCP Artifact Registry with OIDC (alternative to DOCR)
84
+ # - name: Connect to Artifact Registry with OIDC
85
+ # uses: ./.github/actions/registry/connect-to-artifact-registry-with-oidc@v1
86
86
  # with:
87
87
  # project_id: ${{ vars.GCP_PROJECT_ID }}
88
88
  # project_number: ${{ vars.GCP_PROJECT_NUMBER }}
89
89
  # region: ${{ vars.GCP_ARTIFACT_REGISTRY_REGION }}
90
90
 
91
91
  - name: Run DB Migrate
92
- uses: ./.github/actions/db-migrate@v1
92
+ uses: ./.github/actions/common/db-migrate@v1
93
93
 
94
94
  # Repeat per image (it checks if the image is affected and deploys it if it is)
95
95
  - name: Deploy main node
96
- uses: ./.github/actions/deploy-image-k8s@v1
96
+ uses: ./.github/actions/common/deploy-image-k8s@v1
97
97
  with: { "image_name": "main-node" }
98
98
 
99
99
  - name: Deploy main python
100
- uses: ./.github/actions/deploy-image-k8s@v1
100
+ uses: ./.github/actions/common/deploy-image-k8s@v1
101
101
  with: { "image_name": "main-python" }
@@ -9,7 +9,7 @@ on:
9
9
  permissions:
10
10
  contents: read
11
11
  packages: read
12
- # For deploying images to Cloud Run
12
+ # For OIDC authentication to GCP
13
13
  # id-token: write
14
14
 
15
15
  jobs:
@@ -29,7 +29,7 @@ jobs:
29
29
  fetch-depth: 50
30
30
 
31
31
  - name: Setup prerequesites
32
- uses: ./.github/actions/setup-prereq@v1
32
+ uses: ./.github/actions/common/setup-prereq@v1
33
33
 
34
34
  - name: Connect to GKE
35
35
  uses: ./.github/actions/k8s/connect-to-gke@v1
@@ -40,22 +40,22 @@ jobs:
40
40
  service_account_key: ${{ secrets.GCLOUD_SA_KEY }}
41
41
 
42
42
  - name: Connect to Artifact Registry
43
- uses: ./.github/actions/registry/connect-to-artifact-registry@v1
43
+ uses: ./.github/actions/registry/connect-to-artifact-registry-with-sa@v1
44
44
  with:
45
45
  service_account_key: ${{ secrets.GCLOUD_SA_KEY }}
46
46
  project_id: ${{ secrets.GCLOUD_PROJECT_ID }}
47
47
  region: ${{ secrets.GCLOUD_ARTIFACT_REGISTRY_REGION }}
48
48
 
49
- # For deploying images to Cloud Run
50
- # - name: Connect to Cloud Run
51
- # uses: ./.github/actions/connect-to-cloud-run@v1
49
+ # For GCP Artifact Registry with OIDC (alternative to service account key)
50
+ # - name: Connect to Artifact Registry with OIDC
51
+ # uses: ./.github/actions/registry/connect-to-artifact-registry-with-oidc@v1
52
52
  # with:
53
53
  # project_id: ${{ vars.GCP_PROJECT_ID }}
54
54
  # project_number: ${{ vars.GCP_PROJECT_NUMBER }}
55
55
  # region: ${{ vars.GCP_ARTIFACT_REGISTRY_REGION }}
56
56
 
57
57
  - name: Build image
58
- uses: ./.github/actions/build-image@v1
58
+ uses: ./.github/actions/common/build-image@v1
59
59
  with:
60
60
  image_name: ${{ matrix.image_name }}
61
61
  cache_path: ${{ matrix.cache_path || '/root/.bun/install/cache' }}
@@ -71,7 +71,7 @@ jobs:
71
71
  fetch-depth: 50
72
72
 
73
73
  - name: Setup prerequesites
74
- uses: ./.github/actions/setup-prereq@v1
74
+ uses: ./.github/actions/common/setup-prereq@v1
75
75
 
76
76
  - name: Connect to GKE
77
77
  uses: ./.github/actions/k8s/connect-to-gke@v1
@@ -82,28 +82,28 @@ jobs:
82
82
  service_account_key: ${{ secrets.GCLOUD_SA_KEY }}
83
83
 
84
84
  - name: Connect to Artifact Registry
85
- uses: ./.github/actions/registry/connect-to-artifact-registry@v1
85
+ uses: ./.github/actions/registry/connect-to-artifact-registry-with-sa@v1
86
86
  with:
87
87
  service_account_key: ${{ secrets.GCLOUD_SA_KEY }}
88
88
  project_id: ${{ secrets.GCLOUD_PROJECT_ID }}
89
89
  region: ${{ secrets.GCLOUD_ARTIFACT_REGISTRY_REGION }}
90
90
 
91
- # For deploying images to Cloud Run
92
- # - name: Connect to Cloud Run
93
- # uses: ./.github/actions/connect-to-cloud-run@v1
91
+ # For GCP Artifact Registry with OIDC (alternative to service account key)
92
+ # - name: Connect to Artifact Registry with OIDC
93
+ # uses: ./.github/actions/registry/connect-to-artifact-registry-with-oidc@v1
94
94
  # with:
95
95
  # project_id: ${{ vars.GCP_PROJECT_ID }}
96
96
  # project_number: ${{ vars.GCP_PROJECT_NUMBER }}
97
97
  # region: ${{ vars.GCP_ARTIFACT_REGISTRY_REGION }}
98
98
 
99
99
  - name: Run DB Migrate
100
- uses: ./.github/actions/db-migrate@v1
100
+ uses: ./.github/actions/common/db-migrate@v1
101
101
 
102
102
  # Repeat per image (it checks if the image is affected and deploys it if it is)
103
103
  - name: Deploy main node
104
- uses: ./.github/actions/deploy-image-k8s@v1
104
+ uses: ./.github/actions/common/deploy-image-k8s@v1
105
105
  with: { "image_name": "main-node" }
106
106
 
107
107
  - name: Deploy main python
108
- uses: ./.github/actions/deploy-image-k8s@v1
108
+ uses: ./.github/actions/common/deploy-image-k8s@v1
109
109
  with: { "image_name": "main-python" }
@@ -4,6 +4,10 @@ project-name: $PROJECT_NAME
4
4
  # Registry infrastructure: digitalocean, gcp, or harbor
5
5
  registry-infra: harbor
6
6
 
7
+ # When set, devops namespace create will copy this secret from default namespace
8
+ # and patch the default service account to use it. See docs/infra/RegistrySetup.md for details.
9
+ image-pull-secret-name: $PROJECT_NAME-registry-secret
10
+
7
11
  # Only relevant for Digital Ocean. Determines the number of versions to keep for each docker image.
8
12
  image-versions-to-keep: 5
9
13
 
@@ -9,7 +9,7 @@ on:
9
9
  permissions:
10
10
  contents: read
11
11
  packages: read
12
- # For deploying images to Cloud Run
12
+ # For OIDC authentication to GCP
13
13
  # id-token: write
14
14
 
15
15
  jobs:
@@ -29,7 +29,7 @@ jobs:
29
29
  fetch-depth: 50
30
30
 
31
31
  - name: Setup prerequesites
32
- uses: ./.github/actions/setup-prereq@v1
32
+ uses: ./.github/actions/common/setup-prereq@v1
33
33
 
34
34
  - name: Connect to Hetzner K8s
35
35
  uses: ./.github/actions/k8s/connect-to-hetzner-k8s@v1
@@ -42,16 +42,16 @@ jobs:
42
42
  harbor_user: ${{ secrets.HARBOR_USER }}
43
43
  harbor_password: ${{ secrets.HARBOR_PASSWORD }}
44
44
 
45
- # For deploying images to Cloud Run
46
- # - name: Connect to Cloud Run
47
- # uses: ./.github/actions/connect-to-cloud-run@v1
45
+ # For GCP Artifact Registry with OIDC (alternative to Harbor)
46
+ # - name: Connect to Artifact Registry with OIDC
47
+ # uses: ./.github/actions/registry/connect-to-artifact-registry-with-oidc@v1
48
48
  # with:
49
49
  # project_id: ${{ vars.GCP_PROJECT_ID }}
50
50
  # project_number: ${{ vars.GCP_PROJECT_NUMBER }}
51
51
  # region: ${{ vars.GCP_ARTIFACT_REGISTRY_REGION }}
52
52
 
53
53
  - name: Build image
54
- uses: ./.github/actions/build-image@v1
54
+ uses: ./.github/actions/common/build-image@v1
55
55
  with:
56
56
  image_name: ${{ matrix.image_name }}
57
57
  cache_path: ${{ matrix.cache_path || '/root/.bun/install/cache' }}
@@ -67,7 +67,7 @@ jobs:
67
67
  fetch-depth: 50
68
68
 
69
69
  - name: Setup prerequesites
70
- uses: ./.github/actions/setup-prereq@v1
70
+ uses: ./.github/actions/common/setup-prereq@v1
71
71
 
72
72
  - name: Connect to Hetzner K8s
73
73
  uses: ./.github/actions/k8s/connect-to-hetzner-k8s@v1
@@ -80,22 +80,22 @@ jobs:
80
80
  harbor_user: ${{ secrets.HARBOR_USER }}
81
81
  harbor_password: ${{ secrets.HARBOR_PASSWORD }}
82
82
 
83
- # For deploying images to Cloud Run
84
- # - name: Connect to Cloud Run
85
- # uses: ./.github/actions/connect-to-cloud-run@v1
83
+ # For GCP Artifact Registry with OIDC (alternative to Harbor)
84
+ # - name: Connect to Artifact Registry with OIDC
85
+ # uses: ./.github/actions/registry/connect-to-artifact-registry-with-oidc@v1
86
86
  # with:
87
87
  # project_id: ${{ vars.GCP_PROJECT_ID }}
88
88
  # project_number: ${{ vars.GCP_PROJECT_NUMBER }}
89
89
  # region: ${{ vars.GCP_ARTIFACT_REGISTRY_REGION }}
90
90
 
91
91
  - name: Run DB Migrate
92
- uses: ./.github/actions/db-migrate@v1
92
+ uses: ./.github/actions/common/db-migrate@v1
93
93
 
94
94
  # Repeat per image (it checks if the image is affected and deploys it if it is)
95
95
  - name: Deploy main node
96
- uses: ./.github/actions/deploy-image-k8s@v1
96
+ uses: ./.github/actions/common/deploy-image-k8s@v1
97
97
  with: { "image_name": "main-node" }
98
98
 
99
99
  - name: Deploy main python
100
- uses: ./.github/actions/deploy-image-k8s@v1
100
+ uses: ./.github/actions/common/deploy-image-k8s@v1
101
101
  with: { "image_name": "main-python" }
@@ -0,0 +1,29 @@
1
+ name: "Connect to Artifact Registry with OIDC"
2
+ description: "Authenticates to Google Artifact Registry using Workload Identity Federation (OIDC)"
3
+ inputs:
4
+ project_id:
5
+ description: "Google Cloud project ID"
6
+ required: true
7
+ project_number:
8
+ description: "Google Cloud project number"
9
+ required: true
10
+ region:
11
+ description: "Google Cloud region where the Artifact Registry is located"
12
+ required: true
13
+ runs:
14
+ using: "composite"
15
+ steps:
16
+ - name: Auth to GCP via OIDC
17
+ uses: google-github-actions/auth@v2
18
+ with:
19
+ workload_identity_provider: projects/${{ inputs.project_number }}/locations/global/workloadIdentityPools/github/providers/github-oidc
20
+ service_account: gha-deployer@${{ inputs.project_id }}.iam.gserviceaccount.com
21
+ project_id: ${{ inputs.project_id }}
22
+
23
+ - name: Setup gcloud
24
+ uses: google-github-actions/setup-gcloud@v2
25
+
26
+ - name: Configure docker to use Artifact Registry
27
+ shell: bash
28
+ run: gcloud auth configure-docker ${{ inputs.region }}-docker.pkg.dev --quiet
29
+
@@ -1,5 +1,5 @@
1
- name: "Connect to Artifact Registry"
2
- description: "Authenticates to Google Artifact Registry"
1
+ name: "Connect to Artifact Registry with Service Account"
2
+ description: "Authenticates to Google Artifact Registry using a service account JSON key"
3
3
  inputs:
4
4
  service_account_key:
5
5
  description: "Google Cloud service account key in JSON format"
@@ -8,6 +8,7 @@ export type SupportedLanguages = typeof SUPPORTED_LANGUAGES[number];
8
8
  export const constFileSchema = z.object({
9
9
  "project-name": z.string(),
10
10
  "registry-infra": z.enum(["digitalocean", "gcp", "harbor"]),
11
+ "image-pull-secret-name": z.string().optional(),
11
12
  "image-versions-to-keep": z.number().optional(),
12
13
  "registry-base-url": z.string(),
13
14
  "registry-image-path-prefix": z.string().optional(),