Skip to content
Merged
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
112 changes: 112 additions & 0 deletions .github/workflows/terraform-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
name: Terraform CI/CD

on:
pull_request:
branches: [deploy]
push:
branches: [deploy]

permissions:
id-token: write # Required for Azure OIDC
contents: write # Needed to commit manifest updates
pull-requests: write # Needed to open PRs

env:
TF_VAR_application_name: ${{ vars.APPLICATION_NAME }}
TF_VAR_application_oauth_client_id: ${{ secrets.APPLICATION_OAUTH_CLIENT_ID }}
TF_VAR_application_oauth_client_secret: ${{ secrets.APPLICATION_OAUTH_CLIENT_SECRET }}
TF_VAR_location: ${{ vars.AZURE_LOCATION }}
TF_VAR_execution_mode: ci
ACR_NAME: ${{ vars.ACR_NAME }}

jobs:
terraform:
runs-on: ubuntu-latest

steps:
# Checkout repo
- name: Checkout repository
uses: actions/checkout@v4

# Install Terraform
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.10.5

# Temporarily remove repo provider configuration
- name: Disable repo azurerm provider
working-directory: terraform/azure
run: mv providers.tf providers.tf.bak

# Create CI-only backend + OIDC provider
- name: Create CI Azure backend/provider
working-directory: terraform/azure
run: |
cat <<EOF > azure_ci.tf
terraform {
backend "azurerm" {}
}

provider "azurerm" {
features {}
}
EOF

- name: Configure Azure OIDC environment
run: |
echo "ARM_USE_OIDC=true" >> $GITHUB_ENV
echo "ARM_CLIENT_ID=${{ secrets.AZURE_CLIENT_ID }}" >> $GITHUB_ENV
echo "ARM_TENANT_ID=${{ secrets.AZURE_TENANT_ID }}" >> $GITHUB_ENV
echo "ARM_SUBSCRIPTION_ID=${{ secrets.AZURE_SUBSCRIPTION_ID }}" >> $GITHUB_ENV

- name: Azure Login
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

- name: Login to ACR
run: |
TOKEN=$(az acr login --name ${{ env.ACR_NAME }} --expose-token --output tsv --query accessToken)
docker login -u 00000000-0000-0000-0000-000000000000 --password-stdin ${{ env.ACR_NAME }}.azurecr.io <<< $TOKEN

- name: Terraform Init
working-directory: terraform/azure
run: |
terraform init -upgrade -reconfigure\
-backend-config="resource_group_name=${{ vars.AZURE_RG }}" \
-backend-config="storage_account_name=${{ vars.AZURE_STORAGE_ACCOUNT }}" \
-backend-config="container_name=${{ vars.AZURE_CONTAINER }}" \
-backend-config="key=${{ vars.AZURE_TFSTATE_KEY }}" \
-backend-config="use_oidc=true"

- name: Debug backend values
run: |
terraform state pull | head -20
echo "RG=${{ vars.AZURE_RG }}"
echo "SA=${{ vars.AZURE_STORAGE_ACCOUNT }}"
echo "CONTAINER=${{ vars.AZURE_CONTAINER }}"
echo "KEY=${{ vars.AZURE_TFSTATE_KEY }}"

# Terraform plan (PR only)
- name: Terraform Plan
if: github.event_name == 'pull_request'
working-directory: terraform/azure
run: terraform plan -out=tfplan

# Terraform apply (merge to main only)
- name: Terraform Apply
if: github.event_name == 'push'
working-directory: terraform/azure
run: |
terraform plan -out=tfplan
terraform apply -auto-approve tfplan

# Cleanup CI-only files
- name: Cleanup CI Terraform files
working-directory: terraform/azure
run: |
rm -f azure_ci.tf
mv providers.tf.bak providers.tf
14 changes: 9 additions & 5 deletions src/services/dataio.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,15 +200,19 @@ export const searchRecords = (req: IReq<SearchRecordsBody>, res: IRes): IRes =>
}
const db: FileDB = new FileDB(generateFilePath(query.from));
const data: object[] = db.readFile();
const index: number = QueryExecutor.execute(query, data);
if (index === -1) {
const indices: number[] = QueryExecutor.executeAll(query, data);
if (!indices || indices.length === 0) {
console.log('No results found');
return res.json({ records: [] })
}
const dataResult: object = data[index];
convertDateToISO8601(dataResult, query.from);

return res.json({ records: [ResultRehydrator.filterAndRehydrate(query.attributesToSelect, data[index])] });
const records = indices.map((idx: number) => {
const record: object = data[idx];
convertDateToISO8601(record, query.from);
return ResultRehydrator.filterAndRehydrate(query.attributesToSelect, record);
});

return res.json({ records });
} catch (err) {
console.log(`Encountered an error searching data: ${err.message}`);
return res.status(500).json(generateErrorResponse(ErrorCode.INTERNAL_ERROR, err)).send();
Expand Down
17 changes: 17 additions & 0 deletions src/utils/queryExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,23 @@ export class QueryExecutor {
return -1;
}

/**
* Executes a query on the given input data and returns all matching indices.
* @param {IQuery} query - The query to execute.
* @param {object[]} inputData - The data to query against.
* @returns {number[]} An array of indices for matching records (empty if none).
*/
public static executeAll(query: IQuery, inputData: object[]): number[] {
const operation: OperationUnion = query.queryFilter.operation;
const results: number[] = [];
for (let index: number = 0; index < inputData.length; index++) {
if (this.evaluateOperation(operation, inputData[index])) {
results.push(index);
}
}
return results;
}

/**
* Evaluates an operation on a given record.
* @param {OperationUnion} operation - The operation to evaluate.
Expand Down
1 change: 1 addition & 0 deletions terraform/azure/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ module "manifest" {
"${basename(dirname(var.manifest_files_paths[count.index]))}.${basename(var.manifest_files_paths[count.index])}"
])

execution_mode = var.execution_mode
client_id = local.application_oauth_client_id
client_secret = local.application_oauth_client_secret
base_url = local.application_service_url
Expand Down
6 changes: 6 additions & 0 deletions terraform/azure/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,9 @@ variable "tags" {
description = "A map of the tags to apply to various resources"
default = {}
}

variable "execution_mode" {
description = "Execution mode: 'local' or 'ci'"
type = string
default = "local"
}
8 changes: 6 additions & 2 deletions terraform/common/modules/template/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@ locals {
]...
)
])

output_file_path = nonsensitive(local_sensitive_file.this.filename != "/dev/null" ? local_sensitive_file.this.filename : "")
}

resource "local_sensitive_file" "this" {
count = var.execution_mode == "local" ? 1 : 0
content = local.output_file_content
filename = local.enabled ? var.output_file_path : "/dev/null"
}

output "manifest_file_path" {
description = "The intended output file path"
value = var.output_file_path
}
2 changes: 1 addition & 1 deletion terraform/common/modules/template/outputs.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
output "output_file_path" {
description = "The absolute path to the output file"
value = local.output_file_path
value = var.output_file_path
}
11 changes: 11 additions & 0 deletions terraform/common/modules/template/variables.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
variable "execution_mode" {
description = "Controls whether Terraform writes manifests to disk (local) or only renders them (ci)"
type = string
default = "local"

validation {
condition = contains(["local", "ci"], var.execution_mode)
error_message = "execution_mode must be 'local' or 'ci'."
}
}

variable "input_file_path" {
description = "The absolute path to the input file. If it doesn't exist, the module will not do anything"
type = string
Expand Down