Skip to content

Commit

Permalink
poetry: Run poetry env use only after cache is loaded
Browse files Browse the repository at this point in the history
The virtualenv cache might contain invalid entries, such as virtualenvs
built in previous, buggy versions of this action.  The `poetry env use`
command will recreate virtualenvs in case they are invalid, but it has
to be run only *after* the cache is loaded.

Refactor `CacheDistributor` a bit such that the validation (and possible
recreation) of virtualenvs happens only after the cache is loaded.
  • Loading branch information
oranav committed Dec 9, 2022
1 parent bc3992e commit 881ca6e
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 34 deletions.
4 changes: 4 additions & 0 deletions dist/cache-save/index.js
Expand Up @@ -59711,6 +59711,9 @@ class CacheDistributor {
this.cacheDependencyPath = cacheDependencyPath;
this.CACHE_KEY_PREFIX = 'setup-python';
}
handleLoadedCache() {
return __awaiter(this, void 0, void 0, function* () { });
}
restoreCache() {
return __awaiter(this, void 0, void 0, function* () {
const { primaryKey, restoreKey } = yield this.computeKeys();
Expand All @@ -59723,6 +59726,7 @@ class CacheDistributor {
core.saveState(State.CACHE_PATHS, cachePath);
core.saveState(State.STATE_CACHE_PRIMARY_KEY, primaryKey);
const matchedKey = yield cache.restoreCache(cachePath, primaryKey, restoreKey);
yield this.handleLoadedCache();
this.handleMatchResult(matchedKey, primaryKey);
});
}
Expand Down
45 changes: 31 additions & 14 deletions dist/setup/index.js
Expand Up @@ -65787,6 +65787,9 @@ class CacheDistributor {
this.cacheDependencyPath = cacheDependencyPath;
this.CACHE_KEY_PREFIX = 'setup-python';
}
handleLoadedCache() {
return __awaiter(this, void 0, void 0, function* () { });
}
restoreCache() {
return __awaiter(this, void 0, void 0, function* () {
const { primaryKey, restoreKey } = yield this.computeKeys();
Expand All @@ -65799,6 +65802,7 @@ class CacheDistributor {
core.saveState(State.CACHE_PATHS, cachePath);
core.saveState(State.STATE_CACHE_PRIMARY_KEY, primaryKey);
const matchedKey = yield cache.restoreCache(cachePath, primaryKey, restoreKey);
yield this.handleLoadedCache();
this.handleMatchResult(matchedKey, primaryKey);
});
}
Expand Down Expand Up @@ -66097,42 +66101,31 @@ const core = __importStar(__nccwpck_require__(2186));
const cache_distributor_1 = __importDefault(__nccwpck_require__(8953));
const utils_1 = __nccwpck_require__(1314);
class PoetryCache extends cache_distributor_1.default {
constructor(pythonVersion, patterns = '**/poetry.lock') {
constructor(pythonVersion, patterns = '**/poetry.lock', poetryProjects = new Set()) {
super('poetry', patterns);
this.pythonVersion = pythonVersion;
this.patterns = patterns;
this.poetryProjects = poetryProjects;
}
getCacheGlobalDirectories() {
var e_1, _a;
return __awaiter(this, void 0, void 0, function* () {
// Same virtualenvs path may appear for different projects, hence we use a Set
const paths = new Set();
const globber = yield glob.create(this.patterns);
const pythonLocation = yield io.which('python');
if (pythonLocation) {
core.debug(`pythonLocation is ${pythonLocation}`);
}
else {
utils_1.logWarning('python binaries were not found in PATH');
}
try {
for (var _b = __asyncValues(globber.globGenerator()), _c; _c = yield _b.next(), !_c.done;) {
const file = _c.value;
const basedir = path.dirname(file);
core.debug(`Processing Poetry project at ${basedir}`);
this.poetryProjects.add(basedir);
const poetryConfig = yield this.getPoetryConfiguration(basedir);
const cacheDir = poetryConfig['cache-dir'];
const virtualenvsPath = poetryConfig['virtualenvs.path'].replace('{cache-dir}', cacheDir);
paths.add(virtualenvsPath);
if (poetryConfig['virtualenvs.in-project']) {
paths.add(path.join(basedir, '.venv'));
}
if (pythonLocation) {
const { exitCode, stderr } = yield exec.getExecOutput('poetry', ['env', 'use', pythonLocation], { ignoreReturnCode: true, cwd: basedir });
if (exitCode) {
utils_1.logWarning(stderr);
}
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
Expand All @@ -66156,6 +66149,30 @@ class PoetryCache extends cache_distributor_1.default {
};
});
}
handleLoadedCache() {
const _super = Object.create(null, {
handleLoadedCache: { get: () => super.handleLoadedCache }
});
return __awaiter(this, void 0, void 0, function* () {
yield _super.handleLoadedCache.call(this);
// After the cache is loaded -- make sure virtualenvs use the correct Python version (the one that we have just installed).
// This will handle invalid caches, recreating virtualenvs if necessary.
const pythonLocation = yield io.which('python');
if (pythonLocation) {
core.debug(`pythonLocation is ${pythonLocation}`);
}
else {
utils_1.logWarning('python binaries were not found in PATH');
return;
}
for (const poetryProject of this.poetryProjects) {
const { exitCode, stderr } = yield exec.getExecOutput('poetry', ['env', 'use', pythonLocation], { ignoreReturnCode: true, cwd: poetryProject });
if (exitCode) {
utils_1.logWarning(stderr);
}
}
});
}
getPoetryConfiguration(basedir) {
return __awaiter(this, void 0, void 0, function* () {
const { stdout, stderr, exitCode } = yield exec.getExecOutput('poetry', ['config', '--list'], { cwd: basedir });
Expand Down
3 changes: 3 additions & 0 deletions src/cache-distributions/cache-distributor.ts
Expand Up @@ -19,6 +19,7 @@ abstract class CacheDistributor {
primaryKey: string;
restoreKey: string[] | undefined;
}>;
protected async handleLoadedCache() {}

public async restoreCache() {
const {primaryKey, restoreKey} = await this.computeKeys();
Expand All @@ -41,6 +42,8 @@ abstract class CacheDistributor {
restoreKey
);

await this.handleLoadedCache();

this.handleMatchResult(matchedKey, primaryKey);
}

Expand Down
50 changes: 30 additions & 20 deletions src/cache-distributions/poetry-cache.ts
Expand Up @@ -10,7 +10,8 @@ import {logWarning} from '../utils';
class PoetryCache extends CacheDistributor {
constructor(
private pythonVersion: string,
protected patterns: string = '**/poetry.lock'
protected patterns: string = '**/poetry.lock',
protected poetryProjects: Set<string> = new Set<string>()
) {
super('poetry', patterns);
}
Expand All @@ -20,16 +21,10 @@ class PoetryCache extends CacheDistributor {
const paths = new Set<string>();
const globber = await glob.create(this.patterns);

const pythonLocation = await io.which('python');
if (pythonLocation) {
core.debug(`pythonLocation is ${pythonLocation}`);
} else {
logWarning('python binaries were not found in PATH');
}

for await (const file of globber.globGenerator()) {
const basedir = path.dirname(file);
core.debug(`Processing Poetry project at ${basedir}`);
this.poetryProjects.add(basedir);

const poetryConfig = await this.getPoetryConfiguration(basedir);

Expand All @@ -44,18 +39,6 @@ class PoetryCache extends CacheDistributor {
if (poetryConfig['virtualenvs.in-project']) {
paths.add(path.join(basedir, '.venv'));
}

if (pythonLocation) {
const {exitCode, stderr} = await exec.getExecOutput(
'poetry',
['env', 'use', pythonLocation],
{ignoreReturnCode: true, cwd: basedir}
);

if (exitCode) {
logWarning(stderr);
}
}
}

return [...paths];
Expand All @@ -71,6 +54,33 @@ class PoetryCache extends CacheDistributor {
};
}

protected async handleLoadedCache() {
await super.handleLoadedCache();

// After the cache is loaded -- make sure virtualenvs use the correct Python version (the one that we have just installed).
// This will handle invalid caches, recreating virtualenvs if necessary.

const pythonLocation = await io.which('python');
if (pythonLocation) {
core.debug(`pythonLocation is ${pythonLocation}`);
} else {
logWarning('python binaries were not found in PATH');
return;
}

for (const poetryProject of this.poetryProjects) {
const {exitCode, stderr} = await exec.getExecOutput(
'poetry',
['env', 'use', pythonLocation],
{ignoreReturnCode: true, cwd: poetryProject}
);

if (exitCode) {
logWarning(stderr);
}
}
}

private async getPoetryConfiguration(basedir: string) {
const {stdout, stderr, exitCode} = await exec.getExecOutput(
'poetry',
Expand Down

0 comments on commit 881ca6e

Please sign in to comment.