pipeline changes, preparing to dockerize etc
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
export JOPLIN_HOST="localhost"
|
export JOPLIN_HOST="localhost"
|
||||||
export JOPLIN_PORT="41185"
|
export JOPLIN_PORT="41185"
|
||||||
export JOPLIN_API_TOKEN="3f01c4a9f06f7696178b1b93b2db4e3d5b85d42ad35308dcf036670c97aff77c4062bb4454addbc98d0bc01142d5b530171ae47e5c650598aa82ca5b8c51ac3e"
|
|
||||||
|
export JOPLIN_SOURCE_NOTE_TITLE="DSR-Template"
|
||||||
export JOPLIN_NOTE_TITLE="DSR-Template"
|
export JOPLIN_TARGET_NOTEBOOK="Today"
|
||||||
export JOPLIN_NOTEBOOK_PATH="Today"
|
|
||||||
|
@@ -1,19 +1,19 @@
|
|||||||
# Data Gathering for the @ReachableCEO daily stakeholder report
|
# Data Gathering for the @ReachableCEO daily stakeholder report
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
I'm trying to life a fully instrumented CTO/founder life and #buildInPublic. And unlike most of the founders doing so, I'm actually publishing daily reports and live streaming my workstation all dya.
|
I'm trying to life a fully instrumented CTO/founder life and #buildInPublic. And unlike most of the founders doing so, I'm actually publishing daily reports and live streaming my workstation all dya.
|
||||||
|
|
||||||
I want to automate the instrumentation/reporting process as much as possible to get the highest fidelity information for stakeholders consumption.
|
I want to automate the instrumentation/reporting process as much as possible to get the highest fidelity information for stakeholders consumption.
|
||||||
|
|
||||||
## Data sources
|
## Data sources
|
||||||
|
|
||||||
- Apple Health (exporting via AutoHealthExport)
|
- Apple Health (exporting via AutoHealthExport)
|
||||||
- Workout (evaluating a cou
|
- Workout (evaluating a cou
|
||||||
- Nutrition
|
- Nutrition
|
||||||
- Daily habit tracking
|
- Daily habit tracking
|
||||||
- ActivityWatch
|
- ActivityWatch
|
||||||
- WakaAPI
|
- WakaAPI
|
||||||
|
|
||||||
|
|
||||||
## Scripts
|
## Scripts
|
@@ -1,83 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Script to query Gitea API for a user's activity on a specific date
|
|
||||||
|
|
||||||
########################################################################################################
|
|
||||||
#Obtain gitea api key from bitwarden
|
|
||||||
########################################################################################################
|
|
||||||
|
|
||||||
####################################
|
|
||||||
## Step 0: Set to use tsys server
|
|
||||||
####################################
|
|
||||||
bw logout
|
|
||||||
|
|
||||||
echo "Setting cli to use tsys bitwarden server..."
|
|
||||||
bw config server https://pwvault.turnsys.com
|
|
||||||
|
|
||||||
####################################
|
|
||||||
## Step 1: login to bitwarden
|
|
||||||
####################################
|
|
||||||
|
|
||||||
# From: https://bitwarden.com/help/cli/#using-an-api-key
|
|
||||||
|
|
||||||
### Set apikey environment varaible
|
|
||||||
|
|
||||||
echo "Sourcing clientid/apikey data..."
|
|
||||||
source D:/tsys/secrets/bitwarden/data/apikey-bitwarden-reachableceo
|
|
||||||
|
|
||||||
### Login to vault using apikey...
|
|
||||||
|
|
||||||
echo "Logging in..."
|
|
||||||
bw login --apikey $BW_CLIENTID $BW_CLIENTSECRET
|
|
||||||
|
|
||||||
### Step 1.1: unlock / save session id
|
|
||||||
|
|
||||||
echo "Unlocking..."
|
|
||||||
export BW_SESSION="$(bw unlock --passwordenv TSYS_BW_PASSWORD_REACHABLECEO --raw)"
|
|
||||||
|
|
||||||
|
|
||||||
### Step 2: retrive a value into an environment variable
|
|
||||||
|
|
||||||
export GITEA_APIKEY="$(bw get password APIKEY-Gitea)"
|
|
||||||
|
|
||||||
########################################################################################################
|
|
||||||
# Accrss gitea data
|
|
||||||
########################################################################################################
|
|
||||||
|
|
||||||
# Script to query Gitea API for a user's activity on a specific date
|
|
||||||
|
|
||||||
# Usage: ./get_gitea_user_activity.sh <username> <date> [GITEA_URL] [TOKEN]
|
|
||||||
|
|
||||||
# Set username, date, and default Gitea URL
|
|
||||||
USERNAME="${1:-reachableceo}" # Default to "reachableceo" if not provided
|
|
||||||
DATE="${2:-$(date +%Y-%m-%d)}" # Default to today's date if not provided
|
|
||||||
GITEA_URL="${3:-https://git.knownelement.com}" # Default Gitea URL if not provided
|
|
||||||
TOKEN="${GITEA_APIKEY}" # Use APIKEY-GItea or passed argument
|
|
||||||
|
|
||||||
# API Endpoint for user activities
|
|
||||||
API_ENDPOINT="$GITEA_URL/api/v1/users/$USERNAME/timeline"
|
|
||||||
|
|
||||||
# Make the API call
|
|
||||||
if [ -n "$TOKEN" ]; then
|
|
||||||
# If token is provided, use it in the Authorization header
|
|
||||||
RESPONSE=$(curl -s -H "Authorization: token $TOKEN" "$API_ENDPOINT")
|
|
||||||
else
|
|
||||||
# If no token is provided, make an unauthenticated request
|
|
||||||
RESPONSE=$(curl -s "$API_ENDPOINT")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for API errors
|
|
||||||
if [[ "$RESPONSE" == "Not found" || -z "$RESPONSE" ]]; then
|
|
||||||
echo "Error: User '$USERNAME' not found, or endpoint is incorrect."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Validate JSON response
|
|
||||||
if ! echo "$RESPONSE" | jq empty >/dev/null 2>&1; then
|
|
||||||
echo "Error: Invalid JSON response from Gitea API."
|
|
||||||
echo "Response: $RESPONSE"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Filter the activity by date using jq
|
|
||||||
echo "$RESPONSE" | jq --arg date "$DATE" '[.[] | select(.created_at | startswith($date))]'
|
|
@@ -1,59 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Functions
|
|
||||||
|
|
||||||
# Search for a note by title and return its ID
|
|
||||||
search_note() {
|
|
||||||
local title="$1"
|
|
||||||
echo "Searching for note with title: $title"
|
|
||||||
note_id=$(joplin search "$title" --fields id --limit 1 --json | jq -r '.[0].id')
|
|
||||||
|
|
||||||
if [[ -z "$note_id" || "$note_id" == "null" ]]; then
|
|
||||||
echo "Error: Note with title '$title' not found."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Found note with ID: $note_id"
|
|
||||||
echo "$note_id"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Export the note by ID to the specified directory
|
|
||||||
export_note() {
|
|
||||||
local note_id="$1"
|
|
||||||
local output_dir="$2"
|
|
||||||
|
|
||||||
echo "Exporting note ID: $note_id to directory: $output_dir"
|
|
||||||
mkdir -p "$output_dir" || {
|
|
||||||
echo "Error: Unable to create directory $output_dir"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Export the note with attachments to the specified directory
|
|
||||||
joplin export "$note_id" --format md --output "$output_dir" || {
|
|
||||||
echo "Error: Failed to export note ID $note_id"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "Note exported successfully to $output_dir"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Main function
|
|
||||||
main() {
|
|
||||||
if [[ $# -lt 2 ]]; then
|
|
||||||
echo "Usage: $0 <note-title> <output-directory>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local note_title="$1"
|
|
||||||
local output_dir="$2"
|
|
||||||
|
|
||||||
# Search for the note and get its ID
|
|
||||||
local note_id
|
|
||||||
note_id=$(search_note "$note_title")
|
|
||||||
|
|
||||||
# Export the note
|
|
||||||
export_note "$note_id" "$output_dir"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Run the main function with all script arguments
|
|
||||||
main "$@"
|
|
@@ -1,315 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Use the Joplin API and create a new daily stakeholder report from the DSR-Template joplin note and place it in the today notebook
|
|
||||||
|
|
||||||
# Created by chatgpt
|
|
||||||
# v1 https://chatgpt.com/share/6750c7df-6b2c-8005-a91c-1bc5b3875170
|
|
||||||
# i have learned much more about chatpgpt/prompting etc in the interim and give you
|
|
||||||
# V2 on 12/18/2024: https://chatgpt.com/share/676337f2-7414-8005-b3cc-9cc5b6e5ec18
|
|
||||||
# v2.1 https://chatgpt.com/share/676337f2-7414-8005-b3cc-9cc5b6e5ec18
|
|
||||||
|
|
||||||
####################################################
|
|
||||||
# Start of script
|
|
||||||
####################################################
|
|
||||||
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Copyright (C) $(date +%Y) ReachableCEO Enterprises LLC
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# Create a log file with the current date and time
|
|
||||||
LOG_FILE="dsr-log-$(date +%Y%m%d-%H%M%S).log"
|
|
||||||
exec > >(tee -a "$LOG_FILE") 2>&1
|
|
||||||
|
|
||||||
# Source environment variables
|
|
||||||
ENV_FILE="../DSRVariables.env"
|
|
||||||
echo "[INFO] Sourcing environment variables from $ENV_FILE."
|
|
||||||
if [[ ! -f "$ENV_FILE" ]]; then
|
|
||||||
|
|
||||||
echo "Error: Environment file not found at $ENV_FILE." >&2
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
source "$ENV_FILE"
|
|
||||||
|
|
||||||
echo "[INFO] Environment variables sourced successfully."
|
|
||||||
|
|
||||||
# Ensure required variables are set
|
|
||||||
REQUIRED_VARS=(JOPLIN_NOTE_TITLE JOPLIN_HOST JOPLIN_PORT JOPLIN_NOTEBOOK_PATH)
|
|
||||||
for var in "${REQUIRED_VARS[@]}"; do
|
|
||||||
|
|
||||||
if [[ -z "${!var}" ]]; then
|
|
||||||
|
|
||||||
echo "Error: $var is not set or is null. Please check your environment file." >&2
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "[INFO] Required variables are set."
|
|
||||||
|
|
||||||
# Function to get notebook ID by path
|
|
||||||
|
|
||||||
function get_notebook_id()
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
local path="$1"
|
|
||||||
|
|
||||||
echo "[INFO] Fetching notebook ID for path: $path." >&2
|
|
||||||
|
|
||||||
# Fetch all notebook folders
|
|
||||||
local folders
|
|
||||||
folders=$(curl -sf -X GET \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
"http://$JOPLIN_HOST:$JOPLIN_PORT/folders?token=$JOPLIN_API_TOKEN")
|
|
||||||
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
|
|
||||||
echo "Error: Failed to fetch folders from Joplin." >&2
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "[DEBUG] Available folders:" >&2
|
|
||||||
echo "$folders" | jq -r '.items[] | .title' >&2
|
|
||||||
|
|
||||||
# Match the exact folder
|
|
||||||
local result
|
|
||||||
result=$(echo "$folders" | jq -r ".items[] | select(.title == \"$path\") | .id")
|
|
||||||
|
|
||||||
if [[ $? -ne 0 || -z "$result" ]]; then
|
|
||||||
|
|
||||||
echo "Error: No matching notebook found for path: $path. Available notebooks are listed above." >&2
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "[INFO] Notebook ID for path $path: $result." >&2
|
|
||||||
echo "$result"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
# Function to get a note by title, handling pagination
|
|
||||||
|
|
||||||
function get_note_by_title()
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
echo "[INFO] Fetching note by title: $JOPLIN_NOTE_TITLE." >&2
|
|
||||||
local raw_response="[]"
|
|
||||||
local page=1
|
|
||||||
|
|
||||||
while :; do
|
|
||||||
|
|
||||||
echo "[DEBUG] Fetching page: $page" >&2
|
|
||||||
local response
|
|
||||||
response=$(curl -sf -X GET \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
"http://$JOPLIN_HOST:$JOPLIN_PORT/notes?token=$JOPLIN_API_TOKEN&page=$page")
|
|
||||||
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
|
|
||||||
echo "Error: Failed to fetch notes from Joplin." >&2
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Extract items and merge them
|
|
||||||
local items
|
|
||||||
items=$(echo "$response" | jq -c '.items')
|
|
||||||
|
|
||||||
if [[ "$items" == "[]" ]]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
|
|
||||||
raw_response=$(echo "$raw_response" "$items" | jq -s 'add')
|
|
||||||
page=$((page + 1))
|
|
||||||
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "[DEBUG] Consolidated note JSON: $raw_response" >&2
|
|
||||||
|
|
||||||
# List all note titles for debugging
|
|
||||||
echo "[DEBUG] Available note titles:" >&2
|
|
||||||
echo "$raw_response" | jq -r '.[] | .title' >&2
|
|
||||||
|
|
||||||
# Perform case-insensitive matching
|
|
||||||
local result
|
|
||||||
result=$(echo "$raw_response" | jq -c ".[] | select(.title | ascii_downcase == \"$(echo $JOPLIN_NOTE_TITLE | tr '[:upper:]' '[:lower:]')\")")
|
|
||||||
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
|
|
||||||
echo "Error: Failed to parse JSON response." >&2
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "$result" ]]; then
|
|
||||||
|
|
||||||
echo "Error: No note found with title $JOPLIN_NOTE_TITLE. Check if the title is correct and exists in Joplin." >&2
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "[DEBUG] Matched note JSON: $result" >&2
|
|
||||||
echo "$result"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
# Function to create a new note
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function create_new_note()
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
local title="$1"
|
|
||||||
local body="$2"
|
|
||||||
local parent_id="$3"
|
|
||||||
|
|
||||||
echo "[INFO] Creating a new note with title: $title." >&2
|
|
||||||
curl -sf -X POST \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "$(jq -n --arg title "$title" --arg body "$body" --arg parent_id "$parent_id" \
|
|
||||||
'{title: $title, body: $body, parent_id: $parent_id}')" \
|
|
||||||
"http://$JOPLIN_HOST:$JOPLIN_PORT/notes?token=$JOPLIN_API_TOKEN"
|
|
||||||
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
|
|
||||||
echo "Error: Failed to create the note titled $title." >&2
|
|
||||||
echo "[DEBUG] Body content passed to the API: $body" >&2
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "[INFO] Note titled $title created successfully." >&2
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
# Main function to clone the note
|
|
||||||
|
|
||||||
function clone_note_with_date()
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
echo "[INFO] Starting the note cloning process." >&2
|
|
||||||
local current_date
|
|
||||||
current_date=$(date +%Y-%m-%d)
|
|
||||||
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
|
|
||||||
echo "Error: Failed to retrieve the current date." >&2
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "[INFO] Current date retrieved: $current_date." >&2
|
|
||||||
local new_title="DSR-$current_date"
|
|
||||||
|
|
||||||
echo "[INFO] Fetching original note by title: $JOPLIN_NOTE_TITLE." >&2
|
|
||||||
local original_note
|
|
||||||
original_note=$(get_note_by_title)
|
|
||||||
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
|
|
||||||
echo "Error: Failed to fetch the note with title $JOPLIN_NOTE_TITLE." >&2
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "[DEBUG] Raw original note JSON: $original_note" >&2
|
|
||||||
|
|
||||||
# Extract the note ID
|
|
||||||
local note_id
|
|
||||||
note_id=$(echo "$original_note" | jq -r '.id')
|
|
||||||
|
|
||||||
if [[ $? -ne 0 || -z "$note_id" ]]; then
|
|
||||||
|
|
||||||
echo "Error: Failed to extract note ID from the original note." >&2
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "[INFO] Fetching full details of the note with ID: $note_id." >&2
|
|
||||||
local full_note
|
|
||||||
full_note=$(curl -sf -X GET \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
"http://$JOPLIN_HOST:$JOPLIN_PORT/notes/$note_id?token=$JOPLIN_API_TOKEN")
|
|
||||||
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
|
|
||||||
echo "Error: Failed to fetch full details of the note with ID: $note_id." >&2
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "[DEBUG] Full note JSON: $full_note" >&2
|
|
||||||
|
|
||||||
# Extract 'body' from the full note
|
|
||||||
local body
|
|
||||||
body=$(echo "$full_note" | jq -r '.body // "[No content]"')
|
|
||||||
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
|
|
||||||
echo "Error: Failed to extract body from the note details." >&2
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "[INFO] Extracted body: $body" >&2
|
|
||||||
|
|
||||||
echo "[INFO] Fetching notebook ID for path: $JOPLIN_NOTEBOOK_PATH." >&2
|
|
||||||
local notebook_id
|
|
||||||
notebook_id=$(get_notebook_id "$JOPLIN_NOTEBOOK_PATH")
|
|
||||||
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
|
|
||||||
echo "Error: Failed to fetch notebook ID for path $JOPLIN_NOTEBOOK_PATH." >&2
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "[INFO] Notebook ID retrieved: $notebook_id. Creating the new note." >&2
|
|
||||||
|
|
||||||
create_new_note "$new_title" "$body" "$notebook_id"
|
|
||||||
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
|
|
||||||
echo "Error: Failed to create the note titled $new_title." >&2
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "[INFO] Successfully cloned note to $new_title in notebook $JOPLIN_NOTEBOOK_PATH." >&2
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
# Main function
|
|
||||||
|
|
||||||
function main()
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
echo "[INFO] Script execution started." >&2
|
|
||||||
clone_note_with_date
|
|
||||||
echo "[INFO] Script execution completed successfully." >&2
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
@@ -1,114 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Written by ChatGPT
|
|
||||||
# https://chatgpt.com/share/6750c7df-6b2c-8005-a91c-1bc5b3875170
|
|
||||||
|
|
||||||
# Prompt:
|
|
||||||
# Pull any issues from Redmine that have a due date of today via API
|
|
||||||
|
|
||||||
# shellcheck disable=SC1090
|
|
||||||
|
|
||||||
# Bash3 Boilerplate Setup
|
|
||||||
set -o errexit
|
|
||||||
set -o nounset
|
|
||||||
set -o pipefail
|
|
||||||
IFS=$'\n\t'
|
|
||||||
|
|
||||||
# Constants
|
|
||||||
readonly SCRIPT_NAME=$(basename "$0")
|
|
||||||
readonly SCRIPT_VERSION="1.0"
|
|
||||||
readonly SCRIPT_AUTHOR="Charles N Wyble"
|
|
||||||
readonly SCRIPT_DESC="Pull Redmine issues with a due date of today and output in Markdown"
|
|
||||||
|
|
||||||
# Logging and Debugging
|
|
||||||
readonly LOG_FILE="/tmp/${SCRIPT_NAME}.log"
|
|
||||||
readonly TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
|
|
||||||
info() { echo "[INFO] [$TIMESTAMP] $*" | tee -a "$LOG_FILE"; }
|
|
||||||
error() { echo "[ERROR] [$TIMESTAMP] $*" >&2 | tee -a "$LOG_FILE"; }
|
|
||||||
|
|
||||||
# Default Exit Codes
|
|
||||||
readonly ERR_CURL_NOT_INSTALLED=10
|
|
||||||
readonly ERR_API_FAILURE=20
|
|
||||||
|
|
||||||
# Configuration
|
|
||||||
readonly REDMINE_INSTANCE="projects.knownelement.com"
|
|
||||||
readonly REDMINE_API_URL="https://${REDMINE_INSTANCE}"
|
|
||||||
readonly REDMINE_API_KEY="your_api_key_here"
|
|
||||||
readonly DATE=$(date '+%Y-%m-%d')
|
|
||||||
|
|
||||||
# Function: Usage Instructions
|
|
||||||
usage() {
|
|
||||||
cat <<EOF
|
|
||||||
$SCRIPT_DESC
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
$SCRIPT_NAME <project_id>
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-h, --help Display this help message.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
$SCRIPT_NAME 123
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check dependencies
|
|
||||||
require_curl() {
|
|
||||||
if ! command -v curl &>/dev/null; then
|
|
||||||
error "curl is not installed or not in PATH. Please install it and try again."
|
|
||||||
exit $ERR_CURL_NOT_INSTALLED
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Fetch issues from Redmine API
|
|
||||||
fetch_issues() {
|
|
||||||
local project_id="$1"
|
|
||||||
local url="${REDMINE_API_URL}/issues.json?key=${REDMINE_API_KEY}&project_id=${project_id}&due_date=${DATE}"
|
|
||||||
|
|
||||||
info "Fetching issues with due date ${DATE} for project ID ${project_id}..."
|
|
||||||
response=$(curl -s -w "%{http_code}" -o /tmp/redmine_response.json "$url")
|
|
||||||
http_code=$(tail -n1 <<<"$response")
|
|
||||||
|
|
||||||
if [[ "$http_code" -ne 200 ]]; then
|
|
||||||
error "Failed to fetch issues from Redmine API. HTTP Code: $http_code"
|
|
||||||
exit $ERR_API_FAILURE
|
|
||||||
fi
|
|
||||||
|
|
||||||
info "Issues fetched successfully. Parsing and converting to Markdown..."
|
|
||||||
generate_markdown /tmp/redmine_response.json
|
|
||||||
}
|
|
||||||
|
|
||||||
# Generate Markdown output from JSON response
|
|
||||||
generate_markdown() {
|
|
||||||
local json_file="$1"
|
|
||||||
local markdown_output="/tmp/redmine_issues.md"
|
|
||||||
|
|
||||||
echo "# Redmine Issues for ${DATE}" > "$markdown_output"
|
|
||||||
echo "" >> "$markdown_output"
|
|
||||||
|
|
||||||
jq -r --arg base_url "$REDMINE_API_URL" '.issues[] | "## [\(.subject)](\($base_url)/issues/\(.id))\n- **ID**: \(.id)\n- **Status**: \(.status.name)\n- **Due Date**: \(.due_date)\n\n---"' \
|
|
||||||
"$json_file" >> "$markdown_output"
|
|
||||||
|
|
||||||
info "Markdown output written to $markdown_output"
|
|
||||||
cat "$markdown_output"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Main Function
|
|
||||||
main() {
|
|
||||||
local project_id="$1"
|
|
||||||
|
|
||||||
# Ensure curl is installed
|
|
||||||
require_curl
|
|
||||||
|
|
||||||
# Fetch issues for the project
|
|
||||||
fetch_issues "$project_id"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Argument Parsing
|
|
||||||
if [[ $# -lt 1 ]] || [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
|
|
||||||
usage
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
main "$1"
|
|
||||||
|
|
@@ -1,47 +1,48 @@
|
|||||||
###################################################
|
###################################################
|
||||||
# Modify these values to suit
|
# Modify these values to suit
|
||||||
###################################################
|
###################################################
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
#SET THESE VARIABLES OR NOTHING WILL WORK!!!!
|
#SET THESE VARIABLES OR NOTHING WILL WORK!!!!
|
||||||
|
|
||||||
export PipelineClientWorkingDir="D:/tsys/ReachableCEOPublic/MarketingMaterials/DSR/local"
|
export PipelineClientWorkingDir="D:/tsys/ReachableCEOPublic/Software/DSR-Pipeline-ReachableCEO/local"
|
||||||
export StakeholderOutputMarkdownInputFile="$1"
|
export StakeholderOutputMarkdownInputFile="$1"
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
##########################################
|
##########################################
|
||||||
# Layout/title page /formatting options
|
# Layout/title page /formatting options
|
||||||
##########################################
|
##########################################
|
||||||
|
|
||||||
export ReportAuthor="Charles N Wyble"
|
export ReportAuthor="Charles N Wyble"
|
||||||
export AuthorTagline="Tenaciy. Velocity. Focus."
|
export AuthorTagline="Tenaciy. Velocity. Focus."
|
||||||
export AuthorLogo="D:/tsys/@ReachableCEO/ReachableCEO.png"
|
export AuthorLogo="D:/tsys/@ReachableCEO/ReachableCEO.png"
|
||||||
export SourceCode="https://git.knownelement.com/reachableceo/DSR-Pipeline-ReachableCEO"
|
export SourceCode="https://git.knownelement.com/reachableceo/DSR-Pipeline-ReachableCEO"
|
||||||
export URLCOLOR="blue"
|
export URLCOLOR="blue"
|
||||||
export PAGEBACKGROUND="$PipelineClientWorkingDir/build/background5.pdf"
|
export PAGEBACKGROUND="$PipelineClientWorkingDir/build/background5.pdf"
|
||||||
export PANDOC_TEMPLATE="eisvogel"
|
export PANDOC_TEMPLATE="eisvogel"
|
||||||
export YamlInputTemplateFileStakeholderOutput="$PipelineClientWorkingDir/build/BuildTemplate-DSR.yml"
|
export YamlInputTemplateFileStakeholderOutput="$PipelineClientWorkingDir/build/BuildTemplate-DSR.yml"
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
# Output Artifact variables
|
# Output Artifact variables
|
||||||
###################################################################
|
###################################################################
|
||||||
|
|
||||||
export BUILD_TEMP_DIR="$PipelineClientWorkingDir/build-temp"
|
export BUILD_TEMP_DIR="$PipelineClientWorkingDir/build-temp"
|
||||||
export BUILD_OUTPUT_DIR="$PipelineClientWorkingDir/build-output"
|
export BUILD_OUTPUT_DIR="$PipelineClientWorkingDir/build-output"
|
||||||
export BUILDYAML_STAKEHOLDER_OUTPUT="$BUILD_TEMP_DIR/DSR.yml"
|
export BUILDYAML_STAKEHOLDER_OUTPUT="$BUILD_TEMP_DIR/DSR.yml"
|
||||||
|
|
||||||
export StakeholderOutputMarkdownOutputFile="$BUILD_OUTPUT_DIR/$(basename $StakeholderOutputMarkdownInputFile|awk -F '.' '{print $1}').md"
|
export StakeholderOutputMarkdownOutputFile="$BUILD_OUTPUT_DIR/$(basename $StakeholderOutputMarkdownInputFile|awk -F '.' '{print $1}').md"
|
||||||
export StakeholderOutputPDFOutputFile="$BUILD_OUTPUT_DIR/$(basename $StakeholderOutputMarkdownInputFile|awk -F '.' '{print $1}').pdf"
|
export StakeholderOutputPDFOutputFile="$BUILD_OUTPUT_DIR/$(basename $StakeholderOutputMarkdownInputFile|awk -F '.' '{print $1}').pdf"
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
# Publish variables
|
# Publish variables
|
||||||
###################################################################
|
###################################################################
|
||||||
|
|
||||||
export BITWARDEN_SERVER_URL="https://pwvault.turnsys.com"
|
export BITWARDEN_SERVER_URL="https://pwvault.turnsys.com"
|
||||||
export BITWARDEN_CREDS="D:/tsys/secrets/bitwarden/data/apikey-bitwarden-reachableceo"
|
export BITWARDEN_CREDS="D:/tsys/secrets/bitwarden/data/apikey-bitwarden-reachableceo"
|
||||||
export DISCOURSE_URL="https://community.turnsys.com"
|
export DISCOURSE_URL="https://community.turnsys.com"
|
||||||
export DISCOURSE_API_USERNAME="reachableceo"
|
export DISCOURSE_API_USERNAME="reachableceo"
|
||||||
export DISCOURSE_CATEGORY_ID="61"
|
export DISCOURSE_CATEGORY_ID="61"
|
||||||
export TODAY_DATE="$(date +%m-%d-%Y)"
|
#export TODAY_DATE="$(date +%m-%d-%Y)"
|
||||||
export DISCOURSE_POST_TITLE="Daily Stakeholder Report for $TODAY_DATE"
|
export TODAY_DATE="12-21-2024"
|
||||||
|
export DISCOURSE_POST_TITLE="Daily Stakeholder Report for $TODAY_DATE"
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
title: ReachableCEO 2025 Plan
|
title: ReachableCEO 2025 Plan
|
||||||
titlepage: true
|
titlepage: true
|
||||||
toc: true
|
toc: true
|
||||||
toc-own-page: true
|
toc-own-page: true
|
||||||
header-left: "\\hspace{1cm}"
|
header-left: "\\hspace{1cm}"
|
||||||
header-center: "\\leftmark"
|
header-center: "\\leftmark"
|
||||||
header-right: "Page \\thepage"
|
header-right: "Page \\thepage"
|
||||||
footer-left: "Charles N Wyble"
|
footer-left: "Charles N Wyble"
|
||||||
footer-center: "Tenacity. Velocity. Focus."
|
footer-center: "Tenacity. Velocity. Focus."
|
||||||
page-background: "./background5.pdf"
|
page-background: "./background5.pdf"
|
||||||
titlepage-logo: "D:/tsys/@ReachableCEO/ReachableCEO.png"
|
titlepage-logo: "D:/tsys/@ReachableCEO/ReachableCEO.png"
|
||||||
urlcolor: blue
|
urlcolor: blue
|
||||||
|
@@ -0,0 +1,110 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Copyright ReachableCEO Enterprises 2025
|
||||||
|
# Licensed under the AGPL v3.0
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
IFS=$'\n\t'
|
||||||
|
|
||||||
|
# Enable logging
|
||||||
|
log_file="LOG-DSRCreateNewEntry-12-19-2024-14-13-27.log"
|
||||||
|
exec > >(tee -a "$log_file") 2>&1
|
||||||
|
|
||||||
|
function log_message()
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
echo "$(date '+%m-%d-%Y-%H-%M-%S') $1"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function error_exit()
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
echo -e "\033[0;31mERROR: $1\033[0m" >&2
|
||||||
|
log_message "ERROR: $1"
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# Trap for cleanup on script exit
|
||||||
|
trap "error_exit 'Script interrupted or an error occurred.'" ERR
|
||||||
|
|
||||||
|
# Read and verify environment variables
|
||||||
|
env_file="../../DSRVariables.env"
|
||||||
|
if [[ ! -f "$env_file" ]]; then
|
||||||
|
error_exit "Environment file $env_file not found."
|
||||||
|
fi
|
||||||
|
|
||||||
|
source "$env_file"
|
||||||
|
|
||||||
|
: "${JOPLIN_HOST:?Environment variable JOPLIN_HOST is not set}"
|
||||||
|
: "${JOPLIN_PORT:?Environment variable JOPLIN_PORT is not set}"
|
||||||
|
: "${JOPLIN_SOURCE_NOTE_TITLE:?Environment variable JOPLIN_SOURCE_NOTE_TITLE is not set}"
|
||||||
|
: "${JOPLIN_TARGET_NOTEBOOK:?Environment variable JOPLIN_TARGET_NOTEBOOK is not set}"
|
||||||
|
|
||||||
|
# Authenticate and set Joplin token
|
||||||
|
function get_joplin_apikey()
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
bw logout
|
||||||
|
bw config server https://pwvault.turnsys.com
|
||||||
|
echo "Sourcing clientid/apikey data..."
|
||||||
|
source D:/tsys/secrets/bitwarden/data/apikey-bitwarden-reachableceo
|
||||||
|
bw login --apikey $BW_CLIENTID $BW_CLIENTSECRET
|
||||||
|
export BW_SESSION="$(bw unlock --passwordenv TSYS_BW_PASSWORD_REACHABLECEO --raw)"
|
||||||
|
export JOPLIN_TOKEN="$(bw get password APIKEY-Joplin-Streaming)"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
get_joplin_apikey
|
||||||
|
|
||||||
|
: "${JOPLIN_TOKEN:?Joplin API key is not set}"
|
||||||
|
|
||||||
|
# Find the ID of the source note
|
||||||
|
function find_note_id()
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
local page=1
|
||||||
|
local note_id
|
||||||
|
while true; do
|
||||||
|
response=$(curl -s "http://${JOPLIN_HOST}:${JOPLIN_PORT}/notes?token=${JOPLIN_TOKEN}&page=${page}")
|
||||||
|
note_id=$(echo "$response" | jq -r --arg title "$JOPLIN_SOURCE_NOTE_TITLE" '.items[] | select(.title == $title) | .id')
|
||||||
|
if [[ -n "$note_id" ]]; then
|
||||||
|
echo "$note_id"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if [[ "$(echo "$response" | jq -r '.has_more')" == "false" ]]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
((page++))
|
||||||
|
done
|
||||||
|
|
||||||
|
error_exit "Source note titled '$JOPLIN_SOURCE_NOTE_TITLE' not found."
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
note_id=$(find_note_id)
|
||||||
|
|
||||||
|
# Clone the note to the target notebook
|
||||||
|
function clone_note()
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
local cloned_note_title="DSR-$(date '+%m-%d-%Y')"
|
||||||
|
curl -s -X POST "http://${JOPLIN_HOST}:${JOPLIN_PORT}/notes?token=${JOPLIN_TOKEN}" -H "Content-Type: application/json" --data @<(cat <<EOF
|
||||||
|
{
|
||||||
|
"title": "$cloned_note_title",
|
||||||
|
"body": "$(curl -s "http://${JOPLIN_HOST}:${JOPLIN_PORT}/notes/${note_id}?fields=body&token=${JOPLIN_TOKEN}" | jq -r '.body')",
|
||||||
|
"parent_id": "$(curl -s "http://${JOPLIN_HOST}:${JOPLIN_PORT}/folders?token=${JOPLIN_TOKEN}" | jq -r --arg name "$JOPLIN_TARGET_NOTEBOOK" '.items[] | select(.title == $name) | .id')"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
) || error_exit "Failed to clone note."
|
||||||
|
|
||||||
|
log_message "Cloned note titled '$JOPLIN_SOURCE_NOTE_TITLE' to '$cloned_note_title' in notebook '$JOPLIN_TARGET_NOTEBOOK'."
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
clone_note
|
@@ -0,0 +1,31 @@
|
|||||||
|
./DSRCreateNewEntry-Script-12-19-2024-14-13-27.sh: line 44: JOPLIN_TARGET_NOTEBOOK: Environment variable JOPLIN_TARGET_NOTEBOOK is not set
|
||||||
|
Logout required before server config update.You have logged out.Saved setting `config`.Sourcing clientid/apikey data...
|
||||||
|
You are logged in!
|
||||||
|
|
||||||
|
To unlock your vault, use the `unlock` command. ex:
|
||||||
|
$ bw unlockjq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
jq: error (at <stdin>:1): Cannot iterate over null (null)
|
||||||
|
You have logged out.Saved setting `config`.Sourcing clientid/apikey data...
|
||||||
|
You are logged in!
|
||||||
|
|
||||||
|
To unlock your vault, use the `unlock` command. ex:
|
||||||
|
$ bw unlock{"error":"Internal Server Error: Expected ',' or '}' after property value in JSON at position 562 (line 1 column 563): \n\nSyntaxError: Expected ',' or '}' after property value in JSON at position 562 (line 1 column 563)\n at JSON.parse (<anonymous>)\n at Object.default_1 [as fn] (C:\\Users\\tsys\\AppData\\Local\\Temp\\2nn4H0kRc241YEfWibWsJYlam2u\\resources\\app.asar\\node_modules\\@joplin\\lib\\services\\rest\\routes\\notes.js:429:34)\n at Api.route (C:\\Users\\tsys\\AppData\\Local\\Temp\\2nn4H0kRc241YEfWibWsJYlam2u\\resources\\app.asar\\node_modules\\@joplin\\lib\\services\\rest\\Api.js:151:37)\n at execRequest (C:\\Users\\tsys\\AppData\\Local\\Temp\\2nn4H0kRc241YEfWibWsJYlam2u\\resources\\app.asar\\node_modules\\@joplin\\lib\\ClipperServer.js:161:54)\n at IncomingMessage.<anonymous> (C:\\Users\\tsys\\AppData\\Local\\Temp\\2nn4H0kRc241YEfWibWsJYlam2u\\resources\\app.asar\\node_modules\\@joplin\\lib\\ClipperServer.js:204:34)\n at IncomingMessage.emit (node:events:514:28)\n at endReadableNT (node:internal/streams/readable:1408:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:82:21)"}12-19-2024-14-26-00 Cloned note titled 'DSR-Template' to 'DSR-12-19-2024' in notebook 'Today'.
|
Reference in New Issue
Block a user