From 3cb562d4120e6424853a217024b5d95322252d8a Mon Sep 17 00:00:00 2001 From: Erin Millard Date: Fri, 13 Oct 2023 15:34:50 +1000 Subject: [PATCH] Import consumer repo --- .github/workflows/shared-ci-library.yml | 32 +++++++ .github/workflows/shared-publish-package.yml | 35 +++++++ .github/workflows/shared-publish-release.yml | 51 +++++++++++ dot-github/renovate.json | 4 + dot-github/workflows/ci-scheduled.yml | 14 +++ dot-github/workflows/ci.yml | 12 +++ dot-github/workflows/publish-package.yml | 14 +++ .../workflows/publish-release-manual.yml | 27 ++++++ dot-github/workflows/publish-release.yml | 24 +++++ modules/repo/issue-labels.tf | 61 +++++++++++++ modules/repo/license.tf | 9 ++ modules/repo/main.tf | 70 ++++++++++++++ modules/repo/outputs.tf | 4 + modules/repo/renovate.tf | 14 +++ modules/repo/variables.tf | 91 +++++++++++++++++++ modules/repo/versions.tf | 10 ++ modules/repo/workflows.tf | 87 ++++++++++++++++++ repos-unique.tf | 9 ++ repos.tf | 7 ++ 19 files changed, 575 insertions(+) create mode 100644 .github/workflows/shared-ci-library.yml create mode 100644 .github/workflows/shared-publish-package.yml create mode 100644 .github/workflows/shared-publish-release.yml create mode 100644 dot-github/renovate.json create mode 100644 dot-github/workflows/ci-scheduled.yml create mode 100644 dot-github/workflows/ci.yml create mode 100644 dot-github/workflows/publish-package.yml create mode 100644 dot-github/workflows/publish-release-manual.yml create mode 100644 dot-github/workflows/publish-release.yml create mode 100644 modules/repo/issue-labels.tf create mode 100644 modules/repo/license.tf create mode 100644 modules/repo/main.tf create mode 100644 modules/repo/outputs.tf create mode 100644 modules/repo/renovate.tf create mode 100644 modules/repo/variables.tf create mode 100644 modules/repo/versions.tf create mode 100644 modules/repo/workflows.tf create mode 100644 repos-unique.tf create mode 100644 repos.tf diff --git a/.github/workflows/shared-ci-library.yml b/.github/workflows/shared-ci-library.yml new file mode 100644 index 0000000..2f3cfcb --- /dev/null +++ b/.github/workflows/shared-ci-library.yml @@ -0,0 +1,32 @@ +on: + workflow_call: + inputs: + isScheduled: + description: Whether this CI workflow run is scheduled + type: boolean + required: false + default: false + +jobs: + ci: + name: CI + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: "20" + + - name: Install dependencies + run: make link-dependencies + + - name: Make + run: make ci + + - name: Publish coverage + if: ${{ github.event.inputs.isScheduled != 'true' }} + uses: codecov/codecov-action@v3 diff --git a/.github/workflows/shared-publish-package.yml b/.github/workflows/shared-publish-package.yml new file mode 100644 index 0000000..7587dd7 --- /dev/null +++ b/.github/workflows/shared-publish-package.yml @@ -0,0 +1,35 @@ +on: + workflow_call: + secrets: + NPM_TOKEN: + required: true + +jobs: + publish: + runs-on: ubuntu-latest + name: Publish package + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: "20" + registry-url: "https://registry.npmjs.org" + + - name: Install dependencies + run: make link-dependencies + + - name: Make + run: make ci + + - name: Set package version + run: make set-package-version + + - name: Publish package + if: success() + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/shared-publish-release.yml b/.github/workflows/shared-publish-release.yml new file mode 100644 index 0000000..0e27020 --- /dev/null +++ b/.github/workflows/shared-publish-release.yml @@ -0,0 +1,51 @@ +on: + workflow_call: + inputs: + discussionCategory: + description: The discussion category to use for release discussions + type: string + required: false + makeTarget: + description: The make target to run before publishing the release + required: false + type: string + tag: + description: The tag to publish the release from + required: true + type: string + +jobs: + publish: + runs-on: ubuntu-latest + name: Publish release + + permissions: + contents: write + discussions: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: refs/tags/${{ inputs.tag }} + + - name: Check if tag is SemVer + id: checkTag + run: | + if [[ "${{ github.event.inputs.tag }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo isSemVer=true >> $GITHUB_OUTPUT + echo "Tag is SemVer" + else + echo "Tag is not SemVer" + fi + + - name: Make + if: ${{ github.event.inputs.makeTarget }} + run: make ${{ github.event.inputs.makeTarget }} + + - name: Publish release + uses: ghalactic/github-release-from-tag@v5 + with: + reactions: hooray,heart,rocket + discussionCategory: ${{ steps.checkTag.outputs.isSemVer == 'true' && github.event.inputs.discussionCategory || '' }} + discussionReactions: ${{ (github.event.inputs.discussionCategory && steps.checkTag.outputs.isSemVer == 'true') && 'hooray,heart,rocket' || '' }} diff --git a/dot-github/renovate.json b/dot-github/renovate.json new file mode 100644 index 0000000..adaf30a --- /dev/null +++ b/dot-github/renovate.json @@ -0,0 +1,4 @@ +{ + "description": "DO NOT EDIT - This file is managed by ${ org }/repos.", + "extends": ["github>${ org }/renovate"] +} diff --git a/dot-github/workflows/ci-scheduled.yml b/dot-github/workflows/ci-scheduled.yml new file mode 100644 index 0000000..abc9415 --- /dev/null +++ b/dot-github/workflows/ci-scheduled.yml @@ -0,0 +1,14 @@ +# DO NOT EDIT - This file is managed by ${ org }/repos. +name: CI (scheduled) + +on: + schedule: + - cron: 0 14 * * 0 # Sunday 2PM UTC = Monday 12AM AEST + +jobs: + ci: + name: ${ org_name } + uses: ${ org }/repos/.github/workflows/shared-ci-${ ci_type }.yml@main + secrets: inherit + with: + isScheduled: true diff --git a/dot-github/workflows/ci.yml b/dot-github/workflows/ci.yml new file mode 100644 index 0000000..5892564 --- /dev/null +++ b/dot-github/workflows/ci.yml @@ -0,0 +1,12 @@ +# DO NOT EDIT - This file is managed by ${ org }/repos. +name: CI + +on: + push: + pull_request: + +jobs: + ci: + name: ${ org_name } + uses: ${ org }/repos/.github/workflows/shared-ci-${ ci_type }.yml@main + secrets: inherit diff --git a/dot-github/workflows/publish-package.yml b/dot-github/workflows/publish-package.yml new file mode 100644 index 0000000..ed44932 --- /dev/null +++ b/dot-github/workflows/publish-package.yml @@ -0,0 +1,14 @@ +# DO NOT EDIT - This file is managed by ${ org }/repos. +name: Publish package + +on: + push: + tags: + - "v[0-9]+.[0-9]+.[0-9]+" + +jobs: + publish: + name: ${ org_name } + uses: ${ org }/repos/.github/workflows/shared-publish-package.yml@main + secrets: + NPM_TOKEN: ${"$"}{{ secrets.NPM_TOKEN }} diff --git a/dot-github/workflows/publish-release-manual.yml b/dot-github/workflows/publish-release-manual.yml new file mode 100644 index 0000000..dfd288a --- /dev/null +++ b/dot-github/workflows/publish-release-manual.yml @@ -0,0 +1,27 @@ +# DO NOT EDIT - This file is managed by ${ org }/repos. +name: Publish release (manual) + +on: + workflow_dispatch: + inputs: + tag: + description: The tag to publish + type: string + required: true + +jobs: + publish: + name: ${ org_name } + uses: ${ org }/repos/.github/workflows/shared-publish-release.yml@main + secrets: inherit + permissions: + contents: write + discussions: write + with: +%{ if discussion_category != "" ~} + discussionCategory: ${ discussion_category } +%{ endif ~} +%{ if make_target != "" ~} + makeTarget: ${ make_target } +%{ endif ~} + tag: ${"$"}{{ github.event.inputs.tag }} diff --git a/dot-github/workflows/publish-release.yml b/dot-github/workflows/publish-release.yml new file mode 100644 index 0000000..bb5a283 --- /dev/null +++ b/dot-github/workflows/publish-release.yml @@ -0,0 +1,24 @@ +# DO NOT EDIT - This file is managed by ${ org }/repos. +name: Publish release + +on: + push: + tags: + - "*" + +jobs: + publish: + name: ${ org_name } + uses: ${ org }/repos/.github/workflows/shared-publish-release.yml@main + secrets: inherit + permissions: + contents: write + discussions: write + with: +%{ if discussion_category != "" ~} + discussionCategory: ${ discussion_category } +%{ endif ~} +%{ if make_target != "" ~} + makeTarget: ${ make_target } +%{ endif ~} + tag: ${"$"}{{ github.ref_name }} diff --git a/modules/repo/issue-labels.tf b/modules/repo/issue-labels.tf new file mode 100644 index 0000000..4b02643 --- /dev/null +++ b/modules/repo/issue-labels.tf @@ -0,0 +1,61 @@ +locals { + issue_label_color_renovate = "0366D6" + issue_label_color_renovate_safe = "168700" + issue_label_color_renovate_unsafe = "D93F0B" +} + +resource "github_issue_label" "renovate" { + repository = github_repository.this.name + name = "renovate" + description = "Pull requests created by Renovate" + color = local.issue_label_color_renovate +} + +resource "github_issue_label" "github_actions" { + repository = github_repository.this.name + name = "github-actions" + description = "Pull requests that update GitHub Actions dependencies" + color = local.issue_label_color_renovate +} + +resource "github_issue_label" "npm" { + repository = github_repository.this.name + name = "npm" + description = "Pull requests that update NPM dependencies" + color = local.issue_label_color_renovate +} + +resource "github_issue_label" "terraform" { + repository = github_repository.this.name + name = "terraform" + description = "Pull requests that update Terraform dependencies" + color = local.issue_label_color_renovate +} + +resource "github_issue_label" "major" { + repository = github_repository.this.name + name = "major" + description = "Pull requests that update major dependency versions" + color = local.issue_label_color_renovate_unsafe +} + +resource "github_issue_label" "non_major" { + repository = github_repository.this.name + name = "non-major" + description = "Pull requests that update non-major dependency versions" + color = local.issue_label_color_renovate_safe +} + +resource "github_issue_label" "non_dev" { + repository = github_repository.this.name + name = "non-dev" + description = "Pull requests that update non-dev dependencies" + color = local.issue_label_color_renovate_unsafe +} + +resource "github_issue_label" "dev" { + repository = github_repository.this.name + name = "dev" + description = "Pull requests that update dev dependencies" + color = local.issue_label_color_renovate_safe +} diff --git a/modules/repo/license.tf b/modules/repo/license.tf new file mode 100644 index 0000000..43c677f --- /dev/null +++ b/modules/repo/license.tf @@ -0,0 +1,9 @@ +resource "github_repository_file" "license" { + commit_author = module.constants.committer.name + commit_email = module.constants.committer.email + repository = github_repository.this.name + file = "LICENSE" + content = module.constants.license + commit_message = "Update license" + overwrite_on_create = true +} diff --git a/modules/repo/main.tf b/modules/repo/main.tf new file mode 100644 index 0000000..12058f5 --- /dev/null +++ b/modules/repo/main.tf @@ -0,0 +1,70 @@ +resource "github_repository" "this" { + archive_on_destroy = true + + name = var.name + description = var.description + topics = var.topics + homepage_url = var.homepage_url + is_template = var.is_template + visibility = "public" + + auto_init = true + has_discussions = var.has_discussions + has_projects = false + has_wiki = false + has_issues = true + + allow_auto_merge = false + delete_branch_on_merge = true + vulnerability_alerts = true + + dynamic "template" { + for_each = var.template == null ? [] : [null] + + content { + owner = var.template.owner + repository = var.template.repository + } + } + + dynamic "pages" { + for_each = var.pages_branch == null ? [] : [null] + + content { + source { + branch = var.pages_branch + } + } + } +} + +resource "github_actions_repository_permissions" "this" { + repository = github_repository.this.name + allowed_actions = var.has_actions ? "all" : null + enabled = var.has_actions +} + +data "github_repository" "this" { + depends_on = [ + github_repository.this + ] + + name = var.name +} + +resource "github_branch_protection" "default_branch" { + repository_id = github_repository.this.node_id + + pattern = data.github_repository.this.default_branch + enforce_admins = true +} + +data "github_team" "renovate_reviewers" { + slug = "renovate-reviewers" +} + +resource "github_team_repository" "renovate_reviewers" { + team_id = data.github_team.renovate_reviewers.id + repository = github_repository.this.name + permission = "maintain" +} diff --git a/modules/repo/outputs.tf b/modules/repo/outputs.tf new file mode 100644 index 0000000..bcdf15b --- /dev/null +++ b/modules/repo/outputs.tf @@ -0,0 +1,4 @@ +output "name" { + description = "The repository name" + value = github_repository.this.name +} diff --git a/modules/repo/renovate.tf b/modules/repo/renovate.tf new file mode 100644 index 0000000..fb24a77 --- /dev/null +++ b/modules/repo/renovate.tf @@ -0,0 +1,14 @@ +resource "github_repository_file" "dot_github_renovate_json" { + count = var.manage_renovate ? 1 : 0 + + commit_author = module.constants.committer.name + commit_email = module.constants.committer.email + repository = github_repository.this.name + file = ".github/renovate.json" + commit_message = "Update Renovate configuration" + overwrite_on_create = true + + content = templatefile("dot-github/renovate.json", { + org = module.constants.org + }) +} diff --git a/modules/repo/variables.tf b/modules/repo/variables.tf new file mode 100644 index 0000000..ac7477a --- /dev/null +++ b/modules/repo/variables.tf @@ -0,0 +1,91 @@ +module "constants" { + source = "../constants" +} + +variable "name" { + description = "The repository name" + type = string +} + +variable "description" { + description = "The repository description" + type = string +} + +variable "topics" { + description = "The repository topics" + type = list(string) + default = [] +} + +variable "homepage_url" { + description = "The homepage URL" + type = string + default = null +} + +variable "is_template" { + description = "Whether the repository is a template" + type = bool + default = false +} + +variable "template" { + description = "The template repo to use" + type = object({ owner = string, repository = string }) + default = null +} + +variable "pages_branch" { + description = "The pages branch to use" + type = string + default = null +} + +variable "ci_workflows" { + description = "The GitHub Actions CI workflows to use" + type = list(string) + default = [] +} + +variable "has_publish_release_workflow" { + description = "Whether to add a basic GitHub Actions release publishing workflow" + type = bool + default = true +} + +variable "manage_renovate" { + description = "Whether to manage the Renovate configuration" + type = bool + default = true +} + +variable "has_actions" { + description = "Whether the repository has GitHub Actions enabled" + type = bool + default = true +} + +variable "has_discussions" { + description = "Whether the repository has discussions" + type = bool + default = false +} + +variable "has_release_discussions" { + description = "Whether the repository has release discussions" + type = bool + default = false +} + +variable "release_make_target" { + description = "The make target to run before publishing releases" + type = string + default = null +} + +variable "use_release_action_main" { + description = "Use the main branch version of the release action when publishing releases" + type = bool + default = false +} diff --git a/modules/repo/versions.tf b/modules/repo/versions.tf new file mode 100644 index 0000000..bcdfb32 --- /dev/null +++ b/modules/repo/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.0.11" + + required_providers { + github = { + source = "integrations/github" + version = "~> 5.0" + } + } +} diff --git a/modules/repo/workflows.tf b/modules/repo/workflows.tf new file mode 100644 index 0000000..0d05f1c --- /dev/null +++ b/modules/repo/workflows.tf @@ -0,0 +1,87 @@ +resource "github_repository_file" "dot_github_workflows_ci_yml" { + for_each = toset(var.ci_workflows) + + commit_author = module.constants.committer.name + commit_email = module.constants.committer.email + repository = github_repository.this.name + file = ".github/workflows/ci-${each.value}.yml" + commit_message = "Update \"CI\" GHA workflow" + overwrite_on_create = true + + content = templatefile("dot-github/workflows/ci.yml", { + ci_type = each.value + org = module.constants.org + org_name = module.constants.org_name + }) +} + +resource "github_repository_file" "dot_github_workflows_ci_scheduled_yml" { + for_each = toset(var.ci_workflows) + + commit_author = module.constants.committer.name + commit_email = module.constants.committer.email + repository = github_repository.this.name + file = ".github/workflows/ci-${each.value}-scheduled.yml" + commit_message = "Update \"CI (scheduled)\" GHA workflow" + overwrite_on_create = true + + content = templatefile("dot-github/workflows/ci-scheduled.yml", { + ci_type = each.value + org = module.constants.org + org_name = module.constants.org_name + }) +} + +resource "github_repository_file" "dot_github_workflows_publish_package_yml" { + for_each = toset(["basic"]) + + commit_author = module.constants.committer.name + commit_email = module.constants.committer.email + repository = github_repository.this.name + file = ".github/workflows/publish-package.yml" + commit_message = "Update \"Publish package\" GHA workflow" + overwrite_on_create = true + + content = templatefile("dot-github/workflows/publish-package.yml", { + org = module.constants.org + org_name = module.constants.org_name + }) +} + +resource "github_repository_file" "dot_github_workflows_publish_release_yml" { + for_each = toset(var.has_publish_release_workflow ? ["basic"] : []) + + commit_author = module.constants.committer.name + commit_email = module.constants.committer.email + repository = github_repository.this.name + file = ".github/workflows/publish-release.yml" + commit_message = "Update \"Publish release\" GHA workflow" + overwrite_on_create = true + + content = templatefile("dot-github/workflows/publish-release.yml", { + discussion_category = var.has_release_discussions ? "Releases" : "" + make_target = var.release_make_target == null ? "" : var.release_make_target + org = module.constants.org + org_name = module.constants.org_name + use_release_action_main = var.use_release_action_main + }) +} + +resource "github_repository_file" "dot_github_workflows_publish_release_manual_yml" { + for_each = toset(var.has_publish_release_workflow ? ["basic"] : []) + + commit_author = module.constants.committer.name + commit_email = module.constants.committer.email + repository = github_repository.this.name + file = ".github/workflows/publish-release-manual.yml" + commit_message = "Update \"Publish release (manual)\" GHA workflow" + overwrite_on_create = true + + content = templatefile("dot-github/workflows/publish-release-manual.yml", { + discussion_category = var.has_release_discussions ? "Releases" : "" + make_target = var.release_make_target == null ? "" : var.release_make_target + org = module.constants.org + org_name = module.constants.org_name + use_release_action_main = var.use_release_action_main + }) +} diff --git a/repos-unique.tf b/repos-unique.tf new file mode 100644 index 0000000..937084d --- /dev/null +++ b/repos-unique.tf @@ -0,0 +1,9 @@ +# module "repo_renovate" { +# source = "./modules/repo" +# name = "renovate" +# description = "Self-hosted Renovate for Iconduit" +# homepage_url = "https://github.com/iconduit/renovate/actions/workflows/renovate.yml" + +# has_publish_release_workflow = false +# manage_renovate = false +# } diff --git a/repos.tf b/repos.tf new file mode 100644 index 0000000..2015d6e --- /dev/null +++ b/repos.tf @@ -0,0 +1,7 @@ +module "repo_consumer" { + source = "./modules/repo" + name = "consumer" + description = "implifies the use of Iconduit's ouputs in consuming projects" + + ci_workflows = ["library"] +}