Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

Note: Can be used with `sfdx plugins:install sfdx-hardis@beta` and docker image `hardisgroupcom/sfdx-hardis@beta`

- Add workaround to authenticate with JIRA_PAT on Jira Data Center servers

- [hardis:org:select](https://sfdx-hardis.cloudity.com/hardis/org/select/): Fix default org prompt whose response was ignored.
- New command [hardis:datacloud:sql-query.ts](https://sfdx-hardis.cloudity.com/hardis/datacloud/sql-query/) allowing to query Data Cloud tables with Ansi SQL
- New command [hardis:datacloud:extract:agentforce-feedback.ts](https://sfdx-hardis.cloudity.com/hardis/datacloud/extract/agentforce-feedback/) allowing to generate reports of positive and negative Agentforce chats feedback, with full transcript and notifications.
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,20 @@ Everyone is welcome to contribute to sfdx-hardis (even juniors: we'll assist you
- Run `tsc --watch` to transpile typescript into js everytime you update a TS file
- Debug commands using `NODE_OPTIONS=--inspect-brk sf hardis:somecommand --someparameter somevalue` (you can also debug commands using VsCode Sfdx-Hardis setting)

Note: If you want to test CI with the sfdx-hardis version of your current branch, add the the following script in your pipeline before calling sfdx hardis.

```shell
TEMP_DIR=$(mktemp -d)
git clone https://github.com/hardisgroupcom/sfdx-hardis.git $TEMP_DIR
cd $TEMP_DIR
git checkout fixes/jira_data_center
yarn
npm install typescript -g
tsc
sf plugins link
cd -
```

### VsCode Extension: vscode-sfdx-hardis

- Install Node.js ([recommended version](https://nodejs.org/en/))
Expand Down
14 changes: 14 additions & 0 deletions docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,20 @@ Everyone is welcome to contribute to sfdx-hardis (even juniors: we'll assist you
- Run `tsc --watch` to transpile typescript into js everytime you update a TS file
- Debug commands using `NODE_OPTIONS=--inspect-brk sf hardis:somecommand --someparameter somevalue` (you can also debug commands using VsCode Sfdx-Hardis setting)

Note: If you want to test CI with the sfdx-hardis version of your current branch, add the the following script in your pipeline before calling sfdx hardis.

```shell
TEMP_DIR=$(mktemp -d)
git clone https://github.com/hardisgroupcom/sfdx-hardis.git $TEMP_DIR
cd $TEMP_DIR
git checkout fixes/jira_data_center
yarn
npm install typescript -g
tsc
sf plugins link
cd -
```

### VsCode Extension: vscode-sfdx-hardis

- Install Node.js ([recommended version](https://nodejs.org/en/))
Expand Down
16 changes: 12 additions & 4 deletions src/common/ticketProvider/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,22 @@ import { getConfig } from "../../config/index.js";
export const allTicketProviders = [JiraProvider, GenericTicketingProvider, AzureBoardsProvider];

export abstract class TicketProvider {
static getInstances(config: any): TicketProviderRoot[] {
static instances: TicketProviderRoot[] | null = null;

static async getInstances(config: any): Promise<TicketProviderRoot[]> {
if (this.instances !== null) {
return this.instances;
}
const ticketProviders: TicketProviderRoot[] = [];
for (const provider of allTicketProviders) {
if (provider.isAvailable(config)) {
const providerInstance = new provider(config);
await providerInstance.authenticate();
ticketProviders.push(new provider(config));
}
}
return ticketProviders;
this.instances = ticketProviders;
return this.instances;
}

// Returns all providers ticket references from input string
Expand All @@ -35,7 +43,7 @@ export abstract class TicketProvider {
// Adds ticket info by calling ticket providers APIs when possible
public static async collectTicketsInfo(tickets: Ticket[]): Promise<Ticket[]> {
const config = await getConfig("project");
const ticketProviders = this.getInstances(config);
const ticketProviders = await this.getInstances(config);
if (ticketProviders.length === 0) {
uxLog("error", this, c.grey(`[TicketProvider] No ticket provider has been configured`));
}
Expand All @@ -51,7 +59,7 @@ export abstract class TicketProvider {
// Can be comments on JIRA, and maybe later status changes ? 😊
public static async postDeploymentActions(tickets: Ticket[], org: string, pullRequestInfo: CommonPullRequestInfo | null) {
const config = await getConfig("project");
const ticketProviders = this.getInstances(config);
const ticketProviders = await this.getInstances(config);
for (const ticketProvider of ticketProviders) {
if (ticketProvider.isActive) {
await ticketProvider.postDeploymentComments(tickets, org, pullRequestInfo);
Expand Down
44 changes: 44 additions & 0 deletions src/common/ticketProvider/jiraProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { CommonPullRequestInfo } from "../gitProvider/index.js";
export class JiraProvider extends TicketProviderRoot {
private jiraClient: Version3Client | null = null;
private jiraHost: string | null = null;
private jiraAuthMode: "JIRA_EMAIL+JIRA_TOKEN" | "JIRA_PAT" | "JIRA_PAT(DATA_CENTER_WORKAROUND)";
private jiraIsAuthenticated: boolean = false;

constructor(config: any) {
super();
Expand All @@ -30,6 +32,7 @@ export class JiraProvider extends TicketProviderRoot {
},
};
this.isActive = true;
this.jiraAuthMode = "JIRA_EMAIL+JIRA_TOKEN"
uxLog("log", this, c.grey("[JiraProvider] Using JIRA_EMAIL and JIRA_TOKEN for authentication"));
}
// Personal access token
Expand All @@ -40,6 +43,7 @@ export class JiraProvider extends TicketProviderRoot {
},
};
this.isActive = true;
this.jiraAuthMode = "JIRA_PAT"
uxLog("log", this, c.grey("[JiraProvider] Using JIRA_PAT for authentication"));
}
if (this.isActive) {
Expand Down Expand Up @@ -70,6 +74,46 @@ export class JiraProvider extends TicketProviderRoot {
return "sfdx-hardis JIRA connector";
}

public async authenticate(): Promise<boolean> {
if (!this.jiraClient) {
return false;
}
if (this.jiraIsAuthenticated) {
return true;
}
const user = await this.jiraClient!.myself.getCurrentUser();
if (user?.active) {
this.jiraIsAuthenticated = true;
uxLog("log", this, "JIRA authentication successful with mode: " + this.jiraAuthMode);
return true;
}
if (this.jiraAuthMode === "JIRA_PAT") {
uxLog("log", this, "Authentication failed with JIRA_PAT: trying workaround for Jira Data Center...");
// Override the request method to inject Bearer PAT
const originalSendRequest = this.jiraClient.sendRequest.bind(
this.jiraClient,
);
this.jiraClient.sendRequest = async (
requestConfig: any,
callback: any,
) => {
requestConfig.headers = {
...requestConfig.headers,
Authorization: `Bearer ${getEnvVar("JIRA_PAT")}`,
};
return originalSendRequest(requestConfig, callback);
};
this.jiraAuthMode = "JIRA_PAT(DATA_CENTER_WORKAROUND)";
return this.authenticate();
}
uxLog(
"error",
this,
`JIRA authentication failed with mode ${this.jiraAuthMode}: Active user check failed. ${user ? JSON.stringify(user) : user}`,
);
return false;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
public static async getTicketsFromString(text: string, options = {}): Promise<Ticket[]> {
const tickets: Ticket[] = [];
Expand Down
5 changes: 5 additions & 0 deletions src/common/ticketProvider/ticketProviderRoot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ export abstract class TicketProviderRoot {
throw new SfError("getLabel should be implemented on this call");
}

public async authenticate(): Promise<boolean> {
// Method to override if the ticketing provider requires authentication
return true;
}

public async collectTicketsInfo(tickets: Ticket[]) {
uxLog("warning", this, c.yellow("collectTicketsInfo is not implemented on " + this.getLabel()));
return tickets;
Expand Down
5 changes: 3 additions & 2 deletions src/common/utils/gitUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,9 @@ export async function buildCheckDeployCommitSummary() {
flowDiffMarkdown: commitsSummary.flowDiffMarkdown
};
setPullRequestData(prDataCommitsSummary);
} catch (e3) {
uxLog("warning", this, c.yellow('Unable to compute git summary:\n' + e3));
} catch (e3: any) {
uxLog("warning", this, c.yellow('Unable to compute git summary:\n' + e3.message));
uxLog("log", this, c.grey(e3.stack));
}
}

Expand Down
Loading