├── .gitignore
├── .prettierignore
├── .roadierc
├── README.md
├── examples
├── azure-actions
│ ├── skeleton
│ │ └── fileA.txt
│ └── template.yaml
├── update-json-file
│ ├── my-file.json
│ └── template.yaml
└── update-yaml-file
│ ├── my-file.yaml
│ └── template.yaml
└── scaffolder-templates
├── add-branch-protection
└── template.yaml
├── add-codeowners
├── skeleton
│ └── CODEOWNERS.njk
└── template.yaml
├── add-security-tools-yaml
├── skeleton
│ └── security-tools.yml.njk
└── template.yaml
├── add-tenant-to-alerts
└── template.yaml
├── create-aws-serverless-backend
├── skeleton
│ ├── .env
│ ├── .github
│ │ └── workflows
│ │ │ ├── merge.yaml
│ │ │ └── pull-request.yaml
│ ├── .gitignore
│ ├── README.md
│ ├── catalog-info.yaml
│ ├── mkdocs.yml
│ ├── package.json
│ ├── src
│ │ └── lambda.ts
│ ├── sst.json
│ ├── stacks
│ │ ├── MyStack.ts
│ │ └── index.ts
│ ├── test
│ │ └── MyStack.test.ts
│ └── tsconfig.json
└── template.yaml
├── create-aws-serverless-frontend-and-backend
├── skeleton
│ ├── .github
│ │ └── workflows
│ │ │ ├── merge.yaml
│ │ │ └── pull-request.yaml
│ ├── .gitignore
│ ├── README.md
│ ├── catalog-info.yaml
│ ├── frontend
│ │ ├── .env
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── public
│ │ │ ├── favicon.ico
│ │ │ ├── index.html
│ │ │ ├── logo192.png
│ │ │ ├── logo512.png
│ │ │ ├── manifest.json
│ │ │ └── robots.txt
│ │ └── src
│ │ │ ├── App.css
│ │ │ ├── App.js
│ │ │ ├── App.test.js
│ │ │ ├── index.css
│ │ │ ├── index.js
│ │ │ ├── logo.svg
│ │ │ ├── reportWebVitals.js
│ │ │ └── setupTests.js
│ ├── mkdocs.yml
│ ├── package.json
│ ├── src
│ │ └── lambda.js
│ ├── sst.json
│ ├── stacks
│ │ ├── MyStack.js
│ │ └── index.js
│ └── test
│ │ └── MyStack.test.js
└── template.yaml
├── create-empty-project
├── skeleton
│ ├── .github
│ │ └── workflows
│ │ │ └── pull-request.yaml
│ ├── README.md
│ └── catalog-info.yaml
└── template.yaml
├── create-readme
├── skeleton
│ └── README.md.njk
└── template.yaml
├── create-rfc
├── skeleton
│ └── template.md.njk
└── template.yaml
├── create-tenant
└── template.yaml
├── debug-template
├── skeleton
│ └── template.md.njk
└── template.yaml
├── delete-entities
└── template.yaml
├── delete-tenant
└── template.yaml
├── github-pages-site
├── README.md
├── skeleton
│ ├── .github
│ │ └── workflows
│ │ │ └── test.yaml
│ ├── .gitignore
│ ├── README.md
│ ├── catalog-info.yaml
│ ├── cypress.json
│ ├── cypress
│ │ ├── integration
│ │ │ └── sample_spec.js
│ │ ├── plugins
│ │ │ └── index.js
│ │ └── support
│ │ │ ├── commands.js
│ │ │ └── index.js
│ ├── docs
│ │ └── index.md
│ ├── index.html
│ ├── mkdocs.yml
│ ├── package.json
│ ├── package.json.tpl
│ └── yarn.lock
└── template.yaml
├── oneof-example
└── oneof-example.yaml
├── pr-with-catalog-entry
├── skeleton
│ └── catalog-info.yaml.njk
└── template.yaml
├── pull-request-test
├── skeleton
│ └── new-change.yaml
└── template.yaml
├── roadie-agent-entity-provider
├── skeleton
│ ├── Dockerfile
│ ├── README.md
│ ├── config
│ │ └── accept.json
│ ├── package.json
│ └── src
│ │ ├── index.js
│ │ └── myEntityHandler.js
└── template.yaml
├── roadie-agent-scaffolder-action
├── skeleton
│ ├── Dockerfile
│ ├── README.md
│ ├── config
│ │ └── accept.json
│ ├── package.json
│ └── src
│ │ ├── helloWorldScaffolderActionHandler.js
│ │ └── index.js
└── template.yaml
└── roadie-plugin
├── skeleton
├── .eslintrc.js
├── .gitignore
├── .npmrc
├── README.md
├── package-lock.json
├── package.json
└── plugins
│ └── my-plugin
│ ├── .eslintrc.js
│ ├── README.md
│ ├── app-config.yaml
│ ├── dev
│ └── index.tsx
│ ├── package.json
│ ├── src
│ ├── components
│ │ ├── EntityComponentExample
│ │ │ ├── EntityContentComponent.tsx
│ │ │ └── index.ts
│ │ ├── ExampleComponent
│ │ │ ├── ExampleComponent.test.tsx
│ │ │ ├── ExampleComponent.tsx
│ │ │ └── index.ts
│ │ └── ExampleFetchComponent
│ │ │ ├── ExampleFetchComponent.test.tsx
│ │ │ ├── ExampleFetchComponent.tsx
│ │ │ └── index.ts
│ ├── index.ts
│ ├── plugin.test.ts
│ ├── plugin.ts
│ ├── routes.ts
│ └── setupTests.ts
│ └── tsconfig.json
└── template.yaml
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .DS_Store
3 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | # Prettier changes double curly braces and makes files like catalog-info.yaml invalid
2 | scaffolder-templates
3 |
--------------------------------------------------------------------------------
/.roadierc:
--------------------------------------------------------------------------------
1 | validator:
2 | exclude:
3 | - 'scaffolder-templates/*/skeleton/catalog-info.yaml'
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # software-templates
2 |
3 | This repository is a collection of software and documentation templates for the RoadieHQ team. The templates are organized into the folder: `scaffolder-templates` for Software Templates.
--------------------------------------------------------------------------------
/examples/azure-actions/skeleton/fileA.txt:
--------------------------------------------------------------------------------
1 | name: ${{ values.name }}
2 |
--------------------------------------------------------------------------------
/examples/azure-actions/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: azure-repo-demo
5 | title: Azure Repository Test
6 | description: Clone and push to an Azure repository example.
7 | spec:
8 | owner: roadie
9 | type: service
10 |
11 | parameters:
12 | - title: Fill in some steps
13 | required:
14 | - name
15 | properties:
16 | name:
17 | title: Project name
18 | type: string
19 | description: Choose a unique project name.
20 | ui:field: EntityNamePicker
21 | ui:autofocus: true
22 | sourceBranch:
23 | title: Source Branch
24 | type: string
25 | default: master
26 | remoteBranch:
27 | title: Remote Branch
28 | type: string
29 | default: scaffolder
30 | steps:
31 | - id: cloneAzureRepo
32 | name: Clone Azure Repo
33 | action: azure:repo:clone
34 | input:
35 | remoteUrl: "https://roadie-demo@dev.azure.com/roadie-demo/Sample-Services/_git/sample-service"
36 | branch: ${{ parameters.sourceBranch }}
37 | targetPath: ./sub-directory
38 |
39 | - id: fetch
40 | name: Template Skeleton
41 | action: fetch:template
42 | input:
43 | url: ./skeleton
44 | targetPath: ./sub-directory
45 | values:
46 | name: ${{ parameters.name }}
47 |
48 | - id: pushAzureRepo
49 | name: Push to Remote Azure Repo
50 | action: azure:repo:push
51 | input:
52 | branch: ${{ parameters.remoteBranch }}
53 | sourcePath: ./sub-directory
54 | gitCommitMessage: Add ${{ parameters.name }} project files
55 |
56 | - id: pullRequestAzureRepo
57 | name: Create a Pull Request to Azure Repo
58 | action: azure:repo:pr
59 | input:
60 | sourceBranch: ${{ parameters.remoteBranch }}
61 | targetBranch: "master"
62 | repoId: sample-service
63 | title: ${{ parameters.name }}
64 | project: Sample-Services
65 | organization: roadie-demo
66 | supportsIterations: false
67 |
68 | output:
69 | links:
70 | - title: Pull Request
71 | url: "https://dev.azure.com/roadie-demo/Sample-Services/_git/sample-service/pullrequest/${{ outputs.pullRequestAzureRepo.pullRequestId}}"
72 |
--------------------------------------------------------------------------------
/examples/update-json-file/my-file.json:
--------------------------------------------------------------------------------
1 | { "my-key": "" }
--------------------------------------------------------------------------------
/examples/update-json-file/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: update-json-file
5 | title: Update a json file
6 | description: Opens a PR with updates to a json file.
7 |
8 | spec:
9 | owner: engineering
10 | type: example
11 | parameters:
12 | - title: Provide some simple information
13 | required: ['myValue']
14 | properties:
15 | myValue:
16 | title: My Value
17 | type: string
18 | description: Value to assign to my-key
19 |
20 | steps:
21 | - id: fetch
22 | name: Fetch repo
23 | action: fetch:plain
24 | input:
25 | # Path to the root of the repo of interest. You can also use the RepoUrlPicker to choose one.
26 | url: ./
27 |
28 | - id: update
29 | name: Update
30 | action: roadiehq:utils:merge
31 | input:
32 | # This file must exist at this path in the repo referenced above
33 | path: my-file.json
34 | content:
35 | my-key: ${{ parameters.myValue }}
36 |
37 | - id: publish
38 | name: Publish
39 | action: publish:github:pull-request
40 | input:
41 | repoUrl: github.com?repo=software-templates&owner=RoadieHQ
42 | title: Update my-file.json
43 | description: update description
44 | branchName: update-my-file # TODO parameterise?
45 | targetPath: examples/update-json-file
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/examples/update-yaml-file/my-file.yaml:
--------------------------------------------------------------------------------
1 | myKey:
2 | subKey: asdfasdf
3 |
--------------------------------------------------------------------------------
/examples/update-yaml-file/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: update-yaml-file
5 | title: Update a yaml file
6 | description: Opens a PR with updates to a yaml file.
7 |
8 | spec:
9 | owner: engineering
10 | type: example
11 | parameters:
12 | - title: Provide some simple information
13 | required: ['value']
14 | properties:
15 | value:
16 | title: The new value
17 | type: string
18 | description: Update myKey.subKey in the yaml file
19 |
20 | steps:
21 | - id: fetchPlain
22 | name: Fetch the file
23 | action: fetch:plain
24 | input:
25 | url: ./
26 |
27 | - id: update
28 | name: Update
29 | action: roadiehq:utils:merge
30 | input:
31 | # This file must exist at this path in the repo referenced above
32 | path: my-file.yaml
33 | content:
34 | myKey:
35 | subKey: ${{ parameters.value }}
36 |
37 | - id: publish
38 | name: Publish
39 | action: publish:github:pull-request
40 | input:
41 | repoUrl: github.com?repo=software-templates&owner=RoadieHQ
42 | title: Update my-file.yaml
43 | description: update description
44 | targetPath: examples/update-yaml-file
45 | branchName: update-my-file # TODO parameterise?
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/scaffolder-templates/add-branch-protection/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: add-branch-protection
5 | title: Add Branch Protection
6 | description: Turn on branch protection with some sensible defaults.
7 |
8 | spec:
9 | owner: group:roadiehq/engineering
10 | type: file
11 |
12 | parameters:
13 | - title: Where is your codebase?
14 | required:
15 | - repoName
16 | properties:
17 | repoHost:
18 | type: string
19 | default: github.com
20 | ui:widget: hidden
21 | repoOrg:
22 | type: string
23 | default: roadiehq # Change this to match the name of your GitHub org
24 | ui:widget: hidden
25 | repoName:
26 | title: Repository name
27 | type: string
28 | branch:
29 | title: Default branch
30 | type: string
31 | default: main
32 |
33 | - title: Branch protection settings
34 | properties:
35 | allowForcePushes:
36 | title: Allow force pushes
37 | type: boolean
38 | default: false
39 | requiredApprovingRevewCount:
40 | title: Approving reviews required to merge
41 | type: number
42 | default: 1
43 |
44 |
45 | steps:
46 | - id: callGitHubApi
47 | name: Turn on branch protection
48 | action: http:backstage:request
49 | input:
50 | method: 'PUT'
51 | path: /proxy/mygithub/api/repos/${{ parameters.repoOrg }}/${{ parameters.repoName }}/branches/${{ parameters.branch }}/protection
52 | headers:
53 | content-type: 'application/json'
54 | body:
55 | required_status_checks: null
56 | enforce_admins: true
57 | required_pull_request_reviews:
58 | dismiss_stale_reviews: true
59 | required_approving_review_count: ${{ parameters.requiredApprovingRevewCount }}
60 | require_last_push_approval: true
61 | restrictions: null
62 | required_linear_history: false
63 | allow_force_pushes: ${{ parameters.allowForcePushes }}
64 | allow_deletions: true
65 | block_creations: false
66 | required_conversation_resolution: false
67 | lock_branch: false
68 | allow_fork_syncing: true
69 |
70 | output:
71 | links:
72 | - title: Go to branch protection settings
73 | icon: github
74 | url: https://github.com/${{ parameters.repoOrg }}/${{ parameters.repoName }}/settings/branches
75 |
--------------------------------------------------------------------------------
/scaffolder-templates/add-codeowners/skeleton/CODEOWNERS.njk:
--------------------------------------------------------------------------------
1 | # This is a comment.
2 | # Each line is a file pattern followed by one or more owners.
3 |
4 | # These owners will be the default owners for everything in
5 | # the repo. Unless a later match takes precedence,
6 | # @global-owner1 and @global-owner2 will be requested for
7 | # review when someone opens a pull request.
8 | * @global-owner1 @global-owner2
9 |
10 | # Order is important; the last matching pattern takes the most
11 | # precedence. When someone opens a pull request that only
12 | # modifies JS files, only @js-owner and not the global
13 | # owner(s) will be requested for a review.
14 | *.js @js-owner #This is an inline comment.
15 |
16 | # You can also use email addresses if you prefer. They'll be
17 | # used to look up users just like we do for commit author
18 | # emails.
19 | *.go docs@example.com
20 |
21 | # Teams can be specified as code owners as well. Teams should
22 | # be identified in the format @org/team-name. Teams must have
23 | # explicit write access to the repository. In this example,
24 | # the octocats team in the octo-org organization owns all .txt files.
25 | *.txt @octo-org/octocats
26 |
27 | # In this example, @doctocat owns any files in the build/logs
28 | # directory at the root of the repository and any of its
29 | # subdirectories.
30 | /build/logs/ @doctocat
31 |
32 | # The `docs/*` pattern will match files like
33 | # `docs/getting-started.md` but not further nested files like
34 | # `docs/build-app/troubleshooting.md`.
35 | docs/* docs@example.com
36 |
37 | # In this example, @octocat owns any file in an apps directory
38 | # anywhere in your repository.
39 | apps/ @octocat
40 |
41 | # In this example, @doctocat owns any file in the `/docs`
42 | # directory in the root of your repository and any of its
43 | # subdirectories.
44 | /docs/ @doctocat
45 |
46 | # In this example, any change inside the `/scripts` directory
47 | # will require approval from @doctocat or @octocat.
48 | /scripts/ @doctocat @octocat
49 |
50 | # In this example, @octocat owns any file in a `/logs` directory such as
51 | # `/build/logs`, `/scripts/logs`, and `/deeply/nested/logs`. Any changes
52 | # in a `/logs` directory will require approval from @octocat.
53 | **/logs @octocat
54 |
55 | # In this example, @octocat owns any file in the `/apps`
56 | # directory in the root of your repository except for the `/apps/github`
57 | # subdirectory, as its owners are left empty.
58 | /apps/ @octocat
59 | /apps/github
60 |
61 | # In this example, @octocat owns any file in the `/apps`
62 | # directory in the root of your repository except for the `/apps/github`
63 | # subdirectory, as this subdirectory has its own owner @doctocat
64 | /apps/ @octocat
65 | /apps/github @doctocat
66 |
--------------------------------------------------------------------------------
/scaffolder-templates/add-codeowners/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: create-codeowners-in-repo
5 | title: Create a CODEOWNERS file
6 | description: Create a new PR with a basic CODEOWNERS file.
7 | spec:
8 | owner: group:roadiehq/engineering
9 | type: file
10 |
11 | parameters:
12 | - title: Basic info
13 | required:
14 | - repoName
15 | properties:
16 | repoHost:
17 | type: string
18 | default: github.com
19 | ui:widget: hidden
20 | repoOrg:
21 | type: string
22 | default: roadiehq # Change this to match the name of your GitHub org
23 | ui:widget: hidden
24 | repoName:
25 | title: Repository name
26 | type: string
27 |
28 | steps:
29 | - id: fetchTemplate
30 | action: fetch:template
31 | input:
32 | url: ./skeleton
33 | templateFileExtension: .njk
34 |
35 | - id: createPullRequest
36 | name: create-pull-request
37 | action: publish:github:pull-request
38 | input:
39 | repoUrl: ${{ parameters.repoHost }}?owner=${{ parameters.repoOrg }}&repo=${{ parameters.repoName }}
40 | branchName: add-codeowners-${{ '' | now }}
41 | title: Add a CODEOWENERS file
42 | description: |
43 | This PR adds a basic CODEOWNERS file to this repository. It must be edited to be correct.
44 |
45 | [Learn about CODEOWNERS on GitHub](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners)
46 |
47 | It was created via a [scaffolder template on Roadie](https://example.com).
48 |
49 | output:
50 | links:
51 | - title: View the pull request on GitHub
52 | icon: github
53 | url: ${{ steps['createPullRequest'].output.remoteUrl }}
54 | - title: Learn about CODEOWNERS
55 | icon: help
56 | url: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
57 |
--------------------------------------------------------------------------------
/scaffolder-templates/add-security-tools-yaml/skeleton/security-tools.yml.njk:
--------------------------------------------------------------------------------
1 | # Tribe and Squad identification
2 | tribe: ${{ values.tribe }}
3 | squad: ${{ values.squad }}
4 |
5 | security_tools:
6 |
7 | # Secrets Detection
8 | secrets_detection:
9 | enabled: ${{ 1 if values.secretsDetectionEnabled else 0 }}
10 | secrets_scanning: ${{ 1 if values.secretsDetectionScanning else 0 }}
11 | pr_based:
12 | enabled: ${{ 1 if values.secretsDetectionPRs else 0 }}
13 |
14 | # Static Application Security Testing (SAST)
15 | sast:
16 | enabled: ${{ 1 if values.sastEnabled else 0 }}
17 | tools:
18 | codeQL:
19 | enabled: ${{ 1 if values.codeQLEnabled else 0 }}
20 | config_file_path: ${{ values.codeQLConfigFilePath }}
21 | veracode:
22 | enabled: ${{ 1 if values.veracodeEnabled else 0 }}
23 | sonarcloud:
24 | enabled: ${{ 1 if values.sonarcloudEnabled else 0 }}
25 | sobelow:
26 | enabled: ${{ 1 if values.sobelowEnabled else 0 }}
27 | credo:
28 | enabled: ${{ 1 if values.credoEnabled else 0 }}
29 | klocwork:
30 | enabled: ${{ 1 if values.klocworkEnabled else 0 }}
31 |
--------------------------------------------------------------------------------
/scaffolder-templates/add-security-tools-yaml/template.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: scaffolder.backstage.io/v1beta3
3 | kind: Template
4 | metadata:
5 | name: add-security-tools-yaml
6 | title: Add security tools YAML
7 | description: The security tools YAML helps InfoSec to understand which security tools your project is using. This template is an easy way to create the file.
8 | spec:
9 | owner: group:roadiehq/engineering
10 | type: file
11 |
12 | parameters:
13 | - title: Where is your codebase?
14 | required:
15 | - repoName
16 | properties:
17 | repoHost:
18 | type: string
19 | default: github.com
20 | ui:widget: hidden
21 | repoOrg:
22 | type: string
23 | default: roadiehq # Change this to match the name of your GitHub org
24 | ui:widget: hidden
25 | repoName:
26 | title: Repository name
27 | type: string
28 |
29 | - title: Who owns the codebase?
30 | required:
31 | - tribe
32 | - squad
33 | properties:
34 | tribe:
35 | title: Tribe Name
36 | type: string
37 | squad:
38 | title: Squad Name
39 | type: string
40 |
41 |
42 | - title: Secrets Detection
43 | properties:
44 | secretsDetectionEnabled:
45 | title: Is secrets detection enabled on the repo?
46 | type: boolean
47 | secretsDetectionScanning:
48 | title: Is secrets detection scanning enabled on the repo?
49 | type: boolean
50 | secretsDetectionPRs:
51 | title: Are automated PRs opened against scanned repos?
52 | type: boolean
53 |
54 | - title: Static Application Security Testing (SAST)
55 | properties:
56 | sastEnabled:
57 | title: Is SAST enabled on your repo?
58 | type: boolean
59 | codeQLEnabled:
60 | title: Is CodeQL enabled on the repo?
61 | type: boolean
62 | codeQLConfigFilePath:
63 | title: CodeQL file path
64 | type: string
65 | default: '.github/workflows/codeql.yml'
66 | veracodeEnabled:
67 | title: Is Veracode enabled on the repo?
68 | type: boolean
69 | sonarcloudEnabled:
70 | title: Is SonarCloud enabled on the repo?
71 | type: boolean
72 | sobelowEnabled:
73 | title: Is Sobelow enabled on the repo?
74 | type: boolean
75 | credoEnabled:
76 | title: Is Credo enabled on the repo?
77 | type: boolean
78 | klocworkEnabled:
79 | title: Is klocwork enabled on the repo?
80 | type: boolean
81 |
82 | steps:
83 | - id: fetchTemplate
84 | name: Fetch a skeleton security tools file.
85 | action: fetch:template
86 | input:
87 | url: ./skeleton
88 | templateFileExtension: .njk
89 | values:
90 | repoOrg: ${{ parameters.repoOrg }}
91 | repoSlug: ${{ parameters.repoSlug }}
92 | tribe: ${{ parameters.tribe }}
93 | squad: ${{ parameters.squad }}
94 | secretsDetectionEnabled: ${{ parameters.secretsDetectionEnabled }}
95 | secretsDetectionScanning: ${{ parameters.secretsDetectionScanning }}
96 | secretsDetectionPRs: ${{ parameters.secretsDetectionPRs }}
97 | sastEnabled: ${{ parameters.sastEnabled }}
98 | codeQLEnabled: ${{ parameters.codeQLEnabled }}
99 | codeQLConfigFilePath: ${{ parameters.codeQLConfigFilePath }}
100 | veracodeEnabled: ${{ parameters.veracodeEnabled }}
101 | sonarcloudEnabled: ${{ parameters.sonarcloudEnabled }}
102 | sobelowEnabled: ${{ parameters.sobelowEnabled }}
103 | credoEnabled: ${{ parameters.credoEnabled }}
104 | klocworkEnabled: ${{ parameters.klocworkEnabled }}
105 |
106 | - id: createPullRequest
107 | name: Open a PR
108 | action: publish:github:pull-request
109 | input:
110 | repoUrl: ${{ parameters.repoHost }}?owner=${{ parameters.repoOrg }}&repo=${{ parameters.repoName }}
111 | # We append 'now' to the branch name to make the branch name unique. Otherwise the step will fail
112 | # if we run it against the same repo twice.
113 | branchName: add-security-tools-yaml-${{ '' | now }}
114 | title: Add security tools YAML file
115 | # This shows up in the body of the PR. You can use markdown.
116 | description: |
117 | The security tools YAML helps InfoSec to understand which security tools your project is using.
118 | It's created via a [scaffolder template on Roadie](https://example.com).
119 |
120 | output:
121 | links:
122 | - title: View the pull request on GitHub
123 | icon: github
124 | url: ${{ steps['createPullRequest'].output.remoteUrl }}
125 | - title: Read the Security Tools Documentation
126 | icon: help
127 | url: https://example.com
128 |
--------------------------------------------------------------------------------
/scaffolder-templates/add-tenant-to-alerts/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: finalize-new-customer
5 | title: Finalize a new customer
6 | description: Adds the new customer to the PagerDuty alerts and tags them in Intercome with "customer"
7 |
8 | spec:
9 | owner: user:ianlink
10 | type: service
11 |
12 | parameters:
13 | - title: Provide some simple information
14 | required:
15 | - tenant_name
16 | properties:
17 | tenant_name:
18 | title: Name
19 | type: string
20 | description: Must be tenant slug
21 | ui:autofocus: true
22 |
23 | steps:
24 | - id: fetch-alerts-file
25 | name: Fetch alerts file
26 | action: fetch:plain
27 | input:
28 | url: "https://github.com/RoadieHQ/roadie-infrastructure/blob/main/terraform/account-resources-tf/deployments/prod/"
29 | targetPath: 'fetch-folder'
30 | - id: move-alerts-file-to-workbench
31 | name: Move alerts file to a standalone location
32 | action: fs:rename
33 | input:
34 | files:
35 | - from: 'fetch-folder/alertable_tenants.json'
36 | to: './alerts-folder/alertable_tenants.json'
37 | - id: parse-alerts
38 | name: Parse retrieved alerts file
39 | action: roadiehq:utils:fs:parse
40 | input:
41 | path: './alerts-folder/alertable_tenants.json'
42 | - id: log-result
43 | name: "Parse Alerts Output"
44 | action: debug:log
45 | input:
46 | message: 'Alerts content: ${{ steps["parse-alerts"].output.content }}'
47 | - id: add-tenant-to-list
48 | name: Add tenant
49 | action: roadiehq:utils:jsonata:json:transform
50 | input:
51 | path: './alerts-folder/alertable_tenants.json'
52 | loadAll: true
53 | expression: '$.tenant_slugs ~> $append("${{parameters.tenant_name}}") ~> $sort()'
54 | - id: write-alerts-to-file
55 | name: Overwrite the existing alerts file with new contents
56 | action: roadiehq:utils:fs:write
57 | input:
58 | path: './alerts-folder/alertable_tenants.json'
59 | content: '{ "tenant_slugs": ${{ steps["add-tenant-to-list"].output.result }} }'
60 | - id: parse-alerts
61 | name: Parse modified Alerts file
62 | action: roadiehq:utils:fs:parse
63 | input:
64 | path: './alerts-folder/alertable_tenants.json'
65 | - id: log-result
66 | name: Display modified alerts file
67 | action: debug:log
68 | input:
69 | message: 'alertable_tenants.json content: ${{ steps["parse-alerts"].output.content }}'
70 | - id: add-customer-tag
71 | name: Add Customer Tag
72 | action: http:backstage:request
73 | input:
74 | method: POST
75 | path: /proxy/intercom/tags
76 | body: |
77 | {
78 | "name": "Customer",
79 | "companies": [
80 | {
81 | "company_id": "${{parameters.tenant_name}}"
82 | }
83 | ]
84 | }
85 | - id: log-result
86 | name: Display modified alerts file
87 | action: debug:log
88 | input:
89 | message: '${{ steps["add-customer-tag"].output.content }}'
90 | - id: createPullRequest
91 | name: Create a pull request
92 | action: publish:github:pull-request
93 | input:
94 | sourcePath: ./alerts-folder/
95 | targetPath: ./terraform/account-resources-tf/deployments/prod/
96 | repoUrl: github.com?repo=roadie-infrastructure&owner=RoadieHQ
97 | branchName: add-tenant-${{parameters.tenant_name}}-${{ '' | now }}
98 | title: A tenant ${{parameters.tenant_name}} to alerts tenant list
99 | description: "This PR updates the alertable_tenants.json file with the ${{parameters.tenant_name}} tenant slug."
100 | output:
101 | links:
102 | - title: View the pull request on GitHub
103 | icon: github
104 | url: ${{ steps['createPullRequest'].output.remoteUrl }}
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-backend/skeleton/.env:
--------------------------------------------------------------------------------
1 | # These variables are only available in your SST code.
2 | # To apply them to your Lambda functions, checkout this doc - https://docs.serverless-stack.com/environment-variables#environment-variables-in-lambda-functions
3 |
4 | MY_ENV_VAR=i-am-an-environment-variable
5 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-backend/skeleton/.github/workflows/merge.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Deploy
3 |
4 | on:
5 | push:
6 | branches:
7 | - main
8 | workflow_dispatch: {}
9 |
10 | jobs:
11 | deploy-dev:
12 | strategy:
13 | matrix:
14 | node-version: [14.x]
15 |
16 | env:
17 | AWS_PROFILE: default
18 |
19 | runs-on: ubuntu-latest
20 | name: Deploy
21 | steps:
22 | - uses: Fooji/create-aws-profile-action@v1
23 | with:
24 | profile: default
25 | key: ${{ secrets.AWS_ACCESS_KEY_ID }}
26 | secret: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
27 | region: eu-west-1
28 |
29 | - uses: actions/checkout@v2
30 | - name: Use Node.js 14.x
31 | uses: actions/setup-node@v1
32 | with:
33 | node-version: 14.x
34 | - run: yarn install
35 | - run: yarn deploy --stage prod
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-backend/skeleton/.github/workflows/pull-request.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Pre Merge Tests
3 |
4 | on:
5 | pull_request:
6 | branches:
7 | - main
8 |
9 | jobs:
10 | tests:
11 | strategy:
12 | matrix:
13 | node-version: [12.x]
14 |
15 | runs-on: ubuntu-latest
16 | name: Run Tests
17 | steps:
18 | - uses: actions/checkout@v2
19 | - name: Use Node.js 14.x
20 | uses: actions/setup-node@v1
21 | with:
22 | node-version: 12.x
23 | - run: yarn install
24 | - run: yarn prettier:check
25 | - run: yarn test
26 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-backend/skeleton/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # typescript
13 | *.js
14 | *.d.ts
15 |
16 | # misc
17 | .DS_Store
18 |
19 | # sst build output
20 | .build
21 | .sst
22 |
23 | # environments
24 | .env*.local
25 |
26 | npm-debug.log*
27 | yarn-debug.log*
28 | yarn-error.log*
29 |
30 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-backend/skeleton/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Serverless Stack (SST)
2 |
3 | This project was bootstrapped with [Create Serverless Stack](https://docs.serverless-stack.com/packages/create-serverless-stack).
4 |
5 | Start by installing the dependencies.
6 |
7 | ```bash
8 | $ npm install
9 | ```
10 |
11 | ## Commands
12 |
13 | ### `npm run start`
14 |
15 | Starts the local Lambda development environment.
16 |
17 | ### `npm run build`
18 |
19 | Build your app and synthesize your stacks.
20 |
21 | Generates a `.build/` directory with the compiled files and a `.build/cdk.out/` directory with the synthesized CloudFormation stacks.
22 |
23 | ### `npm run deploy [stack]`
24 |
25 | Deploy all your stacks to AWS. Or optionally deploy a specific stack.
26 |
27 | ### `npm run remove [stack]`
28 |
29 | Remove all your stacks and all of their resources from AWS. Or optionally remove a specific stack.
30 |
31 | ### `npm run test`
32 |
33 | Runs your tests using Jest. Takes all the [Jest CLI options](https://jestjs.io/docs/en/cli).
34 |
35 | ## Documentation
36 |
37 | Learn more about the Serverless Stack.
38 |
39 | - [Docs](https://docs.serverless-stack.com)
40 | - [@serverless-stack/cli](https://docs.serverless-stack.com/packages/cli)
41 | - [@serverless-stack/resources](https://docs.serverless-stack.com/packages/resources)
42 |
43 | ## Community
44 |
45 | [Follow us on Twitter](https://twitter.com/ServerlessStack) or [post on our forums](https://discourse.serverless-stack.com).
46 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-backend/skeleton/catalog-info.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: backstage.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: ${{values.component_id | dump}}
5 | description: ${{values.description | dump}}
6 | annotations:
7 | github.com/project-slug: ${{values.destination.owner + "/" + values.destination.repo}}
8 | backstage.io/techdocs-ref: dir:.
9 | spec:
10 | type: website
11 | lifecycle: experimental
12 | owner: ${{values.owner | dump}}
13 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-backend/skeleton/mkdocs.yml:
--------------------------------------------------------------------------------
1 | site_name: ${{values.component_id | dump}}
2 | site_description: ${{values.description | dump}}
3 |
4 | nav:
5 | - Introduction: index.md
6 |
7 | plugins:
8 | - techdocs-core
9 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-backend/skeleton/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "${{values.component_id}}",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "test": "sst test",
7 | "start": "sst start",
8 | "build": "sst build",
9 | "deploy": "sst deploy",
10 | "remove": "sst remove"
11 | },
12 | "eslintConfig": {
13 | "extends": ["serverless-stack"]
14 | },
15 | "devDependencies": {
16 | "@aws-cdk/assert": "1.126.0",
17 | "@types/aws-lambda": "^8.10.70"
18 | },
19 | "dependencies": {
20 | "@serverless-stack/cli": "0.49.0",
21 | "@serverless-stack/resources": "0.49.0",
22 | "@aws-cdk/core": "1.126.0"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-backend/skeleton/src/lambda.ts:
--------------------------------------------------------------------------------
1 | import { APIGatewayProxyEventV2, APIGatewayProxyHandlerV2 } from "aws-lambda";
2 |
3 | export const handler: APIGatewayProxyHandlerV2 = async (
4 | event: APIGatewayProxyEventV2
5 | ) => {
6 | return {
7 | statusCode: 200,
8 | headers: { "Content-Type": "text/plain" },
9 | body: `Hello, World! Your request was received at ${event.requestContext.time}.`,
10 | };
11 | };
12 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-backend/skeleton/sst.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "${{values.component_id}}",
3 | "region": "us-east-1",
4 | "main": "stacks/index.ts"
5 | }
6 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-backend/skeleton/stacks/MyStack.ts:
--------------------------------------------------------------------------------
1 | import * as sst from "@serverless-stack/resources";
2 |
3 | export default class MyStack extends sst.Stack {
4 | constructor(scope: sst.App, id: string, props?: sst.StackProps) {
5 | super(scope, id, props);
6 |
7 | // Create a HTTP API
8 | const api = new sst.Api(this, "Api", {
9 | routes: {
10 | "GET /": "src/lambda.handler",
11 | },
12 | });
13 |
14 | // Show the endpoint in the output
15 | this.addOutputs({
16 | "ApiEndpoint": api.url,
17 | });
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-backend/skeleton/stacks/index.ts:
--------------------------------------------------------------------------------
1 | import MyStack from "./MyStack";
2 | import * as sst from "@serverless-stack/resources";
3 |
4 | export default function main(app: sst.App): void {
5 | // Set default runtime for all functions
6 | app.setDefaultFunctionProps({
7 | runtime: "nodejs12.x"
8 | });
9 |
10 | new MyStack(app, "my-stack");
11 |
12 | // Add more stacks
13 | }
14 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-backend/skeleton/test/MyStack.test.ts:
--------------------------------------------------------------------------------
1 | import { expect, haveResource } from "@aws-cdk/assert";
2 | import * as sst from "@serverless-stack/resources";
3 | import MyStack from "../stacks/MyStack";
4 |
5 | test("Test Stack", () => {
6 | const app = new sst.App();
7 | // WHEN
8 | const stack = new MyStack(app, "test-stack");
9 | // THEN
10 | expect(stack).to(haveResource("AWS::Lambda::Function"));
11 | });
12 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-backend/skeleton/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2018",
4 | "module": "commonjs",
5 | "lib": ["es2018"],
6 | "declaration": true,
7 | "strict": true,
8 | "noImplicitAny": true,
9 | "strictNullChecks": true,
10 | "noImplicitThis": true,
11 | "alwaysStrict": true,
12 | "noUnusedLocals": false,
13 | "noUnusedParameters": false,
14 | "noImplicitReturns": true,
15 | "noFallthroughCasesInSwitch": false,
16 | "inlineSourceMap": true,
17 | "inlineSources": true,
18 | "experimentalDecorators": true,
19 | "strictPropertyInitialization": false,
20 | "typeRoots": ["./node_modules/@types"]
21 | },
22 | "include": ["stacks", "src"]
23 | }
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-backend/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: backstage.io/v1beta2
2 | kind: Template
3 | metadata:
4 | name: create-aws-serverless-backend
5 | title: Create AWS Serverless Backend
6 | description: Create AWS Serverless Backend
7 | tags:
8 | - aws
9 |
10 | spec:
11 | owner: info@roadie.io
12 | type: api
13 | parameters:
14 | - title: Provide some simple information
15 | required:
16 | - component_id
17 | - owner
18 | - region
19 | properties:
20 | component_id:
21 | title: Name
22 | type: string
23 | description: Unique name of the component
24 | region:
25 | title: Region
26 | type: string
27 | description: AWS region to deploy this Serverless stack
28 | description:
29 | title: Description
30 | type: string
31 | description: Help others understand what this website is for.
32 | owner:
33 | title: Owner
34 | type: string
35 | description: Owner of the component
36 | ui:field: OwnerPicker
37 | ui:options:
38 | allowedKinds:
39 | - Group
40 | - title: Choose a location
41 | required:
42 | - repoUrl
43 | properties:
44 | repoUrl:
45 | title: Repository Location
46 | type: string
47 | ui:field: RepoUrlPicker
48 | ui:options:
49 | allowedHosts:
50 | - github.com
51 | steps:
52 | - id: template
53 | name: Fetch Skeleton + Template
54 | action: fetch:template
55 | input:
56 | url: ./skeleton
57 | copyWithoutRender:
58 | - .github/workflows/*
59 | values:
60 | component_id: '{{ parameters.component_id }}'
61 | description: '{{ parameters.description }}'
62 | destination: '{{ parseRepoUrl parameters.repoUrl }}'
63 | owner: '{{ parameters.owner }}'
64 |
65 | - id: publish
66 | name: Publish
67 | action: publish:github
68 | input:
69 | allowedHosts: ['github.com']
70 | description: 'This is {{ parameters.component_id }}'
71 | repoUrl: '{{ parameters.repoUrl }}'
72 | defaultBranch: main
73 |
74 | output:
75 | remoteUrl: '{{ steps.publish.output.remoteUrl }}'
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/.github/workflows/merge.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Deploy
3 |
4 | on:
5 | push:
6 | branches:
7 | - main
8 | workflow_dispatch: {}
9 |
10 | jobs:
11 | deploy-dev:
12 | strategy:
13 | matrix:
14 | node-version: [14.x]
15 |
16 | env:
17 | AWS_PROFILE: default
18 |
19 | runs-on: ubuntu-latest
20 | name: Deploy
21 | steps:
22 | - uses: Fooji/create-aws-profile-action@v1
23 | with:
24 | profile: default
25 | key: ${{ secrets.AWS_ACCESS_KEY_ID }}
26 | secret: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
27 | region: eu-west-1
28 |
29 | - uses: actions/checkout@v2
30 | - name: Use Node.js 14.x
31 | uses: actions/setup-node@v1
32 | with:
33 | node-version: 14.x
34 | - run: yarn install
35 | - run: cd frontend && yarn install && cd ..
36 | - run: yarn build --stage prod
37 | - run: yarn deploy --stage prod
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/.github/workflows/pull-request.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Pre Merge Tests
3 |
4 | on:
5 | pull_request:
6 | branches:
7 | - main
8 |
9 | jobs:
10 | tests:
11 | strategy:
12 | matrix:
13 | node-version: [12.x]
14 |
15 | runs-on: ubuntu-latest
16 | name: Run Tests
17 | steps:
18 | - uses: actions/checkout@v2
19 | - name: Use Node.js 14.x
20 | uses: actions/setup-node@v1
21 | with:
22 | node-version: 12.x
23 | - run: yarn install
24 | - run: yarn prettier:check
25 | - run: yarn test
26 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 |
15 | # sst build output
16 | .build
17 |
18 | npm-debug.log*
19 | yarn-debug.log*
20 | yarn-error.log*
21 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/README.md:
--------------------------------------------------------------------------------
1 | # How to create a React.js app
2 |
3 | An example full-stack serverless React.js app created with SST.
4 |
5 | ## Getting Started
6 |
7 | [**Read the tutorial**](https://serverless-stack.com/examples/how-to-create-a-reactjs-app-with-serverless.html)
8 |
9 | Install the example.
10 |
11 | ```bash
12 | $ npm init serverless-stack --example react-app
13 | # Or with Yarn
14 | $ yarn create serverless-stack --example react-app
15 | ```
16 |
17 | ## Commands
18 |
19 | ### `npm run start`
20 |
21 | Starts the Live Lambda Development environment.
22 |
23 | ### `npm run build`
24 |
25 | Build your app and synthesize your stacks.
26 |
27 | ### `npm run deploy [stack]`
28 |
29 | Deploy all your stacks to AWS. Or optionally deploy, a specific stack.
30 |
31 | ### `npm run remove [stack]`
32 |
33 | Remove all your stacks and all of their resources from AWS. Or optionally removes, a specific stack.
34 |
35 | ### `npm run test`
36 |
37 | Runs your tests using Jest. Takes all the [Jest CLI options](https://jestjs.io/docs/en/cli).
38 |
39 | ## Documentation
40 |
41 | Learn more about the SST.
42 |
43 | - [Docs](https://docs.serverless-stack.com/)
44 | - [@serverless-stack/cli](https://docs.serverless-stack.com/packages/cli)
45 | - [@serverless-stack/resources](https://docs.serverless-stack.com/packages/resources)
46 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/catalog-info.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: backstage.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: ${{values.component_id | dump}}
5 | description: ${{values.description | dump}}
6 | annotations:
7 | github.com/project-slug: ${{values.destination.owner + "/" + values.destination.repo}}
8 | backstage.io/techdocs-ref: dir:.
9 | spec:
10 | type: website
11 | lifecycle: experimental
12 | owner: ${{values.owner | dump}}
13 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/.env:
--------------------------------------------------------------------------------
1 | SKIP_PREFLIGHT_CHECK=true
2 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Create React App
2 |
3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4 |
5 | ## Available Scripts
6 |
7 | In the project directory, you can run:
8 |
9 | ### `yarn start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
13 |
14 | The page will reload if you make edits.\
15 | You will also see any lint errors in the console.
16 |
17 | ### `yarn test`
18 |
19 | Launches the test runner in the interactive watch mode.\
20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21 |
22 | ### `yarn build`
23 |
24 | Builds the app for production to the `build` folder.\
25 | It correctly bundles React in production mode and optimizes the build for the best performance.
26 |
27 | The build is minified and the filenames include the hashes.\
28 | Your app is ready to be deployed!
29 |
30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31 |
32 | ### `yarn eject`
33 |
34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
35 |
36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37 |
38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
39 |
40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
41 |
42 | ## Learn More
43 |
44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45 |
46 | To learn React, check out the [React documentation](https://reactjs.org/).
47 |
48 | ### Code Splitting
49 |
50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
51 |
52 | ### Analyzing the Bundle Size
53 |
54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
55 |
56 | ### Making a Progressive Web App
57 |
58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
59 |
60 | ### Advanced Configuration
61 |
62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
63 |
64 | ### Deployment
65 |
66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
67 |
68 | ### `yarn build` fails to minify
69 |
70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
71 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "frontend",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.11.4",
7 | "@testing-library/react": "^11.1.0",
8 | "@testing-library/user-event": "^12.1.10",
9 | "react": "^17.0.2",
10 | "react-dom": "^17.0.2",
11 | "react-scripts": "4.0.3",
12 | "web-vitals": "^1.0.1"
13 | },
14 | "scripts": {
15 | "start": "sst-env -- react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | },
38 | "devDependencies": {
39 | "@serverless-stack/static-site-env": "^0.33.0"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoadieHQ/software-templates/c830d43d36df4a2aac60a020902d46e5b7f31902/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/public/favicon.ico
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoadieHQ/software-templates/c830d43d36df4a2aac60a020902d46e5b7f31902/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/public/logo192.png
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoadieHQ/software-templates/c830d43d36df4a2aac60a020902d46e5b7f31902/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/public/logo512.png
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/src/App.css:
--------------------------------------------------------------------------------
1 | body,
2 | html {
3 | height: 100%;
4 | display: grid;
5 | }
6 | #root {
7 | margin: auto;
8 | }
9 | .App {
10 | text-align: center;
11 | }
12 | p {
13 | margin-top: 0;
14 | font-size: 20px;
15 | }
16 | button {
17 | font-size: 48px;
18 | }
19 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/src/App.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import "./App.css";
3 |
4 | export default function App() {
5 | const [count, setCount] = useState(null);
6 |
7 | function onClick() {
8 | fetch(process.env.REACT_APP_API_URL, {
9 | method: "POST",
10 | })
11 | .then((response) => response.text())
12 | .then(setCount);
13 | }
14 |
15 | return (
16 |
17 | {count &&
You clicked me {count} times.
}
18 |
19 |
20 | );
21 | }
22 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/src/App.test.js:
--------------------------------------------------------------------------------
1 | import { render, screen } from "@testing-library/react";
2 | import App from "./App";
3 |
4 | test("renders learn react link", () => {
5 | render();
6 | const linkElement = screen.getByText(/learn react/i);
7 | expect(linkElement).toBeInTheDocument();
8 | });
9 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import "./index.css";
4 | import App from "./App";
5 | import reportWebVitals from "./reportWebVitals";
6 |
7 | ReactDOM.render(
8 |
9 |
10 | ,
11 | document.getElementById("root")
12 | );
13 |
14 | // If you want to start measuring performance in your app, pass a function
15 | // to log results (for example: reportWebVitals(console.log))
16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
17 | reportWebVitals();
18 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/src/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/src/reportWebVitals.js:
--------------------------------------------------------------------------------
1 | const reportWebVitals = (onPerfEntry) => {
2 | if (onPerfEntry && onPerfEntry instanceof Function) {
3 | import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4 | getCLS(onPerfEntry);
5 | getFID(onPerfEntry);
6 | getFCP(onPerfEntry);
7 | getLCP(onPerfEntry);
8 | getTTFB(onPerfEntry);
9 | });
10 | }
11 | };
12 |
13 | export default reportWebVitals;
14 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/frontend/src/setupTests.js:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import "@testing-library/jest-dom";
6 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/mkdocs.yml:
--------------------------------------------------------------------------------
1 | site_name: ${{values.component_id | dump}}
2 | site_description: ${{values.description | dump}}
3 |
4 | nav:
5 | - Introduction: index.md
6 |
7 | plugins:
8 | - techdocs-core
9 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "${{values.component_id}}",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "test": "sst test",
7 | "start": "sst start",
8 | "build": "sst build",
9 | "deploy": "sst deploy",
10 | "remove": "sst remove"
11 | },
12 | "eslintConfig": {
13 | "extends": [
14 | "serverless-stack"
15 | ]
16 | },
17 | "dependencies": {
18 | "@serverless-stack/cli": "0.48.0",
19 | "@serverless-stack/resources": "0.48.0",
20 | "aws-sdk": "^2.931.0"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/src/lambda.js:
--------------------------------------------------------------------------------
1 | import AWS from "aws-sdk";
2 |
3 | const dynamoDb = new AWS.DynamoDB.DocumentClient();
4 |
5 | export async function main() {
6 | const getParams = {
7 | // Get the table name from the environment variable
8 | TableName: process.env.tableName,
9 | // Get the row where the counter is called "clicks"
10 | Key: {
11 | counter: "clicks",
12 | },
13 | };
14 | const results = await dynamoDb.get(getParams).promise();
15 |
16 | // If there is a row, then get the value of the
17 | // column called "tally"
18 | let count = results.Item ? results.Item.tally : 0;
19 |
20 | const putParams = {
21 | TableName: process.env.tableName,
22 | Key: {
23 | counter: "clicks",
24 | },
25 | // Update the "tally" column
26 | UpdateExpression: "SET tally = :count",
27 | ExpressionAttributeValues: {
28 | // Increase the count
29 | ":count": ++count,
30 | },
31 | };
32 | await dynamoDb.update(putParams).promise();
33 |
34 | return {
35 | statusCode: 200,
36 | body: count,
37 | };
38 | }
39 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/sst.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "${{values.component_id}}",
3 | "region": "us-east-1",
4 | "main": "stacks/index.js"
5 | }
6 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/stacks/MyStack.js:
--------------------------------------------------------------------------------
1 | import * as sst from "@serverless-stack/resources";
2 |
3 | export default class MyStack extends sst.Stack {
4 | constructor(scope, id, props) {
5 | super(scope, id, props);
6 |
7 | // Create the table
8 | const table = new sst.Table(this, "Counter", {
9 | fields: {
10 | counter: sst.TableFieldType.STRING,
11 | },
12 | primaryIndex: { partitionKey: "counter" },
13 | });
14 |
15 | // Create the HTTP API
16 | const api = new sst.Api(this, "Api", {
17 | defaultFunctionProps: {
18 | // Pass in the table name to our API
19 | environment: {
20 | tableName: table.dynamodbTable.tableName,
21 | },
22 | },
23 | routes: {
24 | "POST /": "src/lambda.main",
25 | },
26 | });
27 |
28 | // Allow the API to access the table
29 | api.attachPermissions([table]);
30 |
31 | // Deploy our React app
32 | const site = new sst.ReactStaticSite(this, "ReactSite", {
33 | path: "frontend",
34 | environment: {
35 | REACT_APP_API_URL: api.url,
36 | },
37 | });
38 |
39 | // Show the URLs in the output
40 | this.addOutputs({
41 | SiteUrl: site.url,
42 | ApiEndpoint: api.url,
43 | });
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/stacks/index.js:
--------------------------------------------------------------------------------
1 | import MyStack from "./MyStack";
2 |
3 | export default function main(app) {
4 | // Set default runtime for all functions
5 | app.setDefaultFunctionProps({
6 | runtime: "nodejs12.x",
7 | });
8 |
9 | new MyStack(app, "my-stack");
10 |
11 | // Add more stacks
12 | }
13 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/skeleton/test/MyStack.test.js:
--------------------------------------------------------------------------------
1 | import { expect, haveResource } from "@aws-cdk/assert";
2 | import * as sst from "@serverless-stack/resources";
3 | import MyStack from "../stacks/MyStack";
4 |
5 | test("Test Stack", () => {
6 | const app = new sst.App();
7 | // WHEN
8 | const stack = new MyStack(app, "test-stack");
9 | // THEN
10 | expect(stack).to(haveResource("AWS::Lambda::Function"));
11 | });
12 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-aws-serverless-frontend-and-backend/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: backstage.io/v1beta2
2 | kind: Template
3 | metadata:
4 | name: create-aws-serverless-frontend-and-backend
5 | title: Create AWS Serverless Frontend and Backend
6 | description: Create AWS Serverless Frontend and Backend
7 | tags:
8 | - aws
9 |
10 | spec:
11 | owner: info@roadie.io
12 | type: service
13 | parameters:
14 | - title: Provide some simple information
15 | required:
16 | - component_id
17 | - owner
18 | - region
19 | properties:
20 | component_id:
21 | title: Name
22 | type: string
23 | description: Unique name of the component
24 | region:
25 | title: Region
26 | type: string
27 | description: AWS region to deploy this Serverless stack
28 | description:
29 | title: Description
30 | type: string
31 | description: Help others understand what this website is for.
32 | owner:
33 | title: Owner
34 | type: string
35 | description: Owner of the component
36 | ui:field: OwnerPicker
37 | ui:options:
38 | allowedKinds:
39 | - Group
40 | - title: Choose a location
41 | required:
42 | - repoUrl
43 | properties:
44 | repoUrl:
45 | title: Repository Location
46 | type: string
47 | ui:field: RepoUrlPicker
48 | ui:options:
49 | allowedHosts:
50 | - github.com
51 | steps:
52 | - id: template
53 | name: Fetch Skeleton + Template
54 | action: fetch:template
55 | input:
56 | url: ./skeleton
57 | copyWithoutRender:
58 | - .github/workflows/*
59 | values:
60 | component_id: '{{ parameters.component_id }}'
61 | description: '{{ parameters.description }}'
62 | destination: '{{ parseRepoUrl parameters.repoUrl }}'
63 | owner: '{{ parameters.owner }}'
64 |
65 | - id: publish
66 | name: Publish
67 | action: publish:github
68 | input:
69 | allowedHosts: ['github.com']
70 | description: 'This is {{ parameters.component_id }}'
71 | repoUrl: '{{ parameters.repoUrl }}'
72 | defaultBranch: main
73 |
74 | output:
75 | remoteUrl: '{{ steps.publish.output.remoteUrl }}'
76 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-empty-project/skeleton/.github/workflows/pull-request.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Pre Merge Tests
3 |
4 | on:
5 | pull_request:
6 | branches:
7 | - main
8 |
9 | jobs:
10 | tests:
11 | runs-on: ubuntu-latest
12 | name: Run Tests
13 | steps:
14 | - uses: actions/checkout@v2
15 | - run: true
16 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-empty-project/skeleton/README.md:
--------------------------------------------------------------------------------
1 | # ${{values.component_id}}
2 |
3 | ${{values.description}}
4 |
5 | ## Local Development
6 |
7 | ### Building
8 |
9 | ### Running
10 |
11 | ### Testing
12 |
13 | ## Deployment
14 |
15 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-empty-project/skeleton/catalog-info.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: backstage.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: ${{values.component_id | dump}}
5 | description: ${{values.description | dump}}
6 | annotations:
7 | github.com/project-slug: ${{values.destination.owner + "/" + values.destination.repo}}
8 | backstage.io/techdocs-ref: dir:.
9 | spec:
10 | type: ${{values.type}}
11 | lifecycle: experimental
12 | owner: ${{values.owner | dump}}
13 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-empty-project/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: create-empty-project
5 | title: Create Empty Project
6 | description: Create Empty Project
7 |
8 | spec:
9 | owner: info@roadie.io
10 | type: service
11 | parameters:
12 | - title: Provide some simple information
13 | required:
14 | - component_id
15 | - owner
16 | - description
17 | - type
18 | properties:
19 | component_id:
20 | title: Name
21 | type: string
22 | description: Unique name of the component
23 | description:
24 | title: Description
25 | type: string
26 | description: Help others understand what this project is for.
27 | type:
28 | title: Type of Component
29 | type: string
30 | description: service, library, etc.
31 | enum: ["service", "library", "website", "other"]
32 | owner:
33 | title: Owner
34 | type: string
35 | description: Owner of the component
36 | ui:field: OwnerPicker
37 | ui:options:
38 | allowedKinds:
39 | - Group
40 | - title: Choose a location
41 | description: |
42 | This section will ask for details about the Owner and Repository name which will then be used
43 | to create a repository in that location using your GitHub credentials.
44 | required:
45 | - repoUrl
46 | properties:
47 | repoUrl:
48 | title: Enter an Owner and Repository Name
49 | description: |
50 | The Owner should be your GitHub username. The Repository name should be a name that is not one that exists already in your GitHub account.
51 | type: string
52 | ui:field: RepoUrlPicker
53 | ui:options:
54 | requestUserCredentials:
55 | secretsKey: USER_OAUTH_TOKEN
56 | additionalScopes:
57 | github:
58 | - workflow
59 | allowedHosts:
60 | - github.com
61 | - bitbucket.org
62 | steps:
63 | - id: template
64 | name: Fetch Skeleton + Template
65 | action: fetch:template
66 | input:
67 | url: ./skeleton
68 | copyWithoutRender:
69 | - .github/workflows/*
70 | values:
71 | component_id: ${{ parameters.component_id }}
72 | description: ${{ parameters.description }}
73 | destination: ${{ parameters.repoUrl | parseRepoUrl }}
74 | owner: ${{ parameters.owner }}
75 | type: ${{ parameters.type }}
76 |
77 | - id: publish
78 | name: Publish
79 | action: publish:github
80 | input:
81 | allowedHosts: ['github.com']
82 | description: 'This is ${{ parameters.component_id }}'
83 | repoUrl: ${{ parameters.repoUrl }}
84 | defaultBranch: main
85 | requireCodeOwnerReviews: true
86 | deleteBranchOnMerge: true
87 |
88 |
89 | output:
90 | remoteUrl: '{{ steps.publish.output.remoteUrl }}'
91 | links:
92 | - title: Repository
93 | url: ${{ steps.publish.output.remoteUrl }}
94 |
95 |
96 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-readme/skeleton/README.md.njk:
--------------------------------------------------------------------------------
1 | # ${{ values.name }}
2 |
3 | ## Why write a README?
4 |
5 | - It is the first file a person will see when they encounter your project, so it should be fairly brief but detailed.
6 | - It will make your project standout from a bunch of others. Also be sure your project is good too.
7 | - It will help you focus on what your project needs to deliver and how.
8 |
9 | ## The most important README sections
10 |
11 | ### 1. Project's Title
12 |
13 | This is the name of the project. It describes the whole project in one sentence, and helps people understand what the main goal and aim of the project is.
14 |
15 | ### 2. Project Description
16 |
17 | This is an important component of your project that many new developers often overlook.
18 |
19 | Your description is an extremely important aspect of your project. A well-crafted description allows you to show off your work to other developers as well as potential employers.
20 |
21 | The quality of a README description often differentiates a good project from a bad project. A good one takes advantage of the opportunity to explain and showcase:
22 |
23 | - What your application does,
24 | - Why you used the technologies you used,
25 | - Some of the challenges you faced and features you hope to implement in the future.
26 |
27 | ### 3. Table of Contents (Optional)
28 |
29 | If your README is very long, you might want to add a table of contents to make it easy for users to navigate to different sections easily. It will make it easier for readers to move around the project with ease.
30 |
31 | ### 4. How to Install and Run the Project
32 |
33 | If you are working on a project that a user needs to install or run locally in a machine like a "POS", you should include the steps required to install your project and also the required dependencies if any.
34 |
35 | Provide a step-by-step description of how to get the development environment set and running.
36 |
37 | ### 5. How to Use the Project
38 |
39 | Provide instructions and examples so users/contributors can use the project. This will make it easy for them in case they encounter a problem – they will always have a place to reference what is expected.
40 |
41 | You can also make use of visual aids by including materials like screenshots to show examples of the running project and also the structure and design principles used in your project.
42 |
43 | Also if your project will require authentication like passwords or usernames, this is a good section to include the credentials.
44 |
45 | ### 6. Include Credits
46 |
47 | If you worked on the project as a team or an organization, list your collaborators/team members. You should also include links to their GitHub profiles and social media too.
48 |
49 | Also, if you followed tutorials or referenced a certain material that might help the user to build that particular project, include links to those here as well.
50 |
51 | This is just a way to show your appreciation and also to help others get a first hand copy of the project.
52 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-readme/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: create-readme-in-repo
5 | title: Create a README
6 | description: Create a new PR with a basic README file.
7 | spec:
8 | owner: group:roadiehq/engineering
9 | type: file
10 |
11 | parameters:
12 | - title: Basic info
13 | required:
14 | - repoName
15 | - name
16 | properties:
17 | repoHost:
18 | type: string
19 | default: github.com
20 | ui:widget: hidden
21 | repoOrg:
22 | type: string
23 | default: roadiehq # Change this to match the name of your GitHub org
24 | ui:widget: hidden
25 | repoName:
26 | title: Repository name
27 | type: string
28 | name:
29 | title: Human readable service name
30 | type: string
31 |
32 | steps:
33 | - id: fetchTemplate
34 | action: fetch:template
35 | input:
36 | url: ./skeleton
37 | templateFileExtension: .njk
38 | values:
39 | name: ${{ parameters.name }}
40 |
41 | - id: createPullRequest
42 | name: create-pull-request
43 | action: publish:github:pull-request
44 | input:
45 | repoUrl: ${{ parameters.repoHost }}?owner=${{ parameters.repoOrg }}&repo=${{ parameters.repoName }}
46 | branchName: add-readme-${{ '' | now }}
47 | title: Add a README file
48 | description: |
49 | This PR adds a basic README file to this repository.
50 |
51 | It was created via a [scaffolder template on Roadie](https://example.com).
52 |
53 | output:
54 | links:
55 | - title: View the pull request on GitHub
56 | icon: github
57 | url: ${{ steps['createPullRequest'].output.remoteUrl }}
58 | - title: Learn about writing READMEs
59 | icon: help
60 | url: https://example.com
61 |
--------------------------------------------------------------------------------
/scaffolder-templates/create-rfc/skeleton/template.md.njk:
--------------------------------------------------------------------------------
1 | # RFC-${{ values.rfcNumber }} - ${{ values.rfcTitle }}
2 |
3 | *Author(s)*:
4 | *Squad*:
5 | *Requested Reviewers*:
6 | *Status*: DRAFT
7 |
8 | ## Abstract
9 | ${{ values.abstract }}
10 |
11 | ## Background
12 |
13 | ## Non-Goals
14 |
15 | ## Key Terms
16 |
17 | ## Problem
18 |
19 | ## Proposal
20 |
21 | ## Technical Limitations
22 |
23 | ## Open Questions
24 |
25 | ## Outcomes and Forward References
--------------------------------------------------------------------------------
/scaffolder-templates/create-rfc/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: create-rfc-template
5 | title: Create a new RFC flavored markdown document
6 | description: Create a new RFC flavored markdown document
7 | spec:
8 | owner: group:default/engineering
9 | type: service
10 |
11 | parameters:
12 | - title: Document front content
13 | properties:
14 | rfcNumber:
15 | title: rfcNumber
16 | type: string
17 | rfcTitle:
18 | title: RFC Title
19 | type: string
20 | abstract:
21 | title: Document Abstract (optional draft version)
22 | type: string
23 | ui:widget: textarea
24 | - title: Repository to place document
25 | properties:
26 | repoUrl:
27 | content:
28 | type: string
29 | description: Name of repository
30 | ui:field: RepoUrlPicker
31 | ui:options:
32 | allowedHosts:
33 | - github.com
34 |
35 | steps:
36 | - id: log-message
37 | name: Log Message
38 | action: debug:log
39 | input:
40 | message: Creating ${{ parameters.rfcNumber }}/index.md
41 |
42 | - id: fetch-template
43 | action: fetch:template
44 | input:
45 | url: https://github.com/RoadieHQ/software-templates/tree/main/scaffolder-templates/create-rfc/skeleton
46 | templateFileExtension: true
47 | targetPath: docs/rfcs/${{ parameters.rfcNumber }}
48 | values:
49 | rfcNumber: ${{ parameters.rfcNumber }}
50 | rfcTitle: ${{ parameters.rfcTitle }}
51 | abstract: ${{ parameters.abstract }}
52 |
53 | - id: move-rfc
54 | action: fs:rename
55 | input:
56 | files:
57 | - from: docs/rfcs/${{ parameters.rfcNumber }}/template.md
58 | to: docs/rfcs/${{ parameters.rfcNumber }}/index.md
59 |
60 | - id: create-pull-request
61 | name: create-pull-request
62 | action: publish:github:pull-request
63 | input:
64 | repoUrl: ${{ parameters.repoUrl }}
65 | branchName: RFC-${{ parameters.rfcNumber }}_${{ parameters.rfcTitle | replace(" ", "-") | replace("\"", "") | replace ("'", "") | lower }}
66 | title: RFC-${{ parameters.rfcNumber }} - ${{ parameters.rfcTitle }}
67 | description: ${{ parameters.abstract }}
--------------------------------------------------------------------------------
/scaffolder-templates/create-tenant/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: create-tenant
5 | title: Create Tenant
6 | description: Send an API call to the tenant manager to create a tenant.
7 | tags:
8 | - Roadie
9 |
10 | spec:
11 | owner: group:roadiehq/solutions
12 | type: Tenant
13 | parameters:
14 | - title: Provide some simple information
15 | required:
16 | - tenant_name
17 | - tenant_email_domain
18 | - admin_email
19 | - tenant_environment
20 | properties:
21 | tenant_name:
22 | title: Name
23 | type: string
24 | description: The name of the tenant, used for the tenant slug.
25 | ui:autofocus: true
26 | maxLength: 30
27 | pattern: '^[a-z][a-z1-9-]*[a-z1-9]+$'
28 | ui:help: Lowercase characters, dash (-), and underscore (_) only.
29 | tenant_email_domain:
30 | title: Email domain
31 | type: string
32 | description: The email domain of users who will be allowed to access the tenant.
33 | pattern: '^[a-zA-Z0-9-]+.[a-zA-Z0-9-]+'
34 | admin_email:
35 | title: Admin email
36 | type: string
37 | description: The email of the person who will drive the evaluation.
38 | pattern: '^[a-zA-Z0-9-_.]+@[a-zA-Z0-9-.]+.[a-zA-Z0-9-]+$'
39 | tenant_environment:
40 | title: Environment
41 | type: string
42 | default: dev
43 | enum: ['dev', 'prod']
44 | createSlack:
45 | title: Create Slack Channel?
46 | type: boolean
47 | default: false
48 | ui:widget: radio
49 | pov:
50 | title: PoV Tenant?
51 | type: boolean
52 | default: true
53 | ui:widget: radio
54 |
55 | steps:
56 | - id: createDevTenant
57 | name: Is it a Dev Tenant?
58 | if: ${{parameters.tenant_environment === 'dev'}}
59 | action: http:backstage:request
60 | input:
61 | method: 'POST'
62 | path: proxy/tenant-manager-dev/api/tenant
63 | body: |
64 | {
65 | "tenantName": "${{ parameters.tenant_name }}",
66 | "tenantEmailDomain": "${{ parameters.tenant_email_domain }}",
67 | "adminEmail": "${{ parameters.admin_email }}",
68 | "tenantEnvironment": "dev",
69 | "skipFailures": false
70 | }
71 |
72 | - id: createProdTenant
73 | name: Is it a Prod Tenant?
74 | if: ${{parameters.tenant_environment === 'prod'}}
75 | action: http:backstage:request
76 | input:
77 | method: 'POST'
78 | path: proxy/tenant-manager/api/tenant
79 | body: |
80 | {
81 | "tenantName": "${{ parameters.tenant_name }}",
82 | "tenantEmailDomain": "${{ parameters.tenant_email_domain }}",
83 | "adminEmail": "${{ parameters.admin_email }}",
84 | "tenantEnvironment": "prod",
85 | "skipFailures": false
86 | }
87 |
88 | - id: addPovTag
89 | name: Is it a PoV Tenant?
90 | if: ${{parameters.pov === true}}
91 | action: http:backstage:request
92 | input:
93 | method: 'POST'
94 | path: proxy/fragments
95 | body: |
96 | {
97 | "decorator": {
98 | "entityRef": "resource:default/${{ parameters.tenant_name }}",
99 | "fragment": {
100 | "metadata": {
101 | "tags": [
102 | "pov"
103 | ]
104 | }
105 | }
106 | }
107 | }
108 |
109 | output:
110 | resp: ${{ steps.createDevTenant.output.body }} ${{ steps.createProdTenant.output.body }}
111 |
--------------------------------------------------------------------------------
/scaffolder-templates/debug-template/skeleton/template.md.njk:
--------------------------------------------------------------------------------
1 | # RFC-${{ values.rfcNumber }} - ${{ values.rfcTitle }}
2 |
3 | *Author(s)*:
4 | *Squad*:
5 | *Requested Reviewers*:
6 | *Status*: DRAFT
7 |
8 | ## Abstract
9 | ${{ values.abstract }}
10 |
11 | ## Background
12 |
13 | ## Non-Goals
14 |
15 | ## Key Terms
16 |
17 | ## Problem
18 |
19 | ## Proposal
20 |
21 | ## Technical Limitations
22 |
23 | ## Open Questions
24 |
25 | ## Outcomes and Forward References
--------------------------------------------------------------------------------
/scaffolder-templates/debug-template/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: debug-template
5 | title: Template to debug skeleton templates
6 | description: Basic template to trigger a github worklfow
7 |
8 | spec:
9 | owner: group:default/engineering
10 | type: service
11 | parameters:
12 | - title: Document front content
13 | properties:
14 | rfcNumber:
15 | title: rfcNumber
16 | type: string
17 | rfcTitle:
18 | title: RFC Title
19 | type: string
20 | abstract:
21 | title: Document Abstract (optional draft version)
22 | type: string
23 | ui:widget: textarea
24 |
25 | steps:
26 | - id: fetch-template
27 | action: fetch:template
28 | input:
29 | url: https://github.com/RoadieHQ/software-templates/tree/main/scaffolder-templates/debug-template/skeleton
30 | templateFileExtension: true
31 | values:
32 | rfcNumber: ${{ parameters.rfcNumber }}
33 | rfcTitle: ${{ parameters.rfcTitle }}
34 | abstract: ${{ parameters.abstract }}
35 |
36 | - id: read-file
37 | name: Read File
38 | action: fs:read
39 | input:
40 | path: ./template.md
41 |
42 | - id: log-message
43 | name: Log Message
44 | action: debug:log
45 | input:
46 | message: ${{ steps['read-file'].output.content }}
47 |
--------------------------------------------------------------------------------
/scaffolder-templates/delete-entities/template.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: scaffolder.backstage.io/v1beta3
3 | kind: Template
4 | metadata:
5 | name: delete-entities
6 | title: Delete Entities
7 | description: Deletes all entities associated with a given YAML file from the catalog. Note - if autodiscovery is turned on these entities will re-appear if the source file is not deleted before.
8 | spec:
9 | owner: roadie
10 | type: template
11 | parameters:
12 | - title: Entities to delete
13 | properties:
14 | catalog-info-url:
15 | title: Catalog info file url
16 | type: string
17 | description: The full SCM url to the YAML file you want to remove entities for from the catalog
18 |
19 | steps:
20 | - id: location
21 | name: Get Root Location
22 | action: http:backstage:request
23 | input:
24 | method: 'GET'
25 | path: '/catalog/entities?filter=spec.target=${{ parameters["catalog-info-url"] | replace("/tree/", "/blob/") }}&filter=metadata.annotations.backstage.io/managed-by-location=url:${{ parameters["catalog-info-url"] | replace("/blob/", "/tree/") }}&fields=metadata.uid,metadata.name'
26 | - id: parse
27 | name: Parse entities response
28 | if: ${{ steps.location.output.code === 200 }}
29 | action: roadiehq:utils:jsonata
30 | input:
31 | data: ${{ steps.location.output.body }}
32 | expression: '$.metadata.uid'
33 | - id: parseNames
34 | name: Parse entity names
35 | if: ${{ steps.location.output.code === 200 }}
36 | action: roadiehq:utils:jsonata
37 | input:
38 | data: ${{ steps.location.output.body }}
39 | expression: '$.metadata.name'
40 | - id: log-to-delete
41 | action: debug:log
42 | if: ${{ steps.location.output.code === 200 }}
43 | input:
44 | message: 'Deleting the following entities: ${{ steps.parseNames.output.result | string }}'
45 | - id: delete-all
46 | if: ${{ steps.parse.output.result is not string }}
47 | name: Delete entities
48 | each: ${{ steps.parse.output.result }}
49 | action: http:backstage:request
50 | input:
51 | method: 'DELETE'
52 | path: '/catalog/entities/by-uid/${{ each.value }}'
53 | - id: delete-one
54 | if: ${{ steps.parse.output.result is string }}
55 | name: Delete entity
56 | action: http:backstage:request
57 | input:
58 | method: 'DELETE'
59 | path: '/catalog/entities/by-uid/${{ steps.parse.output.result }}'
60 | - id: clean-catalog
61 | name: Clean
62 | action: http:backstage:request
63 | input:
64 | method: 'POST'
65 | path: '/catalog-extensions/refresh-state/garbage-collection'
66 | continueOnBadResponse: true
67 | - id: log-result
68 | action: debug:log
69 | input:
70 | message: 'Deleted the following entities for YAML file ${{ parameters["catalog-info-url"] }} with names: ${{ steps.parseNames.output.result | string }}'
71 |
72 |
73 | output:
74 | deletedEntityNames: ${{ steps.parseNames.output.result | string }}
--------------------------------------------------------------------------------
/scaffolder-templates/delete-tenant/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: delete-tenant
5 | title: Delete tenant
6 | description: Send an API call to the tenant manager to delete a tenant.
7 | tags:
8 | - Roadie
9 |
10 | spec:
11 | owner: user:ianlink
12 | type: Tenant
13 | parameters:
14 | - title: Provide some simple information
15 | required:
16 | - tenant_name
17 | - tenant_email_domain
18 | - tenant_environment
19 | - s3_emptied
20 | - alarm_removed
21 | properties:
22 | tenant_name:
23 | title: Name
24 | type: string
25 | description: No special chars, numbers as the first char, or dashes as the first or last char.
26 | ui:autofocus: true
27 | tenant_email_domain:
28 | title: Email domain
29 | type: string
30 | description: The email domain of users who will be allowed to access the tenant.S
31 | tenant_environment:
32 | title: Environment
33 | type: string
34 | default: dev
35 | enum: ['dev', 'prod']
36 | s3_emptied:
37 | title: Have you emptied the tenants S3 Bucket?
38 | type: boolean
39 | ui:widget: radio
40 | alarm_removed:
41 | title: Have you removed the pagerduty alert from roadie-infrastructure?
42 | type: boolean
43 | ui:widget: radio
44 |
45 | steps:
46 | - id: deleteDevTenant
47 | name: Delete development tenant
48 | if: ${{ parameters.tenant_environment === 'dev' and parameters.s3_emptied and parameters.alarm_removed }}
49 | action: http:backstage:request
50 | input:
51 | method: 'DELETE'
52 | path: proxy/tenant-manager-dev/api/tenant
53 | body: |
54 | {
55 | "tenantName": "${{ parameters.tenant_name }}",
56 | "tenantEmailDomain": "${{ parameters.tenant_email_domain }}",
57 | "tenantEnvironment": "dev",
58 | "skipFailures": false
59 | }
60 |
61 | - id: deleteProdTenant
62 | name: Delete production tenant
63 | if: ${{ parameters.tenant_environment === 'prod' and parameters.s3_emptied and parameters.alarm_removed }}
64 | action: http:backstage:request
65 | input:
66 | method: 'DELETE'
67 | path: proxy/tenant-manager/api/tenant
68 | body: |
69 | {
70 | "tenantName": "${{ parameters.tenant_name }}",
71 | "tenantEmailDomain": "${{ parameters.tenant_email_domain }}",
72 | "tenantEnvironment": "prod",
73 | "skipFailures": false
74 | }
75 |
76 | - id: notify-tenant-deletion
77 | name: Notify tenant deletion
78 | if: ${{ parameters.s3_emptied and parameters.alarm_removed }}
79 | action: 'http:backstage:request'
80 | input:
81 | method: 'POST'
82 | header:
83 | - Content-type: application/json
84 | path: /proxy/tenant-deletion-notification
85 | body: |
86 | {
87 | 'blocks': [
88 | {
89 | 'type': 'section',
90 | 'text': {
91 | 'type': 'mrkdwn',
92 | 'text': '${{ user.entity.metadata.name }} has deleted tenant ${{ parameters.tenant_name }}.'
93 | }
94 | }
95 | ]
96 | }
97 |
98 | output:
99 | resp: ${{ steps.deleteDevTenant.output.body }} ${{ steps.deleteProdTenant.output.body }} ${{ steps.logAction.output.body }}
100 |
--------------------------------------------------------------------------------
/scaffolder-templates/github-pages-site/README.md:
--------------------------------------------------------------------------------
1 | ## GitHub Pages Website
2 |
3 | This scaffolder template will perform the following steps
4 |
5 | 1. Create a new GitHub repository with an `index.html` file in it.
6 | 2. Modify the content of the `index.html` file based on the website name the user provides when they run the scaffolder.
7 | 3. Make a HTTP request to the GitHub API to publish the `index.html` via GitHub pages.
8 |
9 | ## Pre-requisites for use outside of Roadie
10 |
11 | If you are running this software template in Roadie, you will need to set a secret GITHUB_TOKEN so that the github proxy can authenticate against GitHub. If you are running a vanilla backstage you will need to create a new proxy congfiguration like the following:
12 |
13 | ```
14 | proxy:
15 | '/github/api':
16 | target: https://api.github.com
17 | headers:
18 | Authorization: 'token ${GITHUB_TOKEN}'
19 | ```
20 |
--------------------------------------------------------------------------------
/scaffolder-templates/github-pages-site/skeleton/.github/workflows/test.yaml:
--------------------------------------------------------------------------------
1 | name: Test
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | pull_request:
7 | branches: [ main ]
8 |
9 | jobs:
10 | build_and_test:
11 | runs-on: ubuntu-latest
12 |
13 | env:
14 | CI: true
15 | NODE_ENV: test
16 |
17 | steps:
18 | - name: Log node version
19 | run: node --version
20 |
21 | - uses: actions/checkout@v2
22 | with:
23 | fetch-depth: '0'
24 |
25 | - name: Install dependencies
26 | run: yarn install --frozen-lockfile
27 |
28 | - name: Cypress run
29 | uses: cypress-io/github-action@v2
30 | with:
31 | start: yarn start --port 8001
32 |
33 | - name: Upload screenshots
34 | uses: actions/upload-artifact@v1
35 | if: failure()
36 | with:
37 | name: cypress-screenshots
38 | path: cypress/screenshots
39 |
40 | - name: Upload videos
41 | uses: actions/upload-artifact@v1
42 | if: always()
43 | with:
44 | name: cypress-videos
45 | path: cypress/videos
46 |
47 |
--------------------------------------------------------------------------------
/scaffolder-templates/github-pages-site/skeleton/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | .parcel-cache
4 |
--------------------------------------------------------------------------------
/scaffolder-templates/github-pages-site/skeleton/README.md:
--------------------------------------------------------------------------------
1 | # ${{ values.website_name | title }}
2 |
3 | This is a website wihch is published on GitHub pages.
4 |
5 | ## Getting started
6 |
7 | ```bash
8 | yarn install
9 | yarn start
10 | ```
11 |
12 | Now open up: http://localhost:1234 in your browser.
13 |
14 | ## Testing
15 |
16 | End to end tests can be written with Cypress.io.
17 |
18 | They are run locally like this:
19 |
20 | ```bash
21 | yarn test
22 | ```
23 |
24 | ## Docs
25 |
26 | Docs can be found in the `docs` directory. They are written in markdown.
27 |
--------------------------------------------------------------------------------
/scaffolder-templates/github-pages-site/skeleton/catalog-info.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: backstage.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: ${{ values.repo_name }}
5 | title: ${{ values.website_name | title }}
6 | description: A static HTML website. Just like the good old days.
7 | links:
8 | - url: https://${{ values.repo_owner}}.github.io/${{ values.repo_name }}/
9 | title: Live website
10 | annotations:
11 | github.com/project-slug: ${{ values.repo_owner }}/${{ values.repo_name }}
12 | spec:
13 | type: website
14 | owner: user:dtuite
15 | lifecycle: experimental
16 |
--------------------------------------------------------------------------------
/scaffolder-templates/github-pages-site/skeleton/cypress.json:
--------------------------------------------------------------------------------
1 | {
2 | "baseUrl": "http://localhost:8001"
3 | }
4 |
--------------------------------------------------------------------------------
/scaffolder-templates/github-pages-site/skeleton/cypress/integration/sample_spec.js:
--------------------------------------------------------------------------------
1 | describe('The website', () => {
2 | it('is accessible', () => {
3 | cy.visit('');
4 | cy.contains('Welcome to ${{ values.website_name }}').click();
5 | })
6 | })
7 |
--------------------------------------------------------------------------------
/scaffolder-templates/github-pages-site/skeleton/cypress/plugins/index.js:
--------------------------------------------------------------------------------
1 | ///
2 | // ***********************************************************
3 | // This example plugins/index.js can be used to load plugins
4 | //
5 | // You can change the location of this file or turn off loading
6 | // the plugins file with the 'pluginsFile' configuration option.
7 | //
8 | // You can read more here:
9 | // https://on.cypress.io/plugins-guide
10 | // ***********************************************************
11 |
12 | // This function is called when a project is opened or re-opened (e.g. due to
13 | // the project's config changing)
14 |
15 | /**
16 | * @type {Cypress.PluginConfig}
17 | */
18 | // eslint-disable-next-line no-unused-vars
19 | module.exports = (on, config) => {
20 | // `on` is used to hook into various events Cypress emits
21 | // `config` is the resolved Cypress config
22 | }
23 |
--------------------------------------------------------------------------------
/scaffolder-templates/github-pages-site/skeleton/cypress/support/commands.js:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 | //
11 | //
12 | // -- This is a parent command --
13 | // Cypress.Commands.add('login', (email, password) => { ... })
14 | //
15 | //
16 | // -- This is a child command --
17 | // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
18 | //
19 | //
20 | // -- This is a dual command --
21 | // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
22 | //
23 | //
24 | // -- This will overwrite an existing command --
25 | // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
26 |
--------------------------------------------------------------------------------
/scaffolder-templates/github-pages-site/skeleton/cypress/support/index.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/index.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands'
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
21 |
--------------------------------------------------------------------------------
/scaffolder-templates/github-pages-site/skeleton/docs/index.md:
--------------------------------------------------------------------------------
1 | These are the docs for the ${{ values.website_name | title }} website.
2 |
3 | This is where you would put information about getting started with the website, maybe how
4 | to authenticate etc.
5 |
6 |
7 | It's just normal markdown. For example, you can write code blocks here like this:
8 |
9 | ```js
10 |
11 | const myFunction = () => {
12 | return 'Hello World';
13 | };
14 | ```
15 |
16 | When you add a new docs file, be sure to update the `mkdocs.yml` file in this repo to
17 | display the file in the sidebar.
18 |
--------------------------------------------------------------------------------
/scaffolder-templates/github-pages-site/skeleton/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ${{ values.website_name | title }}
7 |
8 |
9 | Welcome to ${{ values.website_name }}
10 | This website was created by following the Backstage scaffolder tutorial published by Roadie
11 |
12 |
13 |
--------------------------------------------------------------------------------
/scaffolder-templates/github-pages-site/skeleton/mkdocs.yml:
--------------------------------------------------------------------------------
1 | site_name: ${{ values.website_name | title }}
2 |
3 | nav:
4 | - Home: index.md
5 |
6 | plugins:
7 | - monorepo
8 | - techdocs-core
9 |
--------------------------------------------------------------------------------
/scaffolder-templates/github-pages-site/skeleton/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "${{ values.repo_name }}",
3 | "version": "0.0.1",
4 | "description": "A static HTML website. Just like the good old days.",
5 | "main": "index.js",
6 | "repository": "https://github.com/${{ values.repo_owner }}/${{ values.repo_name }}",
7 | "author": "${{ values.repo_owner }}",
8 | "license": "MIT",
9 | "private": true,
10 | "devDependencies": {
11 | "cypress": "^9.4.1",
12 | "parcel": "^2.2.1"
13 | },
14 | "scripts": {
15 | "start": "parcel index.html",
16 | "test": "cypress open"
17 | }
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/scaffolder-templates/github-pages-site/skeleton/package.json.tpl:
--------------------------------------------------------------------------------
1 | {
2 | "name": "github-pages-site-skeleton",
3 | "version": "0.0.1",
4 | "description": "A skeleton for creating a GitHub pages site.",
5 | "main": "index.js",
6 | "repository": "https://github.com/roadiehq/software-templates",
7 | "author": "David Tuite",
8 | "license": "MIT",
9 | "private": true,
10 | "devDependencies": {
11 | "cypress": "^9.4.1",
12 | "parcel": "^2.2.1"
13 | },
14 | "scripts": {
15 | "start": "parcel index.html",
16 | "test": "cypress open"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/scaffolder-templates/github-pages-site/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: github-pages-website
5 | title: GitHub Pages Website
6 | description: Create a static HTML website and publish it via GitHub pages.
7 | annotations:
8 | roadie.io/certified: "true"
9 |
10 | spec:
11 | owner: user:dtuite
12 | type: website
13 | parameters:
14 | - title: Provide some simple information
15 | required:
16 | - website_name
17 | properties:
18 | website_name:
19 | title: Website name
20 | type: string
21 | name: website-name
22 | description: This will be displayed prominently on your website and in the title tag.
23 | escalation_policy:
24 | title: PagerDuty escalation policy
25 | type: string
26 | ui:field: SelectFieldFromApi
27 | ui:options:
28 | path: "proxy/pagerduty/escalation_policies"
29 | arraySelector: 'escalation_policies'
30 | valueSelector: 'id'
31 | labelSelector: 'summary'
32 | description: 'Choose a Pagerduty Escalation policy to notify when the page goes down'
33 |
34 |
35 | - title: Choose a Source Control Management tool to store your new website in.
36 | required:
37 | - repoUrl
38 | properties:
39 | repoUrl:
40 | title: Repository Location
41 | type: string
42 | ui:field: RepoUrlPicker
43 | ui:options:
44 | allowedHosts:
45 | - github.com
46 |
47 |
48 | steps:
49 | - id: template
50 | name: Fetch Skeleton + Template
51 | action: fetch:template
52 | input:
53 | url: ./skeleton
54 | values:
55 | website_name: ${{ parameters.website_name }}
56 | repo_name: ${{ (parameters.repoUrl | parseRepoUrl)["repo"] }}
57 | repo_owner: ${{ (parameters.repoUrl | parseRepoUrl)["owner"] }}
58 |
59 | - id: publishToGitHub
60 | name: Publish to GitHub
61 | action: publish:github
62 | input:
63 | allowedHosts: ['github.com']
64 | description: 'A static HTML website. Just like the good old days.'
65 | repoUrl: ${{ parameters.repoUrl }}
66 | defaultBranch: main
67 | repoVisibility: public
68 |
69 | - id: publishToWeb
70 | name: Publish to web with GitHub Pages
71 | action: http:backstage:request
72 | input:
73 | method: 'POST'
74 | path: /proxy/mygithub/api/repos/${{ (parameters.repoUrl | parseRepoUrl)["owner"] }}/${{ (parameters.repoUrl | parseRepoUrl)["repo"] }}/pages
75 | headers:
76 | content-type: 'application/json'
77 | body:
78 | source:
79 | branch: main
80 | path: '/'
81 |
82 | - id: registerInBetterUptime
83 | name: Register in Better Uptime
84 | action: http:backstage:request
85 | input:
86 | method: 'POST'
87 | path: /proxy/betteruptime/monitors
88 | headers:
89 | content-type: 'application/json'
90 | body:
91 | url: https://${{ (parameters.repoUrl | parseRepoUrl)["owner"] }}.github.io/${{ (parameters.repoUrl | parseRepoUrl)["repo"] }}/
92 |
93 | output:
94 | remoteUrl: ${{ steps.publishToGitHub.output.remoteUrl }}
95 |
--------------------------------------------------------------------------------
/scaffolder-templates/oneof-example/oneof-example.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: oneof-example
5 | description: An advanced template
6 | spec:
7 | type: service
8 | owner: user:guest
9 | parameters:
10 | - title: Select an Environment
11 | type: object
12 | oneOf:
13 | - properties:
14 | lorem:
15 | type: string
16 | required:
17 | - lorem
18 | title: "Lorem"
19 | - properties:
20 | ipsum:
21 | type: string
22 | required:
23 | - ipsum
24 | title: "Ipsum"
25 |
26 | steps:
27 | - id: log
28 | name: Log
29 | action: debug:log
30 | input:
31 | message: ${{ parameters.lorem }} ${{ parameters.ipsum }}
32 |
--------------------------------------------------------------------------------
/scaffolder-templates/pr-with-catalog-entry/skeleton/catalog-info.yaml.njk:
--------------------------------------------------------------------------------
1 | apiVersion: backstage.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: ${{ values.name }}
5 | title: ${{ values.name | replace(" ", "-") | lower}}
6 | description: ${{ values.description }}
7 | annotations:
8 | github.com/project-slug: ${{ values.repoOrg }}/${{ values.repoSlug }}
9 | {%if values.argoAppName %}argocd/app-name: ${{values.argoAppName}} {% endif %}
10 | {%if values.pagerdutyServiceId %}pagerduty.com/service-id: ${{values.pagerdutyServiceId}} {% endif %}
11 | spec:
12 | type: ${{ values.type }}
13 | owner: ${{ values.owner }}
14 | lifecycle: ${{ values.lifecycle }}
15 |
--------------------------------------------------------------------------------
/scaffolder-templates/pr-with-catalog-entry/template.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: scaffolder.backstage.io/v1beta3
3 | kind: Template
4 | metadata:
5 | name: open-pr-with-catalog-entry
6 | title: Onboard your service to Backstage
7 | description: Create a new PR with your service's details.
8 | spec:
9 | owner: group:roadiehq/engineering
10 | type: service
11 |
12 | parameters:
13 | - title: What is your service about?
14 | required:
15 | - name
16 | - description
17 | - type
18 | - lifecycle
19 | properties:
20 | name:
21 | title: Service name
22 | type: string
23 | description: Human readable name. We'll generate a dasherized version from it.
24 |
25 | description:
26 | title: Service description
27 | type: string
28 |
29 | type:
30 | title: Service type
31 | type: string
32 | default: service
33 | enum: ['service', 'website', 'test', 'documentation', 'library']
34 |
35 | lifecycle:
36 | title: Service lifecycle
37 | type: string
38 | default: production
39 | enum: ['production', 'experimental', 'deprecated']
40 |
41 | owner:
42 | title: Service Owner
43 | type: string
44 | description: Owner of the component
45 | ui:field: OwnerPicker
46 | ui:options:
47 | catalogFilter:
48 | kind: Group
49 |
50 | - title: Where is your codebase?
51 | required:
52 | - repoSlug
53 | properties:
54 | repoHost:
55 | type: string
56 | default: github.com
57 | ui:widget: hidden
58 | repoOrg:
59 | type: string
60 | default: roadiehq # Change this to match the name of your GitHub org
61 | ui:widget: hidden
62 | repoSlug:
63 | title: Repository name
64 | type: string
65 |
66 | - title: Integrations (optional)
67 | properties:
68 | argoAppName:
69 | title: Argo CD App Name
70 | type: string
71 | pagerdutyServiceId:
72 | title: PagerDuty service ID
73 | type: string
74 |
75 | steps:
76 | - id: fetchTemplate
77 | action: fetch:template
78 | input:
79 | url: ./skeleton
80 | templateFileExtension: .njk
81 | values:
82 | name: ${{ parameters.name }}
83 | description: ${{ parameters.description }}
84 | owner: ${{ parameters.owner }}
85 | type: ${{ parameters.type }}
86 | repoOrg: ${{ parameters.repoOrg }}
87 | repoSlug: ${{ parameters.repoSlug }}
88 | argoAppName: ${{ parameters.argoAppName }}
89 | pagerdutyServiceId: ${{ parameters.pagerdutyServiceId }}
90 | lifecycle: ${{ parameters.lifecycle }}
91 |
92 | - id: createPullRequest
93 | name: createPullRequest
94 | action: publish:github:pull-request
95 | input:
96 | repoUrl: ${{ parameters.repoHost }}?owner=${{ parameters.repoOrg }}&repo=${{ parameters.repoSlug }}
97 | branchName: onboard-to-catalog-${{ '' | now }}
98 | title: Onboard service to Catalog
99 | description: This PR adds a metadata file about this service so that it can be registered in our software catalog.
100 |
101 | output:
102 | links:
103 | - title: View the pull request on GitHub
104 | icon: github
105 | url: ${{ steps['createPullRequest'].output.remoteUrl }}
106 |
--------------------------------------------------------------------------------
/scaffolder-templates/pull-request-test/skeleton/new-change.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: image.toolkit.fluxcd.io/v1beta1
3 | kind: ImageRepository
4 | metadata:
5 | name: tenant-backstage
6 | namespace: flux-system
7 | spec:
8 | image: account_id.dkr.ecr.region.amazonaws.com/${{ values.tenant_name }}-backstage
9 | interval: 1m0s
10 | secretRef:
11 | name: ecr-secret
12 | ---
13 | apiVersion: image.toolkit.fluxcd.io/v1beta1
14 | kind: ImagePolicy
15 | metadata:
16 | name: tenant-backstage
17 | namespace: flux-system
18 | spec:
19 | imageRepositoryRef:
20 | name: ${{ values.tenant_name }}-backstage
21 | filterTags:
22 | pattern: ".*-(?P[0-9T]*)$"
23 | extract: "$date"
24 | policy:
25 | alphabetical:
26 | order: asc
27 |
--------------------------------------------------------------------------------
/scaffolder-templates/pull-request-test/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: open-pull-request
5 | title: Open pull request
6 | description: Open a pull request against an IaaC repo.
7 |
8 | spec:
9 | owner: user:dtuite
10 | type: none
11 | parameters:
12 | - title: Provide some simple information
13 | required:
14 | - tenant_name
15 | properties:
16 | tenant_name:
17 | title: Name
18 | type: string
19 | description: No special chars, numbers as the first char, or dashes as the first or last char.
20 | ui:autofocus: true
21 |
22 | steps:
23 |
24 | - id: fetchTemplate
25 | name: Fetch diff
26 | action: fetch:template
27 | input:
28 | url: ./skeleton
29 | values:
30 | tenant_name: ${{ parameters.tenant_name }}
31 |
32 | - id: openPullRequest
33 | name: Open pull request
34 | action: publish:github:pull-request
35 | input:
36 | repoUrl: 'github.com?repo=demo-iaac-repo&owner=RoadieHQ'
37 | branchName: mybranch-124
38 | title: Make a change to state
39 | description: 'This is an automated PR'
40 |
41 | - id: log-message
42 | name: Log Message
43 | action: debug:log
44 | input:
45 | message: 'RemoteURL: ${{ steps.openPullRequest.output.remoteUrl }}, ${{ steps.openPullRequest.output.pullRequestNumber }}!'
46 |
47 | output:
48 | resp: ${{ steps.openPullRequest.output.remoteUrl }}
49 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-agent-entity-provider/skeleton/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:18-alpine
2 |
3 | ARG TOKEN=example-broker-token
4 |
5 | ENV BROKER_TOKEN $TOKEN
6 |
7 | WORKDIR /app
8 |
9 | COPY yarn.lock package.json ./
10 | COPY src ./src
11 | COPY config ./config
12 |
13 | RUN apk add --no-cache tini
14 |
15 | RUN cd /app
16 |
17 | RUN yarn install --frozen-lockfile
18 |
19 | ENTRYPOINT ["/sbin/tini", "--"]
20 | CMD ["node", "src/index"]
21 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-agent-entity-provider/skeleton/README.md:
--------------------------------------------------------------------------------
1 | # Roadie Agent Entity Provider
2 |
3 | See Roadie Agent documentation in https://github.com/RoadieHQ/roadie-agent.
4 |
5 | ## Usage
6 |
7 | Configure your Roadie instance to allow traffic from the IP address this Agent service is running.
8 | Enable and register a Roadie Agent `entity-provider` connection type in Roadie. The token used by this agent service should be configured as environment variable `BROKER_TOKEN`, the name of the Agent provider is `${{ values.agent_name }}`.
9 |
10 | Modify the example entity handler in `src/myEntityHandler.js` to provide entities to your liking.
11 |
12 | ## Running
13 |
14 | Locally:
15 | * `yarn`
16 | * `yarn start`
17 |
18 | ## As a container
19 |
20 | Build the container:
21 | `docker build . --tag my-agent`
22 |
23 | Run the container:
24 | `docker run --env BROKER_TOKEN=my-broker-token my-agent `
25 |
26 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-agent-entity-provider/skeleton/config/accept.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": [
3 | {
4 | "method": "GET",
5 | "path": "/agent-provider/*",
6 | "origin": "http://localhost:7044"
7 | }
8 | ],
9 | "public": [
10 | {
11 | "method": "any",
12 | "path": "/*"
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-agent-entity-provider/skeleton/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "roadie-agent-entity-provider",
3 | "version": "1.0.0",
4 | "description": "A Roadie Agent Entity Provider.",
5 | "main": "index.js",
6 | "repository": "https://github.com/${{ values.repo_owner }}/${{ values.repo_name }}",
7 | "author": "${{ values.repo_owner }}",
8 | "license": "UNLICENSED",
9 | "type": "module",
10 | "scripts": {
11 | "start": "node src/index.js"
12 | },
13 | "dependencies": {
14 | "@roadiehq/roadie-agent": "^1.1.3"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-agent-entity-provider/skeleton/src/index.js:
--------------------------------------------------------------------------------
1 | import { RoadieAgent, createRoadieAgentEntityProvider } from '@roadiehq/roadie-agent';
2 | import { myEntityHandler } from './myEntityHandler.js';
3 |
4 | RoadieAgent.fromConfig({
5 | server: 'https://${{ values.tenant }}.broker.roadie.so',
6 | accept: `${process.cwd()}/config/accept.json`,
7 | identifier: process.env.BROKER_TOKEN
8 | })
9 | .addEntityProvider(createRoadieAgentEntityProvider({
10 | handler: myEntityHandler,
11 | name: '${{ values.agent_name }}'
12 | }))
13 | .start();
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-agent-entity-provider/skeleton/src/myEntityHandler.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A fake payload example
3 | * Replace this with your own implementation to retrieve actual entity information from within your infrastructure
4 | */
5 | const fakePayload = {
6 | type: 'full',
7 | entities: [
8 | {
9 | entity: {
10 | metadata: {
11 | namespace: 'default',
12 | annotations: {},
13 | name: 'locally-provided-group-entity',
14 | title: 'Locally provided entity',
15 | description:
16 | 'Entity that is provided via Broker connection from an entity provider running on a separate machine',
17 | },
18 | apiVersion: 'backstage.io/v1alpha1',
19 | kind: 'Group',
20 | spec: {
21 | type: 'team',
22 | profile: {
23 | displayName: 'Locally provided group entity',
24 | email: 'team-alpha@example.com',
25 | picture:
26 | 'https://avatars.dicebear.com/api/identicon/team-alpha@example.com.svg?background=%23fff&margin=25',
27 | },
28 | children: [],
29 | },
30 | },
31 | },
32 | ],
33 | };
34 |
35 | export const myEntityHandler = async (emit) => {
36 | await emit(fakePayload);
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-agent-entity-provider/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: create-roadie-agent-entity-provider
5 | title: Create Roadie Agent Entity Provider
6 | description: Create a Roadie Agent service repository to provide entities securely from your infrastructure
7 |
8 | spec:
9 | owner: info@roadie.io
10 | type: service
11 | parameters:
12 | - title: Provide some simple information
13 | required:
14 | - agent_name
15 | properties:
16 | agent_name:
17 | title: Name
18 | type: string
19 | description: Unique name of the Roadie Agent Entity Provider.
20 |
21 | - title: Choose a Source Control Management tool to store your Roadie Agent Service in.
22 | required:
23 | - repoUrl
24 | properties:
25 | repoUrl:
26 | title: Repository Location
27 | type: string
28 | ui:field: RepoUrlPicker
29 | ui:options:
30 | allowedHosts:
31 | - github.com
32 | steps:
33 | - id: template
34 | name: Fetch Skeleton + Template
35 | action: fetch:template
36 | input:
37 | url: ./skeleton
38 | values:
39 | repo_name: ${{ (parameters.repoUrl | parseRepoUrl)["repo"] }}
40 | repo_owner: ${{ (parameters.repoUrl | parseRepoUrl)["owner"] }}
41 | tenant: ${{ roadie.tenantName }}
42 | agent_name: ${{ parameters.agent_name }}
43 |
44 | - id: publish
45 | name: Publish
46 | action: publish:github
47 | input:
48 | allowedHosts: ['github.com']
49 | description: 'This is ${{ parameters.agent_name }}'
50 | repoUrl: ${{ parameters.repoUrl }}
51 | defaultBranch: main
52 |
53 | output:
54 | remoteUrl: ${{ steps.publish.output.remoteUrl }}
55 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-agent-scaffolder-action/skeleton/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:18-alpine
2 |
3 | ARG TOKEN=${{ values.agent_name }}
4 |
5 | ENV BROKER_TOKEN $TOKEN
6 |
7 | WORKDIR /app
8 |
9 | COPY yarn.lock package.json ./
10 | COPY src ./src
11 | COPY config ./config
12 |
13 | RUN apk add --no-cache tini
14 |
15 | RUN cd /app
16 |
17 | RUN yarn install --frozen-lockfile
18 |
19 | ENTRYPOINT ["/sbin/tini", "--"]
20 | CMD ["node", "src/index"]
21 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-agent-scaffolder-action/skeleton/README.md:
--------------------------------------------------------------------------------
1 | # Roadie Agent Scaffolder Action
2 |
3 | See Roadie Agent documentation in https://github.com/RoadieHQ/roadie-agent.
4 |
5 | ## Usage
6 |
7 | Configure your Roadie instance to allow traffic from the IP address this Agent service is running.
8 | Enable and register a Roadie Agent `scaffolder-action` connection type in Roadie. The token used by this agent service should be configured as environment variable `BROKER_TOKEN`, the name of the Agent action is `${{ values.agent_name }}`.
9 |
10 | Modify the example scaffolder action handler in `src/myScaffolderActionHandler.js` to run the custom scaffolder code.
11 |
12 | ## Running
13 |
14 | Locally:
15 | * `yarn`
16 | * `yarn start`
17 |
18 | ## As a container
19 |
20 | Build the container:
21 | `docker build . --tag my-agent`
22 |
23 | Run the container:
24 | `docker run --env BROKER_TOKEN=my-broker-token my-agent `
25 |
26 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-agent-scaffolder-action/skeleton/config/accept.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": [
3 | {
4 | "method": "POST",
5 | "path": "/scaffolder-action/*",
6 | "origin": "http://localhost:7044"
7 | }
8 | ],
9 | "public": [
10 | {
11 | "method": "any",
12 | "path": "/*"
13 | }
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-agent-scaffolder-action/skeleton/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "roadie-agent-scaffolder-action",
3 | "version": "1.0.0",
4 | "description": "A Roadie Agent Scaffolder Action.",
5 | "main": "index.js",
6 | "repository": "https://github.com/${{ values.repo_owner }}/${{ values.repo_name }}",
7 | "author": "${{ values.repo_owner }}",
8 | "license": "UNLICENSED",
9 | "type": "module",
10 | "scripts": {
11 | "start": "node src/index.js"
12 | },
13 | "dependencies": {
14 | "@roadiehq/roadie-agent": "^1.1.3"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-agent-scaffolder-action/skeleton/src/helloWorldScaffolderActionHandler.js:
--------------------------------------------------------------------------------
1 | import { writeFileSync } from "fs";
2 |
3 | export const helloWorldScaffolderActionHandler = async (context) => {
4 | try {
5 | const greeting = `Hello, ${context.payload.body.name || 'world!'}`
6 | await context.log(greeting);
7 | writeFileSync(`${context.workspacePath}/greeting.txt`, greeting);
8 | } catch (e) {
9 | console.log('An error occurred');
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-agent-scaffolder-action/skeleton/src/index.js:
--------------------------------------------------------------------------------
1 | import { RoadieAgent, createRoadieAgentScaffolderAction } from '@roadiehq/roadie-agent';
2 | import { helloWorldScaffolderActionHandler } from './helloWorldScaffolderActionHandler.js';
3 |
4 | RoadieAgent.fromConfig({
5 | server: 'https://${{ values.tenant }}.broker.roadie.so',
6 | accept: `${process.cwd()}/config/accept.json`,
7 | identifier: process.env.BROKER_TOKEN
8 | })
9 | .addScaffolderAction(createRoadieAgentScaffolderAction({
10 | name: 'hello-world',
11 | handler: helloWorldScaffolderActionHandler
12 | }))
13 | .start();
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-agent-scaffolder-action/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: create-roadie-agent-scaffolder-action-mono-repo
5 | title: Create Roadie Agent Scaffolder Action Repository
6 | description: Create a Roadie Agent service repository to execute a scaffolder action from your infrastructure. You can run this once to create the repo, and then add multiple scaffolder actions in the created repo.
7 |
8 | spec:
9 | owner: info@roadie.io
10 | type: service
11 | parameters:
12 | - title: Provide some simple information
13 | required:
14 | - agent_name
15 | properties:
16 | agent_name:
17 | title: Name
18 | type: string
19 | description: Unique name of the Roadie Agent Scaffolder Action repository.
20 |
21 | - title: Choose a Source Control Management tool to store your Roadie Agent Service in.
22 | required:
23 | - repoUrl
24 | properties:
25 | repoUrl:
26 | title: Repository Location
27 | type: string
28 | ui:field: RepoUrlPicker
29 | ui:options:
30 | allowedHosts:
31 | - github.com
32 | steps:
33 | - id: template
34 | name: Fetch Skeleton + Template
35 | action: fetch:template
36 | input:
37 | url: ./skeleton
38 | values:
39 | repo_name: ${{ (parameters.repoUrl | parseRepoUrl)["repo"] }}
40 | repo_owner: ${{ (parameters.repoUrl | parseRepoUrl)["owner"] }}
41 | tenant: ${{ roadie.tenantName }}
42 | agent_name: ${{ parameters.agent_name }}
43 |
44 | - id: publish
45 | name: Publish
46 | action: publish:github
47 | input:
48 | allowedHosts: ['github.com']
49 | description: 'This is ${{ parameters.agent_name }}'
50 | repoUrl: ${{ parameters.repoUrl }}
51 | defaultBranch: main
52 |
53 | output:
54 | remoteUrl: ${{ steps.publish.output.remoteUrl }}
55 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
2 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/.npmrc:
--------------------------------------------------------------------------------
1 | legacy-peer-deps=true
2 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/README.md:
--------------------------------------------------------------------------------
1 | # Roadie Plugins monorepo
2 |
3 | Welcome to Roadie plugins monorepo!
4 |
5 | _This plugin was created through a scaffolder template_
6 |
7 | ## Getting started
8 |
9 | This is a TypeScript monorepo repository containing a place to hold and develop Roadie plugins.
10 |
11 | ### Repository structure
12 |
13 | The root level contains configuration files to hold the structure of the monorepo and a top level package.json file.
14 |
15 | The folder `packages` hosts the actual plugins and code files related to them in individual folders. Each plugin has their own `package.json` configuration pre-filled with some useful scripts to develop, build and deploy Roadie plugins.
16 |
17 | ### Installing
18 |
19 | This repository needs `node.js` (> 18.x) and `NPM` installed.
20 |
21 | To install needed dependencies, run:
22 | `npm i -f` or `npm install --force`
23 |
24 | ### Running and developing plugins
25 |
26 | Plugins within the repository can all be run from within the root folder.
27 |
28 | Example commands, if your plugin is named `${{ values.plugin_name }}`
29 |
30 | #### Run in development mode
31 |
32 | This will build the plugin code and start a webserver to host the generated Roadie compatible plugin assets.
33 |
34 | `npm run develop --workspace=${{ values.plugin_name }}`
35 |
36 | #### Run in development mode, with a file watcher
37 |
38 | This will build the plugin code and start a webserver while listening to file changes within the plugin folder. Each change to a file restarts the webserver, allowing for a faster development workflow
39 |
40 | `npm run develop:watch --workspace=${{ values.plugin_name }}`
41 |
42 |
43 | #### Bundling a production build of a plugin
44 |
45 | This will build your wanted plugin and output the generated Roadie compatible assets to the defined folder, so they can be uploaded to a static hosting site.
46 |
47 | ` npm run build --workspace=${{ values.plugin_name }} --host https://my-static-hosting.com/${{ values.plugin_name }}`
48 |
49 |
50 | #### Bundling a production build of a plugin and uploading it to AWS S3
51 |
52 | This will build your wanted plugin and output the generated Roadie compatible assets to the defined folder, and uploads the generated Roadie compatible assets to AWS S3. The command uses environment variables `S3_BUCKET_NAME` & `S3_BUCKET_PREFIX` to determine the S3 bucket and path. Normal AWS credential chain is used to determine AWS credentials.
53 |
54 | ` npm run build:upload:awsS3 --workspace=${{ values.plugin_name }} --host https://static-assets.roadie.so/`
55 |
56 |
57 |
58 |
59 | > For more information, take a look at the package.json within the plugin folder and Roadie CLI documentation in https://www.npmjs.com/package/@roadiehq/roadie-cli
60 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "roadie-plugins",
3 | "version": "1.0.0",
4 | "description": "Roadie Plugins monorepo",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "help": "roadie"
9 | },
10 | "workspaces": ["plugins/*"],
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "@backstage/cli": "^0.22.8",
15 | "@backstage/core-components": "^0.13.2",
16 | "@backstage/plugin-catalog-react": "^1.7.0",
17 | "@material-ui/core": "^4.12.2",
18 | "@roadiehq/roadie-cli": "^1.1.1",
19 | "react": "^17.0.2",
20 | "react-dom": "^17.0.2"
21 | },
22 | "devDependencies": {
23 | "@aoberoi/chokidar-cli": "^2.0.0",
24 | "@spotify/prettier-config": "^14.0.0",
25 | "prettier": "^2.3.2",
26 | "ts-node": "^10.9.1"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
2 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/README.md:
--------------------------------------------------------------------------------
1 | # my-plugin
2 |
3 | Welcome to the ${{ values.plugin_name }} plugin!
4 |
5 | _This plugin was created through the Backstage CLI_
6 |
7 | ## Getting started
8 |
9 | To install needed dependencies, run:
10 | `npm i` or `npm install`
11 |
12 | ### Standalone development
13 |
14 | You can serve the plugin in isolation by running `npm start` in the plugin directory.
15 | This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads.
16 | It is only meant for local development, and the setup for it can be found inside the [/dev](dev) directory.
17 |
18 | ### Developing against Roadie instances
19 |
20 | Each command defined below will provide instructions on how to install the plugin to Roadie application.
21 |
22 | #### Run in development mode
23 |
24 | This will build the plugin code and start a webserver to host the generated Roadie compatible plugin assets.
25 |
26 | `npm run develop`
27 |
28 | #### Run in development mode, with a file watcher
29 |
30 | This will build the plugin code and start a webserver while listening to file changes within the plugin folder. Each change to a file restarts the webserver, allowing for a faster development workflow
31 |
32 | `npm run develop:watch`
33 |
34 |
35 | #### Bundling a production build of a plugin
36 |
37 | This will build your wanted plugin and output the generated Roadie compatible assets to the defined folder, so they can be uploaded to a static hosting site.
38 |
39 | ` npm run build --host https://my-static-hosting.com/${{ values.plugin_name }}`
40 |
41 |
42 | #### Bundling a production build of a plugin and uploading it to AWS S3
43 |
44 | This will build your wanted plugin and output the generated Roadie compatible assets to the defined folder, and uploads the generated Roadie compatible assets to AWS S3. The command uses environment variables `S3_BUCKET_NAME` & `S3_BUCKET_PREFIX` to determine the S3 bucket and path. Normal AWS credential chain is used to determine AWS credentials.
45 |
46 | ` npm run build:upload:s3 --host https://my-static-hosting.com/${{ values.plugin_name }}`
47 |
48 |
49 |
50 | > For more information, take a look at the package.json within the plugin folder and Roadie CLI documentation in https://www.npmjs.com/package/@roadiehq/roadie-cli
51 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/app-config.yaml:
--------------------------------------------------------------------------------
1 | app:
2 | baseUrl: http://localhost:3333
3 | backend:
4 | baseUrl: http://localhost:7777
5 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/dev/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { createDevApp } from "@backstage/dev-utils";
3 | import { myPluginPlugin, MyPluginPage } from "../src/plugin";
4 | import { EntityProvider } from "@backstage/plugin-catalog-react";
5 | import { Entity } from "@backstage/catalog-model";
6 |
7 | const entity = {
8 | apiVersion: "backstage.io/v1alpha1",
9 | kind: "Component",
10 | metadata: {
11 | name: 'awesome-test-entity-1',
12 | },
13 | } as Entity;
14 |
15 | createDevApp()
16 | .registerPlugin(myPluginPlugin)
17 | .addPage({
18 | element: (
19 |
20 |
21 |
22 | ),
23 | title: "Root Page",
24 | path: "/my-plugin",
25 | })
26 | .render();
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "${{ values.plugin_name }}",
3 | "version": "0.1.0",
4 | "main": "src/index.ts",
5 | "types": "src/index.ts",
6 | "license": "Apache-2.0",
7 | "private": true,
8 | "publishConfig": {
9 | "access": "public",
10 | "main": "dist/index.esm.js",
11 | "types": "dist/index.d.ts"
12 | },
13 | "backstage": {
14 | "role": "frontend-plugin"
15 | },
16 | "scripts": {
17 | "develop": "roadie plugin:dev -l $PWD/ --output $PWD/out --port 7046",
18 | "develop:watch": "chokidar \"./src/**\" -c \"npm run develop\" -d 1000 --initial",
19 | "build": "roadie plugin:build -l $PWD/ --output $PWD/out --host",
20 | "build:upload:awsS3": "roadie plugin:build --withUpload -l $PWD/ --output $PWD/out --host",
21 | "start": "backstage-cli package start",
22 | "lint": "backstage-cli package lint",
23 | "test": "backstage-cli package test"
24 | },
25 | "dependencies": {
26 | "@backstage/core-components": "^0.13.2",
27 | "@backstage/core-plugin-api": "^1.5.2",
28 | "@backstage/theme": "^0.4.0",
29 | "@material-ui/core": "^4.12.2",
30 | "@material-ui/icons": "^4.9.1",
31 | "@material-ui/lab": "4.0.0-alpha.61",
32 | "react-router-dom": "^7.1.5",
33 | "react-use": "~17.2.4"
34 | },
35 | "peerDependencies": {
36 | "react": "^16.13.1 || ^17.0.0"
37 | },
38 | "devDependencies": {
39 | "@aoberoi/chokidar-cli": "^2.0.0",
40 | "@backstage/cli": "^0.29.4",
41 | "@backstage/core-app-api": "^1.15.3",
42 | "@backstage/dev-utils": "^1.0.16",
43 | "@backstage/test-utils": "^1.7.3",
44 | "@roadiehq/roadie-cli": "^1.1.1",
45 | "@testing-library/jest-dom": "^5.10.1",
46 | "@testing-library/react": "^12.1.3",
47 | "@testing-library/user-event": "^14.0.0",
48 | "@types/node": "^16.11.26",
49 | "msw": "^1.0.0",
50 | "ts-node": "^10.9.1"
51 | },
52 | "files": [
53 | "dist"
54 | ]
55 | }
56 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/src/components/EntityComponentExample/EntityContentComponent.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useEntity } from "@backstage/plugin-catalog-react";
3 | import { Grid } from "@material-ui/core";
4 | import {
5 | Page,
6 | Content,
7 | ContentHeader,
8 | SupportButton,
9 | } from "@backstage/core-components";
10 | import { ExampleFetchComponent } from "../ExampleFetchComponent";
11 |
12 | export const EntityContentComponent = () => {
13 | const { entity } = useEntity();
14 | console.info(`Displaying data for ${JSON.stringify(entity)}`);
15 | return (
16 |
17 |
18 |
19 | My Custom Roadie Plugin
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | );
29 | };
30 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/src/components/EntityComponentExample/index.ts:
--------------------------------------------------------------------------------
1 | export { EntityContentComponent } from "./EntityContentComponent";
2 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/src/components/ExampleComponent/ExampleComponent.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { ExampleComponent } from './ExampleComponent';
3 | import { rest } from 'msw';
4 | import { setupServer } from 'msw/node';
5 | import { screen } from '@testing-library/react';
6 | import {
7 | setupRequestMockHandlers,
8 | renderInTestApp,
9 | } from "@backstage/test-utils";
10 |
11 | describe('ExampleComponent', () => {
12 | const server = setupServer();
13 | // Enable sane handlers for network requests
14 | setupRequestMockHandlers(server);
15 |
16 | // setup mock response
17 | beforeEach(() => {
18 | server.use(
19 | rest.get('/*', (_, res, ctx) => res(ctx.status(200), ctx.json({}))),
20 | );
21 | });
22 |
23 | it('should render', async () => {
24 | await renderInTestApp();
25 | expect(screen.getByText('Welcome to my-plugin!')).toBeInTheDocument();
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/src/components/ExampleComponent/ExampleComponent.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Typography, Grid } from "@material-ui/core";
3 | import {
4 | InfoCard,
5 | Header,
6 | Page,
7 | Content,
8 | ContentHeader,
9 | HeaderLabel,
10 | SupportButton,
11 | } from "@backstage/core-components";
12 | import { ExampleFetchComponent } from "../ExampleFetchComponent";
13 |
14 | export const ExampleComponent = () => (
15 |
16 |
20 |
21 |
22 | A description of your plugin goes here.
23 |
24 |
25 |
26 |
27 |
28 | All content should be wrapped in a card like this.
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | );
39 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/src/components/ExampleComponent/index.ts:
--------------------------------------------------------------------------------
1 | export { ExampleComponent } from "./ExampleComponent";
2 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { render, screen } from "@testing-library/react";
3 | import { ExampleFetchComponent } from "./ExampleFetchComponent";
4 | import { TestApiProvider } from "@backstage/test-utils";
5 | import { analyticsApiRef } from "@backstage/core-plugin-api";
6 |
7 | const mockAnalyticsApi = {
8 | captureEvent: jest.fn(),
9 | };
10 |
11 | describe("ExampleFetchComponent", () => {
12 | it("renders the user table", async () => {
13 | render(
14 |
15 |
16 |
17 | );
18 |
19 | // Wait for the table to render
20 | const table = await screen.findByRole("table");
21 | const nationality = screen.getAllByText("GB");
22 |
23 | // Assert that the table contains the expected user data
24 | expect(table).toBeInTheDocument();
25 | expect(screen.getByAltText("Carolyn")).toBeInTheDocument();
26 | expect(screen.getByText("Carolyn Moore")).toBeInTheDocument();
27 | expect(screen.getByText("carolyn.moore@example.com")).toBeInTheDocument();
28 | expect(nationality[0]).toBeInTheDocument();
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from "react";
2 | import { makeStyles } from "@material-ui/core/styles";
3 | import {
4 | Table,
5 | TableColumn,
6 | Progress,
7 | ResponseErrorPanel,
8 | } from "@backstage/core-components";
9 | import useAsync from "react-use/lib/useAsync";
10 | import { analyticsApiRef, useApi } from "@backstage/core-plugin-api";
11 |
12 | export const exampleUsers = {
13 | results: [
14 | {
15 | gender: "female",
16 | name: {
17 | title: "Miss",
18 | first: "Carolyn",
19 | last: "Moore",
20 | },
21 | email: "carolyn.moore@example.com",
22 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Carolyn",
23 | nat: "GB",
24 | },
25 | {
26 | gender: "female",
27 | name: {
28 | title: "Ms",
29 | first: "Esma",
30 | last: "Berberoğlu",
31 | },
32 | email: "esma.berberoglu@example.com",
33 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Esma",
34 | nat: "TR",
35 | },
36 | {
37 | gender: "female",
38 | name: {
39 | title: "Ms",
40 | first: "Isabella",
41 | last: "Rhodes",
42 | },
43 | email: "isabella.rhodes@example.com",
44 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Isabella",
45 | nat: "GB",
46 | },
47 | {
48 | gender: "male",
49 | name: {
50 | title: "Mr",
51 | first: "Derrick",
52 | last: "Carter",
53 | },
54 | email: "derrick.carter@example.com",
55 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Derrick",
56 | nat: "IE",
57 | },
58 | {
59 | gender: "female",
60 | name: {
61 | title: "Miss",
62 | first: "Mattie",
63 | last: "Lambert",
64 | },
65 | email: "mattie.lambert@example.com",
66 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Mattie",
67 | nat: "AU",
68 | },
69 | {
70 | gender: "male",
71 | name: {
72 | title: "Mr",
73 | first: "Mijat",
74 | last: "Rakić",
75 | },
76 | email: "mijat.rakic@example.com",
77 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Mijat",
78 | nat: "RS",
79 | },
80 | {
81 | gender: "male",
82 | name: {
83 | title: "Mr",
84 | first: "Javier",
85 | last: "Reid",
86 | },
87 | email: "javier.reid@example.com",
88 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Javier",
89 | nat: "US",
90 | },
91 | {
92 | gender: "female",
93 | name: {
94 | title: "Ms",
95 | first: "Isabella",
96 | last: "Li",
97 | },
98 | email: "isabella.li@example.com",
99 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Isabella",
100 | nat: "CA",
101 | },
102 | {
103 | gender: "female",
104 | name: {
105 | title: "Mrs",
106 | first: "Stephanie",
107 | last: "Garrett",
108 | },
109 | email: "stephanie.garrett@example.com",
110 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Stephanie",
111 | nat: "AU",
112 | },
113 | {
114 | gender: "female",
115 | name: {
116 | title: "Ms",
117 | first: "Antonia",
118 | last: "Núñez",
119 | },
120 | email: "antonia.nunez@example.com",
121 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Antonia",
122 | nat: "ES",
123 | },
124 | {
125 | gender: "male",
126 | name: {
127 | title: "Mr",
128 | first: "Donald",
129 | last: "Young",
130 | },
131 | email: "donald.young@example.com",
132 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Donald",
133 | nat: "US",
134 | },
135 | {
136 | gender: "male",
137 | name: {
138 | title: "Mr",
139 | first: "Iegor",
140 | last: "Holodovskiy",
141 | },
142 | email: "iegor.holodovskiy@example.com",
143 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Iegor",
144 | nat: "UA",
145 | },
146 | {
147 | gender: "female",
148 | name: {
149 | title: "Madame",
150 | first: "Jessica",
151 | last: "David",
152 | },
153 | email: "jessica.david@example.com",
154 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Jessica",
155 | nat: "CH",
156 | },
157 | {
158 | gender: "female",
159 | name: {
160 | title: "Ms",
161 | first: "Eve",
162 | last: "Martinez",
163 | },
164 | email: "eve.martinez@example.com",
165 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Eve",
166 | nat: "FR",
167 | },
168 | {
169 | gender: "male",
170 | name: {
171 | title: "Mr",
172 | first: "Caleb",
173 | last: "Silva",
174 | },
175 | email: "caleb.silva@example.com",
176 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Caleb",
177 | nat: "US",
178 | },
179 | {
180 | gender: "female",
181 | name: {
182 | title: "Miss",
183 | first: "Marcia",
184 | last: "Jenkins",
185 | },
186 | email: "marcia.jenkins@example.com",
187 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Marcia",
188 | nat: "US",
189 | },
190 | {
191 | gender: "female",
192 | name: {
193 | title: "Mrs",
194 | first: "Mackenzie",
195 | last: "Jones",
196 | },
197 | email: "mackenzie.jones@example.com",
198 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Mackenzie",
199 | nat: "NZ",
200 | },
201 | {
202 | gender: "male",
203 | name: {
204 | title: "Mr",
205 | first: "Jeremiah",
206 | last: "Gutierrez",
207 | },
208 | email: "jeremiah.gutierrez@example.com",
209 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Jeremiah",
210 | nat: "AU",
211 | },
212 | {
213 | gender: "female",
214 | name: {
215 | title: "Ms",
216 | first: "Luciara",
217 | last: "Souza",
218 | },
219 | email: "luciara.souza@example.com",
220 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Luciara",
221 | nat: "BR",
222 | },
223 | {
224 | gender: "male",
225 | name: {
226 | title: "Mr",
227 | first: "Valgi",
228 | last: "da Cunha",
229 | },
230 | email: "valgi.dacunha@example.com",
231 | picture: "https://api.dicebear.com/6.x/open-peeps/svg?seed=Valgi",
232 | nat: "BR",
233 | },
234 | ],
235 | };
236 |
237 | const useStyles = makeStyles({
238 | avatar: {
239 | height: 32,
240 | width: 32,
241 | borderRadius: "50%",
242 | },
243 | });
244 |
245 | type User = {
246 | gender: string; // "male"
247 | name: {
248 | title: string; // "Mr",
249 | first: string; // "Duane",
250 | last: string; // "Reed"
251 | };
252 | email: string; // "duane.reed@example.com"
253 | picture: string; // "https://api.dicebear.com/6.x/open-peeps/svg?seed=Duane"
254 | nat: string; // "AU"
255 | };
256 |
257 | type DenseTableProps = {
258 | users: User[];
259 | };
260 |
261 | export const DenseTable = ({ users }: DenseTableProps) => {
262 | const classes = useStyles();
263 |
264 | const columns: TableColumn[] = [
265 | { title: "Avatar", field: "avatar" },
266 | { title: "Name", field: "name" },
267 | { title: "Email", field: "email" },
268 | { title: "Nationality", field: "nationality" },
269 | ];
270 |
271 | const data = users.map((user) => {
272 | return {
273 | avatar: (
274 |
279 | ),
280 | name: `${user.name.first} ${user.name.last}`,
281 | email: user.email,
282 | nationality: user.nat,
283 | };
284 | });
285 |
286 | return (
287 |
293 | );
294 | };
295 |
296 | export const ExampleFetchComponent = () => {
297 | const analyticsApi = useApi(analyticsApiRef);
298 |
299 | useEffect(() => {
300 | analyticsApi.captureEvent({
301 | attributes: { component: "ExampleFetchComponent" },
302 | subject: "test-subject",
303 | value: 1,
304 | action: "component-load",
305 | context: {
306 | extension: "my-custom-plugin",
307 | pluginId: "my-custom-plugin",
308 | routeRef: "myPluginRouteRef",
309 | },
310 | });
311 | }, [analyticsApi]);
312 |
313 | const { value, loading, error } = useAsync(async (): Promise => {
314 | // Would use fetch in a real world example
315 | return exampleUsers.results;
316 | }, []);
317 |
318 | if (loading) {
319 | return ;
320 | } else if (error) {
321 | return ;
322 | }
323 |
324 | return ;
325 | };
326 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/src/components/ExampleFetchComponent/index.ts:
--------------------------------------------------------------------------------
1 | export { ExampleFetchComponent } from './ExampleFetchComponent';
2 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/src/index.ts:
--------------------------------------------------------------------------------
1 | export {
2 | myPluginPlugin,
3 | MyPluginPage,
4 | MyPluginEntityComponentContent,
5 | MyPluginCard,
6 | } from "./plugin";
7 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/src/plugin.test.ts:
--------------------------------------------------------------------------------
1 | import { myPluginPlugin } from './plugin';
2 |
3 | describe('my-plugin', () => {
4 | it('should export plugin', () => {
5 | expect(myPluginPlugin).toBeDefined();
6 | });
7 | });
8 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/src/plugin.ts:
--------------------------------------------------------------------------------
1 | import {
2 | createComponentExtension,
3 | createPlugin,
4 | createRoutableExtension,
5 | createRouteRef,
6 | } from "@backstage/core-plugin-api";
7 |
8 | import { rootRouteRef } from "./routes";
9 |
10 | export const myPluginPlugin = createPlugin({
11 | id: "my-plugin",
12 | routes: {
13 | root: rootRouteRef,
14 | },
15 | });
16 |
17 | export const myPluginRouteRef = createRouteRef({
18 | id: "my-catalog-plugin",
19 | });
20 |
21 | export const MyPluginPage = myPluginPlugin.provide(
22 | createRoutableExtension({
23 | name: "MyPluginPage",
24 | component: () =>
25 | import("./components/ExampleComponent").then((m) => m.ExampleComponent),
26 | mountPoint: rootRouteRef,
27 | })
28 | );
29 |
30 | export const MyPluginCard = myPluginPlugin.provide(
31 | createComponentExtension({
32 | name: "MyPluginContent",
33 | component: {
34 | lazy: () =>
35 | import("./components/ExampleFetchComponent").then(
36 | (m) => m.ExampleFetchComponent
37 | ),
38 | },
39 | })
40 | );
41 |
42 | export const MyPluginEntityComponentContent = myPluginPlugin.provide(
43 | createRoutableExtension({
44 | name: "MyPluginContent",
45 | component: () =>
46 | import("./components/EntityComponentExample").then(
47 | (m) => m.EntityContentComponent
48 | ),
49 | mountPoint: myPluginRouteRef,
50 | })
51 | );
52 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/src/routes.ts:
--------------------------------------------------------------------------------
1 | import { createRouteRef } from '@backstage/core-plugin-api';
2 |
3 | export const rootRouteRef = createRouteRef({
4 | id: 'my-plugin',
5 | });
6 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | import "@testing-library/jest-dom";
2 |
3 | import { TextEncoder } from "util";
4 |
5 | global.TextEncoder = TextEncoder;
6 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/skeleton/plugins/my-plugin/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@backstage/cli/config/tsconfig.json",
3 | "include": [
4 | "src",
5 | "dev"
6 | ],
7 | "exclude": ["node_modules"],
8 | "compilerOptions": {
9 | "outDir": "dist-types",
10 | "rootDir": "."
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/scaffolder-templates/roadie-plugin/template.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scaffolder.backstage.io/v1beta3
2 | kind: Template
3 | metadata:
4 | name: create-roadie-plugins-monorepo
5 | title: Create Roadie Plugins Monorepo
6 | description: Creates a Roadie plugins monorepo with example TypeScript code and example plugin with sample commands to develop, build and deploy Roadie plugins.
7 |
8 | spec:
9 | owner: info@roadie.io
10 | type: service
11 | parameters:
12 | - title: Provide some simple information
13 | required:
14 | - plugin_name
15 | properties:
16 | plugin_name:
17 | title: Plugin name
18 | type: string
19 | description: Unique name of the first plugin in the repository.
20 | ui:placeholder: docs-plugin
21 |
22 | - title: Create a GitHub repo to store your custom plugins in
23 | required:
24 | - repoUrl
25 | properties:
26 | repoUrl:
27 | title: Repository Location
28 | type: string
29 | ui:field: RepoUrlPicker
30 | ui:options:
31 | allowedHosts:
32 | - github.com
33 | steps:
34 | - id: template
35 | name: Fetch Skeleton + Template
36 | action: fetch:template
37 | input:
38 | url: ./skeleton
39 | values:
40 | repo_name: ${{ (parameters.repoUrl | parseRepoUrl)["repo"] }}
41 | repo_owner: ${{ (parameters.repoUrl | parseRepoUrl)["owner"] }}
42 | tenant: ${{ parameters.repository }}
43 | plugin_name: ${{ parameters.plugin_name }}
44 |
45 | - id: fs:rename
46 | name: Fill in names and descriptions
47 | action: fs:rename
48 | input:
49 | files:
50 | - from: ./plugins/my-plugin
51 | to: ./plugins/${{ parameters.plugin_name }}
52 |
53 | - id: publish
54 | name: Publish
55 | action: publish:github
56 | input:
57 | allowedHosts: ['github.com']
58 | description: 'This is ${{ parameters.plugin_name }}'
59 | repoUrl: ${{ parameters.repoUrl }}
60 | defaultBranch: main
61 |
62 |
63 | output:
64 | links:
65 | - title: Repository
66 | icon: github
67 | url: ${{ steps['publish'].output.remoteUrl }}
68 | - title: Roadie CLI documentation
69 | icon: help
70 | url: https://www.npmjs.com/package/@roadiehq/roadie-cli
71 |
--------------------------------------------------------------------------------