Skip to content

Commit 790d9c3

Browse files
implemented requested changes
1 parent ff7cd1d commit 790d9c3

7 files changed

Lines changed: 51 additions & 48 deletions

File tree

CONTRIBUTING.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ npm test
4343
The action uses [Zod](https://zod.dev/) for schema validation, automatically validating code.json in two scenarios:
4444

4545
### 1. Before Generation
46+
4647
Every time the action generates or updates code.json (via schedule or workflow_dispatch), it validates the output before creating a PR or pushing. If validation fails, no changes are made.
4748

4849
### 2. On PR Edits
50+
4951
When the `pull_request` trigger is configured, the action validates code.json whenever it's edited in a PR. This ensures users cannot accidentally merge invalid JSON.
5052

5153
### Workflow and Branching

README.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ method_used:
4646
4747
## Workflow Examples
4848
49-
### Option 1: Direct Push
49+
### Option 1: Direct Push
5050
5151
This approach tries to push directly to the branch using a Personal Access Token, but falls back to creating a pull request if the direct push fails. When users need to edit code.json, they should create a PR which will automatically validate their changes.
5252
@@ -59,7 +59,7 @@ on:
5959
pull_request:
6060
types: [opened, synchronize]
6161
paths:
62-
- 'code.json'
62+
- "code.json"
6363

6464
permissions:
6565
contents: write
@@ -80,7 +80,7 @@ jobs:
8080
uses: DSACMS/automated-codejson-generator@v1.2.0
8181
with:
8282
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
83-
ADMIN_TOKEN: ${{ secrets.ADMIN_PAT }} # PAT with admin/push permissions
83+
ADMIN_TOKEN: ${{ secrets.ADMIN_PAT }} # PAT with admin/push permissions
8484
BRANCH: "main"
8585
SKIP_PR: "true"
8686

@@ -107,7 +107,7 @@ on:
107107
pull_request:
108108
types: [opened, synchronize]
109109
paths:
110-
- 'code.json'
110+
- "code.json"
111111

112112
permissions:
113113
contents: write
@@ -128,17 +128,19 @@ jobs:
128128
with:
129129
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
130130
BRANCH: "main"
131-
SKIP_PR: "false"
131+
SKIP_PR: "false"
132132
```
133133
134134
### How It Works
135135
136136
**Automatic Generation**
137+
137138
- The action calculates metadata, validates it, and creates a PR or pushes directly
138139
- Validation ensures only valid code.json is created
139140
- Users can then fill in manual fields by editing the PR
140141
141142
**PR Validation**
143+
142144
- When users edit code.json in a PR, validation runs automatically on every commit
143145
- The PR cannot be merged if validation fails (when branch protection is enabled)
144146
- Error messages help users fix issues quickly
@@ -158,7 +160,7 @@ To use the direct push functionality, you'll need to create a Personal Access To
158160
5. **Configure Token**:
159161
- **Name**: Give it a name like "code.json Generator"
160162
- **Expiration**: Set appropriate expiration (recommend 90 days or 1 year)
161-
- **Scopes**:
163+
- **Scopes**:
162164
- Select `repo` (full repository access)
163165
6. **Store Token**: Copy and paste your token and store it for the next part
164166

@@ -197,7 +199,7 @@ The automated code.json generator calculates specific fields by analyzing your r
197199

198200
**dateLastModified**: This uses your repository's last update timestamp, reflecting the most recent changes. No configuration needed.
199201

200-
**dateMetaDataLastUpdated**: The generator sets this to the current timestamp each time it runs, providing a record of when the metadata was last refreshed. No configuration needed.
202+
**dateMetadataLastUpdated**: The generator sets this to the current timestamp each time it runs, providing a record of when the metadata was last refreshed. No configuration needed.
201203

202204
**feedbackMechanism**: The repository's issues URL in the format of {repositoryURL}/issues. If you already have a code.json file with existing feedback mechanisms, the generator preserves those values. No configuration needed.
203205

code.json

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,10 @@
2828
"forks": 2,
2929
"clones": 0
3030
},
31-
"platforms": [
32-
"web",
33-
"linux"
34-
],
35-
"categories": [
36-
"developer-tools",
37-
"automation"
38-
],
31+
"platforms": ["web", "linux"],
32+
"categories": ["developer-tools", "automation"],
3933
"softwareType": "standalone/backend",
40-
"languages": [
41-
"TypeScript",
42-
"JavaScript"
43-
],
34+
"languages": ["TypeScript", "JavaScript"],
4435
"maintenance": "internal",
4536
"contractNumber": [],
4637
"SBOM": "https://github.com/DSACMS/automated-codejson-generator/network/dependencies",
@@ -52,9 +43,7 @@
5243
"lastModified": "2025-09-17T22:40:02Z",
5344
"metaDataLastUpdated": "2025-09-26T15:08:24.592Z"
5445
},
55-
"tags": [
56-
"cmsoss-tier2"
57-
],
46+
"tags": ["cmsoss-tier2"],
5847
"contact": {
5948
"email": "opensource@cms.hhs.gov",
6049
"name": "CMS Open Source Team"
@@ -66,15 +55,9 @@
6655
"userInput": false,
6756
"fismaLevel": "Low",
6857
"group": "CMS/OA/DSAC",
69-
"projects": [
70-
"SHARE IT Act"
71-
],
58+
"projects": ["SHARE IT Act"],
7259
"systems": [],
73-
"subsetInHealthcare": [
74-
"Operational"
75-
],
76-
"userType": [
77-
"Government"
78-
],
60+
"subsetInHealthcare": ["Operational"],
61+
"userType": ["Government"],
7962
"maturityModelTier": 3
80-
}
63+
}

src/helper.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export async function calculateMetaData(): Promise<Partial<CodeJSON>> {
6767
date: {
6868
created: basicInfo.date.created,
6969
lastModified: basicInfo.date.lastModified,
70-
metaDataLastUpdated: basicInfo.date.metaDataLastUpdated,
70+
metadataLastUpdated: basicInfo.date.metadataLastUpdated,
7171
},
7272
};
7373
} catch (error) {
@@ -100,7 +100,7 @@ async function getBasicInfo(): Promise<BasicRepoInfo> {
100100
date: {
101101
created: repoData.data.created_at,
102102
lastModified: repoData.data.updated_at,
103-
metaDataLastUpdated: new Date().toISOString(),
103+
metadataLastUpdated: new Date().toISOString(),
104104
},
105105
};
106106
} catch (error) {

src/main.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const baselineCodeJSON: CodeJSON = {
99
longDescription: "",
1010
status: "",
1111
permissions: {
12-
license: [
12+
licenses: [
1313
{
1414
name: "",
1515
URL: "",
@@ -45,7 +45,7 @@ const baselineCodeJSON: CodeJSON = {
4545
date: {
4646
created: "",
4747
lastModified: "",
48-
metaDataLastUpdated: "",
48+
metadataLastUpdated: "",
4949
},
5050
tags: [],
5151
contact: {
@@ -110,8 +110,8 @@ async function getMetaData(
110110
date: {
111111
created: partialCodeJSON.date?.created ?? "",
112112
lastModified: partialCodeJSON.date?.lastModified ?? "",
113-
metaDataLastUpdated:
114-
partialCodeJSON.date?.metaDataLastUpdated ?? new Date().toISOString(),
113+
metadataLastUpdated:
114+
partialCodeJSON.date?.metadataLastUpdated ?? new Date().toISOString(),
115115
},
116116
feedbackMechanism,
117117
SBOM,

src/model.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export interface ReuseFrequency {
4949
}
5050

5151
export interface Permissions {
52-
license: License[];
52+
licenses: License[];
5353
usageType: string[];
5454
exemptionText: string;
5555
}
@@ -78,7 +78,7 @@ export interface Partner {
7878
export interface Date {
7979
created: string;
8080
lastModified: string;
81-
metaDataLastUpdated: string;
81+
metadataLastUpdated: string;
8282
}
8383

8484
export interface Contact {

src/validation.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import { z } from "zod";
33
const DateSchema = z.object({
44
created: z.string().min(1, "created date is required"),
55
lastModified: z.string().min(1, "lastModified date is required"),
6-
metaDataLastUpdated: z
6+
metadataLastUpdated: z
77
.string()
8-
.min(1, "metaDataLastUpdated date is required"),
8+
.min(1, "metadataLastUpdated date is required"),
99
});
1010

1111
const ContactSchema = z.object({
@@ -20,15 +20,31 @@ const LicenseSchema = z.object({
2020

2121
const PermissionsSchema = z
2222
.object({
23-
license: z.array(LicenseSchema).optional(),
24-
licenses: z.array(LicenseSchema).optional(),
23+
licenses: z.array(LicenseSchema).min(1, "at least one license is required"),
2524
usageType: z.union([z.array(z.string()), z.string()]),
2625
exemptionText: z.string(),
2726
})
28-
.refine((data) => data.license || data.licenses, {
29-
message: "Either 'license' or 'licenses' array is required",
30-
path: ["license"],
31-
});
27+
.refine(
28+
(data) => {
29+
const usageTypes = Array.isArray(data.usageType)
30+
? data.usageType
31+
: [data.usageType];
32+
33+
const hasExemption = usageTypes.some(
34+
(type) => typeof type === "string" && type.startsWith("exemptBy"),
35+
);
36+
37+
if (hasExemption) {
38+
return data.exemptionText && data.exemptionText.trim().length > 0;
39+
}
40+
41+
return true;
42+
},
43+
{
44+
message: "exemptionText is required when usageType contains an exemption",
45+
path: ["exemptionText"],
46+
},
47+
);
3248

3349
const ReuseFrequencySchema = z.object({
3450
forks: z.number(),

0 commit comments

Comments
 (0)