Skip to content

Commit

Permalink
feat: support bitbucket-pipelines.yml as container img.image (#751)
Browse files Browse the repository at this point in the history
* feat: support bitbucket-pipelines.yml image and pipes

---------

Signed-off-by: Adam Setch <[email protected]>
  • Loading branch information
setchy authored Nov 30, 2023
1 parent d4b3029 commit ed424be
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 16 deletions.
36 changes: 25 additions & 11 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ import {
MAX_BUFFER,
getNugetMetadata,
frameworksList,
parseContainerFile
parseContainerFile,
parseBitbucketPipelinesFile
} from "./utils.js";
import { spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";
Expand Down Expand Up @@ -3719,6 +3720,11 @@ export const createContainerSpecLikeBom = async (path, options) => {
(options.multiProject ? "**/" : "") + "*Dockerfile*",
options
);
const bbPipelineFiles = getAllFiles(
path,
(options.multiProject ? "**/" : "") + "bitbucket-pipelines.yml",
options
);
const cfFiles = getAllFiles(
path,
(options.multiProject ? "**/" : "") + "*Containerfile*",
Expand Down Expand Up @@ -3747,27 +3753,35 @@ export const createContainerSpecLikeBom = async (path, options) => {
}
// Privado.ai json files
const privadoFiles = getAllFiles(path, ".privado/" + "*.json", options);
// Parse yaml manifest files, dockerfiles or containerfiles
if (dcFiles.length || dfFiles.length || cfFiles.length) {
for (const f of [...dcFiles, ...dfFiles, ...cfFiles]) {

// Parse yaml manifest files, dockerfiles, containerfiles or bitbucket pipeline files
if (
dcFiles.length ||
dfFiles.length ||
cfFiles.length ||
bbPipelineFiles.length
) {
for (const f of [...dcFiles, ...dfFiles, ...cfFiles, ...bbPipelineFiles]) {
if (DEBUG_MODE) {
console.log(`Parsing ${f}`);
}

const dData = readFileSync(f, { encoding: "utf-8" });
let imglist = [];
let imgList = [];
// parse yaml manifest files
if (f.endsWith(".yml") || f.endsWith(".yaml")) {
imglist = parseContainerSpecData(dData);
if (f.endsWith("bitbucket-pipelines.yml")) {
imgList = parseBitbucketPipelinesFile(dData);
} else if (f.endsWith(".yml") || f.endsWith(".yaml")) {
imgList = parseContainerSpecData(dData);
} else {
imglist = parseContainerFile(dData);
imgList = parseContainerFile(dData);
}

if (imglist && imglist.length) {
if (imgList && imgList.length) {
if (DEBUG_MODE) {
console.log("Images identified in", f, "are", imglist);
console.log("Images identified in", f, "are", imgList);
}
for (const img of imglist) {
for (const img of imgList) {
const commonProperties = [
{
name: "SrcFile",
Expand Down
3 changes: 2 additions & 1 deletion server.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ const parseQueryString = (q, body, options = {}) => {
"filter",
"only",
"autoCompositions",
"gitBranch"
"gitBranch",
"active"
];

for (const param of queryParams) {
Expand Down
21 changes: 21 additions & 0 deletions test/data/bitbucket-pipelines.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
image: node:16

definitions:
steps:
- step: &build-step
image: node:18

- step: &build-step-private
image:
name: some.private.org/docker/library/node:20
username: $USERNAME
password: $PASSWORD
email: $EMAIL

- step: &build-step-pipe-deploy
script:
- pipe: atlassian/aws/s3-deploy:0.2.2

- step: &build-step-pipe-deploy-alternate
script:
- pipe: docker://some.private.org/docker/library/some-pipe:1.0.0
70 changes: 67 additions & 3 deletions utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4455,12 +4455,14 @@ export const parseContainerFile = function (fileContents) {
const imgList = [];

let buildStageNames = [];
for (const line of fileContents.split("\n")) {
if (line.trim().startsWith("#")) {
for (let line of fileContents.split("\n")) {
line = line.trim();

if (line.startsWith("#")) {
continue; // skip commented out lines
}

if (line.includes("FROM")) {
if (line.startsWith("FROM")) {
const fromStatement = line.split("FROM")[1].split("AS");

const imageStatement = fromStatement[0].trim();
Expand Down Expand Up @@ -4488,6 +4490,68 @@ export const parseContainerFile = function (fileContents) {
return imgList;
};

export const parseBitbucketPipelinesFile = function (fileContents) {
const imgList = [];

let privateImageBlockFound = false;

for (let line of fileContents.split("\n")) {
line = line.trim();
if (line.startsWith("#")) {
continue; // skip commented out lines
}

// Assume this is a private build image object
if (line.startsWith("name:") && privateImageBlockFound) {
const imageName = line.split("name:").pop().trim();

imgList.push({
image: imageName
});

privateImageBlockFound = false;
}

// Docker image usage
if (line.startsWith("image:")) {
const imageName = line.split("image:").pop().trim();

/**
* Assume this is a private build image object
* See: https://support.atlassian.com/bitbucket-cloud/docs/use-docker-images-as-build-environments/#Using-private-build-images
*/
if (imageName === "") {
privateImageBlockFound = true;
continue;
} else {
/**
* Assume this is a public build image
* See: https://support.atlassian.com/bitbucket-cloud/docs/use-docker-images-as-build-environments/#Using-public-build-images
*/

imgList.push({
image: imageName
});
}
}

// Pipe usage
if (line.startsWith("- pipe:")) {
let pipeName = line.split("- pipe:").pop().trim();

if (pipeName.startsWith("docker://")) {
pipeName = pipeName.replace("docker://", "");
}

imgList.push({
image: pipeName
});
}
}

return imgList;
};

export const parseContainerSpecData = function (dcData) {
const pkgList = [];
const imgList = [];
Expand Down
25 changes: 24 additions & 1 deletion utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ import {
parseSbtTree,
parseCmakeDotFile,
parseCmakeLikeFile,
parseContainerFile
parseContainerFile,
parseBitbucketPipelinesFile
} from "./utils.js";
import { readFileSync } from "node:fs";
import { parse } from "ssri";
Expand Down Expand Up @@ -2753,6 +2754,28 @@ test("parse containerfiles / dockerfiles", async () => {
});
});

test("parse bitbucket-pipelines", async () => {
let dep_list = parseBitbucketPipelinesFile(
readFileSync("./test/data/bitbucket-pipelines.yml", { encoding: "utf-8" })
);
expect(dep_list.length).toEqual(5);
expect(dep_list[0]).toEqual({
image: "node:16"
});
expect(dep_list[1]).toEqual({
image: "node:18"
});
expect(dep_list[2]).toEqual({
image: "some.private.org/docker/library/node:20"
});
expect(dep_list[3]).toEqual({
image: "atlassian/aws/s3-deploy:0.2.2"
});
expect(dep_list[4]).toEqual({
image: "some.private.org/docker/library/some-pipe:1.0.0"
});
});

test("parse cloudbuild data", async () => {
expect(parseCloudBuildData(null)).toEqual([]);
const dep_list = parseCloudBuildData(
Expand Down

0 comments on commit ed424be

Please sign in to comment.