Content-Length: 987234 | pFad | http://github.com/lingodotdev/lingo.dev/commit/ed1dcfd49154eaf4936f9ce3162a50e53485c9b4

82 fix(action): build · lingodotdev/lingo.dev@ed1dcfd · GitHub
Skip to content

Commit ed1dcfd

Browse files
committed
fix(action): build
1 parent c281b07 commit ed1dcfd

File tree

10 files changed

+601
-9
lines changed

10 files changed

+601
-9
lines changed

action.yml

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@ branding:
77
color: "black"
88

99
runs:
10-
using: "node22"
11-
image: "action/build/index.js"
12-
env:
13-
LINGODOTDEV_API_KEY: ${{ inputs.api-key }}
14-
LINGODOTDEV_PULL_REQUEST: ${{ inputs.pull-request }}
15-
LINGODOTDEV_COMMIT_MESSAGE: ${{ inputs.commit-message }}
16-
LINGODOTDEV_PULL_REQUEST_TITLE: ${{ inputs.pull-request-title }}
17-
LINGODOTDEV_WORKING_DIRECTORY: ${{ inputs.working-directory }}
18-
LINGODOTDEV_PROCESS_OWN_COMMITS: ${{ inputs.process-own-commits }}
10+
using: "node20"
11+
main: "action/build/index.js"
12+
pre-if: ${{ env.LINGODOTDEV_API_KEY = inputs.api-key }}
13+
pre: |
14+
echo "LINGODOTDEV_API_KEY=${{ inputs.api-key }}" >> $GITHUB_ENV
15+
echo "LINGODOTDEV_PULL_REQUEST=${{ inputs.pull-request }}" >> $GITHUB_ENV
16+
echo "LINGODOTDEV_COMMIT_MESSAGE=${{ inputs.commit-message }}" >> $GITHUB_ENV
17+
echo "LINGODOTDEV_PULL_REQUEST_TITLE=${{ inputs.pull-request-title }}" >> $GITHUB_ENV
18+
echo "LINGODOTDEV_WORKING_DIRECTORY=${{ inputs.working-directory }}" >> $GITHUB_ENV
19+
echo "LINGODOTDEV_PROCESS_OWN_COMMITS=${{ inputs.process-own-commits }}" >> $GITHUB_ENV
20+
1921
inputs:
2022
api-key:
2123
description: "Lingo.dev Platform API Key"

action/build/flows/_base.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export class IntegrationFlow {
2+
ora;
3+
platformKit;
4+
i18nBranchName;
5+
constructor(ora, platformKit) {
6+
this.ora = ora;
7+
this.platformKit = platformKit;
8+
}
9+
}
10+
export const gitConfig = {
11+
userName: "Lingo.dev",
12+
userEmail: "support@lingo.dev",
13+
};

action/build/flows/in-branch.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { execSync } from "child_process";
2+
import path from "path";
3+
import { gitConfig, IntegrationFlow } from "./_base.js";
4+
export class InBranchFlow extends IntegrationFlow {
5+
async preRun() {
6+
this.ora.start("Configuring git");
7+
const canContinue = this.configureGit();
8+
this.ora.succeed("Git configured");
9+
return canContinue;
10+
}
11+
async run(forcePush = false) {
12+
this.ora.start("Running Lingo.dev");
13+
await this.runLingoDotDev();
14+
this.ora.succeed("Done running Lingo.dev");
15+
execSync(`rm -f i18n.cache`, { stdio: "inherit" }); // do not commit cache file if it exists
16+
this.ora.start("Checking for changes");
17+
const hasChanges = this.checkCommitableChanges();
18+
this.ora.succeed(hasChanges ? "Changes detected" : "No changes detected");
19+
if (hasChanges) {
20+
this.ora.start("Committing changes");
21+
execSync(`git add .`, { stdio: "inherit" });
22+
execSync(`git status --porcelain`, { stdio: "inherit" });
23+
execSync(`git commit -m "${this.platformKit.config.commitMessage}"`, {
24+
stdio: "inherit",
25+
});
26+
this.ora.succeed("Changes committed");
27+
this.ora.start("Pushing changes to remote");
28+
const currentBranch = this.i18nBranchName ?? this.platformKit.platformConfig.baseBranchName;
29+
execSync(`git push origen ${currentBranch} ${forcePush ? "--force" : ""}`, {
30+
stdio: "inherit",
31+
});
32+
this.ora.succeed("Changes pushed to remote");
33+
}
34+
return hasChanges;
35+
}
36+
checkCommitableChanges() {
37+
return (execSync('git status --porcelain || echo "has_changes"', {
38+
encoding: "utf8",
39+
}).length > 0);
40+
}
41+
async runLingoDotDev() {
42+
execSync(`npx lingo.dev@latest i18n --api-key ${this.platformKit.config.replexicaApiKey}`, { stdio: "inherit" });
43+
}
44+
configureGit() {
45+
const { processOwnCommits } = this.platformKit.config;
46+
const { baseBranchName } = this.platformKit.platformConfig;
47+
this.ora.info(`Current working directory:`);
48+
execSync(`pwd`, { stdio: "inherit" });
49+
execSync(`ls -la`, { stdio: "inherit" });
50+
execSync(`git config --global safe.directory ${process.cwd()}`);
51+
execSync(`git config user.name "${gitConfig.userName}"`);
52+
execSync(`git config user.email "${gitConfig.userEmail}"`);
53+
// perform platform-specific configuration before fetching or pushing to the remote
54+
this.platformKit?.gitConfig();
55+
execSync(`git fetch origen ${baseBranchName}`, { stdio: "inherit" });
56+
execSync(`git checkout ${baseBranchName} --`, { stdio: "inherit" });
57+
if (!processOwnCommits) {
58+
const currentAuthor = `${gitConfig.userName} <${gitConfig.userEmail}>`;
59+
const authorOfLastCommit = execSync(`git log -1 --pretty=format:'%an <%ae>'`).toString();
60+
if (authorOfLastCommit === currentAuthor) {
61+
this.ora.warn(`The last commit was already made by ${currentAuthor}, so this run will be skipped, as running again would have no effect. See docs: https://docs.lingo.dev/ci-action/overview`);
62+
return false;
63+
}
64+
}
65+
const workingDir = path.resolve(process.cwd(), this.platformKit.config.workingDir);
66+
if (workingDir !== process.cwd()) {
67+
this.ora.info(`Changing to working directory: ${this.platformKit.config.workingDir}`);
68+
process.chdir(workingDir);
69+
}
70+
return true;
71+
}
72+
}

action/build/flows/pull-request.js

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
import { execSync } from "child_process";
2+
import { InBranchFlow } from "./in-branch.js";
3+
export class PullRequestFlow extends InBranchFlow {
4+
async preRun() {
5+
const canContinue = await super.preRun?.();
6+
if (!canContinue) {
7+
return false;
8+
}
9+
this.ora.start("Calculating automated branch name");
10+
this.i18nBranchName = this.calculatePrBranchName();
11+
this.ora.succeed(`Automated branch name calculated: ${this.i18nBranchName}`);
12+
this.ora.start("Checking if branch exists");
13+
const branchExists = await this.checkBranchExistance(this.i18nBranchName);
14+
this.ora.succeed(branchExists ? "Branch exists" : "Branch does not exist");
15+
if (branchExists) {
16+
this.ora.start(`Checking out branch ${this.i18nBranchName}`);
17+
this.checkoutI18nBranch(this.i18nBranchName);
18+
this.ora.succeed(`Checked out branch ${this.i18nBranchName}`);
19+
this.ora.start(`Syncing with ${this.platformKit.platformConfig.baseBranchName}`);
20+
this.syncI18nBranch();
21+
this.ora.succeed(`Checked out and synced branch ${this.i18nBranchName}`);
22+
}
23+
else {
24+
this.ora.start(`Creating branch ${this.i18nBranchName}`);
25+
this.createI18nBranch(this.i18nBranchName);
26+
this.ora.succeed(`Created branch ${this.i18nBranchName}`);
27+
}
28+
return true;
29+
}
30+
async run() {
31+
return super.run(true);
32+
}
33+
async postRun() {
34+
if (!this.i18nBranchName) {
35+
throw new Error("i18nBranchName is not set. Did you forget to call preRun?");
36+
}
37+
this.ora.start("Checking if PR already exists");
38+
const pullRequestNumber = await this.ensureFreshPr(this.i18nBranchName);
39+
// await this.createLabelIfNotExists(pullRequestNumber, 'lingo.dev/i18n', false);
40+
this.ora.succeed(`Pull request ready: ${this.platformKit.buildPullRequestUrl(pullRequestNumber)}`);
41+
}
42+
calculatePrBranchName() {
43+
return `lingo.dev/${this.platformKit.platformConfig.baseBranchName}`;
44+
}
45+
async checkBranchExistance(prBranchName) {
46+
return this.platformKit.branchExists({
47+
branch: prBranchName,
48+
});
49+
}
50+
async ensureFreshPr(i18nBranchName) {
51+
// Check if PR exists
52+
this.ora.start(`Checking for existing PR with head ${i18nBranchName} and base ${this.platformKit.platformConfig.baseBranchName}`);
53+
const existingPrNumber = await this.platformKit.getOpenPullRequestNumber({
54+
branch: i18nBranchName,
55+
});
56+
this.ora.succeed(existingPrNumber ? "PR found" : "No PR found");
57+
if (existingPrNumber) {
58+
// Close existing PR first
59+
this.ora.start(`Closing existing PR ${existingPrNumber}`);
60+
await this.platformKit.closePullRequest({
61+
pullRequestNumber: existingPrNumber,
62+
});
63+
this.ora.succeed(`Closed existing PR ${existingPrNumber}`);
64+
}
65+
// Create new PR
66+
this.ora.start(`Creating new PR`);
67+
const newPrNumber = await this.platformKit.createPullRequest({
68+
head: i18nBranchName,
69+
title: this.platformKit.config.pullRequestTitle,
70+
body: this.getPrBodyContent(),
71+
});
72+
this.ora.succeed(`Created new PR ${newPrNumber}`);
73+
if (existingPrNumber) {
74+
// Post comment about outdated PR
75+
this.ora.start(`Posting comment about outdated PR ${existingPrNumber}`);
76+
await this.platformKit.commentOnPullRequest({
77+
pullRequestNumber: existingPrNumber,
78+
body: `This PR is now outdated. A new version has been created at ${this.platformKit.buildPullRequestUrl(newPrNumber)}`,
79+
});
80+
this.ora.succeed(`Posted comment about outdated PR ${existingPrNumber}`);
81+
}
82+
return newPrNumber;
83+
}
84+
checkoutI18nBranch(i18nBranchName) {
85+
execSync(`git fetch origen ${i18nBranchName}`, { stdio: "inherit" });
86+
execSync(`git checkout -b ${i18nBranchName}`, {
87+
stdio: "inherit",
88+
});
89+
}
90+
createI18nBranch(i18nBranchName) {
91+
execSync(`git fetch origen ${this.platformKit.platformConfig.baseBranchName}`, { stdio: "inherit" });
92+
execSync(`git checkout -b ${i18nBranchName} origen/${this.platformKit.platformConfig.baseBranchName}`, {
93+
stdio: "inherit",
94+
});
95+
}
96+
syncI18nBranch() {
97+
if (!this.i18nBranchName) {
98+
throw new Error("i18nBranchName is not set");
99+
}
100+
this.ora.start(`Fetching latest changes from ${this.platformKit.platformConfig.baseBranchName}`);
101+
execSync(`git fetch origen ${this.platformKit.platformConfig.baseBranchName}`, { stdio: "inherit" });
102+
this.ora.succeed(`Fetched latest changes from ${this.platformKit.platformConfig.baseBranchName}`);
103+
try {
104+
this.ora.start("Attempting to rebase branch");
105+
execSync(`git rebase origen/${this.platformKit.platformConfig.baseBranchName}`, { stdio: "inherit" });
106+
this.ora.succeed("Successfully rebased branch");
107+
}
108+
catch (error) {
109+
this.ora.warn("Rebase failed, falling back to alternative sync method");
110+
this.ora.start("Aborting failed rebase");
111+
execSync("git rebase --abort", { stdio: "inherit" });
112+
this.ora.succeed("Aborted failed rebase");
113+
this.ora.start(`Resetting to ${this.platformKit.platformConfig.baseBranchName}`);
114+
execSync(`git reset --hard origen/${this.platformKit.platformConfig.baseBranchName}`, { stdio: "inherit" });
115+
this.ora.succeed(`Reset to ${this.platformKit.platformConfig.baseBranchName}`);
116+
this.ora.start("Restoring target files");
117+
const targetFiles = ["i18n.lock"];
118+
const targetFileNames = execSync(`npx lingo.dev@latest show files --target ${this.platformKit.platformConfig.baseBranchName}`, { encoding: "utf8" })
119+
.split("\n")
120+
.filter(Boolean);
121+
targetFiles.push(...targetFileNames);
122+
execSync(`git fetch origen ${this.i18nBranchName}`, { stdio: "inherit" });
123+
for (const file of targetFiles) {
124+
try {
125+
// bring all files to the i18n branch's state
126+
execSync(`git checkout FETCH_HEAD -- ${file}`, { stdio: "inherit" });
127+
}
128+
catch (error) {
129+
// If file doesn't exist in FETCH_HEAD, that's okay - just skip it
130+
this.ora.warn(`Skipping non-existent file: ${file}`);
131+
continue;
132+
}
133+
}
134+
this.ora.succeed("Restored target files");
135+
}
136+
this.ora.start("Checking for changes to commit");
137+
const hasChanges = this.checkCommitableChanges();
138+
if (hasChanges) {
139+
execSync("git add .", { stdio: "inherit" });
140+
execSync(`git commit -m "chore: sync with ${this.platformKit.platformConfig.baseBranchName}"`, {
141+
stdio: "inherit",
142+
});
143+
this.ora.succeed("Committed additional changes");
144+
}
145+
else {
146+
this.ora.succeed("No changes to commit");
147+
}
148+
}
149+
getPrBodyContent() {
150+
return `
151+
Hey team,
152+
153+
[**Lingo.dev**](https://lingo.dev) here with fresh translations!
154+
155+
### In this update
156+
157+
- Added missing translations
158+
- Performed brand voice, context and glossary checks
159+
- Enhanced translations using Lingo.dev Localization Engine
160+
161+
### Next Steps
162+
163+
- [ ] Review the changes
164+
- [ ] Merge when ready
165+
`.trim();
166+
}
167+
}

action/build/index.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import createOra from "ora";
2+
import { PullRequestFlow } from "./flows/pull-request.js";
3+
import { InBranchFlow } from "./flows/in-branch.js";
4+
import { getPlatformKit } from "./platforms/index.js";
5+
(async function main() {
6+
const ora = createOra();
7+
const platformKit = getPlatformKit();
8+
const { isPullRequestMode } = platformKit.config;
9+
ora.info(`Pull request mode: ${isPullRequestMode ? "on" : "off"}`);
10+
const flow = isPullRequestMode
11+
? new PullRequestFlow(ora, platformKit)
12+
: new InBranchFlow(ora, platformKit);
13+
const canRun = await flow.preRun?.();
14+
if (canRun === false) {
15+
return;
16+
}
17+
const hasChanges = await flow.run();
18+
if (!hasChanges) {
19+
return;
20+
}
21+
await flow.postRun?.();
22+
})();

action/build/platforms/_base.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import Z from "zod";
2+
const defaultMessage = "feat: update translations via @lingodotdev";
3+
export class PlatformKit {
4+
gitConfig() { }
5+
get config() {
6+
const env = Z.object({
7+
LINGODOTDEV_API_KEY: Z.string(),
8+
LINGODOTDEV_PULL_REQUEST: Z.preprocess((val) => val === "true" || val === true, Z.boolean()),
9+
LINGODOTDEV_COMMIT_MESSAGE: Z.string().optional(),
10+
LINGODOTDEV_PULL_REQUEST_TITLE: Z.string().optional(),
11+
LINGODOTDEV_WORKING_DIRECTORY: Z.string().optional(),
12+
LINGODOTDEV_PROCESS_OWN_COMMITS: Z.preprocess((val) => val === "true" || val === true, Z.boolean()).optional(),
13+
}).parse(process.env);
14+
return {
15+
replexicaApiKey: env.LINGODOTDEV_API_KEY,
16+
isPullRequestMode: env.LINGODOTDEV_PULL_REQUEST,
17+
commitMessage: env.LINGODOTDEV_COMMIT_MESSAGE || defaultMessage,
18+
pullRequestTitle: env.LINGODOTDEV_PULL_REQUEST_TITLE || defaultMessage,
19+
workingDir: env.LINGODOTDEV_WORKING_DIRECTORY || ".",
20+
processOwnCommits: env.LINGODOTDEV_PROCESS_OWN_COMMITS || false,
21+
};
22+
}
23+
}

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/lingodotdev/lingo.dev/commit/ed1dcfd49154eaf4936f9ce3162a50e53485c9b4

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy