Skip to content

Commit

Permalink
fix: idempotency for retrofit, improved docs
Browse files Browse the repository at this point in the history
Also some projen housekeeping
  • Loading branch information
mikejgray committed Jun 26, 2023
1 parent d4208b4 commit 13aa7f3
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 55 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/upgrade-main.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .projenrc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,10 @@ project.compileTask.exec(
'cp src/files/* lib/files',
);

const upgradeMain = project.tryFindObjectFile('.github/workflows/upgrade-main.yml');
upgradeMain?.addOverride('jobs.pr.steps.4.with.token', '${{ secrets.GITHUB_TOKEN }}');
upgradeMain?.addOverride('jobs.pr.permissions.pull-requests', 'write');
upgradeMain?.addOverride('jobs.pr.permissions.contents', 'write');


project.synth();
66 changes: 44 additions & 22 deletions API.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ It will not:
- Overwrite your README.md file, if it exists, or create one if it does not exist
- Create sample code
- Touch your LICENSE file
- Note that official OVOS and Neon skills have skill license requirements that may not be compatible with your existing license, if you want to submit it as part of one of those organizations. Please review the [OVOS skill license requirements](https://openvoiceos.github.io/ovos-technical-manual/license/).
- Note that official OVOS and Neon skills have skill license requirements that may not be compatible with your existing license, if you want to submit it as part of one of those organizations. Please review the [OVOS skill license requirements](https://openvoiceos.github.io/ovos-technical-manual/license/). If you are not submitting your skill to OVOS or Neon, you can use any license you like, and should set `skillLicenseTest: false` in your `.projenrc.json` file.

Once the retrofit is complete, you can review the changes needed for modernization with `grep TODO __init__.py`. This project attempts to handle as many as possible, but due to differences in code style and structure, some changes will need to be made manually.

If your skill code is not in `__init__.py` in the repository root, the retrofit code won't be able to find it. PRs welcome to add support for other skill structures.
File renamed without changes.
67 changes: 41 additions & 26 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFile
import { join } from 'path';
import { ProjenrcJson, SampleDir, SampleFile, TextFile } from 'projen';
import { GitHubProject, GitHubProjectOptions } from 'projen/lib/github';
import { readmeMd } from './files/README.md';
import { readmeMd } from './files/README';
import { setupPy } from './files/setup.py';
import { LicenseTestsWorkflow, ProposeReleaseWorkflow, PublishAlphaWorkflow, PublishReleaseWorkflow, SkillTestsWorkflow, UpdateSkillJsonWorkflow } from './GithubWorkflows';

Expand All @@ -17,7 +17,7 @@ export interface OVOSSkillProjectOptions extends GitHubProjectOptions {
* The name of the skill class
* @example HelloWorldSkill
*/
readonly skillClass: string;
readonly skillClass?: string;
/**
* The name of the skill's PyPi package
* @example ovos-hello-world-skill
Expand Down Expand Up @@ -86,6 +86,11 @@ export interface OVOSSkillProjectOptions extends GitHubProjectOptions {
* @example "A simple skill that says hello world"
*/
readonly skillDescription?: string;
/**
* Include a test to check that the skill's license is FOSS?
* @default true
*/
readonly skillLicenseTest?: boolean;
}

export class OVOSSkillProject extends GitHubProject {
Expand All @@ -95,11 +100,15 @@ export class OVOSSkillProject extends GitHubProject {
*/
static modernizeSkillCode(file: string) {
let existingSkillFileContents = readFileSync(file).toString();
const ovosImports = `from ovos_workshop.decorators import intent_handler
let ovosImports = `# TODO: Remove unused OVOS imports
from ovos_workshop.decorators import intent_handler
from ovos_workshop.skills import OVOSSkill
from ovos_utils.intents import IntentBuilder
from ovos_bus_client.message import Message`;
// Replacements
if (existingSkillFileContents.includes('AdaptIntent')) {
ovosImports += '\nfrom ovos_utils.intents import AdaptIntent';
}
let skillFileArray = existingSkillFileContents.split('\n');
skillFileArray.forEach((line, index) => {
// Comment out Mycroft imports
Expand Down Expand Up @@ -130,28 +139,30 @@ ${line}`;

constructor(options: OVOSSkillProjectOptions) {
// Default options
const author = options.author ?? 'TODO: Your Name';
const author = options.author ?? 'TODO: Add \'author\' to .projenrc.json and run pj';
const repositoryUrl = options.repositoryUrl ?? 'TODO: Add \'repositoryUrl\' to .projenrc.json and run pj';
const authorAddress = options.authorAddress ?? 'TODO: Add \'authorAddress\' to .projenrc.json and run pj';
const license = options.license ?? '# TODO: Add \'license\' to .projenrc.json and run pj';
const skillClass = options.skillClass ?? 'TODO: Add \'skillClass\' to .projenrc.json and run pj';
const retrofit = options.retrofit ?? false;
const repositoryUrl = options.repositoryUrl ?? 'TODO: PLACEHOLDER';
const packageDir = options.packageDir ?? 'src';
const pypiName = options.pypiName ?? process.cwd().split('/').pop()!;
const authorAddress = options.authorAddress ?? 'TODO: Your Email';
const authorHandle = options.authorHandle ?? '';
const sampleCode = options.sampleCode ?? true;
const skillKeywords = options.skillKeywords ?? 'ovos skill';
const condenseLocaleFolders = options.condenseLocaleFolders ?? true;
const githubworkflows = options.githubWorkflows ?? true;
const license = options.license ?? 'Apache-2.0';
const skillDescription = options.skillDescription ?? '';
const skillLicenseTest = options.skillLicenseTest ?? true;
let packageDir = options.packageDir ?? 'src';
if (retrofit && packageDir === 'src') { packageDir = '';}

// Super
let superProps = { ...options };
if (!retrofit) {
superProps.readme = {
contents: readmeMd({
skillClass: options.skillClass,
authorName: author,
authorHandle: authorHandle,
skillClass: options.skillClass ?? 'OVOSSkill',
authorName: options.author ?? 'authorName',
authorHandle: options.authorHandle ?? 'githubUsername',
skillKeywords: skillKeywords,
}),
};
Expand Down Expand Up @@ -180,7 +191,7 @@ ${line}`;
authorAddress: authorAddress,
license: license,
description: skillDescription,
skillClass: options.skillClass,
skillClass: skillClass,
}).split('\n'),
});
new SampleFile(this, 'skill.json', {
Expand All @@ -196,16 +207,16 @@ ${line}`;
lines: requirements.split('\n'),
});
}
if (existsSync('__init__.py')) {
if (existsSync('__init__.py') && !existsSync('setup.py')) {
OVOSSkillProject.modernizeSkillCode('__init__.py');
} else {
const todoMd = readFileSync('files/TODO.md').toString();
} else if (!existsSync('__init__.py') && !existsSync('setup.py')) {
const todoMd = readFileSync(join(__dirname, 'files', 'TODO.md')).toString();
writeFileSync('TODO.md', `Could not find __init__.py, please update your skill manually:\n${todoMd}`);
}
};
// Github Actions
if (githubworkflows) {
this.createGithubWorkflows();
this.createGithubWorkflows(skillLicenseTest);
}
this.createDevBranch();
}
Expand Down Expand Up @@ -367,8 +378,10 @@ ${line}`;
/**
* Create OVOS standard Github Actions workflows.
*/
createGithubWorkflows() {
new LicenseTestsWorkflow(this.github!);
createGithubWorkflows(skillLicenseTest: boolean) {
if (skillLicenseTest) {
new LicenseTestsWorkflow(this.github!);
}
new ProposeReleaseWorkflow(this.github!);
new PublishAlphaWorkflow(this.github!);
new PublishReleaseWorkflow(this.github!);
Expand All @@ -392,26 +405,28 @@ ${line}`;
*/
restructureLocaleFolders(sourceFolder: string) {
['vocab', 'dialog', 'regex', 'intents'].forEach((dir) => {
const locale = join(sourceFolder, 'locale');
try {
const languageDirs = readdirSync(`${sourceFolder}/${dir}`, { withFileTypes: true })
mkdirSync(locale, { recursive: true });
const languageDirs = readdirSync(join(sourceFolder, dir), { withFileTypes: true })
.filter(dirent => dirent.isDirectory())
.map(dirent => dirent.name);

languageDirs.forEach((lang) => {
if (!existsSync(`${sourceFolder}/locale/${lang}`)) {
mkdirSync(`${sourceFolder}/locale/${lang}`, { recursive: true });
if (!existsSync(join(locale, lang))) {
mkdirSync(join(locale, lang), { recursive: true });
}

// Check if a directory already exists at the new path
if (existsSync(`${sourceFolder}/locale/${lang}/${dir}`)) {
console.warn(`Directory already exists: ${sourceFolder}/locale/${lang}/${dir}. Skipping...`);
if (existsSync(join(locale, lang, dir))) {
console.warn(`Directory already exists: ${join(locale, lang, dir)}. Skipping...`);
} else {
renameSync(`${sourceFolder}/${dir}/${lang}`, `${sourceFolder}/locale/${lang}/${dir}`);
renameSync(join(sourceFolder, dir, lang), join(locale, lang, dir));
}
});

} catch (err) {
console.error(err);
console.debug(err);
}
});
}
Expand Down
10 changes: 5 additions & 5 deletions test/__snapshots__/OVOSSkillProject.test.ts.snap

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 13aa7f3

Please sign in to comment.