.
This commit is contained in:
parent
5238d23b57
commit
78dcc5de06
19
dsr-input/README.md
Normal file
19
dsr-input/README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Data Gathering for the @ReachableCEO daily stakeholder report
|
||||||
|
|
||||||
|
## 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 want to automate the instrumentation/reporting process as much as possible to get the highest fidelity information for stakeholders consumption.
|
||||||
|
|
||||||
|
## Data sources
|
||||||
|
|
||||||
|
- Apple Health (exporting via AutoHealthExport)
|
||||||
|
- Workout (evaluating a cou
|
||||||
|
- Nutrition
|
||||||
|
- Daily habit tracking
|
||||||
|
- ActivityWatch
|
||||||
|
- WakaAPI
|
||||||
|
|
||||||
|
|
||||||
|
## Scripts
|
83
dsr-input/dsr-gather-gitea.sh
Normal file
83
dsr-input/dsr-gather-gitea.sh
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#!/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))]'
|
59
dsr-input/export-joplin-md.sh
Normal file
59
dsr-input/export-joplin-md.sh
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#!/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 "$@"
|
97
dsr-joplin-create/dsr-new.sh
Normal file
97
dsr-joplin-create/dsr-new.sh
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Use the Joplin CLI and create a new note for today. Let me pass in the notebook folder path. Use bash functions.
|
||||||
|
|
||||||
|
# Created by chatgpt
|
||||||
|
# https://chatgpt.com/share/6750c7df-6b2c-8005-a91c-1bc5b3875170
|
||||||
|
|
||||||
|
|
||||||
|
# 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="Create a new Daily Stakeholder Report note in Joplin"
|
||||||
|
|
||||||
|
# Logging and Debugging (from bash3boilerplate)
|
||||||
|
readonly LOG_FILE="/tmp/${SCRIPT_NAME}.log"
|
||||||
|
readonly TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
info() { echo "[INFO] [$TIMESTAMP] $*"; }
|
||||||
|
error() { echo "[ERROR] [$TIMESTAMP] $*" >&2; }
|
||||||
|
|
||||||
|
# Default Exit Codes
|
||||||
|
readonly ERR_JOPLIN_NOT_INSTALLED=10
|
||||||
|
readonly ERR_NOTEBOOK_NOT_FOUND=20
|
||||||
|
|
||||||
|
# Function: Usage Instructions
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
$SCRIPT_DESC
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
$SCRIPT_NAME <notebook_folder_path>
|
||||||
|
|
||||||
|
Example:
|
||||||
|
$SCRIPT_NAME "Stakeholder Reports"
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h, --help Display this help message.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check dependencies
|
||||||
|
require_joplin() {
|
||||||
|
if ! command -v joplin &>/dev/null; then
|
||||||
|
error "Joplin CLI is not installed or not in PATH. Please install it and try again."
|
||||||
|
exit $ERR_JOPLIN_NOT_INSTALLED
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if notebook exists in Joplin
|
||||||
|
notebook_exists() {
|
||||||
|
local notebook="$1"
|
||||||
|
if ! joplin use "$notebook" >/dev/null 2>&1; then
|
||||||
|
error "Notebook '$notebook' does not exist. Please create it first."
|
||||||
|
exit $ERR_NOTEBOOK_NOT_FOUND
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create a new note in the specified notebook
|
||||||
|
create_note() {
|
||||||
|
local notebook="$1"
|
||||||
|
local today_date=$(date '+%d-%m-%Y') # Format: YYYY-MM-DD
|
||||||
|
local title="Daily Stakeholder Report - $date"
|
||||||
|
local content="## Daily Stakeholder Report\n\n**Date:** $date\n\n---\n\n### Key Updates\n\n- \n\n### Issues\n\n- \n\n### Next Steps\n\n- \n"
|
||||||
|
|
||||||
|
joplin create note --title "$title" --body "$content" >/dev/null
|
||||||
|
info "Note created successfully in notebook '$notebook'."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main Function
|
||||||
|
main() {
|
||||||
|
local notebook_path="$1"
|
||||||
|
|
||||||
|
# Ensure Joplin CLI is present
|
||||||
|
require_joplin
|
||||||
|
|
||||||
|
# Verify notebook existence
|
||||||
|
notebook_exists "$notebook_path"
|
||||||
|
|
||||||
|
# Create a new note
|
||||||
|
create_note "$notebook_path"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Argument Parsing
|
||||||
|
if [[ $# -lt 1 ]] || [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
main "$1"
|
114
dsr-joplin-create/dsr-populate-objectives.sh
Normal file
114
dsr-joplin-create/dsr-populate-objectives.sh
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
#!/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"
|
||||||
|
|
35
endstops/end-day.sh
Normal file
35
endstops/end-day.sh
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Wrap up my instrumented day into a (mostly) automated report and publish to discourse
|
||||||
|
|
||||||
|
# Gather DSR assets
|
||||||
|
|
||||||
|
# My manually entered notations
|
||||||
|
./dsr-input/dsr-gather-joplin-log.sh
|
||||||
|
|
||||||
|
# My gitea data
|
||||||
|
./dsr-input/dsr-gather-gitea.sh
|
||||||
|
|
||||||
|
# My redmine data
|
||||||
|
./dsr-input/dsr-gather-redmine.sh
|
||||||
|
|
||||||
|
# My wakapi data
|
||||||
|
./dsr-input/dsr-gather-waka-api.sh
|
||||||
|
|
||||||
|
# My activity watch data
|
||||||
|
./dsr-input/dsr-gather-activitywatch.sh
|
||||||
|
|
||||||
|
# My habit tracker data
|
||||||
|
./dsr-input/dsr-gather-habits.sh
|
||||||
|
|
||||||
|
# My health/fitnes data
|
||||||
|
./dsr-input/dsr-gather-fitness.sh
|
||||||
|
|
||||||
|
# My diet data
|
||||||
|
./dsr-input/dsr-gather-diet.sh
|
||||||
|
|
||||||
|
# Produce DSR PDF asset
|
||||||
|
./dsr-publish/create-dsr-pdf.sh
|
||||||
|
|
||||||
|
# Publish DSR to the world
|
||||||
|
./dsr-publish/publish-dsr.sh
|
9
endstops/start-day.sh
Normal file
9
endstops/start-day.sh
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Start my instrumented day
|
||||||
|
|
||||||
|
# Create a new blank DSR for the day
|
||||||
|
./dsr-joplin-create/dsr-new.sh
|
||||||
|
|
||||||
|
# Populate my Joplin note "Todays objectives" section based on Redmine due dates
|
||||||
|
./dsr-joplin-create/dsr-populate-objectives.sh
|
12
local/build/BuildTemplate-2025Plan.yml
Normal file
12
local/build/BuildTemplate-2025Plan.yml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
title: ReachableCEO 2025 Plan
|
||||||
|
titlepage: true
|
||||||
|
toc: true
|
||||||
|
toc-own-page: true
|
||||||
|
header-left: "\\hspace{1cm}"
|
||||||
|
header-center: "\\leftmark"
|
||||||
|
header-right: "Page \\thepage"
|
||||||
|
footer-left: "Charles N Wyble"
|
||||||
|
footer-center: "Tenacity. Velocity. Focus."
|
||||||
|
page-background: "./background5.pdf"
|
||||||
|
titlepage-logo: "D:/tsys/@ReachableCEO/ReachableCEO.png"
|
||||||
|
urlcolor: blue
|
40
local/build/build-2025Plan.sh
Normal file
40
local/build/build-2025Plan.sh
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# This is a demo script for the DSR-Pipeline-Server
|
||||||
|
# This script creates PDF output from markdown input
|
||||||
|
|
||||||
|
|
||||||
|
###############@##################################
|
||||||
|
#Edit the below file to reflect your information
|
||||||
|
##################################################
|
||||||
|
|
||||||
|
source "../DSRVariables.env"
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
####################################################
|
||||||
|
####################################################
|
||||||
|
#DO NOT CHANGE ANYTHING BELOW THIS LINE
|
||||||
|
####################################################
|
||||||
|
####################################################
|
||||||
|
####################################################
|
||||||
|
|
||||||
|
############################################################################################
|
||||||
|
# Setup key variables that will be used by the create-stakeholder-output-server.sh script
|
||||||
|
############################################################################################
|
||||||
|
|
||||||
|
export MO_PATH="bash ../../vendor/git.knownelement.com/ExternalVendorCode/mo/mo"
|
||||||
|
|
||||||
|
echo "Cleaning up from previous runs..."
|
||||||
|
|
||||||
|
rm $BUILDYAML_STAKEHOLDER_OUTPUT || true
|
||||||
|
rm $StakeholderOutputMarkdownOutputFile || true
|
||||||
|
rm $StakeholderOutputPDFOutputFile || true
|
||||||
|
|
||||||
|
echo "Combining markdown files into single input file for pandoc..."
|
||||||
|
cat $StakeholderOutputMarkdownInputFile > $StakeholderOutputMarkdownOutputFile
|
||||||
|
|
||||||
|
#Call the build stakeholder output microservice
|
||||||
|
echo "Calling the build stakeholder output microservice..."
|
||||||
|
bash ../../vendor/git.knownelement.com/reachableceo/DSR-Pipeline-Server/build/build-stakeholder-output-server.sh
|
Loading…
Reference in New Issue
Block a user