adding content
This commit is contained in:
13
#20260418225944-art_of_computer_programming_notes.org#
Normal file
13
#20260418225944-art_of_computer_programming_notes.org#
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: f1bc3f88-95c5-4013-b0dd-f72428200e72
|
||||||
|
:END:
|
||||||
|
#+title: Art of Computer Programming Notes
|
||||||
|
#+author: Donald Knuth
|
||||||
|
|
||||||
|
* Art of Computer Programming Notes
|
||||||
|
:PROPERTIES:
|
||||||
|
:NOTER_DOCUMENT: ../../pdfs/_technical/Art of Computer Programming - Volume 1 (Fundamental Algorithms).pdf
|
||||||
|
:NOTER_AUTO_SAVE_LAST_LOCATION: t
|
||||||
|
:NOTER_PAGE: 1
|
||||||
|
:END:
|
||||||
|
|
||||||
0
.gitignore
vendored
Executable file → Normal file
0
.gitignore
vendored
Executable file → Normal file
0
.markdown-preview.html
Executable file → Normal file
0
.markdown-preview.html
Executable file → Normal file
0
.projectile
Executable file → Normal file
0
.projectile
Executable file → Normal file
0
20241210233721-brain_moc.org
Executable file → Normal file
0
20241210233721-brain_moc.org
Executable file → Normal file
22
20260418211930-the_book_of_ichigo_ichie_book_notes.org
Normal file
22
20260418211930-the_book_of_ichigo_ichie_book_notes.org
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: 50dd4105-506e-424a-9cc2-4fd494dc4284
|
||||||
|
:END:
|
||||||
|
#+title: The Book of Ichigo Ichie Notes
|
||||||
|
#+filetags: :books:notes:
|
||||||
|
|
||||||
|
* The Book of Ichigo Ichie Notes
|
||||||
|
:PROPERTIES:
|
||||||
|
:NOTER_DOCUMENT: ../../pdfs/_misc/The Book of Ichigo Ichie.pdf
|
||||||
|
:NOTER_AUTO_SAVE_LAST_LOCATION: t
|
||||||
|
:NOTER_PAGE: 8
|
||||||
|
:END:
|
||||||
|
** Notes for page 5
|
||||||
|
:PROPERTIES:
|
||||||
|
:NOTER_PAGE: 5
|
||||||
|
:HIGHLIGHT: #s(pdf-highlight 5 (5 (0.1430084745762712 0.18739770867430441 0.5222457627118644 0.22995090016366612)))
|
||||||
|
:END:
|
||||||
|
#+BEGIN_QUOTE
|
||||||
|
Before beginning to study the sacred texts and constantly singing the sutras, the
|
||||||
|
student should learn to read the love letters sent by the snow, the wind, and the
|
||||||
|
rain.
|
||||||
|
#+END_QUOTE
|
||||||
29
20260418225944-art_of_computer_programming_notes.org
Normal file
29
20260418225944-art_of_computer_programming_notes.org
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: f1bc3f88-95c5-4013-b0dd-f72428200e72
|
||||||
|
:END:
|
||||||
|
#+title: Art of Computer Programming Notes
|
||||||
|
#+filetags: :books:notes:technical:
|
||||||
|
#+author: Donald Knuth
|
||||||
|
|
||||||
|
* Art of Computer Programming Notes
|
||||||
|
:PROPERTIES:
|
||||||
|
:NOTER_DOCUMENT: ../../pdfs/_technical/Art of Computer Programming - Volume 1 (Fundamental Algorithms).pdf
|
||||||
|
:NOTER_AUTO_SAVE_LAST_LOCATION: t
|
||||||
|
:NOTER_PAGE: 5
|
||||||
|
:END:
|
||||||
|
|
||||||
|
** Notes for page 5
|
||||||
|
:PROPERTIES:
|
||||||
|
:NOTER_PAGE: 5
|
||||||
|
:HIGHLIGHT: #s(pdf-highlight 5 (5 (0.2701271186440678 0.25131282820705175 0.861228813559322 0.35333833458364594)))
|
||||||
|
:END:
|
||||||
|
#+BEGIN_QUOTE
|
||||||
|
Here is your book, the one your thousands of letters have asked us
|
||||||
|
to publish. It has taken us years to do, checking and rechecking countless
|
||||||
|
recipes to bring you only the best, only the interesting, only the perfect.
|
||||||
|
Now we can say, without a shadow of a doubt, that every single one of them,
|
||||||
|
if you follow the directions to the letter, will work for you exactly as well
|
||||||
|
as it did for us, even if you have never cooked before.
|
||||||
|
-
|
||||||
|
McCall's Cookbook (1963)
|
||||||
|
#+END_QUOTE
|
||||||
0
Books/20241231172543-the_science_of_self_discipline.org
Executable file → Normal file
0
Books/20241231172543-the_science_of_self_discipline.org
Executable file → Normal file
0
Books/20250715223949-the_clean_coder.org
Executable file → Normal file
0
Books/20250715223949-the_clean_coder.org
Executable file → Normal file
0
Books/20250723182408-so-good-they-cant-ignore-you.org
Executable file → Normal file
0
Books/20250723182408-so-good-they-cant-ignore-you.org
Executable file → Normal file
0
Books/20250723183655-career_capital.org
Executable file → Normal file
0
Books/20250723183655-career_capital.org
Executable file → Normal file
0
Books/20250723183755-deliberate_practice.org
Executable file → Normal file
0
Books/20250723183755-deliberate_practice.org
Executable file → Normal file
0
Books/20250723184430-stanford_marshmallow_experiment.org
Executable file → Normal file
0
Books/20250723184430-stanford_marshmallow_experiment.org
Executable file → Normal file
0
Books/20250723185056-neuroplasticity.org
Executable file → Normal file
0
Books/20250723185056-neuroplasticity.org
Executable file → Normal file
18
Books/20250724230557-books_org_agenda.org
Executable file → Normal file
18
Books/20250724230557-books_org_agenda.org
Executable file → Normal file
@@ -7,7 +7,7 @@
|
|||||||
#+filetags: :books:org:index:
|
#+filetags: :books:org:index:
|
||||||
#+DATE: 2025-05-19
|
#+DATE: 2025-05-19
|
||||||
#+STARTUP: content
|
#+STARTUP: content
|
||||||
#+PROPERTY: GENERATED_AT 2026-04-02T00:00:01.391273
|
#+PROPERTY: GENERATED_AT 2026-04-19T00:00:01.534223
|
||||||
|
|
||||||
* Career
|
* Career
|
||||||
** Clean Code_ A Handbook of Agile Software Craftsmanship - Robert C. Martin :Read:
|
** Clean Code_ A Handbook of Agile Software Craftsmanship - Robert C. Martin :Read:
|
||||||
@@ -102,6 +102,14 @@
|
|||||||
:PATH: /home/zaine/master-folder/projects/calibre/library/Nigel Poulton/Quick Start Kubernetes (31)
|
:PATH: /home/zaine/master-folder/projects/calibre/library/Nigel Poulton/Quick Start Kubernetes (31)
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
|
** Sahih Al Bukhari :Unread:
|
||||||
|
:PROPERTIES:
|
||||||
|
:AUTHOR: Imam Bukhari RH
|
||||||
|
:STATUS: Unread
|
||||||
|
:CALIBRE_ID: 35
|
||||||
|
:PATH: /home/zaine/master-folder/projects/calibre/library/Imam Bukhari RH/Sahih Al Bukhari (35)
|
||||||
|
:END:
|
||||||
|
|
||||||
** The Dose Effect :Unread:
|
** The Dose Effect :Unread:
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:AUTHOR: Tj Power
|
:AUTHOR: Tj Power
|
||||||
@@ -144,6 +152,14 @@
|
|||||||
:PATH: /home/zaine/master-folder/projects/calibre/library/Shaykh Muhammad Al-Khudari Bak Al-Bajuri/Lessons In Islamic History_ Durus fi at-Tarikh al-Islami (33)
|
:PATH: /home/zaine/master-folder/projects/calibre/library/Shaykh Muhammad Al-Khudari Bak Al-Bajuri/Lessons In Islamic History_ Durus fi at-Tarikh al-Islami (33)
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
|
** Sahih Al Bukhari :Unread:
|
||||||
|
:PROPERTIES:
|
||||||
|
:AUTHOR: Imam Bukhari RH
|
||||||
|
:STATUS: Unread
|
||||||
|
:CALIBRE_ID: 35
|
||||||
|
:PATH: /home/zaine/master-folder/projects/calibre/library/Imam Bukhari RH/Sahih Al Bukhari (35)
|
||||||
|
:END:
|
||||||
|
|
||||||
** The Tafseer of Surah Fatiha :Unread:
|
** The Tafseer of Surah Fatiha :Unread:
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:AUTHOR: Shaykh Abdul Raheem Limbada
|
:AUTHOR: Shaykh Abdul Raheem Limbada
|
||||||
|
|||||||
17
Books/20250727174809-books_moc.org
Executable file → Normal file
17
Books/20250727174809-books_moc.org
Executable file → Normal file
@@ -4,11 +4,24 @@
|
|||||||
#+title: Books MOC
|
#+title: Books MOC
|
||||||
#+filetags: :moc:books:
|
#+filetags: :moc:books:
|
||||||
|
|
||||||
|
|
||||||
* Recommendations for books: [[id:238ff7d8-db22-41e2-8aad-fc3c778e6248][Book Recs]]
|
* Recommendations for books: [[id:238ff7d8-db22-41e2-8aad-fc3c778e6248][Book Recs]]
|
||||||
|
|
||||||
* [[id:363dbdfa-f23c-4f7e-a6f3-6d34f78984bb][Books Org Agenda]]
|
* [[id:363dbdfa-f23c-4f7e-a6f3-6d34f78984bb][Books Org Agenda]]
|
||||||
|
|
||||||
* Book Notes:
|
* Book Notes:
|
||||||
|
|
||||||
[[id:fc07cbca-cf1a-4698-912b-de74001f0b5c][Ikigai Book Notes]]
|
** DONE [[id:fc07cbca-cf1a-4698-912b-de74001f0b5c][Ikigai Book Notes]]
|
||||||
|
|
||||||
|
** TODO [[id:2c1d3647-a3be-4a4f-94c2-100f02de1f56][The Dose Effect Book Notes]]
|
||||||
|
|
||||||
|
** TODO [[id:50dd4105-506e-424a-9cc2-4fd494dc4284][The Book of Ichigo Ichie Notes]]
|
||||||
|
|
||||||
|
* Article Notes:
|
||||||
|
|
||||||
|
** DONE [[id:db7b1fdb-28cd-43a8-8137-23399f38cd07][Effect of Tiktok on teens]]
|
||||||
|
|
||||||
|
** TODO [[id:5429d9c8-ace8-419b-a9dc-8403b9c20215][Effects of insufficient sleep on circadian rhythmicity]]
|
||||||
|
|
||||||
|
* Long term:
|
||||||
|
|
||||||
|
** TODO [[id:f1bc3f88-95c5-4013-b0dd-f72428200e72][Art of Computer Programming Notes]]
|
||||||
|
|||||||
0
Books/20250727174903-book_recs.org
Executable file → Normal file
0
Books/20250727174903-book_recs.org
Executable file → Normal file
0
Books/20250727221512-clean_code.org
Executable file → Normal file
0
Books/20250727221512-clean_code.org
Executable file → Normal file
7
Books/20260331113318-ikigai_notes.org
Executable file → Normal file
7
Books/20260331113318-ikigai_notes.org
Executable file → Normal file
@@ -11,7 +11,7 @@
|
|||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:NOTER_DOCUMENT: ../../../pdfs/_misc/Ikigai.pdf
|
:NOTER_DOCUMENT: ../../../pdfs/_misc/Ikigai.pdf
|
||||||
:NOTER_AUTO_SAVE_LAST_LOCATION: t
|
:NOTER_AUTO_SAVE_LAST_LOCATION: t
|
||||||
:NOTER_PAGE: 189
|
:NOTER_PAGE: 184
|
||||||
:END:
|
:END:
|
||||||
** Notes for page 19
|
** Notes for page 19
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
@@ -108,10 +108,9 @@ Logotherapy pushes patients to consciously discover their life’s purpose in or
|
|||||||
:NOTER_PAGE: 47
|
:NOTER_PAGE: 47
|
||||||
:HIGHLIGHT: #s(pdf-highlight 47 (47 (0.5161290322580645 0.4219269102990033 0.7591397849462366 0.42524916943521596)))
|
:HIGHLIGHT: #s(pdf-highlight 47 (47 (0.5161290322580645 0.4219269102990033 0.7591397849462366 0.42524916943521596)))
|
||||||
:END:
|
:END:
|
||||||
Man’s Search for Meaning - Frankl
|
~Man’s Search for Meaning - Frankl~
|
||||||
|
|
||||||
``Morita Therapy and the True Nature of Anxiety-Based
|
~Morita Therapy and the True Nature of Anxiety-Based Disorders~
|
||||||
Disorders,''
|
|
||||||
** “In feelings, it is best to be wealthy and generous.”
|
** “In feelings, it is best to be wealthy and generous.”
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:NOTER_PAGE: 54
|
:NOTER_PAGE: 54
|
||||||
|
|||||||
36
Books/20260402115029-dose_effect_notes.org
Normal file
36
Books/20260402115029-dose_effect_notes.org
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: 2c1d3647-a3be-4a4f-94c2-100f02de1f56
|
||||||
|
:END:
|
||||||
|
#+title: The Dose Effect Book Notes
|
||||||
|
#+filetags: :books:notes:
|
||||||
|
|
||||||
|
* Notes
|
||||||
|
** p. 105
|
||||||
|
[Quote]: Happiness is equal to reality minus expectations
|
||||||
|
** p. 125
|
||||||
|
[Insight]: Hugging someone causes a huge release of oxytocin. Something to think about
|
||||||
|
** p. 131
|
||||||
|
[Insight]:
|
||||||
|
Ideas to connect with one another:
|
||||||
|
- EXERCISING TOGETHER
|
||||||
|
- WALKING AND RELAXING IN NATURE
|
||||||
|
- CALLING INSTEAD OF MESSAGING
|
||||||
|
- EATING AND DRINKING TOGETHER
|
||||||
|
** p. 137
|
||||||
|
[Insight]: Social connection checklist:
|
||||||
|
|
||||||
|
1. Remove phone
|
||||||
|
2. Listen actively
|
||||||
|
3. Compliment
|
||||||
|
4. Make eye contact
|
||||||
|
5. Connect physically
|
||||||
|
6. Ask good questions
|
||||||
|
** p. 140
|
||||||
|
[Insight]: Social Confidence Steps Summary
|
||||||
|
1. STEP 1 Accept it
|
||||||
|
2. STEP 2 Make eye contact and stand tall
|
||||||
|
3. STEP 3 Pay attention and contribute
|
||||||
|
|
||||||
|
In these moments, our aim is to move our attention away from this internal voice in our minds and towards the people we are with.
|
||||||
|
** p. 165
|
||||||
|
[Insight]: The 2 serotonin principles: a) 90% is created within our guts. b) the happier your body, the happier your mind
|
||||||
64
Books/20260417162601-effect_of_tiktok_on_teens_notes.org
Normal file
64
Books/20260417162601-effect_of_tiktok_on_teens_notes.org
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: db7b1fdb-28cd-43a8-8137-23399f38cd07
|
||||||
|
:END:
|
||||||
|
#+title: Effect of Tiktok on teens
|
||||||
|
#+filetags: :articles:notes:
|
||||||
|
|
||||||
|
* Effect of Tiktok on teens Notes
|
||||||
|
:PROPERTIES:
|
||||||
|
:NOTER_DOCUMENT: ../../../pdfs/_misc/_articles/effect-of-tiktok-on-teens.pdf
|
||||||
|
:NOTER_AUTO_SAVE_LAST_LOCATION: t
|
||||||
|
:NOTER_PAGE: 4
|
||||||
|
:END:
|
||||||
|
** Notes for page 1
|
||||||
|
:PROPERTIES:
|
||||||
|
:NOTER_PAGE: 1
|
||||||
|
:END:
|
||||||
|
#+BEGIN_QUOTE
|
||||||
|
The latest TikTok statistics show that, as of July 2022, the platform has over one billion monthly active users worldwide
|
||||||
|
|
||||||
|
In the US 62% of TikTok users are aged between 10 and 29
|
||||||
|
#+END_QUOTE
|
||||||
|
** Article Mention:
|
||||||
|
"TIKTOK - THE INFLUENCE ON SCHOOLPERFORMANCE AND SOCIAL LIFE OF ADOLESCENTS"
|
||||||
|
** Notes for page 2
|
||||||
|
:PROPERTIES:
|
||||||
|
:NOTER_PAGE: 2
|
||||||
|
:END:
|
||||||
|
#+BEGIN_QUOTE
|
||||||
|
“Navigating the New Era of Influencer Marketing: How to be Successful on Instagram, TikTok, & Co”
|
||||||
|
#+END_QUOTE
|
||||||
|
|
||||||
|
#+BEGIN_QUOTE
|
||||||
|
Just like there is no clock in a casino, Tiktok deliberately blurs the user's time judgment and hides the time in design.
|
||||||
|
#+END_QUOTE
|
||||||
|
** The negative impact of Tiktok on adolescent psychology
|
||||||
|
:PROPERTIES:
|
||||||
|
:NOTER_PAGE: 2
|
||||||
|
:HIGHLIGHT: #s(pdf-highlight 2 (2 (0.5423728813559322 0.08838951310861423 0.7023305084745762 0.1101123595505618)))
|
||||||
|
:END:
|
||||||
|
** Notes for page 3
|
||||||
|
:PROPERTIES:
|
||||||
|
:NOTER_PAGE: 3
|
||||||
|
:HIGHLIGHT: #s(pdf-highlight 3 (3 (0.2065677966101695 0.3910112359550562 0.19385593220338984 0.4217228464419476)))
|
||||||
|
:END:
|
||||||
|
#+BEGIN_QUOTE
|
||||||
|
cyber-bullying generally involves using the Internet to threaten, harm, embarrass, or socially exclude others
|
||||||
|
#+END_QUOTE
|
||||||
|
|
||||||
|
#+BEGIN_QUOTE
|
||||||
|
"The key period of personal socialization is the youth stage. In this stage, being bullied will weak adolescents' self-identity and increases the risk of anxiety and depression, which is not conducive to the development of adolescents' mental health and personality shaping"
|
||||||
|
#+END_QUOTE
|
||||||
|
|
||||||
|
#+BEGIN_QUOTE
|
||||||
|
The Internet is a virtual world in which many netizens freely vent their anger and dissatisfaction, and abuse others at will to gain psychological catharsis.
|
||||||
|
#+END_QUOTE
|
||||||
|
|
||||||
|
** Notes for page 4
|
||||||
|
:PROPERTIES:
|
||||||
|
:NOTER_PAGE: 4
|
||||||
|
:HIGHLIGHT: #s(pdf-highlight 4 (4 (0.4576271186440678 0.37378277153558054 0.2468220338983051 0.4794007490636704)))
|
||||||
|
:END:
|
||||||
|
#+BEGIN_QUOTE
|
||||||
|
“We are in an era of great change. This is the best time, and it is also a the worst times. Teenagers should constantly improve themselves, strengthen self-control and the ability to distinguish right from wrong, make use of the advantages brought by the Internet, and constantly explore the boundaries of the future, dare to try and create their own value”
|
||||||
|
#+END_QUOTE
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: 5429d9c8-ace8-419b-a9dc-8403b9c20215
|
||||||
|
:END:
|
||||||
|
#+title: Effects of insufficient sleep on circadian rhythmicity
|
||||||
|
#+filetags: :articles:notes:
|
||||||
|
|
||||||
|
* Effects of insufficient sleep on circadian rhythmicity Notes
|
||||||
|
:PROPERTIES:
|
||||||
|
:NOTER_DOCUMENT: ../../pdfs/_misc/_articles/Effects of insufficient sleep on circadian rhythmicity and expression amplitude of the human blood transcriptome.pdf
|
||||||
|
:END:
|
||||||
0
Career Concepts/20250722221649-career_moc.org
Executable file → Normal file
0
Career Concepts/20250722221649-career_moc.org
Executable file → Normal file
0
Career Concepts/20250723200800-postgres.org
Executable file → Normal file
0
Career Concepts/20250723200800-postgres.org
Executable file → Normal file
0
Career Concepts/20250727122406-database_moc.org
Executable file → Normal file
0
Career Concepts/20250727122406-database_moc.org
Executable file → Normal file
0
Career Concepts/20250804201706-big_o_complexity.org
Executable file → Normal file
0
Career Concepts/20250804201706-big_o_complexity.org
Executable file → Normal file
0
Career Concepts/20251223215636-design_patterns_notes.org
Executable file → Normal file
0
Career Concepts/20251223215636-design_patterns_notes.org
Executable file → Normal file
0
Career Concepts/20251229180039-airflow.org
Executable file → Normal file
0
Career Concepts/20251229180039-airflow.org
Executable file → Normal file
0
Career Concepts/20251229180156-airflow_tasks.org
Executable file → Normal file
0
Career Concepts/20251229180156-airflow_tasks.org
Executable file → Normal file
0
Career Concepts/20251229180249-airflow_dags.org
Executable file → Normal file
0
Career Concepts/20251229180249-airflow_dags.org
Executable file → Normal file
16
Career Concepts/20260101010049-concepts.org
Executable file → Normal file
16
Career Concepts/20260101010049-concepts.org
Executable file → Normal file
@@ -7,6 +7,10 @@
|
|||||||
|
|
||||||
In this node lies notes relating to theoretical concepts tying with maths and/or computer science. I will need to find a way to categorise different notes, but it's a wip.
|
In this node lies notes relating to theoretical concepts tying with maths and/or computer science. I will need to find a way to categorise different notes, but it's a wip.
|
||||||
|
|
||||||
|
* Microlise:
|
||||||
|
** ESS
|
||||||
|
- [[id:abe43fdc-e90d-4c2c-9320-cc7929f0c99a][ESS]]
|
||||||
|
|
||||||
* Mathematical Concepts
|
* Mathematical Concepts
|
||||||
|
|
||||||
Part of being a software engineer is having a good grasp of mathematical concepts. Here are some notes on various mathematical concepts that I find useful.
|
Part of being a software engineer is having a good grasp of mathematical concepts. Here are some notes on various mathematical concepts that I find useful.
|
||||||
@@ -27,6 +31,9 @@ Part of being a software engineer is having a good grasp of mathematical concept
|
|||||||
|
|
||||||
- [[id:67ad330b-cc11-4e8e-b054-12b9da45ea60][Software Development Methodologies]]
|
- [[id:67ad330b-cc11-4e8e-b054-12b9da45ea60][Software Development Methodologies]]
|
||||||
|
|
||||||
|
- [[id:fdb8fa52-0c9d-4332-9f32-53bc6fee24b9][MVP and MVT]]
|
||||||
|
|
||||||
|
|
||||||
Some core programming concepts that are essential for software development. The things I need to add here are:
|
Some core programming concepts that are essential for software development. The things I need to add here are:
|
||||||
|
|
||||||
* APIs
|
* APIs
|
||||||
@@ -37,12 +44,19 @@ Some core programming concepts that are essential for software development. The
|
|||||||
|
|
||||||
- [[id:e7f082e4-1b9f-4ebe-96d6-94d92e80a07e][API Intro Notes]]
|
- [[id:e7f082e4-1b9f-4ebe-96d6-94d92e80a07e][API Intro Notes]]
|
||||||
|
|
||||||
- [[id:b2fd7038-42a8-4cbe-882b-92fbe2c12a11][ASP.NET Core Web API Fundamental Notes]]
|
- [[id:b2fd7038-42a8-4cbe-882b-92fbe2c12a11][ASP.NET Core Web API Fundamental Notes]] (todo)
|
||||||
|
|
||||||
* Database Related
|
* Database Related
|
||||||
|
|
||||||
- [[id:b4858f6a-b05c-47f2-972e-905e0bb2c352][Database Permissions, Roles, and Accounts]]
|
- [[id:b4858f6a-b05c-47f2-972e-905e0bb2c352][Database Permissions, Roles, and Accounts]]
|
||||||
|
|
||||||
|
* Misc
|
||||||
|
|
||||||
|
- [[id:faa7f193-5af6-4a2f-a73e-540f833a7fd0][Windows Services]]
|
||||||
|
|
||||||
|
- [[id:e717c252-0e15-4403-898f-93163dd1b147][Dynamic Link Library (DLL)]]
|
||||||
|
|
||||||
|
|
||||||
* Concepts to learn and talk about (cs and maths)
|
* Concepts to learn and talk about (cs and maths)
|
||||||
- +xor+
|
- +xor+
|
||||||
- +big O notation+
|
- +big O notation+
|
||||||
|
|||||||
0
Career Concepts/20260101011126-xor.org
Executable file → Normal file
0
Career Concepts/20260101011126-xor.org
Executable file → Normal file
0
Career Concepts/20260101012549-solid_principles.org
Executable file → Normal file
0
Career Concepts/20260101012549-solid_principles.org
Executable file → Normal file
0
Career Concepts/20260101012731-solid_principles_examples.org
Executable file → Normal file
0
Career Concepts/20260101012731-solid_principles_examples.org
Executable file → Normal file
0
Career Concepts/20260115152626-apim.org
Executable file → Normal file
0
Career Concepts/20260115152626-apim.org
Executable file → Normal file
0
Career Concepts/20260121173318-api_architecture.org
Executable file → Normal file
0
Career Concepts/20260121173318-api_architecture.org
Executable file → Normal file
0
Career Concepts/20260305102210-cicd_example.org
Executable file → Normal file
0
Career Concepts/20260305102210-cicd_example.org
Executable file → Normal file
0
Career Concepts/20260305111610-cicd_summary.org
Executable file → Normal file
0
Career Concepts/20260305111610-cicd_summary.org
Executable file → Normal file
0
Career Concepts/20260305130457-database_perms_roles_accounts.org
Executable file → Normal file
0
Career Concepts/20260305130457-database_perms_roles_accounts.org
Executable file → Normal file
0
Career Concepts/20260305132058-restful_api.org
Executable file → Normal file
0
Career Concepts/20260305132058-restful_api.org
Executable file → Normal file
0
Career Concepts/20260327110908-api_intro_notes.org
Executable file → Normal file
0
Career Concepts/20260327110908-api_intro_notes.org
Executable file → Normal file
0
Career Concepts/20260327114708-asp_net_core_6_apis_notes.org
Executable file → Normal file
0
Career Concepts/20260327114708-asp_net_core_6_apis_notes.org
Executable file → Normal file
0
Career Concepts/20260328215014-software_dev_methodologies.org
Executable file → Normal file
0
Career Concepts/20260328215014-software_dev_methodologies.org
Executable file → Normal file
20
Career Concepts/20260407102129-mvp_mvt.org
Normal file
20
Career Concepts/20260407102129-mvp_mvt.org
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: fdb8fa52-0c9d-4332-9f32-53bc6fee24b9
|
||||||
|
:END:
|
||||||
|
#+title: MVP and MVT
|
||||||
|
|
||||||
|
* MVP and MVT
|
||||||
|
|
||||||
|
- An **MVP** is a **minimal functional product** built to validate what customers actually want by observing real usage.
|
||||||
|
- An **MVT** (often called **Minimum Viable Experiment/Test**) is a **small, fast, low‑cost test** designed to validate a specific assumption before you build anything substantial.
|
||||||
|
|
||||||
|
**Minimum Viable Product (MVP)**
|
||||||
|
A simplified but working version of a product that early users can interact with.
|
||||||
|
Purpose: validate product‑market fit and gather real behavioural feedback.
|
||||||
|
|
||||||
|
**Minimum Viable Test (MVT / MVE)**
|
||||||
|
A quick experiment to validate a single assumption — often before building an MVP.
|
||||||
|
Examples: landing page, survey, fake‑door button, email test.
|
||||||
|
|
||||||
|
- **MVT** = “Should we even build this?”
|
||||||
|
- **MVP** = “We think this is worth building — now let’s test the simplest working version.”
|
||||||
101
Career Concepts/20260410115348-microlise_ess.org
Normal file
101
Career Concepts/20260410115348-microlise_ess.org
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: abe43fdc-e90d-4c2c-9320-cc7929f0c99a
|
||||||
|
:END:
|
||||||
|
#+title: ESS
|
||||||
|
#+filetags: :microlise:ess:coding:technical:
|
||||||
|
|
||||||
|
Joined team Shackleton on <2026-04-07 Tue>, who are now overseeing the deployment process for ESS applications.
|
||||||
|
|
||||||
|
[[id:a6c345df-8db9-4538-b87e-0e72e2414905][ESP Deployment Pipeline — Index]]
|
||||||
|
|
||||||
|
* AI generated overview of ESP
|
||||||
|
** What's the Big Picture?
|
||||||
|
Your team is building an *automated deployment pipeline* for a software suite called *ESP* (made by a company called ESS). Right now, deploying ESP to customer environments is done *manually* - someone has to go through a checklist and do things by hand. That's slow, error-prone, and relies on people who are leaving the company. The goal is to automate all of that.
|
||||||
|
|
||||||
|
The pipeline will live in *Azure DevOps (AzDO)* - Microsoft's platform for CI/CD (building and deploying software automatically).
|
||||||
|
|
||||||
|
** Why Is This Happening Now?
|
||||||
|
The engineers who originally built and understood ESP have mostly left ESS. The ones who remain are tied up on paid customer work. So this task was handed off to a Microlise team (*Team Ludo*) who got the ball rolling - they got ESP /building/ in AzDO and started on deployment. Now Ludo have been pulled onto other work too, and *your team* has inherited it.
|
||||||
|
|
||||||
|
So you're the third team to touch this. Expect some rough edges and gaps in knowledge.
|
||||||
|
|
||||||
|
|
||||||
|
** What Is ESP, Exactly?
|
||||||
|
ESP is a *suite of applications* sold to customers. Think of it like a product bundle - each customer gets the apps they actually need (not every customer gets everything). It's delivered and runs on the customer's environment, which means:
|
||||||
|
|
||||||
|
- You're deploying to *their servers*, not yours
|
||||||
|
- Different customers have different sets of apps installed
|
||||||
|
- Some customers might have *test and production on the same server* - which is a headache, because you have to be careful not to accidentally deploy to prod when you meant test
|
||||||
|
|
||||||
|
The apps in the suite are:
|
||||||
|
|
||||||
|
- *One database* - =EspBroker= (SQL Server database)
|
||||||
|
- *Six Windows Services* - background processes that run on a server (DLService, EmailService, etc.)
|
||||||
|
- *Three Citrix Applications* - desktop apps delivered via Citrix (VPlanner, VPlannerAdmin, ImportApp). Citrix is a technology that streams apps to users remotely, like a remote desktop but per-app.
|
||||||
|
|
||||||
|
** What Is the Pipeline Actually Going to Do?
|
||||||
|
The pipeline will run *PowerShell scripts* that walk through a deployment in stages. Think of it like a structured checklist that will eventually become fully automated. The stages are:
|
||||||
|
|
||||||
|
| Stage | What it does |
|
||||||
|
|-----------------+------------------------------------------------------------------------------|
|
||||||
|
| *Validate* | Loads and checks the manifest (config file describing the environment) |
|
||||||
|
| *Prerequisites* | Checks the target server has everything it needs before you touch it |
|
||||||
|
| *Predeploy* | Copies the new version's files to the server and configures them |
|
||||||
|
| *Deploy* | The actual upgrade - stops services, swaps old files for new, starts back up |
|
||||||
|
| *Postdeploy* | Checks everything came back up healthy |
|
||||||
|
|
||||||
|
You can run any combination of these stages, so for example you might just run Validate to check your config is right, without actually deploying anything.
|
||||||
|
|
||||||
|
|
||||||
|
** The Script Architecture (This Is Important)
|
||||||
|
The scripts are designed in *three tiers*, like a layered cake:
|
||||||
|
|
||||||
|
*Tier 1 - The Entry Point* You call one script (e.g. ~Invoke-Deployment.ps1~) and tell it the customer, environment, and which stages to run. It loads the manifest, loads all the modules, then hands off to Tier 2.
|
||||||
|
|
||||||
|
*Tier 2 - The Orchestrator* One script per stage (PreDeployment, Deployment, etc.). This is the "brain" - it decides /what/ needs to happen and in what order, then calls Tier 3 to actually do it. It never does anything directly itself.
|
||||||
|
|
||||||
|
*Tier 3 - The Workers* Small, self-contained functions that each do /one thing/ - stop a Windows service, run a SQL query, copy a file, etc. They know nothing about ESP specifically. They just take parameters and do the job. This is useful because you can test them in isolation.
|
||||||
|
|
||||||
|
*Why this structure matters for you:* Right now, many Tier 3 functions are essentially *placeholders* - instead of actually doing something, they prompt a human to do it manually. The plan is to replace those manual prompts with real automation over time. So initially the pipeline is more of a guided checklist than true automation.
|
||||||
|
|
||||||
|
|
||||||
|
** The Manifest - What Is That?
|
||||||
|
A manifest is a *config file* that describes a specific customer's environment - which apps they have, what servers they're on, credentials, etc. The idea is that you have one manifest per customer/environment combo (e.g.ROMAC DEV), and the scripts read that to know what to do. The manifest design isn't fully defined yet, which is one of the open items.
|
||||||
|
|
||||||
|
** The Dacpac - What's That?
|
||||||
|
A *dacpac* is a packaged SQL Server database schema. Instead of writing raw SQL migration scripts, you describe what the database /should look like/, and the dacpac tool works out what changes to make to get there. Team Ludo built one for the ESP database.
|
||||||
|
|
||||||
|
*The big problem:* The existing customer databases are in an inconsistent state - they've drifted from the official schema over time (probably from manual fixes and patches). Before you can deploy via dacpac, someone will need to manually clean up each database to get it into a consistent state. Until that's done, the database deployment step can't be automated.
|
||||||
|
|
||||||
|
** The Known Pain Points You Should Be Aware Of
|
||||||
|
These are the things most likely to cause your team grief:
|
||||||
|
|
||||||
|
1. *Inconsistent databases* - Can't use the dacpac until each customer's DB is manually fixed first. The pipeline needs to detect this and fail gracefully rather than making things worse.
|
||||||
|
|
||||||
|
2. *The build artifact is a mess* - The ESP build produces a huge folder of DLLs all jumbled together, rather than neatly separated per application. Your scripts will need to figure out which files belong to which app.
|
||||||
|
|
||||||
|
3. *No test environment* - You don't have a safe sandbox to practice deployments on. Any deployment you run is against a real customer environment. This is a significant risk.
|
||||||
|
|
||||||
|
4. *Can't run locally* - Licensing restrictions mean you can't run ESP on your own machine to test things. Everything has to happen on the actual servers.
|
||||||
|
|
||||||
|
5. *Citrix is complicated* - Deploying the Citrix apps requires notifying users, waiting for them to quit, killing sessions if they don't, and then doing the upgrade. The exact mechanism for the upgrade itself (how do you actually swap the Citrix app?) is still TBC.
|
||||||
|
|
||||||
|
6. *Cycle checks* - Post-deployment checks involve navigating through the Citrix UI to verify things work. That's very hard to automate.
|
||||||
|
|
||||||
|
** What's Still Not Decided
|
||||||
|
Several important things are still open:
|
||||||
|
|
||||||
|
- *Rollback plan* - If a deployment goes wrong, how do you undo it? Not defined yet.
|
||||||
|
- *Test plan* - How will you test the pipeline itself?
|
||||||
|
- *Citrix deployment method* - Believed to be a file copy but not confirmed
|
||||||
|
- *Manifest structure* - What does the config file actually look like?
|
||||||
|
- *Full scope* - Will this eventually cover production and ESS's own data centre too?
|
||||||
|
|
||||||
|
** What Should You Focus On First?
|
||||||
|
To provide real value quickly, I'd suggest getting comfortable with:
|
||||||
|
|
||||||
|
1. *Azure DevOps YAML pipelines* - understand how they're structured and how they trigger scripts
|
||||||
|
2. *PowerShell scripting* - the whole deployment mechanism is PowerShell
|
||||||
|
3. *The existing Ludo work* - look at the existing pipeline runs and deploy scripts linked in the document before writing anything new
|
||||||
|
4. *The manifest concept* - helping define what that config file looks like is impactful foundational work
|
||||||
|
5. *The dacpac situation* - understanding which customer databases need manual cleanup before automation can work
|
||||||
66
Career Concepts/20260410121527-ess_esp_index.org
Normal file
66
Career Concepts/20260410121527-ess_esp_index.org
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: a6c345df-8db9-4538-b87e-0e72e2414905
|
||||||
|
:END:
|
||||||
|
#+title: ESP Deployment Pipeline — Index
|
||||||
|
#+filetags: :ess:microlise:pipelines:index:
|
||||||
|
|
||||||
|
* Overview
|
||||||
|
:PROPERTIES:
|
||||||
|
:NOTE: This is the master index file. Each heading links to a dedicated notes file.
|
||||||
|
:END:
|
||||||
|
|
||||||
|
The ESP Deployment Pipeline project is an effort to automate the deployment of the ESP application suite (built by ESS) into customer environments using Azure DevOps (AzDO) YAML pipelines and PowerShell scripts.
|
||||||
|
|
||||||
|
We are the third team to inherit this work. Team Ludo started it, got the build working in AzDO, and began deployment work before being reassigned. We pick up from there.
|
||||||
|
|
||||||
|
* Quick Reference — Key Concepts
|
||||||
|
| Concept | What it is | Notes File |
|
||||||
|
|-----------------+------------------------------------------------------+--------------------------------------|
|
||||||
|
| ESP | Suite of apps deployed per-customer | [[id:091e9bbc-0c9f-43da-81f9-464882c2a15b][ESP Applications]] |
|
||||||
|
| AzDO Pipeline | YAML-based CI/CD pipeline in Azure DevOps | [[id:d66e946f-6785-4e8e-ba00-bb25a52237d1][ESP — AzDO Pipeline]] |
|
||||||
|
| PowerShell Arch | Three-tier script architecture (T1/T2/T3) | [[id:bf63b6c5-f32f-462e-82ad-8d4a15f7ba48][ESP — PowerShell Script Architecture]] |
|
||||||
|
| Manifest | Config file defining a customer environment | [[id:9bf19a8b-5581-4be8-9892-913c51df0128][ESP — The Manifest]] |
|
||||||
|
| Dacpac | Packaged SQL Server DB schema deployment | [[id:46add22d-e562-4e3a-a301-d4aea2552952][ESP — Database & Dacpac]] |
|
||||||
|
| Stages | Validate / Prerequisites / Predeploy / Deploy / Post | [[id:cd3cd02f-c9b3-4455-8ce5-b2a5aa458fed][ESP — Deployment Stages]] |
|
||||||
|
| Known Issues | Pain points, risks, and gaps | [[id:53d803aa-7e6f-44ed-8d99-a243a5ed5aab][ESP — Known Issues & Risks]] |
|
||||||
|
| Open Questions | Things still TBC or not yet designed | [[id:82c3d447-d6d3-498e-9f66-aee60c752462][ESP — Open Questions & TBC Items]] |
|
||||||
|
| Glossary | Terminology reference | [[id:2c950d25-6f86-4f83-a7b4-69e2ca2f7023][ESP — Glossary]] |
|
||||||
|
|
||||||
|
* Context — Why This Project Exists
|
||||||
|
|
||||||
|
- Few original ESS engineers remain; those left are on paid customer work
|
||||||
|
- Manual deployments are slow, risky, and rely on tribal knowledge
|
||||||
|
- Business goal: /all deployments are consistently repeatable with no manual VM work/
|
||||||
|
- Initial scope: ROMAC DEV environment only
|
||||||
|
- Future scope: all environments including PROD and ESS's own data centre
|
||||||
|
|
||||||
|
* Team History
|
||||||
|
|
||||||
|
| Team | Contribution | Current Status |
|
||||||
|
|-----------+---------------------------------------------------------+-----------------------------|
|
||||||
|
| ESS | Built ESP; wrote original deployment docs | Mostly departed |
|
||||||
|
| Team Ludo | Full ESP build in AzDO; started deploy pipeline; dacpac | Reassigned to customer work |
|
||||||
|
| Our Team | Inheriting deploy pipeline work | Active |
|
||||||
|
|
||||||
|
* Existing Resources to Review
|
||||||
|
|
||||||
|
- Handover from Team Ludo: ~ESP_Pipeline_Handover.docx~
|
||||||
|
- Ludo deployment docs: ~DEPLOY.md~ (in Repos)
|
||||||
|
- Ludo deploy scripts: ~deploy~ folder (in Repos)
|
||||||
|
- ESP Main Build pipeline: AzDO → Pipelines → ~ESS.esp Main Build~
|
||||||
|
- ESP Deploy Pipeline: AzDO → Pipelines → ~ESS.esp Deploy~
|
||||||
|
|
||||||
|
* File Index
|
||||||
|
|
||||||
|
| File | Contents |
|
||||||
|
|--------------------------------------+-----------------------------------------|
|
||||||
|
| [[id:a6c345df-8db9-4538-b87e-0e72e2414905][ESP Deployment Pipeline — Index]] | This file — master index |
|
||||||
|
| [[id:091e9bbc-0c9f-43da-81f9-464882c2a15b][ESP Applications]] | ESP app suite breakdown |
|
||||||
|
| [[id:d66e946f-6785-4e8e-ba00-bb25a52237d1][ESP — AzDO Pipeline]] | AzDO pipeline structure and concepts |
|
||||||
|
| [[id:bf63b6c5-f32f-462e-82ad-8d4a15f7ba48][ESP — PowerShell Script Architecture]] | Three-tier PowerShell architecture |
|
||||||
|
| [[id:9bf19a8b-5581-4be8-9892-913c51df0128][ESP — The Manifest]] | Manifest design and purpose |
|
||||||
|
| [[id:46add22d-e562-4e3a-a301-d4aea2552952][ESP — Database & Dacpac]] | Database, dacpac, and SQL concerns |
|
||||||
|
| [[id:cd3cd02f-c9b3-4455-8ce5-b2a5aa458fed][ESP — Deployment Stages]] | Stages of deployment — detail per stage |
|
||||||
|
| [[id:53d803aa-7e6f-44ed-8d99-a243a5ed5aab][ESP — Known Issues & Risks]] | Known issues and risks |
|
||||||
|
| [[id:53d803aa-7e6f-44ed-8d99-a243a5ed5aab][ESP — Known Issues & Risks]] | TBC items and open design questions |
|
||||||
|
| [[id:2c950d25-6f86-4f83-a7b4-69e2ca2f7023][ESP — Glossary]] | Glossary of all technical terms |
|
||||||
95
Career Concepts/20260410121719-esp_applications.org
Normal file
95
Career Concepts/20260410121719-esp_applications.org
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: 091e9bbc-0c9f-43da-81f9-464882c2a15b
|
||||||
|
:END:
|
||||||
|
#+DATE: 2026-04-10
|
||||||
|
#+filetags: :esp:ess:microlise:citrix:database:
|
||||||
|
#+STARTUP: showall
|
||||||
|
#+title: ESP Applications
|
||||||
|
|
||||||
|
* What is ESP?
|
||||||
|
:PROPERTIES:
|
||||||
|
:RELATED: [[id:091e9bbc-0c9f-43da-81f9-464882c2a15b][ESP Applications]]
|
||||||
|
:END:
|
||||||
|
|
||||||
|
ESP is a software suite built by ESS and sold to customers. It is deployed on a *per-customer basis* — similar to TMC (another internal product) but with fewer applications in the suite.
|
||||||
|
|
||||||
|
Key traits:
|
||||||
|
- Customers only have the apps *they use* — not every customer gets everything
|
||||||
|
- Customers may have multiple environments (e.g. TEST and PROD)
|
||||||
|
- Test and PROD instances may live on the *same server* — this is a risk to be mindful of during deployment
|
||||||
|
|
||||||
|
* Application Categories
|
||||||
|
|
||||||
|
ESP applications fall into three categories:
|
||||||
|
|
||||||
|
** 1. Databases
|
||||||
|
| Application | Type | Notes |
|
||||||
|
|-------------+------------+---------------------------------------------|
|
||||||
|
| EspBroker | SQL Server | The core ESP database. Deployed via dacpac. |
|
||||||
|
|
||||||
|
See [[id:46add22d-e562-4e3a-a301-d4aea2552952][ESP — Database & Dacpac]] for dacpac detail.
|
||||||
|
|
||||||
|
** 2. Windows Services
|
||||||
|
[[id:faa7f193-5af6-4a2f-a73e-540f833a7fd0][Windows Services]] are background processes that run on a Windows server. They have no UI — they start, run, and are managed via the Windows Service Manager (or PowerShell commands like ~Stop-Service~, ~Start-Service~).
|
||||||
|
|
||||||
|
| Service Name | Notes |
|
||||||
|
|-----------------+-----------------------------------|
|
||||||
|
| DLService | Unknown specific function (TBC) |
|
||||||
|
| EmailService | Likely handles outbound emails |
|
||||||
|
| ExPlService | Unknown specific function (TBC) |
|
||||||
|
| MISService | Unknown specific function (TBC) |
|
||||||
|
| OutboundService | Likely handles outbound messaging |
|
||||||
|
| ULService | Unknown specific function (TBC) |
|
||||||
|
|
||||||
|
*** Working with Windows Services in PowerShell
|
||||||
|
#+BEGIN_SRC powershell
|
||||||
|
# Stop a service
|
||||||
|
Stop-Service -Name "DLService" -Force
|
||||||
|
|
||||||
|
# Start a service
|
||||||
|
Start-Service -Name "DLService"
|
||||||
|
|
||||||
|
# Check service status
|
||||||
|
Get-Service -Name "DLService"
|
||||||
|
|
||||||
|
# Wait for a service to stop
|
||||||
|
(Get-Service -Name "DLService").WaitForStatus('Stopped', '00:01:00')
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
*** Why Services Must Be Stopped Before Deployment
|
||||||
|
When deploying a new version, the old service process holds file locks on its [[id:e717c252-0e15-4403-898f-93163dd1b147][DLLs]]. You cannot overwrite a locked file on Windows. Therefore the sequence is:
|
||||||
|
1. Stop the service
|
||||||
|
2. Swap the files (old → new)
|
||||||
|
3. Start the service
|
||||||
|
|
||||||
|
** 3. Citrix Applications
|
||||||
|
Citrix is a technology that *streams desktop applications* to users remotely - the app runs on a server but the user sees it on their machine, similar to a remote desktop but on a per-app basis.
|
||||||
|
|
||||||
|
| Application | Notes |
|
||||||
|
|---------------+------------------------------|
|
||||||
|
| VPlanner | Main planning application |
|
||||||
|
| VPlannerAdmin | Admin interface for VPlanner |
|
||||||
|
| ImportApp | Data import application |
|
||||||
|
|
||||||
|
*** Citrix Deployment Considerations
|
||||||
|
Citrix apps are more complex to deploy than Windows Services because:
|
||||||
|
- *Active user sessions* may be running — you can't just swap files
|
||||||
|
- You must *notify users* of the upcoming upgrade and give a grace period
|
||||||
|
- After the grace period, *kill any remaining sessions*
|
||||||
|
- The actual upgrade mechanism is *still TBC* — believed to be a file copy with handling for locked executables built in
|
||||||
|
- Post-deploy *cycle checks* require navigating Citrix UI — hard to automate
|
||||||
|
|
||||||
|
* Per-Customer App Lists
|
||||||
|
|
||||||
|
Unlike TMC (where presumably all customers get everything), ESP is a subset deployment. This means:
|
||||||
|
|
||||||
|
- The manifest (see [[id:9bf19a8b-5581-4be8-9892-913c51df0128][ESP — The Manifest]]) must define *which apps each customer has*
|
||||||
|
- The deployment scripts must skip apps not applicable to a given customer
|
||||||
|
- There is no universal "deploy everything" - each customer's list must be explicitly defined and maintained
|
||||||
|
|
||||||
|
* Completeness of This List
|
||||||
|
:PROPERTIES:
|
||||||
|
:STATUS: Unconfirmed
|
||||||
|
:END:
|
||||||
|
|
||||||
|
The handover document states this list is believed complete but *has not been confirmed*. Treat it as a working assumption, not a guarantee. Validate against actual customer environments when possible.
|
||||||
157
Career Concepts/20260410121927-esp_pipeline.org
Normal file
157
Career Concepts/20260410121927-esp_pipeline.org
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: d66e946f-6785-4e8e-ba00-bb25a52237d1
|
||||||
|
:END:
|
||||||
|
#+DATE: 2026-04-10
|
||||||
|
#+filetags: :esp:azdo:ess:microlise:yaml:cicd:
|
||||||
|
#+STARTUP: showall
|
||||||
|
#+title: ESP — AzDO Pipeline
|
||||||
|
|
||||||
|
* What is Azure DevOps (AzDO)?
|
||||||
|
:PROPERTIES:
|
||||||
|
:RELATED: [[id:a6c345df-8db9-4538-b87e-0e72e2414905][ESP Deployment Pipeline — Index]]
|
||||||
|
:END:
|
||||||
|
|
||||||
|
Azure DevOps is Microsoft's platform for DevOps workflows. It covers:
|
||||||
|
- *Repos* — Git source code repositories
|
||||||
|
- *Pipelines* — automated build and deployment (CI/CD)
|
||||||
|
- *Boards* — work items, epics, features, tasks
|
||||||
|
- *Artifacts* — storing build outputs (packages, DLLs, etc.)
|
||||||
|
|
||||||
|
For this project, the relevant parts are *Pipelines* and *Repos*.
|
||||||
|
|
||||||
|
* What is a YAML Pipeline?
|
||||||
|
|
||||||
|
AzDO pipelines can be defined in two ways: through a GUI (classic) or via a YAML file stored in the repo. We use *YAML pipelines* — this means the pipeline definition lives in source control alongside the code, making it versioned and auditable.
|
||||||
|
|
||||||
|
** Basic YAML Pipeline Structure
|
||||||
|
#+BEGIN_SRC yaml
|
||||||
|
trigger:
|
||||||
|
branches:
|
||||||
|
include:
|
||||||
|
- main
|
||||||
|
|
||||||
|
pool:
|
||||||
|
vmImage: 'windows-latest' # or a self-hosted agent
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- stage: Build
|
||||||
|
jobs:
|
||||||
|
- job: BuildJob
|
||||||
|
steps:
|
||||||
|
- task: PowerShell@2
|
||||||
|
inputs:
|
||||||
|
filePath: 'scripts/Invoke-Deployment.ps1'
|
||||||
|
arguments: '-Customer ROMAC -Environment DEV -Stages PREDEPLOY,DEPLOY'
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** Key YAML Concepts
|
||||||
|
| Term | Meaning |
|
||||||
|
|------------+---------------------------------------------------------------------|
|
||||||
|
| ~trigger~ | What causes the pipeline to run (e.g. a push to main) |
|
||||||
|
| ~pool~ | The agent (machine) that runs the pipeline |
|
||||||
|
| ~stage~ | A high-level grouping of jobs (e.g. Build, Deploy) |
|
||||||
|
| ~job~ | A unit of work that runs on one agent |
|
||||||
|
| ~step~ | An individual action within a job (run a script, call a task, etc.) |
|
||||||
|
| ~task~ | A pre-built step from the AzDO marketplace (e.g. PowerShell@2) |
|
||||||
|
| ~artifact~ | Output from one stage/job that can be consumed by another |
|
||||||
|
|
||||||
|
* The ESP Pipelines
|
||||||
|
|
||||||
|
There are two existing pipelines to be aware of:
|
||||||
|
|
||||||
|
** ESS.esp Main Build
|
||||||
|
- *Purpose:* Builds the ESP applications from source code
|
||||||
|
- *Output:* Build artifacts (DLLs, binaries)
|
||||||
|
- *Known Issue:* The artifact does not separate applications cleanly - it produces a large flat folder of DLLs. See [[id:53d803aa-7e6f-44ed-8d99-a243a5ed5aab][ESP — Known Issues & Risks]]
|
||||||
|
- *Location:* AzDO → Pipelines → Runs for ~ESS.esp Main Build~
|
||||||
|
|
||||||
|
** ESS.esp Deploy
|
||||||
|
- *Purpose:* Deploys ESP to a customer environment
|
||||||
|
- *Status:* Started by Team Ludo, incomplete
|
||||||
|
- *Location:* AzDO → Pipelines → Runs for ~ESS.esp Deploy~
|
||||||
|
- This is the primary pipeline your team is responsible for completing
|
||||||
|
|
||||||
|
* How the Pipeline Calls Our Scripts
|
||||||
|
|
||||||
|
The pipeline's job is relatively thin - it is an *orchestrator* that calls our PowerShell entry point with the correct parameters.
|
||||||
|
|
||||||
|
#+BEGIN_SRC
|
||||||
|
Pipeline (YAML)
|
||||||
|
└── Calls: Invoke-Deployment.ps1 -Customer ROMAC -Environment DEV -Stages PREDEPLOY,DEPLOY,POSTDEPLOY
|
||||||
|
└── Tier 1 script (loads manifest, loads modules)
|
||||||
|
└── Calls Tier 2 scripts (PreDeployment.ps1, Deployment.ps1, etc.)
|
||||||
|
└── Calls Tier 3 functions (Stop-WindowsService, Invoke-Sql, etc.)
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
See [[id:bf63b6c5-f32f-462e-82ad-8d4a15f7ba48][ESP — PowerShell Script Architecture]] for full detail on the script architecture.
|
||||||
|
|
||||||
|
* Pipeline Agents
|
||||||
|
|
||||||
|
An *agent* is the machine that actually runs the pipeline. There are two types:
|
||||||
|
|
||||||
|
| Type | Description |
|
||||||
|
|------------------+-------------------------------------------------------------|
|
||||||
|
| Microsoft-hosted | Azure spins up a fresh VM for each run; ephemeral |
|
||||||
|
| Self-hosted | A persistent machine you manage; has access to your network |
|
||||||
|
|
||||||
|
For deploying to customer VMs (ROMAC DEV), we will almost certainly need a *self-hosted agent* — a Microsoft-hosted agent running in Azure would not have network access to the customer's internal servers.
|
||||||
|
|
||||||
|
* Pipeline Variables and Secrets
|
||||||
|
|
||||||
|
Pipelines can use variables for configuration. Sensitive values (passwords, connection strings) should be stored as *secret variables* or in *Azure Key Vault*, never hardcoded in the YAML.
|
||||||
|
|
||||||
|
#+BEGIN_SRC yaml
|
||||||
|
variables:
|
||||||
|
- name: CustomerName
|
||||||
|
value: ROMAC
|
||||||
|
- name: DbPassword
|
||||||
|
value: $(DB_PASSWORD) # references a secret variable set in AzDO UI
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
* Approvals and Gates
|
||||||
|
|
||||||
|
For higher environments (PROD), AzDO supports *manual approval gates* between stages — a human must approve before the pipeline continues. This is important when the scope expands beyond DEV.
|
||||||
|
|
||||||
|
* Pipeline Run History
|
||||||
|
|
||||||
|
Each pipeline run is logged in AzDO with full step-by-step output. This is your primary debugging tool when a deployment fails.
|
||||||
|
|
||||||
|
* Relationship to Our PowerShell Scripts
|
||||||
|
|
||||||
|
A key design goal is that the PowerShell scripts should be able to run *independently of AzDO* — i.e. you could call ~Invoke-Deployment.ps1~ directly from a terminal if needed. AzDO is just a convenient trigger and logging wrapper. This means the logic must not be baked into the YAML itself.
|
||||||
|
|
||||||
|
* One other note on agents:
|
||||||
|
Almost certainly **Virtual Machines (VMs)**. Physical ("bare metal") servers are rarely used in modern infrastructure for this kind of thing. A data centre typically runs a small number of powerful physical machines, and on top of those you run many VMs — each VM behaves like its own independent server but they're all sharing the underlying physical hardware.
|
||||||
|
|
||||||
|
So the full picture is probably:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
Physical machine(s) in ESS Altrincham DC
|
||||||
|
└── VM: AzDO Self-Hosted Agent
|
||||||
|
└── VM: App Server (runs the Windows Services, Citrix apps)
|
||||||
|
└── VM: SQL Server (runs EspBroker database)
|
||||||
|
... possibly more VMs
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
And the flow when you kick off a deployment in AzDO:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
|
||||||
|
You click "Run Pipeline" in AzDO (cloud)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
AzDO talks to the self-hosted agent VM in Altrincham
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
The agent picks up the job and runs the PowerShell scripts
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
The scripts connect (via PowerShell remoting) to the App Server VM
|
||||||
|
The scripts connect to the SQL Server VM
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Deployment happens
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
The agent itself isn't the thing being deployed *to* — it's just the middleman that has network access to the other VMs in the same DC. Which also ties back to why each customer needs unique credentials — even though they share that infrastructure in DEV, each customer's VMs are in their own domain, so the agent needs the right credentials to authenticate into each one.
|
||||||
269
Career Concepts/20260410122116-ess_scripts.org
Normal file
269
Career Concepts/20260410122116-ess_scripts.org
Normal file
@@ -0,0 +1,269 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: bf63b6c5-f32f-462e-82ad-8d4a15f7ba48
|
||||||
|
:END:
|
||||||
|
#+DATE: 2026-04-10
|
||||||
|
#+filetags: :powershell:scripts:ess:esp:microlise:
|
||||||
|
#+STARTUP: showall
|
||||||
|
#+title: ESP — PowerShell Script Architecture
|
||||||
|
|
||||||
|
* Overview
|
||||||
|
:PROPERTIES:
|
||||||
|
:RELATED: [[id:a6c345df-8db9-4538-b87e-0e72e2414905][ESP Deployment Pipeline — Index]]
|
||||||
|
:END:
|
||||||
|
|
||||||
|
The deployment scripts are structured in *three tiers*, loosely analogous to a presentation/domain/data layered architecture in software. This separation exists to:
|
||||||
|
|
||||||
|
- Keep ESP-specific knowledge isolated to higher tiers
|
||||||
|
- Allow Tier 3 functions to be tested in isolation
|
||||||
|
- Allow the scripts to run independently of AzDO
|
||||||
|
- Make incremental automation easier (replace manual prompts one function at a time)
|
||||||
|
|
||||||
|
* Entry Point — How to Call the Scripts
|
||||||
|
|
||||||
|
#+BEGIN_SRC powershell
|
||||||
|
Invoke-Deployment.ps1 -Customer ROMAC -Environment DEV -Stages PREDEPLOY,DEPLOY,POSTDEPLOY
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
You can pass any combination of stages. For example, to only validate:
|
||||||
|
|
||||||
|
#+BEGIN_SRC powershell
|
||||||
|
Invoke-Deployment.ps1 -Customer ROMAC -Environment DEV -Stages VALIDATE
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
* Tier 1 — Entry Point (Presentation Layer)
|
||||||
|
|
||||||
|
** Responsibility
|
||||||
|
- The *single entry point* to the whole deployment system
|
||||||
|
- Loads and validates the manifest (see [[id:9bf19a8b-5581-4be8-9892-913c51df0128][ESP — The Manifest]])
|
||||||
|
- Loads all required PowerShell modules (Tier 2, Tier 3, helpers)
|
||||||
|
- Calls the appropriate Tier 2 functions for the requested stages
|
||||||
|
- Passes the manifest object through to Tier 2
|
||||||
|
|
||||||
|
** Key Characteristics
|
||||||
|
- One script: ~Invoke-Deployment.ps1~
|
||||||
|
- Does NOT contain deployment logic itself
|
||||||
|
- Acts as a wiring layer only
|
||||||
|
|
||||||
|
** Pseudocode
|
||||||
|
#+BEGIN_SRC powershell
|
||||||
|
param(
|
||||||
|
[string]$Customer,
|
||||||
|
[string]$Environment,
|
||||||
|
[string[]]$Stages
|
||||||
|
)
|
||||||
|
|
||||||
|
$manifest = Load-Manifest -Customer $Customer -Environment $Environment
|
||||||
|
Assert-ManifestValid -Manifest $manifest
|
||||||
|
|
||||||
|
Import-Module ./Tier2/PreDeployment.psm1
|
||||||
|
Import-Module ./Tier2/Deployment.psm1
|
||||||
|
Import-Module ./Tier2/PostDeployment.psm1
|
||||||
|
Import-Module ./Helpers/Logging.psm1
|
||||||
|
|
||||||
|
foreach ($stage in $Stages) {
|
||||||
|
switch ($stage) {
|
||||||
|
"PREDEPLOY" { Invoke-PreDeployment -Manifest $manifest }
|
||||||
|
"DEPLOY" { Invoke-Deployment -Manifest $manifest }
|
||||||
|
"POSTDEPLOY" { Invoke-PostDeployment -Manifest $manifest }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
* Tier 2 — Orchestration Layer (Domain Layer)
|
||||||
|
|
||||||
|
** Responsibility
|
||||||
|
- One script per deployment stage (e.g. ~PreDeployment.psm1~, ~Deployment.psm1~)
|
||||||
|
- Contains the *logic and sequencing* of what needs to happen
|
||||||
|
- Decides *which* Tier 3 functions to call and in what order
|
||||||
|
- Reacts to return values from Tier 3 (e.g. if a function fails, abort or retry)
|
||||||
|
|
||||||
|
** Key Constraints
|
||||||
|
- *Does NOT* pass the manifest to Tier 3 — all required data is extracted and passed as explicit parameters
|
||||||
|
- *Does NOT* directly perform any action itself — delegates entirely to Tier 3
|
||||||
|
- *Does* have knowledge of ESP and what a deployment involves
|
||||||
|
|
||||||
|
** Why "Does Not Pass Manifest to Tier 3"?
|
||||||
|
Tier 3 functions are designed to be generic and reusable. If they accepted a manifest object, they'd need to know about its structure — breaking isolation. Instead, Tier 2 extracts what Tier 3 needs:
|
||||||
|
|
||||||
|
#+BEGIN_SRC powershell
|
||||||
|
# BAD — passes the whole manifest (couples Tier 3 to manifest structure)
|
||||||
|
Stop-WindowsService -Manifest $manifest
|
||||||
|
|
||||||
|
# GOOD — extracts what's needed and passes explicitly
|
||||||
|
Stop-WindowsService -ServiceName $manifest.Services.DLService.Name `
|
||||||
|
-ServerName $manifest.Servers.AppServer
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** Scripts in This Tier
|
||||||
|
| Script | Stage it covers |
|
||||||
|
|-----------------------+---------------------|
|
||||||
|
| ~Validation.psm1~ | VALIDATE stage |
|
||||||
|
| ~Prerequisites.psm1~ | PREREQUISITES stage |
|
||||||
|
| ~PreDeployment.psm1~ | PREDEPLOY stage |
|
||||||
|
| ~Deployment.psm1~ | DEPLOY stage |
|
||||||
|
| ~PostDeployment.psm1~ | POSTDEPLOY stage |
|
||||||
|
|
||||||
|
* Tier 3 — Functional Layer (Workers)
|
||||||
|
|
||||||
|
** Responsibility
|
||||||
|
- Small, *single-purpose* functions
|
||||||
|
- No knowledge of ESP, the manifest, or deployment context
|
||||||
|
- Accept all required data as *explicit parameters*
|
||||||
|
- Can be tested in isolation with mock data
|
||||||
|
|
||||||
|
** Key Characteristics
|
||||||
|
- Examples: ~Stop-WindowsService~, ~Invoke-SqlScript~, ~Copy-Files~, ~Get-RemoteSession~, ~Send-CitrixNotification~
|
||||||
|
- Initially implemented as *manual prompt wrappers* — the function prints instructions to a human and waits for confirmation
|
||||||
|
- Will be replaced with real automation incrementally
|
||||||
|
|
||||||
|
** The Manual Prompt Pattern (Current State)
|
||||||
|
#+BEGIN_SRC powershell
|
||||||
|
function Stop-WindowsService {
|
||||||
|
param([string]$ServiceName, [string]$ServerName)
|
||||||
|
|
||||||
|
# Current implementation — prompts a human
|
||||||
|
$response = Invoke-ManualPrompt -Message "Please stop service '$ServiceName' on '$ServerName', then press Enter."
|
||||||
|
return $response
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** Target Implementation (Automated)
|
||||||
|
#+BEGIN_SRC powershell
|
||||||
|
function Stop-WindowsService {
|
||||||
|
param([string]$ServiceName, [string]$ServerName)
|
||||||
|
|
||||||
|
$session = Get-RemoteSession -ServerName $ServerName
|
||||||
|
Invoke-Command -Session $session -ScriptBlock {
|
||||||
|
Stop-Service -Name $using:ServiceName -Force
|
||||||
|
(Get-Service -Name $using:ServiceName).WaitForStatus('Stopped', '00:01:00')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** Exceptions — Functions That Cannot Be Manual Prompts
|
||||||
|
A small number of Tier 3 functions *must* be implemented for real from the start because they return data the scripts need to function:
|
||||||
|
|
||||||
|
| Function | Why it can't be a manual prompt |
|
||||||
|
|---------------------+-------------------------------------------------------|
|
||||||
|
| ~Load-Manifest~ | Returns the manifest object — must actually read file |
|
||||||
|
| ~Get-RemoteSession~ | Returns a PS session — must actually connect |
|
||||||
|
| ~Read-File~ | Returns file contents — must actually read |
|
||||||
|
|
||||||
|
* Helper Modules
|
||||||
|
|
||||||
|
In addition to the three tiers, *general-purpose helper modules* exist that can be called from anywhere (Tier 1, 2, or 3):
|
||||||
|
|
||||||
|
| Module | Purpose |
|
||||||
|
|----------------+--------------------------------------------|
|
||||||
|
| ~Logging.psm1~ | Write structured log output |
|
||||||
|
| ~Prompt.psm1~ | The manual prompt mechanism used by Tier 3 |
|
||||||
|
| | |
|
||||||
|
|
||||||
|
Helpers follow the same rule as Tier 3: *the manifest is never passed to them*.
|
||||||
|
|
||||||
|
* Testing Strategy
|
||||||
|
|
||||||
|
Because Tier 3 functions are isolated, they can be unit tested without any connection to a real ESP environment:
|
||||||
|
|
||||||
|
#+BEGIN_SRC powershell
|
||||||
|
# Example Pester test for Stop-WindowsService
|
||||||
|
Describe "Stop-WindowsService" {
|
||||||
|
It "calls Invoke-Command with correct service name" {
|
||||||
|
Mock Invoke-Command {}
|
||||||
|
Mock Get-RemoteSession { return [PSCustomObject]@{ Session = "MockSession" } }
|
||||||
|
|
||||||
|
Stop-WindowsService -ServiceName "DLService" -ServerName "SERVER01"
|
||||||
|
|
||||||
|
Assert-MockCalled Invoke-Command -Times 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
* Incremental Automation Plan
|
||||||
|
|
||||||
|
The architecture is designed so that automation can be added *one function at a time*, without restructuring anything:
|
||||||
|
|
||||||
|
1. Deploy with all Tier 3 functions as manual prompts (guided checklist)
|
||||||
|
2. Identify the lowest-risk, simplest functions to automate first
|
||||||
|
3. Replace manual prompts with real implementations one by one
|
||||||
|
4. Each replacement can be independently tested before deployment
|
||||||
|
|
||||||
|
Suggested automation order (rough):
|
||||||
|
1. ~Stop-WindowsService~ / ~Start-WindowsService~ — well-understood, low risk
|
||||||
|
2. ~Copy-Files~ — straightforward file operations
|
||||||
|
3. ~Invoke-SqlScript~ — once databases are in dacpac-ready state
|
||||||
|
4. Citrix-related functions — last, most complex
|
||||||
|
|
||||||
|
* Architecture Diagram (Text)
|
||||||
|
|
||||||
|
#+BEGIN_SRC
|
||||||
|
AzDO Pipeline (YAML)
|
||||||
|
│
|
||||||
|
└─► Invoke-Deployment.ps1 [TIER 1]
|
||||||
|
│ Loads manifest
|
||||||
|
│ Loads all modules
|
||||||
|
│
|
||||||
|
├─► PreDeployment.psm1 [TIER 2]
|
||||||
|
│ ├─► Copy-Files [TIER 3]
|
||||||
|
│ └─► ...
|
||||||
|
│
|
||||||
|
├─► Deployment.psm1 [TIER 2]
|
||||||
|
│ ├─► Stop-WindowsService [TIER 3]
|
||||||
|
│ ├─► Invoke-SqlScript [TIER 3]
|
||||||
|
│ ├─► Start-WindowsService [TIER 3]
|
||||||
|
│ └─► ...
|
||||||
|
│
|
||||||
|
└─► PostDeployment.psm1 [TIER 2]
|
||||||
|
├─► Get-ServiceStatus [TIER 3]
|
||||||
|
└─► ...
|
||||||
|
|
||||||
|
[Helpers: Logging, Prompt — available at any tier]
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** Mermaid Diagram (Text)
|
||||||
|
#+BEGIN_SRC mermaid
|
||||||
|
graph TD
|
||||||
|
|
||||||
|
%% Tier 1
|
||||||
|
subgraph "Tier 1 - Entry Point"
|
||||||
|
A[Invoke-Deployment.ps1]
|
||||||
|
end
|
||||||
|
|
||||||
|
%% Tier 2
|
||||||
|
subgraph "Tier 2 - Deployment Phases"
|
||||||
|
B[PreDeployment.psm1]
|
||||||
|
C[Deployment.psm1]
|
||||||
|
D[PostDeployment.psm1]
|
||||||
|
end
|
||||||
|
|
||||||
|
%% Tier 3
|
||||||
|
subgraph "Tier 3 - Actions"
|
||||||
|
E[Copy-Files]
|
||||||
|
F[Stop-WindowsService]
|
||||||
|
G[Invoke-SqlScript]
|
||||||
|
H[Start-WindowsService]
|
||||||
|
I[Get-ServiceStatus]
|
||||||
|
end
|
||||||
|
|
||||||
|
%% Helpers
|
||||||
|
subgraph "Helpers (All Tiers)"
|
||||||
|
J[Logging Helper]
|
||||||
|
K[Prompt Helper]
|
||||||
|
end
|
||||||
|
|
||||||
|
%% Relationships
|
||||||
|
A --> B
|
||||||
|
A --> C
|
||||||
|
A --> D
|
||||||
|
|
||||||
|
B --> E
|
||||||
|
|
||||||
|
C --> F
|
||||||
|
C --> G
|
||||||
|
C --> H
|
||||||
|
|
||||||
|
D --> I
|
||||||
|
|
||||||
|
A --> J
|
||||||
|
A --> K
|
||||||
|
#+END_SRC
|
||||||
127
Career Concepts/20260410122303-ess_manifest.org
Normal file
127
Career Concepts/20260410122303-ess_manifest.org
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: 9bf19a8b-5581-4be8-9892-913c51df0128
|
||||||
|
:END:
|
||||||
|
#+DATE: 2026-04-10
|
||||||
|
#+filetags: :ess:esp:microlise:manifest:
|
||||||
|
#+STARTUP: showall
|
||||||
|
#+title: ESP — The Manifest
|
||||||
|
|
||||||
|
* What Is the Manifest?
|
||||||
|
:PROPERTIES:
|
||||||
|
:RELATED: [[id:a6c345df-8db9-4538-b87e-0e72e2414905][ESP Deployment Pipeline — Index]]
|
||||||
|
:STATUS: Design not yet finalised
|
||||||
|
:END:
|
||||||
|
|
||||||
|
The manifest is a *configuration file* that describes a specific customer environment. The deployment scripts read the manifest to understand *what* to deploy, *where*, and *how*.
|
||||||
|
|
||||||
|
There will be one manifest per customer/environment combination, for example:
|
||||||
|
- ~ROMAC_DEV.json~ (or ~.yaml~, ~.psd1~ — format TBC)
|
||||||
|
- ~ROMAC_PROD.json~
|
||||||
|
- ~ACMECORP_DEV.json~
|
||||||
|
|
||||||
|
* Why the Manifest Matters
|
||||||
|
|
||||||
|
Without a manifest, the scripts would have no way of knowing:
|
||||||
|
- Which server(s) to connect to
|
||||||
|
- Which apps this customer actually uses
|
||||||
|
- What credentials to use
|
||||||
|
- What version is being deployed
|
||||||
|
- What environment-specific configuration to apply
|
||||||
|
|
||||||
|
It is the *single source of truth* for a deployment. Tier 1 loads it, validates it, and passes it to Tier 2. Tier 2 extracts values from it and passes those to Tier 3.
|
||||||
|
|
||||||
|
* Design Status
|
||||||
|
|
||||||
|
The manifest *structure has not yet been fully designed*. This is an open work item. See [[id:82c3d447-d6d3-498e-9f66-aee60c752462][ESP — Open Questions & TBC Items]] for a list of design questions to resolve.
|
||||||
|
|
||||||
|
What follows is a *proposed structure* based on what the scripts will need.
|
||||||
|
|
||||||
|
* Proposed Manifest Structure
|
||||||
|
|
||||||
|
#+BEGIN_SRC json
|
||||||
|
{
|
||||||
|
"customer": "ROMAC",
|
||||||
|
"environment": "DEV",
|
||||||
|
"version": "3.2.1",
|
||||||
|
|
||||||
|
"servers": {
|
||||||
|
"appServer": "ROMAC-DEV-APP01",
|
||||||
|
"dbServer": "ROMAC-DEV-DB01",
|
||||||
|
"citrixServer": "ROMAC-DEV-CTX01"
|
||||||
|
},
|
||||||
|
|
||||||
|
"database": {
|
||||||
|
"name": "EspBroker",
|
||||||
|
"dacpacReady": false
|
||||||
|
},
|
||||||
|
|
||||||
|
"windowsServices": {
|
||||||
|
"DLService": { "enabled": true, "installPath": "C:\\ESP\\DLService" },
|
||||||
|
"EmailService": { "enabled": true, "installPath": "C:\\ESP\\EmailService" },
|
||||||
|
"ExPlService": { "enabled": false },
|
||||||
|
"MISService": { "enabled": true, "installPath": "C:\\ESP\\MISService" },
|
||||||
|
"OutboundService": { "enabled": true, "installPath": "C:\\ESP\\OutboundService" },
|
||||||
|
"ULService": { "enabled": false }
|
||||||
|
},
|
||||||
|
|
||||||
|
"citrixApps": {
|
||||||
|
"VPlanner": { "enabled": true, "installPath": "C:\\ESP\\VPlanner" },
|
||||||
|
"VPlannerAdmin": { "enabled": true, "installPath": "C:\\ESP\\VPlannerAdmin" },
|
||||||
|
"ImportApp": { "enabled": false }
|
||||||
|
},
|
||||||
|
|
||||||
|
"citrix": {
|
||||||
|
"notificationMinutes": 15,
|
||||||
|
"sessionKillGracePeriodMinutes": 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
* Key Fields to Define
|
||||||
|
|
||||||
|
| Field | Purpose |
|
||||||
|
|-----------------------------+-------------------------------------------------------------|
|
||||||
|
| ~customer~ | Identifies the customer |
|
||||||
|
| ~environment~ | Identifies the environment (DEV/TEST/PROD) |
|
||||||
|
| ~version~ | Version of ESP being deployed |
|
||||||
|
| ~servers.*~ | Hostnames/IPs of servers to connect to |
|
||||||
|
| ~database.dacpacReady~ | Flag to indicate if DB is in a state for dacpac deployment |
|
||||||
|
| ~windowsServices.*.enabled~ | Whether this customer uses this service |
|
||||||
|
| ~citrixApps.*.enabled~ | Whether this customer uses this Citrix app |
|
||||||
|
| ~citrix.*~ | Citrix-specific config (notification timing, grace periods) |
|
||||||
|
|
||||||
|
* Manifest Validation (VALIDATE Stage)
|
||||||
|
|
||||||
|
The VALIDATE stage (see [[id:cd3cd02f-c9b3-4455-8ce5-b2a5aa458fed][ESP — Deployment Stages]]) loads the manifest and checks it is well-formed before any deployment activity. Things to validate:
|
||||||
|
|
||||||
|
- All required fields are present
|
||||||
|
- Server names are resolvable/pingable
|
||||||
|
- ~version~ matches available build artifacts
|
||||||
|
- ~dacpacReady~ flag prevents DB deployment if false
|
||||||
|
- No conflicting settings (e.g. test and prod on same server without flag)
|
||||||
|
|
||||||
|
* Manifest Location and Storage
|
||||||
|
|
||||||
|
Where manifests should live is TBC, but candidates include:
|
||||||
|
- A dedicated folder in the AzDO repo (versioned with the scripts)
|
||||||
|
- A separate config repo
|
||||||
|
- An external config store (Azure App Configuration, Key Vault, etc.)
|
||||||
|
|
||||||
|
Sensitive values (passwords, connection strings) should *never* be in the manifest file in plaintext — they should reference a secret store.
|
||||||
|
|
||||||
|
* Per-Customer App Lists
|
||||||
|
|
||||||
|
Because not all customers use all apps, the manifest is the mechanism that drives per-customer deployment. Tier 2 scripts iterate over enabled apps:
|
||||||
|
|
||||||
|
#+BEGIN_SRC powershell
|
||||||
|
foreach ($service in $manifest.WindowsServices.GetEnumerator()) {
|
||||||
|
if ($service.Value.Enabled) {
|
||||||
|
Stop-WindowsService -ServiceName $service.Key `
|
||||||
|
-ServerName $manifest.Servers.AppServer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
* Environments on the Same Server
|
||||||
|
|
||||||
|
The handover document flags that some customers may have TEST and PROD on the same physical server. The manifest must account for this — likely via distinct install paths per environment and explicit environment tagging to prevent accidental cross-environment deployment.
|
||||||
127
Career Concepts/20260410122425-ess_database.org
Normal file
127
Career Concepts/20260410122425-ess_database.org
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: 46add22d-e562-4e3a-a301-d4aea2552952
|
||||||
|
:END:
|
||||||
|
#+DATE: 2026-04-10
|
||||||
|
#+filetags: :database:sql:ess:esp:microlise:
|
||||||
|
#+STARTUP: showall
|
||||||
|
#+title: ESP — Database & Dacpac
|
||||||
|
|
||||||
|
* The ESP Database
|
||||||
|
:PROPERTIES:
|
||||||
|
:RELATED: [[id:a6c345df-8db9-4538-b87e-0e72e2414905][ESP Deployment Pipeline — Index]]
|
||||||
|
:END:
|
||||||
|
|
||||||
|
ESP uses a single SQL Server database called *EspBroker*. This is deployed and upgraded as part of the overall ESP deployment process.
|
||||||
|
|
||||||
|
* What Is a Dacpac?
|
||||||
|
|
||||||
|
A *dacpac* (Data-tier Application Package) is a packaged representation of a SQL Server database *schema*. It is a file with the extension ~.dacpac~.
|
||||||
|
|
||||||
|
Rather than writing migration scripts that say "ALTER TABLE, ADD COLUMN..." manually, you instead describe the *desired end state* of the database, and the dacpac deployment tool (~sqlpackage~) calculates the delta and applies it automatically.
|
||||||
|
|
||||||
|
** How Dacpac Deployment Works
|
||||||
|
#+BEGIN_SRC
|
||||||
|
Your dacpac file (desired schema)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
sqlpackage.exe
|
||||||
|
│
|
||||||
|
├── Connects to target database
|
||||||
|
├── Compares desired schema to actual schema
|
||||||
|
├── Generates a diff
|
||||||
|
└── Applies the diff (ALTER TABLE, CREATE INDEX, etc.)
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** Advantages Over Raw SQL Scripts
|
||||||
|
| Dacpac | Raw SQL Scripts |
|
||||||
|
|-----------------------------------------+-------------------------------------------|
|
||||||
|
| Declarative — describe what you want | Imperative — describe each change step |
|
||||||
|
| Tool calculates the diff automatically | You must track and apply changes manually |
|
||||||
|
| Idempotent — safe to run multiple times | Can fail if run twice without care |
|
||||||
|
| Schema is versioned as code | Scripts can get out of sync |
|
||||||
|
|
||||||
|
** Relevant PowerShell / CLI
|
||||||
|
#+BEGIN_SRC powershell
|
||||||
|
# Deploy a dacpac using sqlpackage
|
||||||
|
& "C:\Program Files\Microsoft SQL Server\160\DAC\bin\sqlpackage.exe" `
|
||||||
|
/Action:Publish `
|
||||||
|
/SourceFile:"EspBroker.dacpac" `
|
||||||
|
/TargetServerName:"ROMAC-DEV-DB01" `
|
||||||
|
/TargetDatabaseName:"EspBroker"
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
* Team Ludo's Dacpac
|
||||||
|
|
||||||
|
Team Ludo built a dacpac solution for EspBroker. This is already in the repo and represents the *target schema* that all customer databases should eventually conform to.
|
||||||
|
|
||||||
|
* The Critical Problem — Schema Inconsistency
|
||||||
|
|
||||||
|
** What the Problem Is
|
||||||
|
Existing customer databases have drifted from the official schema over time. This drift likely happened due to:
|
||||||
|
- Manual hotfixes applied directly to production databases
|
||||||
|
- Different versions of ESP deployed to different customers at different times
|
||||||
|
- No enforced schema management historically
|
||||||
|
|
||||||
|
This means the dacpac's expected schema does not match what is actually in customer databases.
|
||||||
|
|
||||||
|
** Consequence
|
||||||
|
If you attempt to deploy the dacpac against an inconsistent database, ~sqlpackage~ will either:
|
||||||
|
- Fail with errors (best case — nothing is changed)
|
||||||
|
- Apply incorrect changes that corrupt data (worst case)
|
||||||
|
|
||||||
|
** What Needs to Happen
|
||||||
|
Before the dacpac can be used for a customer:
|
||||||
|
1. A database expert must *manually inspect* the customer's database
|
||||||
|
2. Identify all schema differences between actual and expected state
|
||||||
|
3. Write and apply *manual SQL scripts* to bring the DB into alignment
|
||||||
|
4. Verify the dacpac can then deploy cleanly (ideally against a copy)
|
||||||
|
5. Only then mark the customer as ~dacpacReady: true~ in the manifest
|
||||||
|
|
||||||
|
** Pipeline Safeguard
|
||||||
|
The deployment pipeline *must* check the ~dacpacReady~ flag before attempting database deployment, and fail clearly if it is ~false~:
|
||||||
|
|
||||||
|
#+BEGIN_SRC powershell
|
||||||
|
function Invoke-DatabaseDeployment {
|
||||||
|
param($Manifest)
|
||||||
|
|
||||||
|
if (-not $Manifest.Database.DacpacReady) {
|
||||||
|
Write-Error "Database for $($Manifest.Customer) $($Manifest.Environment) is not dacpac-ready. " +
|
||||||
|
"Manual schema alignment is required before deployment."
|
||||||
|
throw "Database not ready for dacpac deployment."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Proceed with dacpac deployment...
|
||||||
|
Deploy-Dacpac -DacpacPath $artifactPath -Server $Manifest.Servers.DbServer -Database "EspBroker"
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
* Database Deployment in the Deployment Stage
|
||||||
|
|
||||||
|
Database deployment sits inside the *DEPLOY stage*. See [[id:cd3cd02f-c9b3-4455-8ce5-b2a5aa458fed][ESP — Deployment Stages]] for full stage detail. The database is typically deployed before services are started up to ensure the schema is ready for the new application code.
|
||||||
|
|
||||||
|
Suggested order within the DEPLOY stage:
|
||||||
|
1. Stop Windows Services
|
||||||
|
2. Deploy database dacpac (if dacpacReady)
|
||||||
|
3. Handle Citrix sessions
|
||||||
|
4. Swap application files
|
||||||
|
5. Start Windows Services back up
|
||||||
|
|
||||||
|
* Rollback Considerations
|
||||||
|
|
||||||
|
If the dacpac deploys successfully but a subsequent step fails, rolling back the database is non-trivial. Dacpac does not natively support rollback — options are:
|
||||||
|
- Restore from backup (requires a backup to have been taken immediately before)
|
||||||
|
- Write a counter-dacpac that reverts the schema (complex, error-prone)
|
||||||
|
|
||||||
|
This is one of the reasons the *rollback plan is still TBC*. See [[id:82c3d447-d6d3-498e-9f66-aee60c752462][ESP — Open Questions & TBC Items]].
|
||||||
|
|
||||||
|
A *database backup must be taken before any deployment* — this should be a mandatory step in the PREDEPLOY stage.
|
||||||
|
|
||||||
|
* SQL Server Concepts Relevant Here
|
||||||
|
|
||||||
|
| Concept | Relevance |
|
||||||
|
|----------------+--------------------------------------------------------------|
|
||||||
|
| Schema | The structure of tables, columns, indexes, constraints, etc. |
|
||||||
|
| ~sqlpackage~ | Microsoft CLI tool that applies dacpac files |
|
||||||
|
| ~BACPAC~ | Like dacpac but includes data — useful for backup/restore |
|
||||||
|
| SQL Agent Jobs | Scheduled SQL jobs that may need to be handled during deploy |
|
||||||
|
| Linked Servers | DB connections to other servers — may be part of ESP's setup |
|
||||||
150
Career Concepts/20260410122604-ess_deploy_stages.org
Normal file
150
Career Concepts/20260410122604-ess_deploy_stages.org
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: cd3cd02f-c9b3-4455-8ce5-b2a5aa458fed
|
||||||
|
:END:
|
||||||
|
#+DATE: 2026-04-10
|
||||||
|
#+filetags: :ess:esp:microlise:deployment:
|
||||||
|
#+STARTUP: showall
|
||||||
|
#+title: ESP — Deployment Stages
|
||||||
|
#+TAGS: stages predeploy deploy postdeploy validate prerequisites
|
||||||
|
|
||||||
|
* Overview
|
||||||
|
:PROPERTIES:
|
||||||
|
:RELATED: [[id:a6c345df-8db9-4538-b87e-0e72e2414905][ESP Deployment Pipeline — Index]]
|
||||||
|
:END:
|
||||||
|
|
||||||
|
The deployment is broken into *discrete stages* that can be run in any combination. This allows you to, for example, only run validation, or only run post-deploy checks, without triggering a full deployment.
|
||||||
|
|
||||||
|
Entry point call:
|
||||||
|
#+BEGIN_SRC powershell
|
||||||
|
Invoke-Deployment.ps1 -Customer ROMAC -Environment DEV -Stages VALIDATE,PREDEPLOY,DEPLOY,POSTDEPLOY
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
* Stage Summary
|
||||||
|
|
||||||
|
| Stage | Script (Tier 2) | Safe to Run Alone? | Notes |
|
||||||
|
|---------------+-----------------------+--------------------+---------------------------|
|
||||||
|
| VALIDATE | ~Validation.psm1~ | Yes — read only | No changes made |
|
||||||
|
| PREREQUISITES | ~Prerequisites.psm1~ | Yes — read only | No changes made |
|
||||||
|
| PREDEPLOY | ~PreDeployment.psm1~ | Yes (with care) | Stages files, no swap yet |
|
||||||
|
| DEPLOY | ~Deployment.psm1~ | No — destructive | Requires PREDEPLOY first |
|
||||||
|
| POSTDEPLOY | ~PostDeployment.psm1~ | Yes (after DEPLOY) | Checks only, no changes |
|
||||||
|
|
||||||
|
* Stage 1 — VALIDATE
|
||||||
|
|
||||||
|
** Purpose
|
||||||
|
Load the manifest and verify it is well-formed and consistent before anything else happens.
|
||||||
|
|
||||||
|
** What It Does
|
||||||
|
- Reads the manifest file for the given customer/environment
|
||||||
|
- Checks all required fields are present
|
||||||
|
- Validates server names, version references, and flags
|
||||||
|
- Checks that the referenced build artifact version exists
|
||||||
|
- Fails fast with a clear error if anything is wrong
|
||||||
|
|
||||||
|
** What It Does NOT Do
|
||||||
|
- Makes no changes to any server
|
||||||
|
- Does not connect to target servers (it may ping/resolve names only)
|
||||||
|
|
||||||
|
** Why It Exists Separately
|
||||||
|
You might want to validate a new manifest you've written without triggering a full deployment. Running VALIDATE alone takes seconds and gives you confidence before committing to the rest.
|
||||||
|
|
||||||
|
* Stage 2 — PREREQUISITES
|
||||||
|
|
||||||
|
** Purpose
|
||||||
|
Verify that the target environment meets all requirements before deployment begins.
|
||||||
|
|
||||||
|
** What It Checks (Not Exhaustive — Full List TBC)
|
||||||
|
- Required software is installed on target servers (e.g. .NET runtime, SQL client)
|
||||||
|
- Correct environment labels/flags are set up
|
||||||
|
- Services exist (so the deployment can stop/start them)
|
||||||
|
- Network connectivity between agent and target servers
|
||||||
|
- Sufficient disk space on target servers
|
||||||
|
- Database is accessible
|
||||||
|
- If DEPLOY will include DB: check ~dacpacReady~ flag (see [[id:46add22d-e562-4e3a-a301-d4aea2552952][ESP — Database & Dacpac]])
|
||||||
|
|
||||||
|
** Outcome
|
||||||
|
- Pass: continue to next stage
|
||||||
|
- Fail: abort with a clear list of what's missing — *no changes made*
|
||||||
|
|
||||||
|
* Stage 3 — PREDEPLOY
|
||||||
|
|
||||||
|
** Purpose
|
||||||
|
Prepare the new version's files on the target servers *without* switching anything live. Think of it as laying everything out ready before the actual switch.
|
||||||
|
|
||||||
|
** What It Does
|
||||||
|
- Copies build artifacts from the AzDO artifact store to a *staging location* on each target server (not the live installation path)
|
||||||
|
- Applies environment-specific configuration to the staged files (e.g. replaces connection strings, config values from the manifest)
|
||||||
|
- Takes a *backup of the current live installation* and the database
|
||||||
|
- Verifies the staged files look correct
|
||||||
|
|
||||||
|
** Why Stage Before Deploying?
|
||||||
|
Pre-staging minimises the time during which the application is down. When DEPLOY runs, it can simply swap directories (fast) rather than copying large amounts of data (slow) while services are stopped.
|
||||||
|
|
||||||
|
** Artifact Staging Note
|
||||||
|
The ESP build artifact is currently a *flat folder of DLLs* — not separated per application. Predeploy will need to handle the mapping of DLLs to their correct applications. See [[id:53d803aa-7e6f-44ed-8d99-a243a5ed5aab][ESP — Known Issues & Risks]].
|
||||||
|
|
||||||
|
* Stage 4 — DEPLOY
|
||||||
|
|
||||||
|
** Purpose
|
||||||
|
The actual upgrade — swap the old version for the new version.
|
||||||
|
|
||||||
|
** Sequence (High Level)
|
||||||
|
|
||||||
|
*** 4a. Database
|
||||||
|
1. Check ~dacpacReady~ flag — fail if false
|
||||||
|
2. Deploy the dacpac to EspBroker (see [[id:46add22d-e562-4e3a-a301-d4aea2552952][ESP — Database & Dacpac]])
|
||||||
|
|
||||||
|
*** 4b. Windows Services
|
||||||
|
1. Stop all enabled Windows Services (one by one or in parallel — TBC)
|
||||||
|
2. For each service:
|
||||||
|
a. Move/delete old installation directory
|
||||||
|
b. Move staged new files into the installation directory
|
||||||
|
3. Apply any final configuration adjustments
|
||||||
|
|
||||||
|
*** 4c. Citrix Applications
|
||||||
|
1. Send notification to active Citrix users (e.g. "System upgrade in 15 mins")
|
||||||
|
2. Wait for grace period to expire
|
||||||
|
3. Kill any remaining Citrix sessions
|
||||||
|
4. Perform Citrix application upgrade (mechanism TBC — believed to be file copy)
|
||||||
|
|
||||||
|
*** 4d. Start Up
|
||||||
|
1. Start all enabled Windows Services
|
||||||
|
2. Wait for each to reach Running state before moving on
|
||||||
|
|
||||||
|
** Order Matters
|
||||||
|
The database schema must be deployed *before* starting the new application code, because the new application version expects the new schema. Starting services before the dacpac is deployed would likely cause errors.
|
||||||
|
|
||||||
|
** Risk
|
||||||
|
This is the most *destructive* stage. If something goes wrong mid-deploy, the system may be in a partially upgraded state. This is why rollback planning (currently TBC) is critical. See [[id:82c3d447-d6d3-498e-9f66-aee60c752462][ESP — Open Questions & TBC Items]].
|
||||||
|
|
||||||
|
* Stage 5 — POSTDEPLOY
|
||||||
|
|
||||||
|
** Purpose
|
||||||
|
Verify the deployment succeeded and the system is healthy.
|
||||||
|
|
||||||
|
** What It Does
|
||||||
|
|
||||||
|
*** Basic Service Checks
|
||||||
|
- Verify all enabled Windows Services are in ~Running~ state
|
||||||
|
- Verify no services crashed immediately after start
|
||||||
|
|
||||||
|
*** Cycle Checks
|
||||||
|
- Extensive checks that exercise the application's functionality
|
||||||
|
- Currently heavily reliant on *Citrix UI navigation* — very difficult to automate
|
||||||
|
- May initially be a manual prompt ("Please run the cycle checks and confirm pass/fail")
|
||||||
|
- Long term: UI automation or API-based checks
|
||||||
|
|
||||||
|
** What It Does NOT Do
|
||||||
|
- Makes no changes to the system
|
||||||
|
- Should be safe to re-run at any time
|
||||||
|
|
||||||
|
* Running Subsets of Stages
|
||||||
|
|
||||||
|
| Goal | Stages to Run |
|
||||||
|
|-----------------------------------+------------------------------------|
|
||||||
|
| Check config before deploying | ~VALIDATE~ |
|
||||||
|
| Full pre-flight check | ~VALIDATE,PREREQUISITES~ |
|
||||||
|
| Stage files only (no deploy yet) | ~VALIDATE,PREREQUISITES,PREDEPLOY~ |
|
||||||
|
| Full deployment | All stages |
|
||||||
|
| Re-run health checks after deploy | ~POSTDEPLOY~ |
|
||||||
|
| Everything except DB | Custom flags TBC |
|
||||||
178
Career Concepts/20260410122754-esp_known_issues.org
Normal file
178
Career Concepts/20260410122754-esp_known_issues.org
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: 53d803aa-7e6f-44ed-8d99-a243a5ed5aab
|
||||||
|
:END:
|
||||||
|
#+DATE: 2026-04-10
|
||||||
|
#+filetags: :ess:esp:microlise:risks:
|
||||||
|
#+STARTUP: showall
|
||||||
|
#+title: ESP — Known Issues & Risks
|
||||||
|
|
||||||
|
* Overview
|
||||||
|
:PROPERTIES:
|
||||||
|
:RELATED: [[id:a6c345df-8db9-4538-b87e-0e72e2414905][ESP Deployment Pipeline — Index]]
|
||||||
|
:END:
|
||||||
|
|
||||||
|
This file documents all known issues, risks, and blockers identified in the handover material. Understanding these early will help you avoid surprises.
|
||||||
|
|
||||||
|
* Issue 1 — Database Schema Inconsistency
|
||||||
|
:PROPERTIES:
|
||||||
|
:SEVERITY: High — Blocks automated DB deployment
|
||||||
|
:STATUS: Unresolved — requires manual effort per customer
|
||||||
|
:END:
|
||||||
|
|
||||||
|
** What the Problem Is
|
||||||
|
Existing customer databases have drifted from the official ESP schema. The dacpac built by Team Ludo reflects what the schema *should* be, but what's actually in customer databases doesn't match.
|
||||||
|
|
||||||
|
** Impact
|
||||||
|
- The dacpac *cannot be used* against any customer database until that database is manually aligned
|
||||||
|
- Deploying a dacpac against a mismatched DB risks data corruption or failures
|
||||||
|
|
||||||
|
** What Needs to Happen
|
||||||
|
For each customer database:
|
||||||
|
1. A DBA or developer inspects the actual DB schema
|
||||||
|
2. Identifies differences from the dacpac's expected schema
|
||||||
|
3. Writes and applies manual scripts to bring the DB into line
|
||||||
|
4. Verifies a trial dacpac deployment succeeds against a copy
|
||||||
|
5. Marks the manifest ~dacpacReady: true~
|
||||||
|
|
||||||
|
** Mitigations in the Pipeline
|
||||||
|
- The pipeline *must* check the ~dacpacReady~ flag before touching the database
|
||||||
|
- If ~false~, fail immediately with a clear error message
|
||||||
|
- See [[id:46add22d-e562-4e3a-a301-d4aea2552952][ESP — Database & Dacpac]] for implementation detail
|
||||||
|
|
||||||
|
* Issue 2 — Build Artifact Is a Flat DLL Dump
|
||||||
|
:PROPERTIES:
|
||||||
|
:SEVERITY: Medium — Complicates PREDEPLOY scripting
|
||||||
|
:STATUS: Unresolved — needs mapping/investigation
|
||||||
|
:END:
|
||||||
|
|
||||||
|
** What the Problem Is
|
||||||
|
The ESP Main Build pipeline produces a single large flat folder containing all DLLs for all applications mixed together. There is no clear separation like:
|
||||||
|
#+BEGIN_SRC
|
||||||
|
/artifacts/DLService/DLService.dll
|
||||||
|
/artifacts/EmailService/EmailService.dll
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
Instead it's more like:
|
||||||
|
#+BEGIN_SRC
|
||||||
|
/artifacts/DLService.dll
|
||||||
|
/artifacts/SomeSharedLibrary.dll
|
||||||
|
/artifacts/EmailService.dll
|
||||||
|
/artifacts/AnotherThing.dll
|
||||||
|
... (hundreds of files)
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** Impact
|
||||||
|
- The PREDEPLOY stage can't simply copy a folder to a service's install path
|
||||||
|
- Scripts will need to know *which DLLs belong to which application*
|
||||||
|
- This mapping does not yet exist
|
||||||
|
|
||||||
|
** What Needs to Happen
|
||||||
|
- Investigate the build artifact structure in detail
|
||||||
|
- Create a mapping: application → list of DLLs/files it needs
|
||||||
|
- This mapping may need to be stored in the scripts, the manifest, or a separate config file
|
||||||
|
- Ideally, feed back to the build team to separate the artifacts properly
|
||||||
|
|
||||||
|
* Issue 3 — No Test Environment
|
||||||
|
:PROPERTIES:
|
||||||
|
:SEVERITY: High — Significant operational risk
|
||||||
|
:STATUS: Unresolved — environment setup is TBC
|
||||||
|
:END:
|
||||||
|
|
||||||
|
** What the Problem Is
|
||||||
|
There is no dedicated sandbox environment to run test deployments against.
|
||||||
|
Any deployment the team runs is against a *real customer environment*.
|
||||||
|
|
||||||
|
** Impact
|
||||||
|
- Mistakes affect real customers
|
||||||
|
- You cannot safely iterate and test the pipeline without risk
|
||||||
|
- Developing and debugging deployment logic is much harder
|
||||||
|
|
||||||
|
** What Needs to Happen
|
||||||
|
- Set up a dedicated ESP test environment (raised as TBC in handover)
|
||||||
|
- This may require ESS to provision a server, or Microlise to build one
|
||||||
|
- Until then, exercise *extreme caution* with any deployment run
|
||||||
|
|
||||||
|
* Issue 4 — Licensing Prevents Local Execution
|
||||||
|
:PROPERTIES:
|
||||||
|
:SEVERITY: Medium — Developer experience impact
|
||||||
|
:STATUS: Inherent constraint — unlikely to change
|
||||||
|
:END:
|
||||||
|
|
||||||
|
** What the Problem Is
|
||||||
|
ESP cannot be run on developer machines due to licensing restrictions.
|
||||||
|
|
||||||
|
** Impact
|
||||||
|
- You cannot test your deployment scripts against a local ESP instance
|
||||||
|
- Debugging requires deploying to a real (or test) server
|
||||||
|
- Makes the development feedback loop longer
|
||||||
|
|
||||||
|
** Mitigation
|
||||||
|
- The three-tier architecture helps here: Tier 3 functions can be unit tested in isolation without a real ESP environment
|
||||||
|
- Use Pester (PowerShell testing framework) for unit tests
|
||||||
|
- End-to-end testing requires access to a real environment
|
||||||
|
|
||||||
|
* Issue 5 — Cycle Checks Require Citrix UI Navigation
|
||||||
|
:PROPERTIES:
|
||||||
|
:SEVERITY: Medium — Blocks full POSTDEPLOY automation
|
||||||
|
:STATUS: Partially mitigated (manual prompt initially)
|
||||||
|
:END:
|
||||||
|
|
||||||
|
** What the Problem Is
|
||||||
|
Post-deployment validation ("cycle checks") involves navigating through the Citrix application UI to verify functionality. This is:
|
||||||
|
- Extensive and time-consuming
|
||||||
|
- Very hard to automate (requires UI automation tooling like Selenium or Tosca)
|
||||||
|
- Dependent on Citrix being accessible from the test runner
|
||||||
|
|
||||||
|
** Short-Term Mitigation
|
||||||
|
Implement cycle checks as a manual prompt in the POSTDEPLOY stage — the pipeline pauses and waits for a human to confirm the checks passed.
|
||||||
|
|
||||||
|
** Long-Term Options
|
||||||
|
- Investigate API-level checks if ESP exposes any (bypasses UI entirely)
|
||||||
|
- UI automation tools (e.g. Ranorex, Tosca, Selenium with Citrix plugin)
|
||||||
|
- Simplified smoke tests that don't require full UI navigation
|
||||||
|
|
||||||
|
* Issue 6 — Citrix Upgrade Mechanism Unknown
|
||||||
|
:PROPERTIES:
|
||||||
|
:SEVERITY: Medium — Blocks Citrix deployment automation
|
||||||
|
:STATUS: TBC — believed to be file copy
|
||||||
|
:END:
|
||||||
|
|
||||||
|
** What the Problem Is
|
||||||
|
The exact technical mechanism for upgrading a Citrix-delivered application is not yet confirmed. The working assumption is that it involves:
|
||||||
|
- Copying files to the Citrix server
|
||||||
|
- Handling any locked executable (the running app may lock its own ~.exe~)
|
||||||
|
|
||||||
|
** What Needs to Happen
|
||||||
|
- Confirm with ESS or Citrix documentation how Citrix app upgrades work
|
||||||
|
- Determine if there's a Citrix-native method (e.g. App Layering, PVS updates) vs. a simple file swap
|
||||||
|
- Understand how to handle sessions that lock the executable
|
||||||
|
|
||||||
|
* Issue 7 — Test/Prod on Same Server
|
||||||
|
:PROPERTIES:
|
||||||
|
:SEVERITY: Medium — Risk of deploying to wrong environment
|
||||||
|
:STATUS: Design mitigation needed in manifest
|
||||||
|
:END:
|
||||||
|
|
||||||
|
** What the Problem Is
|
||||||
|
Some customers may have their TEST and PROD instances on the same physical server, differentiated only by install path or port.
|
||||||
|
|
||||||
|
** Impact
|
||||||
|
A misconfigured manifest or script bug could cause a PROD deployment when a TEST deployment was intended.
|
||||||
|
|
||||||
|
** Mitigations
|
||||||
|
- The manifest must clearly separate TEST and PROD config even if they share a server
|
||||||
|
- Consider an explicit confirmation prompt when deploying to PROD
|
||||||
|
- AzDO approval gates for PROD stages (not yet designed)
|
||||||
|
- The VALIDATE stage should catch obvious misconfigurations
|
||||||
|
|
||||||
|
* Risk Register Summary
|
||||||
|
|
||||||
|
| # | Issue | Severity | Status | Mitigation |
|
||||||
|
|---+----------------------------------+----------+-------------------+---------------------------------------|
|
||||||
|
| 1 | DB schema inconsistency | High | Unresolved | dacpacReady flag, manual DB fix first |
|
||||||
|
| 2 | Flat DLL artifact | Medium | Unresolved | Needs DLL-to-app mapping |
|
||||||
|
| 3 | No test environment | High | TBC | Treat all runs as live |
|
||||||
|
| 4 | No local execution | Medium | Inherent | Unit test Tier 3 with Pester |
|
||||||
|
| 5 | Cycle checks need UI | Medium | Manual short-term | Automate later; manual prompt now |
|
||||||
|
| 6 | Citrix upgrade mechanism unknown | Medium | TBC | Investigate with ESS |
|
||||||
|
| 7 | Test/Prod on same server | Medium | Design needed | Manifest separation, approval gates |
|
||||||
188
Career Concepts/20260410122935-esp_open_questions.org
Normal file
188
Career Concepts/20260410122935-esp_open_questions.org
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: 82c3d447-d6d3-498e-9f66-aee60c752462
|
||||||
|
:END:
|
||||||
|
#+DATE: 2026-04-10
|
||||||
|
#+filetags: :esp:ess:microlise:question:
|
||||||
|
#+STARTUP: showall
|
||||||
|
#+title: ESP — Open Questions & TBC Items
|
||||||
|
|
||||||
|
* Overview
|
||||||
|
:PROPERTIES:
|
||||||
|
:RELATED: [[id:a6c345df-8db9-4538-b87e-0e72e2414905][ESP Deployment Pipeline — Index]]
|
||||||
|
:END:
|
||||||
|
|
||||||
|
These are items explicitly marked as TBC or not yet designed in the handover material. They represent real blockers or gaps that need to be resolved before the pipeline is complete. Use this file to track answers as they are determined.
|
||||||
|
|
||||||
|
* Q1 — What Is the Rollback Plan?
|
||||||
|
:PROPERTIES:
|
||||||
|
:STATUS: TBC
|
||||||
|
:PRIORITY: High
|
||||||
|
:END:
|
||||||
|
|
||||||
|
** The Question
|
||||||
|
If a deployment fails partway through (e.g. the dacpac succeeds but a service won't start), how do we restore the system to its pre-deployment state?
|
||||||
|
|
||||||
|
** Why It's Hard
|
||||||
|
- The database cannot be easily rolled back without a restore from backup
|
||||||
|
- Files may have been partially swapped
|
||||||
|
- Citrix sessions may have been killed already
|
||||||
|
|
||||||
|
** Things to Consider
|
||||||
|
- Mandatory pre-deployment backup of database AND application files
|
||||||
|
- Snapshot-based restore if the server supports it (e.g. VM snapshots)
|
||||||
|
- A dedicated "rollback" stage that the pipeline can call
|
||||||
|
- Whether rollback is always manual or can be automated
|
||||||
|
|
||||||
|
** Answer (Fill In When Known)
|
||||||
|
_Not yet determined._
|
||||||
|
|
||||||
|
* Q2 — What Is the Test Plan?
|
||||||
|
:PROPERTIES:
|
||||||
|
:STATUS: TBC
|
||||||
|
:PRIORITY: High
|
||||||
|
:END:
|
||||||
|
|
||||||
|
** The Question
|
||||||
|
How will the pipeline and scripts themselves be tested before being used against customer environments?
|
||||||
|
|
||||||
|
** Things to Consider
|
||||||
|
- Unit tests for Tier 3 functions using Pester
|
||||||
|
- Integration tests against a test environment (once available — see Issue 3)
|
||||||
|
- Dry-run mode where the pipeline goes through all steps but prompts instead of acting
|
||||||
|
- Staged rollout: run full pipeline against ROMAC DEV first before any other environment
|
||||||
|
|
||||||
|
** Answer (Fill In When Known)
|
||||||
|
_Not yet determined._
|
||||||
|
|
||||||
|
* Q3 — What Is the Final Scope?
|
||||||
|
:PROPERTIES:
|
||||||
|
:STATUS: TBC
|
||||||
|
:PRIORITY: Medium
|
||||||
|
:END:
|
||||||
|
|
||||||
|
** The Question
|
||||||
|
Will the pipeline eventually cover:
|
||||||
|
- All customer environments (not just ROMAC DEV)?
|
||||||
|
- Production environments?
|
||||||
|
- Environments hosted in ESS's own data centre (not Microlise's)?
|
||||||
|
|
||||||
|
** Current Scope
|
||||||
|
ROMAC DEV only, as an initial target.
|
||||||
|
|
||||||
|
** Answer (Fill In When Known)
|
||||||
|
_Not yet determined — pending business decision._
|
||||||
|
|
||||||
|
* Q4 — How Exactly Are Citrix Apps Deployed/Upgraded?
|
||||||
|
:PROPERTIES:
|
||||||
|
:STATUS: TBC
|
||||||
|
:PRIORITY: High
|
||||||
|
:END:
|
||||||
|
|
||||||
|
** The Question
|
||||||
|
What is the technical mechanism for upgrading a Citrix-delivered application?
|
||||||
|
|
||||||
|
** Working Assumption
|
||||||
|
A file copy to the Citrix server, with handling for the running executable being locked by active sessions.
|
||||||
|
|
||||||
|
** Things to Investigate
|
||||||
|
- Does Citrix use App Layering or Provisioning Services (PVS)? If so, the upgrade process is very different from a file copy
|
||||||
|
- Are there Citrix-native PowerShell cmdlets for managing published apps?
|
||||||
|
- How are locked executables handled — do sessions need to be fully terminated first, or is there a staging mechanism?
|
||||||
|
- Who at ESS has this knowledge?
|
||||||
|
|
||||||
|
** Answer (Fill In When Known)
|
||||||
|
_Not yet determined._
|
||||||
|
|
||||||
|
* Q5 — What Is the Manifest Structure?
|
||||||
|
:PROPERTIES:
|
||||||
|
:STATUS: TBC — needs design
|
||||||
|
:PRIORITY: High
|
||||||
|
:END:
|
||||||
|
|
||||||
|
** The Question
|
||||||
|
What does the manifest config file look like? What format, what fields, where is it stored?
|
||||||
|
|
||||||
|
** See Also
|
||||||
|
[[id:9bf19a8b-5581-4be8-9892-913c51df0128][ESP — The Manifest]] contains a proposed structure. This needs to be validated against actual deployment requirements and agreed by the team.
|
||||||
|
|
||||||
|
** Answer (Fill In When Known)
|
||||||
|
_Proposed in [[id:9bf19a8b-5581-4be8-9892-913c51df0128][ESP — The Manifest]] - not yet confirmed._
|
||||||
|
|
||||||
|
* Q6 — How Are Build Artifacts Mapped to Applications?
|
||||||
|
:PROPERTIES:
|
||||||
|
:STATUS: TBC
|
||||||
|
:PRIORITY: High
|
||||||
|
:END:
|
||||||
|
|
||||||
|
** The Question
|
||||||
|
Given that the ESP build produces a flat folder of DLLs, how do we determine which DLLs belong to which application?
|
||||||
|
|
||||||
|
** Things to Investigate
|
||||||
|
- Does the build process have any metadata or manifest about what it produced?
|
||||||
|
- Can the build pipeline be modified to output per-application folders?
|
||||||
|
- Is there existing documentation from ESS about which files belong where?
|
||||||
|
- Can we infer the mapping from the existing install directories on ROMAC DEV?
|
||||||
|
|
||||||
|
** Answer (Fill In When Known)
|
||||||
|
_Not yet determined._
|
||||||
|
|
||||||
|
* Q7 — Full Detail of Tier 2 & Tier 3 Functions Needed
|
||||||
|
:PROPERTIES:
|
||||||
|
:STATUS: TBC
|
||||||
|
:PRIORITY: Medium
|
||||||
|
:END:
|
||||||
|
|
||||||
|
** The Question
|
||||||
|
The handover defines the architecture but not the complete list of all Tier 2 logic and Tier 3 functions needed for a full deployment. What is the complete list?
|
||||||
|
|
||||||
|
** Approach to Resolve
|
||||||
|
- Work through each deployment stage manually with a human operator
|
||||||
|
- Document every step they perform
|
||||||
|
- Each manual step maps to at least one Tier 3 function
|
||||||
|
- Aggregate these into a complete function inventory
|
||||||
|
|
||||||
|
** Answer (Fill In When Known)
|
||||||
|
_Ongoing — to be determined through walkthroughs with ESS/ops._
|
||||||
|
|
||||||
|
* Q8 — What Are All the Prerequisites?
|
||||||
|
:PROPERTIES:
|
||||||
|
:STATUS: TBC — described as "extensive"
|
||||||
|
:PRIORITY: Medium
|
||||||
|
:END:
|
||||||
|
|
||||||
|
** The Question
|
||||||
|
The PREREQUISITES stage is described as checking "an extensive list" of prerequisites, but the full list has not been documented.
|
||||||
|
|
||||||
|
** Things to Investigate
|
||||||
|
- What software must be installed on each server type (app server, DB server, Citrix server)?
|
||||||
|
- What Windows configuration must be in place?
|
||||||
|
- What network connectivity is required?
|
||||||
|
- What service accounts / permissions must exist?
|
||||||
|
- What environment labels/flags are needed?
|
||||||
|
|
||||||
|
** Answer (Fill In When Known)
|
||||||
|
_Not yet documented._
|
||||||
|
|
||||||
|
* Q9 — How Should Secrets Be Managed?
|
||||||
|
:PROPERTIES:
|
||||||
|
:STATUS: Not addressed in handover
|
||||||
|
:PRIORITY: High
|
||||||
|
:END:
|
||||||
|
|
||||||
|
** The Question
|
||||||
|
The manifest and scripts will need credentials (DB passwords, server credentials, service account passwords). Where do these live and how are they accessed securely?
|
||||||
|
|
||||||
|
** Options
|
||||||
|
- AzDO secret pipeline variables
|
||||||
|
- Azure Key Vault (referenced by name in manifest, retrieved at runtime)
|
||||||
|
- Windows Credential Manager on a self-hosted agent
|
||||||
|
- Encrypted secrets in the repo (not recommended)
|
||||||
|
|
||||||
|
** Answer (Fill In When Known)
|
||||||
|
_Not yet determined._
|
||||||
|
|
||||||
|
* Resolved Questions
|
||||||
|
|
||||||
|
| # | Question | Resolved Date | Answer |
|
||||||
|
|---+-----------------------+---------------+--------|
|
||||||
|
| | _(none resolved yet)_ | | |
|
||||||
169
Career Concepts/20260410123131-esp_glossary.org
Normal file
169
Career Concepts/20260410123131-esp_glossary.org
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: 2c950d25-6f86-4f83-a7b4-69e2ca2f7023
|
||||||
|
:END:
|
||||||
|
#+DATE: 2026-04-10
|
||||||
|
#+filetags: :terms:ess:esp:notes:microlise:
|
||||||
|
#+STARTUP: showall
|
||||||
|
#+title: ESP — Glossary
|
||||||
|
|
||||||
|
* Overview
|
||||||
|
:PROPERTIES:
|
||||||
|
:RELATED: [[id:a6c345df-8db9-4538-b87e-0e72e2414905][ESP Deployment Pipeline — Index]]
|
||||||
|
:END:
|
||||||
|
|
||||||
|
Reference glossary for all technical and project-specific terms used across the ESP deployment pipeline project. Alphabetically ordered.
|
||||||
|
|
||||||
|
* A
|
||||||
|
|
||||||
|
** Agent (AzDO)
|
||||||
|
The machine that executes an AzDO pipeline. Can be *Microsoft-hosted* (a fresh Azure VM for each run) or *self-hosted* (a persistent machine you manage).
|
||||||
|
For deploying to customer servers, a self-hosted agent is required to have network access to those servers.
|
||||||
|
|
||||||
|
** Artifact (Build)
|
||||||
|
The output of a build pipeline — typically compiled binaries, DLLs, config files, etc. packaged and stored so a deployment pipeline can consume them.
|
||||||
|
The ESP build artifact is currently a flat folder of DLLs. See [[id:53d803aa-7e6f-44ed-8d99-a243a5ed5aab][ESP — Known Issues & Risks]]
|
||||||
|
|
||||||
|
** AzDO / Azure DevOps
|
||||||
|
Microsoft's DevOps platform. Provides Repos (Git), Pipelines (CI/CD), Boards (work tracking), and Artifacts (package storage). The ESP pipeline lives here.
|
||||||
|
|
||||||
|
* B
|
||||||
|
|
||||||
|
** BACPAC
|
||||||
|
A SQL Server package format that includes both schema *and* data. Useful for backup/restore. Contrast with Dacpac (schema only).
|
||||||
|
|
||||||
|
** Build Pipeline
|
||||||
|
An AzDO pipeline that compiles source code and produces a build artifact. The ESP build pipeline is ~ESS.esp Main Build~.
|
||||||
|
|
||||||
|
* C
|
||||||
|
|
||||||
|
** CI/CD
|
||||||
|
*Continuous Integration / Continuous Delivery (or Deployment)*. The practice of automatically building, testing, and deploying software whenever changes are made. AzDO pipelines implement this.
|
||||||
|
|
||||||
|
** Citrix
|
||||||
|
A technology platform that delivers desktop applications to users remotely. The application runs on a Citrix server; users see and interact with it via the Citrix Workspace client. Three ESP applications (VPlanner, VPlannerAdmin, ImportApp) are delivered this way.
|
||||||
|
|
||||||
|
** Cycle Checks
|
||||||
|
Post-deployment validation checks for ESP that involve navigating through the Citrix application UI to verify the system is functioning correctly. These are extensive and difficult to automate. See [[id:cd3cd02f-c9b3-4455-8ce5-b2a5aa458fed][ESP — Deployment Stages]].
|
||||||
|
|
||||||
|
* D
|
||||||
|
|
||||||
|
** Dacpac
|
||||||
|
*Data-tier Application Package*. A ~.dacpac~ file that represents the desired schema of a SQL Server database. Deployed using ~sqlpackage.exe~, which calculates the difference between desired and actual schema and applies it. See [[id:46add22d-e562-4e3a-a301-d4aea2552952][ESP — Database & Dacpac]].
|
||||||
|
|
||||||
|
** ~dacpacReady~
|
||||||
|
A flag in the manifest (see [[id:9bf19a8b-5581-4be8-9892-913c51df0128][ESP — The Manifest]]) that indicates whether a customer's database has been manually aligned to be compatible with the dacpac. Must be ~true~ before the pipeline will attempt database deployment.
|
||||||
|
|
||||||
|
** Deploy Pipeline
|
||||||
|
The AzDO pipeline responsible for deploying ESP to customer environments. Currently: ~ESS.esp Deploy~. This is the primary pipeline your team owns.
|
||||||
|
|
||||||
|
** DLL
|
||||||
|
*Dynamic Link Library*. A compiled Windows binary file (~.dll~) containing reusable code. Windows Services and other Windows applications are composed of DLLs. Deploying a new version means replacing old DLLs with new ones.
|
||||||
|
|
||||||
|
* E
|
||||||
|
|
||||||
|
** Environment
|
||||||
|
In the context of ESP, an environment is a specific deployment target for a customer (e.g. DEV, TEST, PROD). A customer may have multiple environments. Each environment has its own manifest.
|
||||||
|
|
||||||
|
** ESP
|
||||||
|
The application suite built by ESS. Delivered to customers on a per-customer basis. Contains databases, Windows Services, and Citrix applications. See [[id:091e9bbc-0c9f-43da-81f9-464882c2a15b][ESP Applications]].
|
||||||
|
|
||||||
|
** ESS
|
||||||
|
The company that built ESP. Formerly had a larger engineering team; now reduced. Has a data centre of their own where some customer instances are hosted.
|
||||||
|
|
||||||
|
** EspBroker
|
||||||
|
The SQL Server database used by ESP. The only database in the suite currently. Deployed via dacpac.
|
||||||
|
|
||||||
|
* G
|
||||||
|
|
||||||
|
** Grace Period
|
||||||
|
In the context of Citrix deployment: the time given to active Citrix users to save their work and quit before their session is forcibly terminated to allow the upgrade to proceed.
|
||||||
|
|
||||||
|
* J
|
||||||
|
|
||||||
|
** Job (AzDO)
|
||||||
|
A unit of work within an AzDO pipeline stage. Each job runs on a single agent. A stage can have multiple parallel jobs.
|
||||||
|
|
||||||
|
* L
|
||||||
|
|
||||||
|
** Layer / Tier
|
||||||
|
The architectural layers in the PowerShell script design. Tier 1 = entry point; Tier 2 = orchestration; Tier 3 = isolated worker functions. See [[id:bf63b6c5-f32f-462e-82ad-8d4a15f7ba48][ESP — PowerShell Script Architecture]].
|
||||||
|
|
||||||
|
* M
|
||||||
|
|
||||||
|
** Manifest
|
||||||
|
A configuration file defining a specific customer environment. Used by the deployment scripts to know what to deploy, where, and how.
|
||||||
|
See [[id:9bf19a8b-5581-4be8-9892-913c51df0128][ESP — The Manifest]].
|
||||||
|
|
||||||
|
** Microlise
|
||||||
|
The company the team works for. The ESP pipeline project is being done by Microlise engineers to assist ESS.
|
||||||
|
|
||||||
|
** Module (PowerShell)
|
||||||
|
A packaged collection of PowerShell functions, stored in a ~.psm1~ file. Modules are loaded with ~Import-Module~. The Tier 2 and Tier 3 scripts are structured as modules.
|
||||||
|
|
||||||
|
* P
|
||||||
|
|
||||||
|
** Pester
|
||||||
|
The standard PowerShell testing framework. Used for writing unit tests for PowerShell functions. Particularly useful for testing Tier 3 functions in isolation.
|
||||||
|
|
||||||
|
** Pipeline (AzDO)
|
||||||
|
An automated workflow defined in YAML that can build, test, and deploy software. Triggered by events (code pushes, schedules, manual runs).
|
||||||
|
|
||||||
|
** PowerShell
|
||||||
|
Microsoft's scripting language and shell, built on .NET. Used for all deployment scripting in this project.
|
||||||
|
|
||||||
|
** Prerequisites
|
||||||
|
The PREREQUISITES deployment stage — checks that the target environment has all required software, configuration, and connectivity before deployment begins.
|
||||||
|
|
||||||
|
** ~.psm1~
|
||||||
|
The file extension for a PowerShell module file.
|
||||||
|
|
||||||
|
* R
|
||||||
|
|
||||||
|
** Remote Session (PowerShell)
|
||||||
|
A PowerShell remoting session to another machine, created with ~New-PSSession~. Allows you to run PowerShell commands on a remote server. Required for managing Windows Services and files on customer servers.
|
||||||
|
|
||||||
|
#+BEGIN_SRC powershell
|
||||||
|
$session = New-PSSession -ComputerName "ROMAC-DEV-APP01"
|
||||||
|
Invoke-Command -Session $session -ScriptBlock { Get-Service }
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** ROMAC DEV
|
||||||
|
The initial target customer environment for the pipeline. ROMAC is the customer name; DEV is the environment tier.
|
||||||
|
|
||||||
|
* S
|
||||||
|
|
||||||
|
** Schema (Database)
|
||||||
|
The structure of a SQL Server database — its tables, columns, indexes, constraints, stored procedures, etc. The dacpac encodes the desired schema.
|
||||||
|
|
||||||
|
** Self-Hosted Agent
|
||||||
|
An AzDO agent running on a machine you manage (rather than a Microsoft-managed Azure VM). Required for this project to have network access to customer servers.
|
||||||
|
|
||||||
|
** ~sqlpackage.exe~
|
||||||
|
Microsoft's command-line tool for deploying dacpac files to SQL Server.
|
||||||
|
|
||||||
|
** Stage (Deployment)
|
||||||
|
One of the five phases of the ESP deployment: VALIDATE, PREREQUISITES, PREDEPLOY, DEPLOY, POSTDEPLOY. Each can be run independently. See [[id:cd3cd02f-c9b3-4455-8ce5-b2a5aa458fed][ESP — Deployment Stages]].
|
||||||
|
|
||||||
|
** Stage (AzDO Pipeline)
|
||||||
|
A high-level grouping within an AzDO YAML pipeline, containing jobs. Not the same as a deployment stage — naming coincidence.
|
||||||
|
|
||||||
|
* T
|
||||||
|
|
||||||
|
** Team Ludo
|
||||||
|
The Microlise team that preceded your team on this project. They built the ESP suite in AzDO, started deployment work, and built the dacpac. Now reassigned to paid customer work.
|
||||||
|
|
||||||
|
** Tier 1 / 2 / 3
|
||||||
|
See *Layer / Tier* above and [[id:bf63b6c5-f32f-462e-82ad-8d4a15f7ba48][ESP — PowerShell Script Architecture]].
|
||||||
|
|
||||||
|
** TMC
|
||||||
|
Another Microlise product, referenced in the handover as a comparison point for how ESP works (per-customer deployment, multiple environments, etc.).
|
||||||
|
|
||||||
|
* W
|
||||||
|
|
||||||
|
** Windows Service
|
||||||
|
A background process that runs on a Windows server, managed by the Windows Service Control Manager. Can be started, stopped, and queried via PowerShell. Six ESP services exist: DLService, EmailService, ExPlService, MISService, OutboundService, ULService.
|
||||||
|
|
||||||
|
* Y
|
||||||
|
|
||||||
|
** YAML
|
||||||
|
*YAML Ain't Markup Language*. A human-readable data format used for AzDO pipeline definitions. Stored in the repo as a ~.yml~ file.
|
||||||
77
Career Concepts/20260413120825-windows_services.org
Normal file
77
Career Concepts/20260413120825-windows_services.org
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: faa7f193-5af6-4a2f-a73e-540f833a7fd0
|
||||||
|
:END:
|
||||||
|
#+title: Windows Services
|
||||||
|
#+filetags: :windows:notes:
|
||||||
|
|
||||||
|
* Summary
|
||||||
|
Windows Services are essential components of the Windows operating system that run in the background to perform critical system functions. They operate without user interaction, starting automatically during system boot and continuing until shutdown. Managed by the Service Control Manager, they handle tasks such as network connectivity, hardware management, and system security. Administrators can manage services using tools like Services.msc, command-line utilities, and PowerShell for automation.
|
||||||
|
|
||||||
|
|
||||||
|
* Definition and Purpose
|
||||||
|
|
||||||
|
**Windows Services** are long-running executable applications that operate in the background of the Windows operating system. They are designed to perform specific system-level functions without requiring user interaction, making them essential for the stable and continuous operation of Windows.
|
||||||
|
|
||||||
|
These services typically start during system boot and continue running until the system shuts down. They handle core tasks such as **network connectivity**, **hardware management**, **system security**, and **scheduled operations**.
|
||||||
|
|
||||||
|
** Key Characteristics
|
||||||
|
|
||||||
|
Windows Services differ from regular desktop applications in several important ways:
|
||||||
|
|
||||||
|
- **No User Interface (UI)**: They run without a graphical interface, operating silently in the background.
|
||||||
|
- **Automatic Startup**: Can be configured to start automatically when the system boots.
|
||||||
|
- **Session Independence**: Run in their own Windows sessions (often Session 0), independent of logged-in users.
|
||||||
|
- **Service Control Manager (SCM)**: Managed by the SCM (~services.exe~), which handles starting, stopping, and monitoring services.
|
||||||
|
- **Security Context**: Operate under specific user accounts such as **SYSTEM**, **Local Service**, or **Network Service**, allowing them to function even when no user is logged in.
|
||||||
|
|
||||||
|
Prior to Windows Vista, some services could interact with the desktop, but this capability has been largely disabled due to **Windows Service Hardening** and **Session 0 Isolation** for security reasons.
|
||||||
|
|
||||||
|
** Common Examples
|
||||||
|
|
||||||
|
Many critical Windows functions are implemented as services. Some well-known examples include:
|
||||||
|
|
||||||
|
- **Print Spooler**: Manages print jobs and printer communication.
|
||||||
|
- **DHCP Client**: Obtains IP addresses dynamically for network connectivity.
|
||||||
|
- **Windows Update**: Downloads and installs system updates.
|
||||||
|
- **Task Scheduler**: Executes tasks at predefined times or events.
|
||||||
|
- **DNS Client**: Resolves domain names to IP addresses.
|
||||||
|
- **Windows Time**: Synchronizes the system clock with internet time servers.
|
||||||
|
|
||||||
|
Third-party applications like antivirus software, database servers, and cloud sync tools also often install their own services to ensure continuous background operation.
|
||||||
|
|
||||||
|
** Management Tools
|
||||||
|
|
||||||
|
Windows provides several built-in tools to manage services:
|
||||||
|
|
||||||
|
- **Services.msc**: The graphical **Services Manager** accessible via Run command or Control Panel. It allows viewing, starting, stopping, and configuring services.
|
||||||
|
- **Command Line (sc.exe)**: A powerful tool for querying and controlling services. For example:
|
||||||
|
#+begin_src cmd
|
||||||
|
sc query eventlog
|
||||||
|
sc start "Print Spooler"
|
||||||
|
#+end_src
|
||||||
|
- **PowerShell**: Offers cmdlets like ~Get-Service~, ~Start-Service~, ~Stop-Service~, and ~Set-Service~ for automation and scripting.
|
||||||
|
- **Task Manager**: In Windows Vista and later, it can display and control services under the "Services" tab.
|
||||||
|
- **MSConfig**: Allows enabling or disabling services at startup for troubleshooting.
|
||||||
|
|
||||||
|
** Startup Types
|
||||||
|
|
||||||
|
Each service has a **startup type** that determines when and how it starts:
|
||||||
|
|
||||||
|
- **Automatic**: Starts immediately during system boot.
|
||||||
|
- **Automatic (Delayed Start)**: Starts shortly after boot to improve startup performance.
|
||||||
|
- **Manual**: Starts only when triggered by a user, application, or system event.
|
||||||
|
- **Disabled**: Cannot be started under any circumstances until re-enabled.
|
||||||
|
|
||||||
|
These settings help balance system performance and functionality, especially during boot.
|
||||||
|
|
||||||
|
** Administration Methods
|
||||||
|
|
||||||
|
Administrators can manage services using various interfaces:
|
||||||
|
|
||||||
|
- **Graphical**: Services snap-in (~services.msc~) provides full configuration including recovery actions, logon accounts, and dependencies.
|
||||||
|
- **Command-Line**: ~sc.exe~ allows scriptable service management and remote administration.
|
||||||
|
- **PowerShell**: Ideal for automation and bulk operations across multiple systems.
|
||||||
|
- **Remote Management**: The Services MMC snap-in can connect to remote computers on the network.
|
||||||
|
|
||||||
|
Services can also be created programmatically using the **System.ServiceProcess** namespace in .NET, or wrapped using tools like **SrvAny.exe** from the Windows Resource Kit.
|
||||||
|
|
||||||
7
Career Concepts/20260413154901-dll.org
Normal file
7
Career Concepts/20260413154901-dll.org
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: e717c252-0e15-4403-898f-93163dd1b147
|
||||||
|
:END:
|
||||||
|
#+title: Dynamic Link Library (DLL)
|
||||||
|
#+filetags: :windows:notes:
|
||||||
|
|
||||||
|
A Dynamic Link Library (DLL) is a type of file that contains code and data that can be used by multiple programs simultaneously. It allows developers to modularise their applications, enabling code reuse and efficient memory usage. DLLs are commonly used in Windows operating systems, but they can also be found in other platforms.
|
||||||
3
Emacs/20241210004247-emacs_moc.org
Executable file → Normal file
3
Emacs/20241210004247-emacs_moc.org
Executable file → Normal file
@@ -14,7 +14,8 @@ The purpose of this file is to store things related to emacs (that being package
|
|||||||
- [[id:45CC3AF5-5E20-4B03-A36C-8D4BDD5CBB13][Emacs Evil Mode]]
|
- [[id:45CC3AF5-5E20-4B03-A36C-8D4BDD5CBB13][Emacs Evil Mode]]
|
||||||
- [[id:7d2e867e-f091-4362-a583-453f732207fe][Emacs ORG Publish]]
|
- [[id:7d2e867e-f091-4362-a583-453f732207fe][Emacs ORG Publish]]
|
||||||
- [[id:168b6b10-d670-4f9d-89cf-aeb59aa644a1][Emacs Org Noter]]
|
- [[id:168b6b10-d670-4f9d-89cf-aeb59aa644a1][Emacs Org Noter]]
|
||||||
- [[id:10b1f18e-b221-4ab8-bce4-b6f20ad417db][emacs-calendar]]
|
- [[id:10b1f18e-b221-4ab8-bce4-b6f20ad417db][Emacs Calendar/Agenda]]
|
||||||
|
- [[id:1c87e4f1-fa7e-4200-9a29-a5a98d4c7ac9][Emacs Config]]
|
||||||
|
|
||||||
* Resources
|
* Resources
|
||||||
- A link that contains all the key bindings for emacs: [[http://xahlee.info/emacs/emacs/emacs_keybinding_list.html][Keybindings list]]
|
- A link that contains all the key bindings for emacs: [[http://xahlee.info/emacs/emacs/emacs_keybinding_list.html][Keybindings list]]
|
||||||
|
|||||||
0
Emacs/20241210004329-org_roam.org
Executable file → Normal file
0
Emacs/20241210004329-org_roam.org
Executable file → Normal file
0
Emacs/20241210004453-gtd.org
Executable file → Normal file
0
Emacs/20241210004453-gtd.org
Executable file → Normal file
3
Emacs/20250218174735-emacs_stuff_keybindings.org
Executable file → Normal file
3
Emacs/20250218174735-emacs_stuff_keybindings.org
Executable file → Normal file
@@ -16,3 +16,6 @@ Type `C-h m` to get information for a major mode.
|
|||||||
* Projectile:
|
* Projectile:
|
||||||
- `SPC-p p` - switch project
|
- `SPC-p p` - switch project
|
||||||
- `SPC-p f` - find project
|
- `SPC-p f` - find project
|
||||||
|
|
||||||
|
|
||||||
|
* Use C-u SPC X P to run powershell with args
|
||||||
|
|||||||
0
Emacs/20250326002128-emacs_stuff_elisp.org
Executable file → Normal file
0
Emacs/20250326002128-emacs_stuff_elisp.org
Executable file → Normal file
0
Emacs/20250329231658-emacs_stuff_magit.org
Executable file → Normal file
0
Emacs/20250329231658-emacs_stuff_magit.org
Executable file → Normal file
0
Emacs/20250420012258-emacs_stuff_evil.org
Executable file → Normal file
0
Emacs/20250420012258-emacs_stuff_evil.org
Executable file → Normal file
0
Emacs/20250806155335-emacs_stuff_org_publish.org
Executable file → Normal file
0
Emacs/20250806155335-emacs_stuff_org_publish.org
Executable file → Normal file
33
20260401100130-emacs_org_noter.org → Emacs/20260401100130-emacs_org_noter.org
Executable file → Normal file
33
20260401100130-emacs_org_noter.org → Emacs/20260401100130-emacs_org_noter.org
Executable file → Normal file
@@ -4,6 +4,8 @@
|
|||||||
#+title: Emacs Org Noter
|
#+title: Emacs Org Noter
|
||||||
#+filetags: :emacs:org:notes:
|
#+filetags: :emacs:org:notes:
|
||||||
|
|
||||||
|
**For the config, see [[id:1c87e4f1-fa7e-4200-9a29-a5a98d4c7ac9][Emacs Config]] for the Source of truth**
|
||||||
|
|
||||||
In order to create notes for a book:
|
In order to create notes for a book:
|
||||||
1. Create an empty org roam file
|
1. Create an empty org roam file
|
||||||
2. Add the relative file path in metadata for that node, with the title ~NOTER_DOCUMENT~
|
2. Add the relative file path in metadata for that node, with the title ~NOTER_DOCUMENT~
|
||||||
@@ -37,6 +39,37 @@ In order to create notes for a book:
|
|||||||
|
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
For non pdfs notes:
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
|
||||||
|
(setq org-capture-templates
|
||||||
|
'(("d" "Daily TODO" entry
|
||||||
|
(file+headline (lambda () (z/find-current-week-file)) "TODOs")
|
||||||
|
"* TODO %?\nSCHEDULED: %t\n"
|
||||||
|
:empty-lines 1)
|
||||||
|
|
||||||
|
("c" "Add to calendar.org" entry
|
||||||
|
(file+headline "~/master-folder/org_files/calendar.org" "Calendar")
|
||||||
|
"* TODO %?\nSCHEDULED: %^t\n"
|
||||||
|
:empty-lines 1)
|
||||||
|
|
||||||
|
("n" "Add notes" entry
|
||||||
|
(file+headline (lambda () (z/find-current-week-file)) "Notes")
|
||||||
|
"* Note: %?\n"
|
||||||
|
:empty-lines 1)
|
||||||
|
|
||||||
|
("w" "Weekly Review" entry
|
||||||
|
(file+function (lambda () (z/find-current-week-file)) z/goto-weekly-review)
|
||||||
|
"* Review: %?\nEntered on %U\n"
|
||||||
|
:empty-lines 1)
|
||||||
|
|
||||||
|
("b" "Book Note" entry
|
||||||
|
(file+headline (lambda () (buffer-file-name)) "Notes")
|
||||||
|
"** p. %^{Page}\n[%^{Type|Insight|Important|Quote|Confusing}] %?\n")
|
||||||
|
))
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
* Keybindings:
|
* Keybindings:
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(dt/leader-keys
|
(dt/leader-keys
|
||||||
2
20260401100839-emacs_calendar.org → Emacs/20260401100839-emacs_calendar.org
Executable file → Normal file
2
20260401100839-emacs_calendar.org → Emacs/20260401100839-emacs_calendar.org
Executable file → Normal file
@@ -4,6 +4,8 @@
|
|||||||
#+title: Emacs Calendar/Agenda
|
#+title: Emacs Calendar/Agenda
|
||||||
#+filetags: :emacs:workflow:work:
|
#+filetags: :emacs:workflow:work:
|
||||||
|
|
||||||
|
**For the config, see [[id:1c87e4f1-fa7e-4200-9a29-a5a98d4c7ac9][Emacs Config]] for the Source of truth**
|
||||||
|
|
||||||
* Config:
|
* Config:
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(require 'org-caldav)
|
(require 'org-caldav)
|
||||||
599
Emacs/20260407083539-emacs_config.org
Normal file
599
Emacs/20260407083539-emacs_config.org
Normal file
@@ -0,0 +1,599 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: 1c87e4f1-fa7e-4200-9a29-a5a98d4c7ac9
|
||||||
|
:END:
|
||||||
|
#+title: Emacs Config
|
||||||
|
#+filetags: :emacs:org:functions:
|
||||||
|
|
||||||
|
|
||||||
|
* Org Noter
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
|
||||||
|
(setq org-noter-notes-search-path
|
||||||
|
'("D:\\_nextcloud\\master-folder\\org_files\\org_roam\\"))
|
||||||
|
(setq org-noter-always-create-frame nil)
|
||||||
|
(setq org-noter-property-doc-file "NOTER_DOCUMENT")
|
||||||
|
|
||||||
|
(require 'pdf-tools)
|
||||||
|
(pdf-tools-install)
|
||||||
|
(use-package pdf-view-restore
|
||||||
|
:after pdf-tools
|
||||||
|
:config
|
||||||
|
(add-hook 'pdf-view-mode-hook 'pdf-view-restore-mode)
|
||||||
|
(setq pdf-view-restore-filename "~/.emacs.d/.pdf-view-restore"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* CALDAV and org agenda calendars:
|
||||||
|
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(require 'org-caldav)
|
||||||
|
(require 'url)
|
||||||
|
(require 'icalendar)
|
||||||
|
(modify-coding-system-alist 'file "caldav-work\\.org\\'" 'utf-8-unix)
|
||||||
|
(setq org-icalendar-timezone "Europe/London")
|
||||||
|
(setq calendar-time-zone 60) ;; minutes offset from UTC (BST = +60)
|
||||||
|
(setq calendar-standard-time-zone-name "GMT")
|
||||||
|
(setq calendar-daylight-time-zone-name "BST")
|
||||||
|
(setq org-caldav-timezone "Europe/London")
|
||||||
|
(defvar my/outlook-ics-url
|
||||||
|
"https://outlook.office365.com/owa/calendar/b910ea835e414663831e505f3d10baa2@microlise.com/d2568a0134fb49af92d39c1669c4729317662288011094411305/calendar.ics")
|
||||||
|
|
||||||
|
(defvar my/outlook-org-file
|
||||||
|
"D:\\_nextcloud\\master-folder\\org_files\\calendar\\caldav-work.org")
|
||||||
|
|
||||||
|
(defvar my/ics-python-script
|
||||||
|
"D:\\_nextcloud\\master-folder\\org_files\\calendar\\ics_to_org.py")
|
||||||
|
|
||||||
|
(defun my/sync-outlook-calendar ()
|
||||||
|
"Fetch and expand Outlook ICS (including recurrences) into org file."
|
||||||
|
(interactive)
|
||||||
|
(message "Syncing Outlook calendar...")
|
||||||
|
(let* ((cmd (format "python \"%s\" \"%s\" \"%s\""
|
||||||
|
my/ics-python-script
|
||||||
|
my/outlook-ics-url
|
||||||
|
my/outlook-org-file))
|
||||||
|
(result (shell-command-to-string cmd)))
|
||||||
|
(message "Outlook calendar sync: %s" (string-trim result))))
|
||||||
|
|
||||||
|
;; Sync on startup and every 30 minutes
|
||||||
|
(my/sync-outlook-calendar)
|
||||||
|
(run-with-timer (* 30 60) (* 30 60) #'my/sync-outlook-calendar)
|
||||||
|
;; --- CalDAV for native Nextcloud calendars ---
|
||||||
|
(setq org-caldav-url "https://nextcloud.zainezq.com/remote.php/dav/calendars/zaine/")
|
||||||
|
(setq org-caldav-calendars
|
||||||
|
'((:calendar-id "personal"
|
||||||
|
:inbox "D:\\_nextcloud\\master-folder\\org_files\\calendar\\caldav-personal.org"
|
||||||
|
:files nil)
|
||||||
|
(:calendar-id "zxh"
|
||||||
|
:inbox "D:\\_nextcloud\\master-folder\\org_files\\calendar\\caldav-family.org"
|
||||||
|
:files nil)))
|
||||||
|
|
||||||
|
;; --- Agenda files ---
|
||||||
|
(setq org-agenda-files
|
||||||
|
'("D:\\_nextcloud\\master-folder\\org_files\\calendar\\caldav-personal.org"
|
||||||
|
"D:\\_nextcloud\\master-folder\\org_files\\calendar\\caldav-work.org"
|
||||||
|
"D:\\_nextcloud\\master-folder\\org_files\\calendar\\caldav-family.org"
|
||||||
|
"D:\\_nextcloud\\master-folder\\org_files\\org_roam\\Books\\20250724230557-books_org_agenda.org"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Notes when reading physical book
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
("b" "Book Note" entry
|
||||||
|
(file+headline (lambda () (buffer-file-name)) "Notes")
|
||||||
|
"** p. %^{Page}\n[%^{Type|Insight|Important|Quote|Confusing}] %?\n")
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Org image inserter:
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
;;; --- Org image inserter (improved search UX) -----------------------------
|
||||||
|
(use-package vertico
|
||||||
|
:init (vertico-mode))
|
||||||
|
|
||||||
|
(use-package orderless
|
||||||
|
:custom
|
||||||
|
(completion-styles '(orderless basic))
|
||||||
|
(completion-category-defaults nil))
|
||||||
|
|
||||||
|
|
||||||
|
(defgroup zq/org-assets nil
|
||||||
|
"Insert image links from predefined asset profiles."
|
||||||
|
:group 'org)
|
||||||
|
|
||||||
|
(defcustom zq/org-asset-profiles
|
||||||
|
'(("org-roam" . "D:\\_nextcloud\\master-folder\\org_files\\org_roam\\assets")
|
||||||
|
("org-web" . "D:\\_nextcloud\\master-folder\\org_files\\org_web\\assets"))
|
||||||
|
"Alist of (PROFILE-NAME . ASSETS-DIR)."
|
||||||
|
:type '(alist :key-type string :value-type directory)
|
||||||
|
:group 'zq/org-assets)
|
||||||
|
|
||||||
|
(defcustom zq/org-image-extensions
|
||||||
|
'("png" "jpg" "jpeg" "gif" "svg" "webp" "mov" "mp4" "mp3")
|
||||||
|
"File extensions considered when offering candidates."
|
||||||
|
:type '(repeat string)
|
||||||
|
:group 'zq/org-assets)
|
||||||
|
|
||||||
|
(defun zq/org--image-regexp ()
|
||||||
|
(concat "\\." (regexp-opt zq/org-image-extensions t) "\\'"))
|
||||||
|
|
||||||
|
(defun zq/org--image-files (dir)
|
||||||
|
(when (and dir (file-directory-p dir))
|
||||||
|
(directory-files-recursively dir (zq/org--image-regexp))))
|
||||||
|
|
||||||
|
(defun zq/org--parse-name (filename)
|
||||||
|
"Split FILENAME into (DATE . REST)."
|
||||||
|
(if (string-match "^\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\)-\\(.*\\)" filename)
|
||||||
|
(cons (match-string 1 filename)
|
||||||
|
(match-string 2 filename))
|
||||||
|
(cons nil filename)))
|
||||||
|
|
||||||
|
(defun zq/org--display-name (path)
|
||||||
|
(let* ((name (file-name-nondirectory path))
|
||||||
|
(dir (file-name-nondirectory (directory-file-name (file-name-directory path))))
|
||||||
|
(parsed (zq/org--parse-name name))
|
||||||
|
(date (car parsed))
|
||||||
|
(rest (cdr parsed)))
|
||||||
|
(format "%s (%s | %s)" rest (or date "no-date") dir)))
|
||||||
|
|
||||||
|
(defun zq/org--build-candidates (files)
|
||||||
|
"Return an alist of (DISPLAY . FULLPATH), handling duplicates."
|
||||||
|
(let ((table (make-hash-table :test 'equal))
|
||||||
|
result)
|
||||||
|
(dolist (path files)
|
||||||
|
(let* ((display (zq/org--display-name path))
|
||||||
|
(existing (gethash display table)))
|
||||||
|
(if existing
|
||||||
|
;; duplicate → include full filename to disambiguate
|
||||||
|
(push (cons (file-name-nondirectory path) path) result)
|
||||||
|
(puthash display t table)
|
||||||
|
(push (cons display path) result))))
|
||||||
|
result))
|
||||||
|
|
||||||
|
|
||||||
|
(defun zq/org-insert-asset-image (&optional profile use-file-prefix)
|
||||||
|
"Insert an Org link to an image chosen from a PROFILE’s assets dir.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- Fuzzy search (with Vertico/Orderless/Ivy/Helm)
|
||||||
|
- Clean names (date stripped)
|
||||||
|
- Relative paths inserted
|
||||||
|
|
||||||
|
With prefix arg (C-u), use file: links."
|
||||||
|
(interactive
|
||||||
|
(list (completing-read
|
||||||
|
"Profile: "
|
||||||
|
(mapcar #'car zq/org-asset-profiles)
|
||||||
|
nil t nil nil "org-roam")
|
||||||
|
current-prefix-arg))
|
||||||
|
(let* ((base-dir (cdr (assoc profile zq/org-asset-profiles)))
|
||||||
|
(_ (unless (and base-dir (file-directory-p base-dir))
|
||||||
|
(user-error "Invalid directory for profile '%s'" profile)))
|
||||||
|
|
||||||
|
(files (or (zq/org--image-files base-dir)
|
||||||
|
(user-error "No assets found in %s" base-dir)))
|
||||||
|
|
||||||
|
(candidates (zq/org--build-candidates files))
|
||||||
|
|
||||||
|
;; user selects clean name, we resolve full path
|
||||||
|
(selected (completing-read "Image: " candidates nil t))
|
||||||
|
(abs-path (cdr (assoc selected candidates)))
|
||||||
|
|
||||||
|
(here (or (buffer-file-name) default-directory))
|
||||||
|
(rel (file-relative-name abs-path (file-name-directory here)))
|
||||||
|
|
||||||
|
(link (format "[[%s%s]]"
|
||||||
|
(if use-file-prefix "file:" "")
|
||||||
|
rel)))
|
||||||
|
|
||||||
|
(insert link)
|
||||||
|
|
||||||
|
(when (derived-mode-p 'org-mode)
|
||||||
|
(org-display-inline-images t t))))
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Weekly org review file:
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
;; Create weekly review files for Sundays, with catch-up command to fill in any missing ones up to the current week.
|
||||||
|
(require 'seq)
|
||||||
|
|
||||||
|
(defvar zaine/weekly-review-base-dir
|
||||||
|
"D:/_nextcloud/master-folder/org_files/org_web/blogs/"
|
||||||
|
"Base directory for weekly review blog entries.")
|
||||||
|
|
||||||
|
(defun zaine/weekly-review--month-dir (time)
|
||||||
|
"Return the directory for TIME in the format YYYY/MM-month."
|
||||||
|
(let ((year (format-time-string "%Y" time))
|
||||||
|
(month-num (format-time-string "%m" time))
|
||||||
|
(month-name (downcase (format-time-string "%B" time))))
|
||||||
|
(expand-file-name (format "%s/%s-%s" year month-num month-name)
|
||||||
|
zaine/weekly-review-base-dir)))
|
||||||
|
|
||||||
|
(defun zaine/weekly-review--normalize-to-review-time (time)
|
||||||
|
"Normalize TIME to 12:00 on the same date."
|
||||||
|
(let* ((decoded (decode-time time))
|
||||||
|
(day (nth 3 decoded))
|
||||||
|
(month (nth 4 decoded))
|
||||||
|
(year (nth 5 decoded)))
|
||||||
|
(encode-time 0 0 12 day month year)))
|
||||||
|
|
||||||
|
(defun zaine/weekly-review--sunday-of-week (&optional time)
|
||||||
|
"Return the most recent Sunday on or before TIME, normalized to 12:00."
|
||||||
|
(let* ((time (or time (current-time)))
|
||||||
|
(decoded (decode-time time))
|
||||||
|
(dow (nth 6 decoded))
|
||||||
|
(day (nth 3 decoded))
|
||||||
|
(month (nth 4 decoded))
|
||||||
|
(year (nth 5 decoded)))
|
||||||
|
(encode-time 0 0 12 (- day dow) month year)))
|
||||||
|
|
||||||
|
(defun zaine/weekly-review--next-sunday (&optional time)
|
||||||
|
"Return the next Sunday strictly after TIME, normalized to 12:00.
|
||||||
|
If TIME is a Sunday, returns the following Sunday."
|
||||||
|
(let* ((time (or time (current-time)))
|
||||||
|
(decoded (decode-time time))
|
||||||
|
(dow (nth 6 decoded))
|
||||||
|
(days-ahead (if (= dow 0) 7 (- 7 dow))))
|
||||||
|
(zaine/weekly-review--normalize-to-review-time
|
||||||
|
(time-add time (days-to-time days-ahead)))))
|
||||||
|
|
||||||
|
(defun zaine/weekly-review--coming-sunday (&optional time)
|
||||||
|
"Return the coming Sunday relative to TIME, normalized to 12:00.
|
||||||
|
If TIME is a Sunday, return that day. Otherwise return the next Sunday."
|
||||||
|
(let* ((time (or time (current-time)))
|
||||||
|
(decoded (decode-time time))
|
||||||
|
(dow (nth 6 decoded)))
|
||||||
|
(if (= dow 0)
|
||||||
|
(zaine/weekly-review--normalize-to-review-time time)
|
||||||
|
(zaine/weekly-review--next-sunday time))))
|
||||||
|
|
||||||
|
(defun zaine/weekly-review--file-name (time)
|
||||||
|
"Return the weekly review filename for TIME."
|
||||||
|
(format-time-string "%d-%m-week-review.org" time))
|
||||||
|
|
||||||
|
(defun zaine/weekly-review--slug (time)
|
||||||
|
"Return the weekly review slug for TIME."
|
||||||
|
(format-time-string "%d-%m-%y-week-review" time))
|
||||||
|
|
||||||
|
(defun zaine/weekly-review--title (time)
|
||||||
|
"Return the title for TIME."
|
||||||
|
(format "%s - Weekly Review"
|
||||||
|
(format-time-string "[%d-%m-%Y]" time)))
|
||||||
|
|
||||||
|
(defun zaine/weekly-review--header (time)
|
||||||
|
"Return Org header text for weekly review at TIME."
|
||||||
|
(concat
|
||||||
|
(format "#+TITLE: %s\n" (zaine/weekly-review--title time))
|
||||||
|
"#+OPTIONS: num:nil\n"
|
||||||
|
(format "#+DATE: %s\n" (format-time-string "<%Y-%m-%d %a 12:00>" time))
|
||||||
|
"#+filetags: :review:\n"
|
||||||
|
"#+COMMENTS: t\n"
|
||||||
|
(format "#+SLUG: %s\n\n" (zaine/weekly-review--slug time))))
|
||||||
|
|
||||||
|
(defun zaine/weekly-review--all-review-files ()
|
||||||
|
"Return all weekly review files under `zaine/weekly-review-base-dir`."
|
||||||
|
(when (file-directory-p zaine/weekly-review-base-dir)
|
||||||
|
(directory-files-recursively
|
||||||
|
zaine/weekly-review-base-dir
|
||||||
|
"^[0-9]\\{2\\}-[0-9]\\{2\\}-week-review\\.org$")))
|
||||||
|
|
||||||
|
(defun zaine/weekly-review--extract-date-from-file (file)
|
||||||
|
"Extract review date from FILE path.
|
||||||
|
Expected path like:
|
||||||
|
.../blogs/YYYY/MM-month/DD-MM-week-review.org"
|
||||||
|
(when (string-match
|
||||||
|
"/blogs/\\([0-9]\\{4\\}\\)/[0-9]\\{2\\}-[[:lower:]]+/\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\)-week-review\\.org$"
|
||||||
|
file)
|
||||||
|
(let* ((year (string-to-number (match-string 1 file)))
|
||||||
|
(day (string-to-number (match-string 2 file)))
|
||||||
|
(month (string-to-number (match-string 3 file))))
|
||||||
|
(encode-time 0 0 12 day month year))))
|
||||||
|
|
||||||
|
(defun zaine/weekly-review--latest-existing-sunday ()
|
||||||
|
"Return the latest Sunday review time found, or nil if none exist."
|
||||||
|
(let* ((files (zaine/weekly-review--all-review-files))
|
||||||
|
(dates (delq nil (mapcar #'zaine/weekly-review--extract-date-from-file files))))
|
||||||
|
(when dates
|
||||||
|
(seq-reduce
|
||||||
|
(lambda (latest current)
|
||||||
|
(if (time-less-p latest current) current latest))
|
||||||
|
(cdr dates)
|
||||||
|
(car dates)))))
|
||||||
|
|
||||||
|
(defun zaine/weekly-review--create-file-for-sunday (sunday)
|
||||||
|
"Create a weekly review file for SUNDAY if it doesn't exist.
|
||||||
|
Opens the file and returns its path. If it already exists, just opens it."
|
||||||
|
(let* ((target-dir (zaine/weekly-review--month-dir sunday))
|
||||||
|
(file-name (zaine/weekly-review--file-name sunday))
|
||||||
|
(file-path (expand-file-name file-name target-dir)))
|
||||||
|
(make-directory target-dir t)
|
||||||
|
(unless (file-exists-p file-path)
|
||||||
|
(with-temp-file file-path
|
||||||
|
(insert (zaine/weekly-review--header sunday))))
|
||||||
|
file-path))
|
||||||
|
|
||||||
|
;;; Public commands
|
||||||
|
|
||||||
|
(defun zaine/weekly-review-catchup ()
|
||||||
|
"Create all missing weekly review files from the oldest gap up to this week's Sunday.
|
||||||
|
If today is Monday 30 March, catches up through Sunday 29 March.
|
||||||
|
Creates one file per call so you can review each before continuing."
|
||||||
|
(interactive)
|
||||||
|
(let* ((past-sunday (zaine/weekly-review--sunday-of-week (current-time)))
|
||||||
|
(latest (zaine/weekly-review--latest-existing-sunday))
|
||||||
|
(next-needed (if latest
|
||||||
|
(zaine/weekly-review--normalize-to-review-time
|
||||||
|
(time-add latest (days-to-time 7)))
|
||||||
|
past-sunday)))
|
||||||
|
(if (time-less-p past-sunday next-needed)
|
||||||
|
(message "Weekly reviews are already up to date through %s."
|
||||||
|
(format-time-string "%d-%m-%Y" past-sunday))
|
||||||
|
(let ((file-path (zaine/weekly-review--create-file-for-sunday next-needed)))
|
||||||
|
(find-file file-path)
|
||||||
|
(message "Created missing review for Sunday %s — call again to catch up further."
|
||||||
|
(format-time-string "%d-%m-%Y" next-needed))))))
|
||||||
|
|
||||||
|
(defun zaine/weekly-review-create-coming ()
|
||||||
|
"Create the weekly review for the coming Sunday.
|
||||||
|
If today is Wednesday 1 April, creates the file for Sunday 5 April
|
||||||
|
in the April directory, creating it if needed.
|
||||||
|
If today is Sunday, creates today's review.
|
||||||
|
If the file already exists, just opens it."
|
||||||
|
(interactive)
|
||||||
|
(let* ((coming-sunday (zaine/weekly-review--coming-sunday (current-time)))
|
||||||
|
(file-path (zaine/weekly-review--create-file-for-sunday coming-sunday)))
|
||||||
|
(find-file file-path)
|
||||||
|
(message "%s review for Sunday %s."
|
||||||
|
(if (file-exists-p file-path) "Opened existing" "Created")
|
||||||
|
(format-time-string "%d-%m-%Y" coming-sunday))))
|
||||||
|
|
||||||
|
(global-set-key (kbd "C-c w r") #'zaine/weekly-review-catchup)
|
||||||
|
(global-set-key (kbd "C-c w c") #'zaine/weekly-review-create-coming)
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Insert org web entries
|
||||||
|
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
;; Create org web entries for blogs and posts with a consistent template and naming convention.
|
||||||
|
(defun zaine/create-org-web-entry ()
|
||||||
|
"Create a new org web entry in either blogs or posts."
|
||||||
|
(interactive)
|
||||||
|
(let* ((entry-type (completing-read "Choose type (blogs/posts): " '("blogs" "posts") nil t))
|
||||||
|
(slug (read-string "Filename / slug: "))
|
||||||
|
(title (read-string "Title: "))
|
||||||
|
(now (current-time))
|
||||||
|
(date-for-title (format-time-string "[%d-%m-%Y]" now))
|
||||||
|
(date-for-org (format-time-string "<%Y-%m-%d %a %H:%M>" now))
|
||||||
|
(year (format-time-string "%Y" now))
|
||||||
|
(month-num (format-time-string "%m" now))
|
||||||
|
(month-name (downcase (format-time-string "%B" now)))
|
||||||
|
(blog-dir (format "D:/_nextcloud/master-folder/org_files/org_web/blogs/%s/%s-%s"
|
||||||
|
year month-num month-name))
|
||||||
|
(post-dir "D:/_nextcloud/master-folder/org_files/org_web/posts/career")
|
||||||
|
(target-dir (if (string= entry-type "blogs") blog-dir post-dir))
|
||||||
|
(file-path (expand-file-name (concat slug ".org") target-dir))
|
||||||
|
(filetags (if (string= entry-type "blogs") ":life:" ":post:")))
|
||||||
|
|
||||||
|
;; Create directory if it does not exist
|
||||||
|
(unless (file-directory-p target-dir)
|
||||||
|
(make-directory target-dir t))
|
||||||
|
|
||||||
|
;; Open file and insert template if new
|
||||||
|
(find-file file-path)
|
||||||
|
(when (= (buffer-size) 0)
|
||||||
|
(insert (format "#+TITLE: %s\n" title))
|
||||||
|
(insert "#+OPTIONS: num:nil\n")
|
||||||
|
(insert (format "#+DATE: %s\n" date-for-org))
|
||||||
|
(insert (format "#+filetags: %s\n" filetags))
|
||||||
|
(insert "#+COMMENTS: t\n")
|
||||||
|
(insert (format "#+SLUG: %s\n\n" slug))
|
||||||
|
(save-buffer))))
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Insert org macros:
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(defun org-insert-macro ()
|
||||||
|
"Interactively select and insert an Org macro with prompted values."
|
||||||
|
(interactive)
|
||||||
|
(let* ((macro-defs
|
||||||
|
'(("sidenote" . ("ID" "Content"))
|
||||||
|
("epigraph" . ("Quote" "Footer"))
|
||||||
|
("epigraph_single" . ("Quote"))
|
||||||
|
("epigraph3" . ("Quote" "Author" "Work"))
|
||||||
|
("kbd" . ("Key"))
|
||||||
|
("margimg" . ("Image URL" "Alt text" "Caption (optional)"))
|
||||||
|
("countdown" . ("ISO datetime (e.g. 2025-12-31T00:00:00)" "Label"))))
|
||||||
|
(name (completing-read "Insert macro: " (mapcar #'car macro-defs) nil t))
|
||||||
|
(args (cdr (assoc name macro-defs)))
|
||||||
|
(values (mapcar (lambda (prompt)
|
||||||
|
(read-string (format "%s: " prompt)))
|
||||||
|
args))
|
||||||
|
(macro (format "{{{%s(%s)}}}"
|
||||||
|
name
|
||||||
|
(mapconcat #'identity values ","))))
|
||||||
|
(insert macro)))
|
||||||
|
|
||||||
|
(define-key org-mode-map (kbd "C-c m") #'org-insert-macro)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Old stuff:
|
||||||
|
** org image inserter:
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
;; Core group & settings (dedupe: define these only once)
|
||||||
|
;; (defgroup zq/org-assets nil
|
||||||
|
;; "Insert image links from predefined asset profiles."
|
||||||
|
;; :group 'org)
|
||||||
|
|
||||||
|
;; (defcustom zq/org-asset-profiles
|
||||||
|
;; '(("org-roam" . "D:\\_nextcloud\\master-folder\\org_files\\org_roam\\assets")
|
||||||
|
;; ("org-web" . "D:\\_nextcloud\\master-folder\\org_files\\org_web\\assets"))
|
||||||
|
;; "Alist of (PROFILE-NAME . ASSETS-DIR)."
|
||||||
|
;; :type '(alist :key-type string :value-type directory)
|
||||||
|
;; :group 'zq/org-assets)
|
||||||
|
|
||||||
|
;; (defcustom zq/org-image-extensions '("png" "jpg" "jpeg" "gif" "svg" "webp" "mov" "mp4" "mp3")
|
||||||
|
;; "Image file extensions considered when offering candidates."
|
||||||
|
;; :type '(repeat string)
|
||||||
|
;; :group 'zq/org-assets)
|
||||||
|
|
||||||
|
;; (defun zq/org--image-regexp ()
|
||||||
|
;; "Build a regexp that matches configured image extensions."
|
||||||
|
;; (concat "\\." (regexp-opt zq/org-image-extensions t) "\\'"))
|
||||||
|
|
||||||
|
;; (defun zq/org--image-files (dir)
|
||||||
|
;; "Return a list of image files under DIR (recursively)."
|
||||||
|
;; (when (and dir (file-directory-p dir))
|
||||||
|
;; (directory-files-recursively dir (zq/org--image-regexp))))
|
||||||
|
|
||||||
|
;; (defun zq/org-insert-asset-image (&optional profile use-file-prefix)
|
||||||
|
;; "Insert an Org link to an image chosen from a PROFILE’s assets dir.
|
||||||
|
|
||||||
|
;; Interactively:
|
||||||
|
;; - Prompts for PROFILE (from `zq/org-asset-profiles`).
|
||||||
|
;; - Presents only image files under that profile’s assets directory.
|
||||||
|
;; - Inserts a relative link like [[path/to/image.png]].
|
||||||
|
;; - With prefix arg (C-u), uses [[file:path/to/image.png]].
|
||||||
|
|
||||||
|
;; Non-interactively:
|
||||||
|
;; PROFILE is the profile name string, USE-FILE-PREFIX non-nil forces file: prefix."
|
||||||
|
;; (interactive
|
||||||
|
;; (list (completing-read "Profile: "
|
||||||
|
;; (mapcar #'car zq/org-asset-profiles)
|
||||||
|
;; nil t nil nil "org-roam")
|
||||||
|
;; current-prefix-arg))
|
||||||
|
;; (let* ((base-dir (cdr (assoc profile zq/org-asset-profiles)))
|
||||||
|
;; (_ (unless (and base-dir (file-directory-p base-dir))
|
||||||
|
;; (user-error "Profile '%s' has no valid directory: %s" profile base-dir)))
|
||||||
|
;; (candidates (or (zq/org--image-files base-dir)
|
||||||
|
;; (user-error "No images found in %s" base-dir)))
|
||||||
|
;; (abs-path (expand-file-name (completing-read "Image: " candidates nil t)))
|
||||||
|
;; (here (or (buffer-file-name) default-directory))
|
||||||
|
;; (rel (file-relative-name abs-path (file-name-directory here)))
|
||||||
|
;; (link (format "[[%s%s]]"
|
||||||
|
;; (if use-file-prefix "file:" "")
|
||||||
|
;; rel)))
|
||||||
|
;; (insert link)
|
||||||
|
;; (when (derived-mode-p 'org-mode)
|
||||||
|
;; (org-display-inline-images t t))))
|
||||||
|
|
||||||
|
|
||||||
|
;;; --- Robust paste-into-profile without org-download--clipboard-image-p ---
|
||||||
|
|
||||||
|
;; (require 'url) ;; for url-copy-file
|
||||||
|
;; (require 'org-download) ;; for org-download-clipboard
|
||||||
|
|
||||||
|
;; (defun zq/org--ensure-dir (dir)
|
||||||
|
;; "Ensure DIR exists and is a directory; error if invalid."
|
||||||
|
;; (unless (and dir (file-directory-p dir))
|
||||||
|
;; (user-error "Profile directory invalid or not found: %s" dir))
|
||||||
|
;; (make-directory dir t)
|
||||||
|
;; dir)
|
||||||
|
|
||||||
|
;; (defun zq/org--unique-image-filename (&optional ext)
|
||||||
|
;; "Return a unique filename like 20260227_160404.png. Default EXT is png."
|
||||||
|
;; (concat (format-time-string "%Y%m%d_%H%M%S") "." (or ext "png")))
|
||||||
|
|
||||||
|
;; (defun zq/org--rel-link-to (abs-path)
|
||||||
|
;; "Return a relative Org link for ABS-PATH from current buffer."
|
||||||
|
;; (let* ((here (or (buffer-file-name) default-directory))
|
||||||
|
;; (rel (file-relative-name abs-path (file-name-directory here))))
|
||||||
|
;; (format "[[%s]]" rel)))
|
||||||
|
|
||||||
|
;; (defun zq/org--clipboard-text ()
|
||||||
|
;; "Return current clipboard text (or nil) without altering kill ring."
|
||||||
|
;; (let ((str (current-kill 0 t)))
|
||||||
|
;; (when (and str (stringp str) (> (length str) 0)) str)))
|
||||||
|
|
||||||
|
;; (defun zq/org--grab-clipboard-image-to-temp ()
|
||||||
|
;; "Try to capture clipboard image into a temporary PNG file.
|
||||||
|
;; Return the temp filename on success; nil otherwise. Temp file is caller-managed."
|
||||||
|
;; (let ((tmp (make-temp-file "zq-clip-" nil ".png"))
|
||||||
|
;; (ok nil))
|
||||||
|
;; (unwind-protect
|
||||||
|
;; (progn
|
||||||
|
;; ;; Try to save clipboard to TMP; some systems signal error when no image
|
||||||
|
;; (condition-case _err
|
||||||
|
;; (org-download-clipboard tmp)
|
||||||
|
;; (error
|
||||||
|
;; ;; ignore; ok remains nil
|
||||||
|
;; ))
|
||||||
|
;; ;; Validate: file exists, non-empty, and Emacs recognizes image type
|
||||||
|
;; (when (and (file-exists-p tmp)
|
||||||
|
;; (> (nth 7 (file-attributes tmp)) 0)
|
||||||
|
;; (ignore-errors (image-type-from-file tmp)))
|
||||||
|
;; (setq ok t)))
|
||||||
|
;; (unless ok
|
||||||
|
;; (when (file-exists-p tmp) (delete-file tmp))))
|
||||||
|
;; (when ok tmp)))
|
||||||
|
|
||||||
|
;; (defun zq/org--save-data-uri (data-uri target)
|
||||||
|
;; "Save a data:image/...;base64,... DATA-URI to TARGET."
|
||||||
|
;; (unless (string-match "\\`data:image/\\([a-zA-Z0-9+.-]+\\);base64,\\(.*\\)\\'" data-uri)
|
||||||
|
;; (user-error "Clipboard looks like a data URI but not an image/base64"))
|
||||||
|
;; (let ((bytes (base64-decode-string (match-string 2 data-uri))))
|
||||||
|
;; (with-temp-file target
|
||||||
|
;; (set-buffer-multibyte nil)
|
||||||
|
;; (insert bytes))))
|
||||||
|
|
||||||
|
;; (defun zq/org--download-url-to-file (url target)
|
||||||
|
;; "Download image from URL to TARGET (synchronously)."
|
||||||
|
;; (url-copy-file url target t))
|
||||||
|
|
||||||
|
;; (defun zq/org-paste-image-into-profile (&optional profile)
|
||||||
|
;; "Paste image (clipboard/URL/data-URI) into PROFILE assets and insert a relative Org link."
|
||||||
|
;; (interactive
|
||||||
|
;; (list (completing-read "Profile: "
|
||||||
|
;; (mapcar #'car zq/org-asset-profiles)
|
||||||
|
;; nil t nil nil "org-roam")))
|
||||||
|
;; (let* ((assets-dir (cdr (assoc profile zq/org-asset-profiles))))
|
||||||
|
;; (zq/org--ensure-dir assets-dir)
|
||||||
|
|
||||||
|
;; (let* ((filename (zq/org--unique-image-filename "png"))
|
||||||
|
;; (target (expand-file-name filename assets-dir))
|
||||||
|
;; (handled nil))
|
||||||
|
|
||||||
|
;; ;; 1) Preferred: raw image from clipboard via org-download backends
|
||||||
|
;; (let ((tmp (zq/org--grab-clipboard-image-to-temp)))
|
||||||
|
;; (when tmp
|
||||||
|
;; (rename-file tmp target t) ;; move tmp → target
|
||||||
|
;; (setq handled t)))
|
||||||
|
|
||||||
|
;; ;; 2) If no raw image, try clipboard text: data URI or URL
|
||||||
|
;; (unless handled
|
||||||
|
;; (let ((clip (zq/org--clipboard-text)))
|
||||||
|
;; (cond
|
||||||
|
;; ;; data URI
|
||||||
|
;; ((and clip (string-prefix-p "data:image/" clip))
|
||||||
|
;; (zq/org--save-data-uri clip target)
|
||||||
|
;; (setq handled t))
|
||||||
|
;; ;; http(s) URL
|
||||||
|
;; ((and clip (string-match-p "\\`https?://" clip))
|
||||||
|
;; (zq/org--download-url-to-file clip target)
|
||||||
|
;; (setq handled t)))))
|
||||||
|
|
||||||
|
;; (unless handled
|
||||||
|
;; (user-error
|
||||||
|
;; (concat
|
||||||
|
;; "No image found in clipboard.\n\n"
|
||||||
|
;; "Tips:\n"
|
||||||
|
;; "• In your browser, use **Copy image** (not “Copy image address”)\n"
|
||||||
|
;; "• Or copy from an image viewer / screenshot tool (to clipboard)\n"
|
||||||
|
;; "• On Wayland: install `wl-clipboard` (provides `wl-paste`)\n"
|
||||||
|
;; "• On X11: install `xclip` or `xsel`\n"
|
||||||
|
;; "• Alternatively: copy an image URL or a data:image/...;base64,... and retry")))
|
||||||
|
|
||||||
|
;; ;; Insert the relative link and display inline
|
||||||
|
;; (insert (zq/org--rel-link-to target))
|
||||||
|
;; (when (derived-mode-p 'org-mode)
|
||||||
|
;; (org-display-inline-images t t))
|
||||||
|
;; (message "Saved image → %s" target))))
|
||||||
|
|
||||||
|
|
||||||
|
#+end_src
|
||||||
0
Linux/20250213124335-i3_wm.org
Executable file → Normal file
0
Linux/20250213124335-i3_wm.org
Executable file → Normal file
0
Linux/20250417173809-linux_moc.org
Executable file → Normal file
0
Linux/20250417173809-linux_moc.org
Executable file → Normal file
0
Linux/20250417173809-linux_stuff.org
Executable file → Normal file
0
Linux/20250417173809-linux_stuff.org
Executable file → Normal file
0
Linux/20250417173821-wacom_notes.org
Executable file → Normal file
0
Linux/20250417173821-wacom_notes.org
Executable file → Normal file
0
Linux/20250428133236-systemd_services.org
Executable file → Normal file
0
Linux/20250428133236-systemd_services.org
Executable file → Normal file
0
Linux/20250516161728-gpg_encryption.org
Executable file → Normal file
0
Linux/20250516161728-gpg_encryption.org
Executable file → Normal file
0
Linux/20250703183239-linux_arch_linux.org
Executable file → Normal file
0
Linux/20250703183239-linux_arch_linux.org
Executable file → Normal file
0
Linux/20250723190927-self_hosting.org
Executable file → Normal file
0
Linux/20250723190927-self_hosting.org
Executable file → Normal file
0
Linux/20250727120306-nextcloud.org
Executable file → Normal file
0
Linux/20250727120306-nextcloud.org
Executable file → Normal file
1
Linux/20251019114736-server_moc.org
Executable file → Normal file
1
Linux/20251019114736-server_moc.org
Executable file → Normal file
@@ -16,3 +16,4 @@
|
|||||||
|
|
||||||
- [[id:e12ef44d-69a4-45c8-a823-c810d2c3857c][Vaultwarden]]
|
- [[id:e12ef44d-69a4-45c8-a823-c810d2c3857c][Vaultwarden]]
|
||||||
|
|
||||||
|
- [[id:43afdfdd-e1fe-4e3a-a6f6-0d99b253fc8a][Cloudflare]]
|
||||||
|
|||||||
0
Linux/20260104155940-server_backend.org
Executable file → Normal file
0
Linux/20260104155940-server_backend.org
Executable file → Normal file
0
Linux/20260227103506-vaultwarden.org
Executable file → Normal file
0
Linux/20260227103506-vaultwarden.org
Executable file → Normal file
72
Linux/20260409135127-cloudflare.org
Normal file
72
Linux/20260409135127-cloudflare.org
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: 43afdfdd-e1fe-4e3a-a6f6-0d99b253fc8a
|
||||||
|
:END:
|
||||||
|
#+title: Cloudflare
|
||||||
|
#+filetags: :cloudflare:server:networking:
|
||||||
|
|
||||||
|
* Origin certificate
|
||||||
|
#+begin_src
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEojCCA4qgAwIBAgIUGvC9u3SW6C6y5uOcQjul2hyghmgwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwgYsxCzAJBgNVBAYTAlVTMRkwFwYDVQQKExBDbG91ZEZsYXJlLCBJbmMuMTQw
|
||||||
|
MgYDVQQLEytDbG91ZEZsYXJlIE9yaWdpbiBTU0wgQ2VydGlmaWNhdGUgQXV0aG9y
|
||||||
|
aXR5MRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlh
|
||||||
|
MB4XDTI2MDQwOTEyNDYwMFoXDTQxMDQwNTEyNDYwMFowYjEZMBcGA1UEChMQQ2xv
|
||||||
|
dWRGbGFyZSwgSW5jLjEdMBsGA1UECxMUQ2xvdWRGbGFyZSBPcmlnaW4gQ0ExJjAk
|
||||||
|
BgNVBAMTHUNsb3VkRmxhcmUgT3JpZ2luIENlcnRpZmljYXRlMIIBIjANBgkqhkiG
|
||||||
|
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwnW7egyN30IndtYbCdk4EA9IVb+icJo4d9mR
|
||||||
|
Bsiw4TJ6YSlnFkVXuHl1iitSZiMnlGxHke5AsDGm8rnyCa5BzT/n+VI27WwyncoO
|
||||||
|
PJXjSjOFIWVg/VAaHJUwXcc+taqNn/U3661iSN+1TlJFgpVwF6ei6t+raJcCAXxN
|
||||||
|
ajrA3ksf4FhMWQcpdi6J0ecM8LWsa94nNHFZJCH8nTGsND90zw7ueOMu5JIhc6Ru
|
||||||
|
0Iw5kke2jIkhVQpg4DYTzKoEa1SmgGCZAPBlBaOc7Ii4VpVMmydhRh0TFDZbe5Bz
|
||||||
|
lgVMslOSj1qnq4o7nFCk0LY8gfSykbuKJEHr/aboOEkot+E4kwIDAQABo4IBJDCC
|
||||||
|
ASAwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD
|
||||||
|
ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBThHBF5Sw8X+uuHUB0NIANwIakBsjAf
|
||||||
|
BgNVHSMEGDAWgBQk6FNXXXw0QIep65TbuuEWePwppDBABggrBgEFBQcBAQQ0MDIw
|
||||||
|
MAYIKwYBBQUHMAGGJGh0dHA6Ly9vY3NwLmNsb3VkZmxhcmUuY29tL29yaWdpbl9j
|
||||||
|
YTAlBgNVHREEHjAcgg0qLnphaW5lenEuY29tggt6YWluZXpxLmNvbTA4BgNVHR8E
|
||||||
|
MTAvMC2gK6AphidodHRwOi8vY3JsLmNsb3VkZmxhcmUuY29tL29yaWdpbl9jYS5j
|
||||||
|
cmwwDQYJKoZIhvcNAQELBQADggEBALfCfzqPuLXLepdyY/O8j9+0kiwdgby6ir1x
|
||||||
|
1O8HKm0y47WZx7nntromSo4Bgq+R1KglUCvkcy+kCwlsfFk1WmCgVMiE9WCnn6Pv
|
||||||
|
NriftoM5Q1tiHeSR0kLOJ9mROmiy5roThMm2EOWCjhWw2jJzVfvTj1s651dpmGRj
|
||||||
|
E6BoX6NJr9NvzVEeCqhgjoiCXIv5bfGEwl1Mj/mIj2/GIbLiayT90vi8T89ixgca
|
||||||
|
RTLlmRiEEJnKP0NN45vGYjgtJCgkXtCDL0lfSBt5FuEXq4sXIjDhhIn/hH004doJ
|
||||||
|
fHlwK4tTfpZPYterSRRuy4zSgV7IekKS2z9pjCloQbDbMjqnAKI=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Private key
|
||||||
|
#+begin_src
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDCdbt6DI3fQid2
|
||||||
|
1hsJ2TgQD0hVv6Jwmjh32ZEGyLDhMnphKWcWRVe4eXWKK1JmIyeUbEeR7kCwMaby
|
||||||
|
ufIJrkHNP+f5UjbtbDKdyg48leNKM4UhZWD9UBoclTBdxz61qo2f9TfrrWJI37VO
|
||||||
|
UkWClXAXp6Lq36tolwIBfE1qOsDeSx/gWExZByl2LonR5wzwtaxr3ic0cVkkIfyd
|
||||||
|
Maw0P3TPDu544y7kkiFzpG7QjDmSR7aMiSFVCmDgNhPMqgRrVKaAYJkA8GUFo5zs
|
||||||
|
iLhWlUybJ2FGHRMUNlt7kHOWBUyyU5KPWqerijucUKTQtjyB9LKRu4okQev9pug4
|
||||||
|
SSi34TiTAgMBAAECggEADPLiBQKI//Dbx+IB8unv/cHGw077dhwO3owySA1dGeHO
|
||||||
|
nGGxZ54+dR5BYW35EqwMmqmLKoB+9jyYLVmMcHCWGSDERanf1nd591/ZCtfARtSf
|
||||||
|
bNXfW37V/klA6z21Q0uUGq6thpgJD2k2HX0E++kPicOz6YfzVgeYLpkkXoqDBUpF
|
||||||
|
dzC+eGZDzjI1BECoW/N/U3P2F8nv7fHv/4xVudkMehlkPJ56BiMbx2K15jvh2Dyz
|
||||||
|
znZvelNNw/XRHv29GgOkggh4BQRDXHl3/mTMTe8JmLWU560rNZ99xjpv1lrbqwuO
|
||||||
|
W5WNRKcQRXCELXsEDiH1dEsteU1wVUaOyZSzEg6OYQKBgQD4InmF5kuhPrgnNwKu
|
||||||
|
uRYZB60JFvkVdxal1xIGDwjylWBVsWWJEIAko3wbt6iI2/r1Est4tsBnap9nMciG
|
||||||
|
Zn4FKJRAj0bZW6CwFHUZy6q91qK7JFM1e1dcrDXhgFOCG4rI802roPSjCo/rztkI
|
||||||
|
LEQomGbMVs/86KtqaSRqVjGXXQKBgQDIn7StCglsRD/+RDWFIgtSOJbdIe0imP1h
|
||||||
|
ewRa7iSKBMbc8ZFwDuZ3JxDI1a0DTQdMM3MpZRtGO2urnnepNV3fqSnZaaruaEL0
|
||||||
|
1IKvCtZn1MHMEi4gErqpEBqgHfvSOIBvFhKQ6bbclmZJ5u1OFBrbu9EALfLk1Tkz
|
||||||
|
Luje1fnArwKBgF7zIjlgtJQRIfqvjDE71f7h9w7BYbMbDOmM8PKskinxixl/dnEK
|
||||||
|
hV5/yJ/6mV01gESDWqTomZt5K2IbpLX5RkPHEWPa76uA6m42hdDHJKDcHw0pi0Wt
|
||||||
|
2vI1W7DcoBfrXiIjKBeC0doJ0qTTVC1Scwpttvh+R7xpdB6V+T9PmE5pAoGBALhm
|
||||||
|
On31xLVzgdImRX8JzJgVFW1JOpnbPsFzfYxKaOFHBLWdf40c1O3dxUqjQ3POQA/l
|
||||||
|
FkuM9+W0xgEnFVs8hv0FkkaYHhklUa2RClDzSCCFaF82spiePl0YRTC4fnY5oqr4
|
||||||
|
Abaaao4T2w7AJ4vlZM5ksfRVR3TXGs0Vp8rxp65XAoGAPNgi8uz9zcAp5tUizZVg
|
||||||
|
6nP68Cws6I3PmExMnbr2BmYAi2tl2NY93PQG1OT9MZ51Z0W+ynM6nTzti2zm7iXO
|
||||||
|
Rs4AAsErEG1YDt4U0GExJdoEBIJ14+9Q6PSYPAMBbx0nv1WA1hvdvDHIUaYNPWqZ
|
||||||
|
wuSVw419xlxUkj9uCb1kQoo=
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
|
||||||
|
|
||||||
|
#+end_src
|
||||||
21
Misc/#20251101123637-backlog.org#
Normal file
21
Misc/#20251101123637-backlog.org#
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: 580cc3a5-af8e-4cbe-b5ad-5b06680e6c37
|
||||||
|
:END:
|
||||||
|
#+title: Backlog
|
||||||
|
#+filetags: :backlog:
|
||||||
|
|
||||||
|
* Ideas
|
||||||
|
** Building a code smells coverage checker for the ~output~ dir
|
||||||
|
** Powershell script to give insights on the build scripts. This can be fed into the daily logs/discord pipeline
|
||||||
|
have a central point where we can see the server details and documentations
|
||||||
|
- Have a two way sync between the cookbook and org-roam notes (see: [[https://nextcloud.github.io/cookbook/dev/api/0.1.3/index.html#/Recipes/listRecipes][swagger]])
|
||||||
|
|
||||||
|
- Sort out all the iphone chrome nitter/xcancel links (so we don't go there again)
|
||||||
|
- sort out all the book notes. the current ones are:
|
||||||
|
- the science of self-discipline
|
||||||
|
- clean coder
|
||||||
|
- so good they can't ignore you
|
||||||
|
** source of truth for all most used functions
|
||||||
|
* To sort:
|
||||||
|
|
||||||
|
* Checked:
|
||||||
2
Misc/20241210001045-technical_moc.org
Executable file → Normal file
2
Misc/20241210001045-technical_moc.org
Executable file → Normal file
@@ -35,3 +35,5 @@ In this file I want to include technical information (things related to programm
|
|||||||
- [[id:37495d5f-2a77-40bc-b45c-8163189bbe6b][Technical Commonplace]]
|
- [[id:37495d5f-2a77-40bc-b45c-8163189bbe6b][Technical Commonplace]]
|
||||||
|
|
||||||
- [[id:22737796-6D31-49D5-84F2-F7BC73E45144][Concepts]]
|
- [[id:22737796-6D31-49D5-84F2-F7BC73E45144][Concepts]]
|
||||||
|
|
||||||
|
- [[id:84c371ea-6789-450e-978c-f1d77e725f4b][Website Stuff]]
|
||||||
|
|||||||
0
Misc/20241211161232- job_application_cover_letters.org
Executable file → Normal file
0
Misc/20241211161232- job_application_cover_letters.org
Executable file → Normal file
0
Misc/20241211161232-applications.org
Executable file → Normal file
0
Misc/20241211161232-applications.org
Executable file → Normal file
0
Misc/20250402185735-java_moc.org
Executable file → Normal file
0
Misc/20250402185735-java_moc.org
Executable file → Normal file
0
Misc/20250430001952-microlise_assessment.org
Executable file → Normal file
0
Misc/20250430001952-microlise_assessment.org
Executable file → Normal file
0
Misc/20250717230336-recipes_moc.org
Executable file → Normal file
0
Misc/20250717230336-recipes_moc.org
Executable file → Normal file
0
Misc/20250719174944-recipes_ideas.org
Executable file → Normal file
0
Misc/20250719174944-recipes_ideas.org
Executable file → Normal file
0
Misc/20250719175023-recipes_done.org
Executable file → Normal file
0
Misc/20250719175023-recipes_done.org
Executable file → Normal file
0
Misc/20250723185829-test_driven_development.org
Executable file → Normal file
0
Misc/20250723185829-test_driven_development.org
Executable file → Normal file
0
Misc/20250723185943-bowling_kata.org
Executable file → Normal file
0
Misc/20250723185943-bowling_kata.org
Executable file → Normal file
0
Misc/20250723190203-java_portswrigger_test.org
Executable file → Normal file
0
Misc/20250723190203-java_portswrigger_test.org
Executable file → Normal file
0
Misc/20250723190656-java_junit_testing.org
Executable file → Normal file
0
Misc/20250723190656-java_junit_testing.org
Executable file → Normal file
6
Misc/20250806111925-non_technical_moc.org
Executable file → Normal file
6
Misc/20250806111925-non_technical_moc.org
Executable file → Normal file
@@ -12,4 +12,10 @@
|
|||||||
|
|
||||||
- [[id:45eefd5b-a3d8-4b83-84ea-5a6984025755][Proverbs]]
|
- [[id:45eefd5b-a3d8-4b83-84ea-5a6984025755][Proverbs]]
|
||||||
|
|
||||||
|
- [[id:023285a5-af32-4143-91e7-e0942a2635ad][Resources]]
|
||||||
|
|
||||||
|
- [[id:79ba54e3-d300-4352-a7e6-3e7ec342cca3][Finances]]
|
||||||
|
|
||||||
|
- [[id:46c01e4f-4363-4017-9bb8-ef313266d5e2][Decluttering Plan]]
|
||||||
|
|
||||||
|
- [[id:cf614dfb-f764-4689-be69-e0166f4b9260][Chrome Tabs Backup]]
|
||||||
|
|||||||
0
Misc/20250918120519-misc_moc.org
Executable file → Normal file
0
Misc/20250918120519-misc_moc.org
Executable file → Normal file
0
Misc/20250918120706-wedding_moc.org
Executable file → Normal file
0
Misc/20250918120706-wedding_moc.org
Executable file → Normal file
0
Misc/20250926151524-workflow_moc.org
Executable file → Normal file
0
Misc/20250926151524-workflow_moc.org
Executable file → Normal file
0
Misc/20251002154125-microlise_moc.org
Executable file → Normal file
0
Misc/20251002154125-microlise_moc.org
Executable file → Normal file
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user