Skip to content

Commit 378d130

Browse files
committed
oci action
1 parent a627dfa commit 378d130

6 files changed

Lines changed: 129 additions & 17 deletions

File tree

.github/devcontainers-action/action.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ inputs:
4444
required: false
4545
default: "false"
4646
description: "Publish release artifacts (classic)"
47+
publish-to-oci:
48+
required: false
49+
default: "false"
50+
description: "Publish to OCI?"
4751

4852
runs:
4953
using: 'node16'

.github/devcontainers-action/dist/index.js

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,12 @@ function run() {
216216
const shouldTagIndividualFeatures = core.getInput('tag-individual-features').toLowerCase() === 'true';
217217
const shouldPublishToNPM = core.getInput('publish-to-npm').toLowerCase() === 'true';
218218
const shouldPublishReleaseArtifacts = core.getInput('publish-release-artifacts').toLowerCase() === 'true';
219+
const shouldPublishToOCI = core.getInput('publish-to-oci').toLowerCase() === 'true';
219220
const opts = {
220221
shouldTagIndividualFeatures,
221222
shouldPublishToNPM,
222-
shouldPublishReleaseArtifacts
223+
shouldPublishReleaseArtifacts,
224+
shouldPublishToOCI
223225
};
224226
const featuresBasePath = core.getInput('base-path-to-features');
225227
const templatesBasePath = core.getInput('base-path-to-templates');
@@ -440,9 +442,45 @@ function addCollectionsMetadataFile(featuresMetadata, templatesMetadata) {
440442
});
441443
}
442444
exports.addCollectionsMetadataFile = addCollectionsMetadataFile;
445+
function pushArtifactToOCI(repositoryOwner, version, featureName, artifactPath) {
446+
return __awaiter(this, void 0, void 0, function* () {
447+
const exec = (0, util_1.promisify)(child_process.exec);
448+
const ociRepo = `${repositoryOwner}/${featureName}:${version}`;
449+
try {
450+
const cmd = `oras push ghcr.io/${ociRepo} \
451+
--manifest-config /dev/null:application/vnd.devcontainers \
452+
./${artifactPath}:application/vnd.devcontainers.layer.v1+tar`;
453+
yield exec(cmd);
454+
console.log(`Pushed artifact to '${ociRepo}'`);
455+
}
456+
catch (error) {
457+
if (error instanceof Error)
458+
core.setFailed(`Failed to push '${ociRepo}': ${error.message}`);
459+
}
460+
});
461+
}
462+
function loginToGHCR() {
463+
return __awaiter(this, void 0, void 0, function* () {
464+
const exec = (0, util_1.promisify)(child_process.exec);
465+
// Get GITHUB_TOKEN from environment
466+
const githubToken = process.env.GITHUB_TOKEN;
467+
if (!githubToken) {
468+
core.setFailed('GITHUB_TOKEN environment variable is not set.');
469+
return;
470+
}
471+
try {
472+
yield exec(`oras login ghcr.io -u USERNAME -p ${githubToken}`);
473+
console.log('Oras logged in successfully!');
474+
}
475+
catch (error) {
476+
if (error instanceof Error)
477+
core.setFailed(` Oras login failed!`);
478+
}
479+
});
480+
}
443481
function getFeaturesAndPackage(basePath, opts) {
444482
return __awaiter(this, void 0, void 0, function* () {
445-
const { shouldPublishToNPM, shouldTagIndividualFeatures, shouldPublishReleaseArtifacts } = opts;
483+
const { shouldPublishToNPM, shouldTagIndividualFeatures, shouldPublishReleaseArtifacts, shouldPublishToOCI } = opts;
446484
const featureDirs = fs.readdirSync(basePath);
447485
let metadatas = [];
448486
const exec = (0, util_1.promisify)(child_process.exec);
@@ -464,6 +502,24 @@ function getFeaturesAndPackage(basePath, opts) {
464502
}
465503
metadatas.push(featureMetadata);
466504
const sourceInfo = getGitHubMetadata();
505+
if (!sourceInfo.owner) {
506+
core.setFailed('Could not determine repository owner.');
507+
return;
508+
}
509+
const archiveName = `${f}.tgz`;
510+
// ---- PUBLISH RELEASE ARTIFACTS (classic method) ----
511+
if (shouldPublishReleaseArtifacts || shouldPublishToOCI) {
512+
core.info(`** Tar'ing feature`);
513+
yield tarDirectory(featureFolder, archiveName);
514+
}
515+
// ---- PUBLISH TO NPM ----
516+
if (shouldPublishToOCI) {
517+
core.info(`** Publishing to OCI`);
518+
// HACK TO GET THE GITHUB UI TO NOT 500
519+
// END HACK
520+
yield loginToGHCR();
521+
yield pushArtifactToOCI(sourceInfo.owner, featureMetadata.version, f, archiveName);
522+
}
467523
// ---- TAG INDIVIDUAL FEATURES ----
468524
if (shouldTagIndividualFeatures) {
469525
core.info(`** Tagging individual feature`);
@@ -498,12 +554,6 @@ function getFeaturesAndPackage(basePath, opts) {
498554
core.error(`${publishOutput.stderr}`);
499555
}
500556
}
501-
// ---- PUBLISH RELEASE ARTIFACTS (classic method) ----
502-
if (shouldPublishReleaseArtifacts) {
503-
core.info(`** Publishing release`);
504-
const archiveName = `${f}.tgz`;
505-
yield tarDirectory(featureFolder, archiveName);
506-
}
507557
}
508558
})));
509559
if (metadatas.length === 0) {

.github/devcontainers-action/dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/devcontainers-action/lib/main.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,12 @@ function run() {
5050
const shouldTagIndividualFeatures = core.getInput('tag-individual-features').toLowerCase() === 'true';
5151
const shouldPublishToNPM = core.getInput('publish-to-npm').toLowerCase() === 'true';
5252
const shouldPublishReleaseArtifacts = core.getInput('publish-release-artifacts').toLowerCase() === 'true';
53+
const shouldPublishToOCI = core.getInput('publish-to-oci').toLowerCase() === 'true';
5354
const opts = {
5455
shouldTagIndividualFeatures,
5556
shouldPublishToNPM,
56-
shouldPublishReleaseArtifacts
57+
shouldPublishReleaseArtifacts,
58+
shouldPublishToOCI
5759
};
5860
const featuresBasePath = core.getInput('base-path-to-features');
5961
const templatesBasePath = core.getInput('base-path-to-templates');

.github/devcontainers-action/lib/utils.js

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,45 @@ function addCollectionsMetadataFile(featuresMetadata, templatesMetadata) {
149149
});
150150
}
151151
exports.addCollectionsMetadataFile = addCollectionsMetadataFile;
152+
function pushArtifactToOCI(repositoryOwner, version, featureName, artifactPath) {
153+
return __awaiter(this, void 0, void 0, function* () {
154+
const exec = (0, util_1.promisify)(child_process.exec);
155+
const ociRepo = `${repositoryOwner}/${featureName}:${version}`;
156+
try {
157+
const cmd = `oras push ghcr.io/${ociRepo} \
158+
--manifest-config /dev/null:application/vnd.devcontainers \
159+
./${artifactPath}:application/vnd.devcontainers.layer.v1+tar`;
160+
yield exec(cmd);
161+
console.log(`Pushed artifact to '${ociRepo}'`);
162+
}
163+
catch (error) {
164+
if (error instanceof Error)
165+
core.setFailed(`Failed to push '${ociRepo}': ${error.message}`);
166+
}
167+
});
168+
}
169+
function loginToGHCR() {
170+
return __awaiter(this, void 0, void 0, function* () {
171+
const exec = (0, util_1.promisify)(child_process.exec);
172+
// Get GITHUB_TOKEN from environment
173+
const githubToken = process.env.GITHUB_TOKEN;
174+
if (!githubToken) {
175+
core.setFailed('GITHUB_TOKEN environment variable is not set.');
176+
return;
177+
}
178+
try {
179+
yield exec(`oras login ghcr.io -u USERNAME -p ${githubToken}`);
180+
console.log('Oras logged in successfully!');
181+
}
182+
catch (error) {
183+
if (error instanceof Error)
184+
core.setFailed(` Oras login failed!`);
185+
}
186+
});
187+
}
152188
function getFeaturesAndPackage(basePath, opts) {
153189
return __awaiter(this, void 0, void 0, function* () {
154-
const { shouldPublishToNPM, shouldTagIndividualFeatures, shouldPublishReleaseArtifacts } = opts;
190+
const { shouldPublishToNPM, shouldTagIndividualFeatures, shouldPublishReleaseArtifacts, shouldPublishToOCI } = opts;
155191
const featureDirs = fs.readdirSync(basePath);
156192
let metadatas = [];
157193
const exec = (0, util_1.promisify)(child_process.exec);
@@ -173,6 +209,24 @@ function getFeaturesAndPackage(basePath, opts) {
173209
}
174210
metadatas.push(featureMetadata);
175211
const sourceInfo = getGitHubMetadata();
212+
if (!sourceInfo.owner) {
213+
core.setFailed('Could not determine repository owner.');
214+
return;
215+
}
216+
const archiveName = `${f}.tgz`;
217+
// ---- PUBLISH RELEASE ARTIFACTS (classic method) ----
218+
if (shouldPublishReleaseArtifacts || shouldPublishToOCI) {
219+
core.info(`** Tar'ing feature`);
220+
yield tarDirectory(featureFolder, archiveName);
221+
}
222+
// ---- PUBLISH TO NPM ----
223+
if (shouldPublishToOCI) {
224+
core.info(`** Publishing to OCI`);
225+
// HACK TO GET THE GITHUB UI TO NOT 500
226+
// END HACK
227+
yield loginToGHCR();
228+
yield pushArtifactToOCI(sourceInfo.owner, featureMetadata.version, f, archiveName);
229+
}
176230
// ---- TAG INDIVIDUAL FEATURES ----
177231
if (shouldTagIndividualFeatures) {
178232
core.info(`** Tagging individual feature`);
@@ -207,12 +261,6 @@ function getFeaturesAndPackage(basePath, opts) {
207261
core.error(`${publishOutput.stderr}`);
208262
}
209263
}
210-
// ---- PUBLISH RELEASE ARTIFACTS (classic method) ----
211-
if (shouldPublishReleaseArtifacts) {
212-
core.info(`** Publishing release`);
213-
const archiveName = `${f}.tgz`;
214-
yield tarDirectory(featureFolder, archiveName);
215-
}
216264
}
217265
})));
218266
if (metadatas.length === 0) {

.github/workflows/release-oci.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ jobs:
1111
steps:
1212
- uses: actions/checkout@v2
1313

14+
- name: Install Oras
15+
run: |
16+
curl -LO https://github.com/oras-project/oras/releases/download/v0.13.0/oras_0.13.0_linux_amd64.tar.gz
17+
mkdir -p oras-install/
18+
tar -zxf oras_0.13.0_*.tar.gz -C oras-install/
19+
mv oras-install/oras /usr/local/bin/
20+
rm -rf oras_0.13.0_*.tar.gz oras-install/
21+
1422
- name: "Publish features to OCI"
1523
uses: ./.github/devcontainers-action # TODO: Once 'devcontainers/action' is published, use that.
1624
with:

0 commit comments

Comments
 (0)