Skip to content

Commit

Permalink
chore: upgrade to cdktf 0.17 and tsx (#199)
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielMSchmidt authored Sep 7, 2023
1 parent e3dbc75 commit 81132b2
Show file tree
Hide file tree
Showing 11 changed files with 2,461 additions and 795 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/deploy-cdktf-stacks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ jobs:
- name: Setup Terraform
uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1
with:
terraform_version: 1.0.7
terraform_version: 1.4.6
cli_config_credentials_token: ${{ secrets.TF_CLOUD_TOKEN }}

- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
with:
node-version: "14"
node-version: "18"

- name: Install
run: yarn install
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/diff-cdktf-stacks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ jobs:
- name: Setup Terraform
uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1
with:
terraform_version: 1.0.7
terraform_version: 1.4.6
cli_config_credentials_token: ${{ secrets.TF_CLOUD_TOKEN }}

- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
with:
node-version: "14"
node-version: "18"

- run: yarn install
- name: Synth
Expand Down
4 changes: 2 additions & 2 deletions cdktf.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"language": "typescript",
"app": "npm run --silent compile && node main.js",
"app": "npx tsx main.ts",
"projectId": "46fb4da5-e0c7-486d-aba8-24e91527e550"
}
}
24 changes: 24 additions & 0 deletions lib/logical-id-override.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

import { TerraformElement } from "cdktf";
import { Node } from "constructs";
import { makeUniqueId } from "./unique-id-override";

function allocateLogicalId(tfElement: TerraformElement | Node): string {
const node = TerraformElement.isTerraformElement(tfElement)
? tfElement.node
: tfElement;

// This is the previous behavior, which we want for now.
const stackIndex = 0;

const components = node.scopes.slice(stackIndex + 1).map((c) => c.node.id);
return components.length > 0 ? makeUniqueId(components, false) : "";
}

export function setOldId(tfElement: TerraformElement): void {
tfElement.overrideLogicalId(allocateLogicalId(tfElement));
}
98 changes: 53 additions & 45 deletions lib/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@
*/

import { Construct } from "constructs";
import {
Repository,
TeamRepository,
BranchProtection,
IssueLabel,
RepositoryWebhook,
GithubProvider,
DataGithubRepository,
} from "@cdktf/provider-github";
import { SecretFromVariable } from "./secrets";
import { GithubProvider } from "@cdktf/provider-github/lib/provider";
import { Repository } from "@cdktf/provider-github/lib/repository";
import { DataGithubRepository } from "@cdktf/provider-github/lib/data-github-repository";
import { IssueLabel } from "@cdktf/provider-github/lib/issue-label";
import { BranchProtection } from "@cdktf/provider-github/lib/branch-protection";
import { TeamRepository } from "@cdktf/provider-github/lib/team-repository";
import { RepositoryWebhook } from "@cdktf/provider-github/lib/repository-webhook";
import { setOldId } from "./logical-id-override";

export interface ITeam {
id: string;
Expand Down Expand Up @@ -51,50 +50,58 @@ export class RepositorySetup extends Construct {
webhookUrl,
} = config;

new IssueLabel(this, `automerge-label`, {
color: "5DC8DB",
name: "automerge",
repository: repository.name,
provider,
});
setOldId(
new IssueLabel(this, `automerge-label`, {
color: "5DC8DB",
name: "automerge",
repository: repository.name,
provider,
})
);

if (protectMain) {
new BranchProtection(this, "main-protection", {
pattern: "main",
repositoryId: repository.name,
enforceAdmins: true,
allowsDeletions: false,
allowsForcePushes: false,
requiredStatusChecks: [
{
strict: true,
contexts: protectMainChecks,
},
],
provider,
});
setOldId(
new BranchProtection(this, "main-protection", {
pattern: "main",
repositoryId: repository.name,
enforceAdmins: true,
allowsDeletions: false,
allowsForcePushes: false,
requiredStatusChecks: [
{
strict: true,
contexts: protectMainChecks,
},
],
provider,
})
);
}

new TeamRepository(this, "managing-team", {
repository: repository.name,
teamId: team.id,
permission: "admin",
provider,
});
setOldId(
new TeamRepository(this, "managing-team", {
repository: repository.name,
teamId: team.id,
permission: "admin",
provider,
})
);

// Slack integration so we can be notified about new PRs and Issues
new RepositoryWebhook(this, "slack-webhook", {
repository: repository.name,
setOldId(
new RepositoryWebhook(this, "slack-webhook", {
repository: repository.name,

configuration: {
url: webhookUrl,
contentType: "json",
},
configuration: {
url: webhookUrl,
contentType: "json",
},

// We don't need to notify about PRs since they are auto-created
events: ["issues"],
provider,
});
// We don't need to notify about PRs since they are auto-created
events: ["issues"],
provider,
})
);
}
}

Expand Down Expand Up @@ -133,6 +140,7 @@ export class GithubRepository extends Construct {
topics,
provider,
});
setOldId(this.resource);

new RepositorySetup(this, "repository-setup", {
...config,
Expand Down
41 changes: 22 additions & 19 deletions lib/secrets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@
*/

import { Construct } from "constructs";
import { Resource, TerraformVariable } from "cdktf";
import {
ActionsSecret,
DataGithubRepository,
GithubProvider,
Repository,
} from "@cdktf/provider-github";
import { TerraformVariable } from "cdktf";
import { constantCase } from "change-case";
import { Repository } from "@cdktf/provider-github/lib/repository";
import { DataGithubRepository } from "@cdktf/provider-github/lib/data-github-repository";
import { GithubProvider } from "@cdktf/provider-github/lib/provider";
import { ActionsSecret } from "@cdktf/provider-github/lib/actions-secret";
import { setOldId } from "./logical-id-override";

export class SecretFromVariable extends Resource {
export class SecretFromVariable extends Construct {
public readonly name: string;
public readonly variable: TerraformVariable;
public secretNames: string[] = [];
Expand All @@ -39,20 +38,24 @@ export class SecretFromVariable extends Resource {
repository: Repository | DataGithubRepository,
ghProvider: GithubProvider
) {
const secret = new ActionsSecret(repository, `secret-${this.name}`, {
plaintextValue: this.variable.value,
secretName: constantCase(this.name),
repository: repository.name,
provider: ghProvider,
});

this.secretNames.forEach((name) => {
new ActionsSecret(repository, `secret-${this.name}-alias-${name}`, {
const secret = setOldId(
new ActionsSecret(repository, `secret-${this.name}`, {
plaintextValue: this.variable.value,
secretName: constantCase(name),
secretName: constantCase(this.name),
repository: repository.name,
provider: ghProvider,
});
})
);

this.secretNames.forEach((name) => {
setOldId(
new ActionsSecret(repository, `secret-${this.name}-alias-${name}`, {
plaintextValue: this.variable.value,
secretName: constantCase(name),
repository: repository.name,
provider: ghProvider,
})
);
});

return secret;
Expand Down
126 changes: 126 additions & 0 deletions lib/unique-id-override.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Copyright (c) HashiCorp, Inc
// SPDX-License-Identifier: MPL-2.0

/**
* We have to copy this from the old CDKTF version for now, so that we can
* calculate the old logical IDs for now and for later for the migration.
*/

// tslint:disable-next-line:no-var-requires
import * as crypto from "crypto";

/**
* Resources with this ID are hidden from humans
*
* They do not appear in the human-readable part of the logical ID,
* but they are included in the hash calculation.
*/
const HIDDEN_FROM_HUMAN_ID = "Resource";

/**
* Resources with this ID are complete hidden from the logical ID calculation.
*/
const HIDDEN_ID = "Default";

const PATH_SEP = "/";
const UNIQUE_SEP = "_";

const HASH_LEN = 8;
const MAX_HUMAN_LEN = 240; // max ID len is 255
const MAX_ID_LEN = 255;

/**
* Calculates a unique ID for a set of textual components.
*
* This is done by calculating a hash on the full path and using it as a suffix
* of a length-limited "human" rendition of the path components.
*
* @param components The path components
* @returns a unique alpha-numeric identifier with a maximum length of 255
*/
export function makeUniqueId(components: string[], allowSepChars: boolean) {
components = components.filter((x) => x !== HIDDEN_ID);

if (components.length === 0) {
throw new Error(
"Unable to calculate a unique id for an empty set of components"
);
}

// top-level resources will simply use the `name` as-is in order to support
// transparent migration of cloudformation templates to the CDK without the
// need to rename all resources.
if (components.length === 1) {
// we filter out non-alpha characters but that is actually a bad idea
// because it could create conflicts ("A-B" and "AB" will render the same
// logical ID). sadly, changing it in the 1.x version line is impossible
// because it will be a breaking change. we should consider for v2.0.
// https://github.com/aws/aws-cdk/issues/6421
const candidate = removeDisallowedCharacters(components[0], allowSepChars);

// if our candidate is short enough, use it as is. otherwise, fall back to
// the normal mode.
if (candidate.length <= MAX_ID_LEN) {
return candidate;
}
}

const hash = pathHash(components);
const human = removeDupes(components)
.filter((x) => x !== HIDDEN_FROM_HUMAN_ID)
.map((s) => removeDisallowedCharacters(s, allowSepChars))
.join(UNIQUE_SEP)
.slice(0, MAX_HUMAN_LEN);

return human + UNIQUE_SEP + hash;
}

/**
* Take a hash of the given path.
*
* The hash is limited in size.
*/
function pathHash(path: string[]): string {
const md5 = crypto
.createHash("md5")
.update(path.join(PATH_SEP))
.digest("hex");
return md5.slice(0, HASH_LEN).toUpperCase();
}

function removeDisallowedCharacters(s: string, allowSepChars: boolean) {
if (allowSepChars) {
return removeNonAlphanumericSep(s);
} else {
return removeNonAlphanumeric(s);
}
}

/**
* Removes all non-alphanumeric characters in a string.
*/
function removeNonAlphanumeric(s: string) {
return s.replace(/[^A-Za-z0-9]/g, "");
}

function removeNonAlphanumericSep(s: string) {
return s.replace(/[^A-Za-z0-9_-]/g, "");
}

/**
* Remove duplicate "terms" from the path list
*
* If the previous path component name ends with this component name, skip the
* current component.
*/
function removeDupes(path: string[]): string[] {
const ret = new Array<string>();

for (const component of path) {
if (ret.length === 0 || !ret[ret.length - 1].endsWith(component)) {
ret.push(component);
}
}

return ret;
}
Loading

0 comments on commit 81132b2

Please sign in to comment.