2023 Resolutions and How to survive them!

As we are leaping towards 2023, I’m getting very excited for new year resolutions and I can think of tons of them. And like everyone I want to achieve / excel at all of them. But as you may already know, our commitment to these resolutions doesn’t last beyond January and we always fail miserably towards the end of the year.

There are thousands of resolution tracker apps there which can help individuals to keep focused. But still we can’t reach the finish line to call it a year a successful one. So what we can do it to make it better?

Today I was talking with friends and families, on what are their goals / resolutions for 2023, I thought why not make it a fun competition to nudge us to achieve what we want and that’s when 2023 Doers Challenge is born!

Idea is very similar to what we done in the past as part of Uncle and Me challenge which I’ve talked about here and here. Difference is we’re talking about year long challenge!

Without further ado, here are the base rules that we are going to stick to see if we can do what we want to do in 2023.

  • We will give rewards to consistent performers. This will be measured monthly.
    • Prizes will given at the end of the month.
    • Grand prize will be offered at the end of the year!
  • One need to buy in to participate.
    • $50 in two installments.
      • $25 in first week of January
      • $25 in first week of June
  • Everyone enters their names on spreadsheet with at least 2-5 activities / goals across different categories such as Personal Development, Financial Improvements, Work Skills Growth and for a Better Community around us.
    • Personal Development – This can be acquiring new habits, trashing bad habits, new milestones in physical fitness, health or learning new skills such as getting better at new sports, playing new instrument and so on.
    • Financial Improvements – Possible categories: saving goals, getting rid of debt, learning / practicing new ways to improve your wealth.
    • Work Skills GrowthNew certifications, learning new programming language, doing more coding at Hacker Rank; Leet code, participating in hackathons and beyond.
    • Better CommunityGiving back for all that we receive! One can be a mentor, actively volunteer to provide services to those who need help!
  • Finally your goals should be smart – and SMART
    • S – Specific
    • M – Measurable
    • A – Achievable
    • R – Relevant
    • T – Time-bound
  • We will be using Google Spreadsheet to track activities across to all the participants.
    • Use secret names to make it more exciting so that all participants will be curious not only about your challenges but person itself!
    • Also by not using your real name, you will be more ready to share your goals with everyone.
    • You can also have secret goals, which you can keep track of yourself. It will not be qualified for the rewards though if you can’t share the progress.
  • We will have few judges among us who will make sure your goals are SMART and measured through out the year to decide upon the monthly and annual winner.

I’m hoping to have greater participation so that we can have worthy rewards which will keep everyone focused to be persistent throughout the year. And that’s the real objective of this competition!

So are you ready for 2023? I am 🙂

Uncle and .us – Half time Report

It’s been 2 months since we started this learning experiment on UncleAnd.us I (Uncle) am happy to report that we’re doing great; much better than I’d imagined!

Here is the quick summary of what we’ve achieved in the last 2 months.


Uncle Raju

On 1st May 2020, I wrote a blog post about this summer challenge and our goals that we are planning to achieve in the coming four months (May-August 2020).

Back then I thought these were lofty goals, something that if we do 20% of what we promised, I will celebrate as a win! Boy, I was so wrong!! Atharva, Gaurav, Sam, Avik surprised me big time.

First let me summarize our objectives and then I will share what we have achieved.

Our objectives:

  • Finish Linux fundamentals course
  • Complete Full Stack Open 2020 course (Main course!)
  • (At least one) AWS
  • Write a blog post every week
  • Create your own project to demonstrate your learning from each course.

And here is what we accomplished:

  1. Everyone is attending our weekly call. They always come prepared and excited to share their completed blog posts and what they have learned in the past week.

    Personally I’ve learned a lot from these meetings. It shows that everyone is really passionate about this initiative and putting all efforts to stay on the course!
  2. The first goal, Linux Fundamentals Course completed by everyone.
  3. Now, these young Turks are about to finish the hardest course – Full Stack Open 2020 course; which will give them the power to implement their own ideas.
  4. Atharva
    1. Implemented Trash Suite for Linux to showcase his Bash skills learned from fundamentals course.
    2. He ended up writing a detailed blog post on Git and GitHub.
    3. Another interesting write up is on how to create GCP instance and then how to SSH into it.
    4. Tomorrow he is going to unveil his side project based on learning from Full Stack Course. Can’t wait to see things in action!
  5. Sam
    1. He is already ahead of the curve in the completion of these courses.
    2. My favorite posts from his blog are:
      1. The Missing Semester – which is the basis of our this 4 months learning experiment.
      2. My First Bash Script explains how he used the power of Bash to automate the boring tedious tasks of converting old vintage analog videos into digital format.
      3. Very recent blog posts highlight the importance of automation for provisioning in Cloud Infrastructure such as GCP, AWS, And introduces us to the concept of Terraform.
  6. Gaurav
    1. He is the only one who has completed both Linux Fundamentals and Full Stack course!
      Full Stack Course completion is under review before he is eligible to get the $50.
    2. Now he is on the mission of getting AWS Certified!
    3. Also working on building a Twitter clone based on his learning so far!
    4. And we also got to know his love for designer sneakers!
  7. Avik
    1. He is busy with a fundraiser for his High School
    2. And finally found his love at Alarm.com where he is pursuing an internship.
  8. And last not but least, I’ve given away $225 for the successful completion of the first course by all four lads ($50 to 3 of them and $75 Atharva for going beyond by making an awesome project, during Linux Fundamentals course completion) If you ask me, money well spent!
    And special bonding that we got between all of us is priceless!

Where we go from here

As we do while running a marathon, we are striving for negative split; it means second half of the marathon we aim to run faster than first one.

The same principle we’ve decided to apply for the second half of this challenge. I’m waiting for some more great news from these guys.

Till then, keep reading all these four blogs to keep yourself up-to-date!

Yours,
Raju Uncle

Field Hockey in Bay Area, California

In order to build a grow the game of Field Hockey, not only we need to work at grass root level which will help us to get local talent, but we also have to provide our youth here: best facilities so that they can compete with the best talent not in the USA, but around the world!

It’s a sad fact that we don’t have one single facility where our clubs, players can practice on Astro-turf regularly. Why can’t we do it here in a Bay Area; in Silicon Valley where so many dreams come true? Maybe we haven’t given enough push or thought about it.

It’s time to act now!

On February 28th, I wrote my thoughts on how we can grow this beautiful game of Field Hockey here in California. It’s been almost 4 months since then; a lot more has happened that is I think to help us going in right direction!

  • US Field Hockey announced the creation of State chapters that can help Sports leaders, passionate individuals, coaches, parents to spread this game in three states to start with: Michigan, California, and Kentucky. It’s very heartwarming to hear that US Field Hockey believes; exponential growth can only occur when national, regional, and local sports leaders work together, adopting, applying shared goals, values, and development philosophies.
  • As a result of this California State Chapter came into existence. Our CA chapter leadership includes President – Kendall Beveridge, Vice President – Nicole Ng, NorCal Presentative – Jessica Hendricks, and SoCal Representative – Lindsay Coony. It’s very exciting to see we got experienced, passionate folks coming forward to take this opportunity and help all of us to the common goal.
  • I myself have volunteered to work as in the position of Webmaster!

As a Field Hockey parent, this topic is very dear to me. My kid started playing Field Hockey at the age of 6. We started with knowing nothing about this game, but we grew up with passionate people who were working tirelessly to introduce Field Hockey to the next generation.

First-year we were on the sidelines, thinking should we continue this game or not. But over time, kids gelled and so do we as parents. Going to Calcup become a big part of life. This is the first time in the last 8 years, we missed our trip to Moorpark College. Many of our boys went on to play for the US National team (U16, U21). In the last two years, our U14 girls’ team went on winning most of the local tournaments. For the first time in the history of our club last year in 2019, three of our U14 girls (Adya, Jaiya, and Matilda) were selected as part of USA Futures, to play in National Futures Championship representing California! We are very excited about the prospect of seeing our players growing along with this sport.

But at the same time trip to “Home of Hockey” in Lancaster County, Pennsylvania, made us realized some of the real facts. It showed me that we as Bay Area residents, Field Hockey enthusiasts are far behind in facility, training to be par with East Coast Hockey Clubs. Lot more needs to be done so that we can produce quality players who can make their stamp at National/International level!

In my opinion, the two biggest challenges that we have been facing are – a steady flow of players from a very young age (U8-12). Also if small clubs need to have age groups (U14, U16, and beyond) it’s very important that you have an affiliation with some school field hockey program otherwise it’s just impossible to retain the team as players move on. We’ve experienced this first hand! This year we couldn’t able to form a U16 team just because for the 11v11 game we need to have at least 15-16 players on our roaster. And that’s the reason I’ve decided to volunteer my time with US Field Hockey so that we as a CA Chapter and US Field Hockey can work together to help each other introducing this game to many School Districts in different counties across the Bay Area and beyond!

Right now this game is mainly played in Santa Clara County, but it’s a neighboring counties (where there are few Field Hockey clubs) – Almeda County, Contra Costa; don’t have this game in High School. We ourselves live in FUSD (Fremont Unified School District) where this game is not yet included in the High School Sports list. We as parents recently started discussions on how together we can help to change this. We are very determined to make this happen, will need guidance from all Field Hockey passionate folks within Bay Area, CA Chapter, and US Field Hockey.

One more thing that will help us to get better at Field Hockey is having a dedicated facility as sports demands it. Yes, we’re talking about the Astro-turf field! Right now all local hockey clubs are being forced to use the Football field for practice sessions. It’s an improvement over the Grass. But that’s not enough, as our players go to high schools, games become fast. With lack of regular facility with Astro-turf field, when they go to many major events and have to play Astro-turf, speed of game surprises them as they are not used to it. It’s not that they can’t run fast or control the ball; it’s a simple fact that they are haven’t got exposure to such field on a regular basis.

So the question is what we can do to provide such a facility to our youth here in the Bay Area? Should we just keep quiet ourselves and continue to complain that we don’t have better infrastructure otherwise we could have excel ourselves!

We think we can do better here. We’re living here in Silicon Valley which is the center of IT, we’ve seen many big dreams came true. We’re very proud to be called as Bay Area residents. Yes we as passionate Field Hockey lovers, want to work toward making a state of art infrastructure available to our coming generation. We believe that we can be the change that we seek. We: local residents here, CA Chapter, and US Field Hockey should work together as a team to make this happen!

Who knows we may produce future Olympians who will be part of US Field Hockey Men’s and Women’s team and help us to fetch us our first Gold Medal for Field Hockey right here in LA in 2028! There will not be an any better opportunity than this to make it happen!

We’re working on a plan to get this going. We would love to get your feedback and guidance. Thank you for your time.

Sunshine Bagel Toast – My Very First Recipe

I’ve been helping my kid to make their own breakfast. We’d tried few times Sunshine Bread toast. But couple of days back when we received our Bagel delivery, I couldn’t stop myself trying Sunshine toast recipe with Bagel. It turned out grand success, to be frank it was much better than traditional bread toast, much crunchy, tasty. So here is my weekend invention, presenting Sunshine Bagel Toast.

Sunshine Bagel Toast – Chef Raju 🙂
IngredientsQuantity
Half Parmesan Cheese Bagel1
Eggs2
Butter2 Tbsp
Vegetable Oil1 Tbsp
Salt, PepperAs you like

Cutting board, Cookie cutter, Small bowl, Frying pan, Spatula

You will also need!

Steps

  1. Slice the bagel in two halves. Pick the half with top of Bagel. Cut a hole in middle of it with a cookie cutter.
    Break the eggs into a small bowl.
  2. Heat the pan for few minutes. Put the bagel in the frying pan and bake it on bottom side mainly. Keep bagel aside.
  3. Now heat the butter and oil in a frying pan. When they are hot, put the bagel in the frying pan again with (cheese) side facing down for a minute. Turn the slide of bagel over with a spatula, then pour the eggs out of bowl into the hole in the middle of the bagel.
  4. Fry the bagel and egg until the egg white is set but the yolk is still runny, then lift it out of the pan onto a plate
  5. As a final touch sprinkle salt and pepper as you like!

Preparation time: 5 minutes
Cooking time: 10 minutes
Total time: 15 minutes

Note: If you are not able to cut bagel in perfect halves, don’t worry. Eggs slip through these uneven surfaces and you get egg touch not only on top of bagel but even bottom side.

So are you ready to give a try? Let me know how it goes!

Update All Jira Usernames

Recently I’d been asked to integrate Jira with Identity Provider (IdP) so that we can have Single Sign On (SSO) in place. We’re using out of box integration available in Jira, but it was not working as expected!

It turns out that IdP was providing email as SAML userid but Jira was expecting plain username. And since this both are different in Jira world, end result was Jira couldn’t able to log in given user.

To fix this problem, Atlassian suggested we need to update all usernames as emails. This in turn forced me to write a script using Jira REST APIs so that I could all usernames to their emails.

Also I was able to use TQDM library to show progress of username retrieval, something I learned new along the way.

Here is the link to source code if you like to give a try. Let me know what do you think

import logging
import requests
from dotenv import load_dotenv
import os
import sys
from pprint import pformat
import json
from datetime import datetime

# https://towardsdatascience.com/progress-bars-in-python-4b44e8a4c482?gi=6a0158a5a16e
from tqdm.auto import tqdm

logging_level_dict = {
    'DEBUG': logging.DEBUG,
    'INFO': logging.INFO,
    'ERROR': logging.ERROR,
    'WARNING': logging.WARNING,
    'CRITICAL': logging.CRITICAL
}

def get_jira_users(jira_logger, jira_base_url, auth, group_name, include_inactive_users, start_at):

    users = []
    user_count = 0
    pbar = tqdm(total=100)

    resp = requests.get(f'{jira_base_url}rest/api/2/group/member?groupname={group_name}&includeInactiveUsers={include_inactive_users}&startAt={start_at}', auth=auth)    
    if resp.status_code == 200:
        total = resp.json()['total']
        start_at = resp.json()['startAt']
        current_result_count = len(resp.json()['values'])

        while (current_result_count > 0):
            jira_logger.debug(f'Total - {total}, Starts At - {start_at}, Current Result Count - {current_result_count}')
            current_user_set = resp.json()['values']
            for i in range(current_result_count):
                jira_logger.debug(f"{current_user_set[i]['name']},{current_user_set[i]['emailAddress']},{current_user_set[i]['displayName']},{current_user_set[i]['active']}")
                users.append(f"{current_user_set[i]['name']},{current_user_set[i]['emailAddress']},{current_user_set[i]['displayName']},{current_user_set[i]['active']}")
                user_count += 1
            
            percent = (current_result_count/total)*100
            pbar.update(percent)

            # Get next set of results if available.
            start_at = start_at + current_result_count            
            resp = requests.get(f'{jira_base_url}rest/api/2/group/member?groupname={group_name}&includeInactiveUsers={include_inactive_users}&startAt={start_at}', auth=auth)    
            current_result_count = len(resp.json()['values'])
    else:
        jira_logger.error(f"Response Code: {resp.status_code}, Response Message: {resp.text}")

    jira_logger.info(f"Total {user_count} users found in group - '{group_name}'")    
    pbar.close()

    return users

def update_jira_username(jira_logger, jira_base_url, auth, username, new_username_value):

    is_update_successful = True
    update_status_code = 200
    update_status_message = ""
    
    headers = {'Content-type': 'application/json'}
    
    # name is username attribute in Jira Internal Directory
    json_body = {
        'name' : new_username_value
    }
    
    resp = requests.put(f'{jira_base_url}rest/api/2/user?username={username}', data=json.dumps(json_body), auth=auth, headers=headers)
    if resp.status_code != 200:
        is_update_successful = False
        update_status_code = resp.status_code
        update_status_message = resp.json()["errors"]["active"]
        jira_logger.error(f"Response Code: {update_status_code}, Response Message: {update_status_message}")
    
    jira_logger.info(f"{username} - update status: {is_update_successful}")
    return is_update_successful, update_status_code, update_status_message

# update user name with value from emailAddress
def update_jira_usernames(jira_logger, jira_base_url, auth, group_name, user_dict):
    update_operation_status_list = []
    update_operation_status_list.append("username,Is Update Successful?, Error Details")

    with open(f"{group_name}.group_users_update_execution.csv", "a") as output_csvfile:

        output_csvfile.writelines("\n\n")
        output_csvfile.writelines(datetime.now().strftime("%d/%b/%Y %H:%M:%S") + "\n\n")
        
        for username in user_dict:
            #if username is already updated to email, skip this user!
            if username != user_dict[username]:
                jira_logger.info(f"Update username from {username} to {user_dict[username]}")
                update_status_info_tuple = update_jira_username(jira_logger, jira_base_url, auth, username, user_dict[username])
                jira_logger.debug(f"{username} - {update_status_info_tuple[0]}")
                update_operation_status_list.append(username + "," + str(update_status_info_tuple[0]) + "," + update_status_info_tuple[2])
                output_csvfile.writelines(username + "," + str(update_status_info_tuple[0]) + "," + update_status_info_tuple[2]+ "\n")
            
def main():

    load_dotenv(override=True)

    jira_base_url = os.getenv('JIRA_ENV_BASE_URL')
    jira_env = os.getenv('JIRA_ENV')

    jira_logger = logging.getLogger(__name__)
    # Following check is necessary otherwise everytime we run this in Jupyter lab Cell, new handler is getting added resulting in duplicate logs printed!
    if not jira_logger.handlers:
        jira_logger.setLevel(logging_level_dict[os.getenv('LOG_LEVEL')])

        file_handler = logging.FileHandler(os.getenv('LOG_FILE'))
        file_handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - line %(lineno)d - %(message)s'))

        out_hdlr = logging.StreamHandler(sys.stdout)
        out_hdlr.setFormatter(logging.Formatter('line %(lineno)d - %(message)s'))

        jira_logger.addHandler(out_hdlr)
        jira_logger.addHandler(file_handler)

    auth = (os.getenv('USERID'), os.getenv('PASSWORD'))

    group_name = 'jira-software-users'
    include_inactive_users = 'true'
    start_at = 0
    
    jira_logger.info("Reteriving current usernames to store in backup file!")
    users = get_jira_users(jira_logger, jira_base_url, auth, group_name, include_inactive_users, start_at)
    
    if users:
        jira_logger.info("Backup complete!")
        # First write current usernames into backup file in case we need them.
        with open(f"{group_name}.{jira_env}.txt", 'w') as filehandle:
            filehandle.writelines("username,email,display_name,is_user_active\n")
            filehandle.writelines("%s\n" % user for user in users)

        username_email_dict = {}
        for user in users:
            #Also we will skip username as which we will be running this script, so that subsequent calls will not fail!
            username = user.split(',')[0].strip()
            email = user.split(',')[1].strip()
            # We don't want to update logged in User's username otherwise script will fail.
            # we will need to update username to email to make it working agian!
            if username not in [os.getenv('USERID')]:
                username_email_dict[username] = email

        jira_logger.info("Updting usernames now...")
        update_jira_usernames(jira_logger, jira_base_url, auth, group_name, username_email_dict)
        jira_logger.info("Update complete!")

if __name__ == '__main__':
    main()

Running a Half Marathon between Two Walls inside the Home!

Today I completed my first indoor half marathon within house by running in the hall room. I finished 13.11 miles in 2 hours 19 minutes.

Fun Facts

  • During earlier weeks of training I ran 30+ miles per week.
  • For first time I ran 100 miles in month of April.
  • My race course was 25 feet in length guarded by two Hall walls!
  • I made 2768 trips to walls on either side as part of my half marathon.
  • Yes quite few times I literally hit the wall as I about to turn around. Sometime I bumped my head and sometimes my toes that got the hit.
  • My 13th mile was the best mile of this run, I ran it 7:59 minutes per mile.
  • And yes, as usual it was barefoot run but this time on wood surface.

And here is the Proof from Strava!

Uncle and .us – Experiment in Learning Together

Starting today, I and four more folks will be committing four months of our time to get better with programming, especially at Web Application development. Our goal is to complete 3 courses between May-August 2020


https://uncleand.us

Goal

Our goal is to complete following 3 courses between May – August 2020.

  • Learn Linux Fundamentals
  • Get certified with AWS. We will be starting with AWS Certified Cloud Practitioner.
  • Complete the Full Stack Open 2020 course – This is the most important (& mandatory) course as part of this challenge!
  • (Optional & Stretched goal) – Completion of Data Science Course

So What’s the Criteria for Calling it a success?

I’m glad you asked. Since we are going on long journey ( 4 months) together, we’ve decided to do following things to help us stay focused and track our progress through out these months.

  1. Weekly Meetups (via Web Conference as we all are over the places). These hour long meetups will help us to ask questions to each other and ask for help if needed.
  2. Every week all work / assignments one worked on should be uploaded to GitHub.
  3. Write at least one blog post per week that talks about problem we solved, things we learned as Individual as part of this course or totally outside, but worth sharing. (At the end of this post, you will be introduced to these four participants and blogs that they will be using.)
  4. If course offers certificate, then we should earn it at the end.

That’s pretty much it is. If all four participants are up for rewards for completion of this learning experience, then they needs to qualify for the same as mentioned below.

Rewards

  • Each participant will earn $50 after completion of each course.
  • Each participant will earn $50 each if all participants successfully completes this challenge. We highly encourage helping each others to complete the work. Only one condition, don’t copy and paste the code please. Honesty rules!
  • $100 per participant if they use these newly acquired skills to solve real world problem that they have faced or their friends and families. Here are few starter ideas:
    • Starter Idea # 1 – Creating a WordPress (or any other platform that they like) website theme to show case skills and work they completed so far. Here few developer blogs that they can use as inspiration to develop their website:
    • Other option is contribution to any Open Source Project.
      • Beginner Starter Idea – Writing a extractor for Youtube-dl @ GitHub for any website that is not yet listed there.
      • Advance Starter Idea – Understand how websites such as https://indiacovid19.github.io/ and https://ncov2019.live/ aggregate data from different sources all over the internet and publish data in visual format. Later suggest or enhance these website with at least one new useful feature.

So Are you ready to get Introduced to Actors?

  1. Uncle – That’s me! You earn this nick name in India as you start growing grey hairs. Sadly I’m at that phase and there is no point of return

    I also happen to be sponsoring this whole experience, yes all that money will be going out of my pocket. And I will be very happy to part with money as returns are so high,as I strongly believe this exercise will give my buddies a confidence to fight with Imposter Syndrome

    So without further ado, let me introduce you to my buddies aka participants in not any particular order:
  2. Sam – Sam wise is very smart kid that I’ve came across! Very hands on person. I’m very confident that the will complete all these courses and go beyond. So if you want to bet on, that will be Sam! He will be live at https://sam.uncleand.us
  3. Gaurav – The cool kid! He is the one who keeps calm and keeps doing what he suppose to. You can reach him at https://gaurav.uncleand.us
  4. Avik – Very energetic and confident bro! You can call him the Dark Horse among all. So watch out for him at https://avik.uncleand.us
  5. Atharva – This guy is the reason we all are here in first place! It all started over the last summer when he and other participants hang out with us for a few days. So if you like to blame him or curious to track his progress; he will be blogging at https://atharva.uncleand.us

Final Thoughts (and a Kicker)

We all are going to give our best to achieve these lofty goals and help ourselves to become a better skilled person who can then contribute rather becoming a just Armchair Quarterback!

Okay so what if these participants didn’t rise to occasion? What if they didn’t even give a try and surrender without putting any efforts or in a worst case scenario, ignore me? Well in such scenario, all this reward money will be giving to individuals whom they dislike the most! So guys if you are on their nerve list, congratulations; you will receive a 3 digit check if we all agree that participants were short on efforts. That being said I’m very confident, that all of us will stick to plan and put our best efforts forward!

Sam, Gaurav, Avik and Atharva; May the Force be with you! Good luck!!

How to create *Date* type ScriptRunner Script Field in Jira

This post describes how one can create a calculated Script Field of type Date based on existing Jira custom field of type Date / Date Time.

Tested on Jira Server, Data Center. You will need awesome ScriptRunner App to start with.

Why one need Calculated Field?

I’m glad you asked! Here is use case that I was tasked to solve. Our users fill Proposed Purchase Date as part of new Jira ticket creation process. Over the lifetime of this Jira ticket, this field is updated as we get more up-to-date information. But recently our Business Team came back saying they would like to know very first value that was set for this field for a given Jira Ticket. Since this value is already recorded into Change History for field Proposed Purchase Date, I wanted to find out how can I retrieve this value and present it every time Ticket is viewed. And this is where ScriptRunner comes into picture. ScriptRunner provides ability to create *calculated fields* based on available data within in Jira.

But very soon I found out that creation of this field is not easy as it sounds also there was not much documentation available either. So by joining forces with Atlassian Community finally I was able to successfully create calculated field which we can call as First Proposed Purchase Date to display initial value of Proposed Purchase Date.

Steps for creation of Script Field of type Date

  • Create a regular customer field of type Script Field
    • Navigate to Administration >> Issues >> Custom Fields >> Add Custom Fields
    • On Select a Field Type screen, select Scripted Field
    • After completion of the new custom field, go to Edit Custom Field Details screen for this new field.
      • Make sure you set Search Template as a Date Time Range Picker
      • Also as a good practice, limit the application context of this field to specific project that you are interested in.
    • Edit this Custom field to set Date Time Range picker as a Search Template
  • ScriptRunner logic setup for this Script Field
    • Go to Manage Apps >> Script Fields >> Script Fields section
    • You should see field First Proposed Purchase Date which we created as part of our first step. Click on Gear Icon >> Edit
    • Select Date Time as a template
    • And in script section enter following code
import com.atlassian.jira.component.ComponentAccessor
import java.text.SimpleDateFormat
import org.apache.log4j.Logger
import org.apache.log4j.Level
import java.util.Date

def log = Logger.getLogger("jira.script_field.first_proposed_purchase_date")
log.setLevel(Level.DEBUG);
log.debug("Inside 'First Proposed Purchase Date' Script Field Calculation, Issue Key - "+ issue.key);

def proposed_purchase_date_changes = ComponentAccessor.getChangeHistoryManager().getChangeItemsForField(issue, "Proposed Purchase Date")

//Make sure last_deployed_date has been set at least once. Else this Scripted field should return nothing!
if (proposed_purchase_date_changes && proposed_purchase_date_changes.size() > 0){
    def formatter = new SimpleDateFormat("yyyy-MM-dd")
	formatter.setTimeZone(TimeZone.getTimeZone("PST"));

    def first_change_in_proposed_purchase_date = proposed_purchase_date_changes.first()
    def from_date = first_change_in_proposed_purchase_date?.from;
    def to_date = first_change_in_proposed_purchase_date?.to;
    
    Date first_proposed_purchase_date = null;
    //If "Proposed Purchase Date" has been set during issue creation then we should use "From Date" from change History
    //Else "To Date" should be used from Change History.
    if (from_date){
    	first_proposed_purchase_date = formatter.parse(from_date)
    }
    else{
        first_proposed_purchase_date = formatter.parse(to_date)
    }

    return first_proposed_purchase_date;
}

More about Groovy Code

Code listed above is one that working successfully and helped me to resolved following bugs during testing.

  1. Calculated Field was not displayed if source field was set during Ticket Creation process itself!
    • If Proposed Purchase Date was set as part of Ticket creation process, then Jira doesn’t produce ChangeHistory for it. And hence in such cases First Proposed Purchase Date was not displayed though it should be.
    • Fix was make sure we retrieve 1st change from ChangeHistory and check if From is available or not. If yes, use this value!
  2. Calculated field was not displaying correct value for some Tickets.
    • This was due to first fix! In situations where field has been updated as part of Ticket Editing, first change is captured in *To* value.
    • So correct logic should be – In 1st change, we should always verify if *From* is available or not. If available, use that value else use *To* value
  3. Calculated field was showing incorrect value (one day offset) for some Tickets.
    • This was a tricky one. And after few tries I realized problem arising because our Jira Server time is based on UTC and hence Date Object is created it was in UTC object. Later Jira converts it into user selected time zone and that was reason it was getting it wrong sometimes!
    • To get around this problem, I’ve to set the timezone on DateFormatter to PST/PDT (our user base is primarily here in West Coast – I still think there should be better way to get this done.) And then we have a date as user set it for first time!
  4. There was also one weird problem that I faced was if we haven’t set Search Template to *Date Time Range picker*, Jira couldn’t able to re-index this field and it was not allowing creation of any new tickets across Jira. So please be careful and do this!

Want to say big thank you to Dev & Prasad for helping me to create this field successfully.

How to get Automated Alerts on Instacart Delivery availability using Postman & Python bot


For impatient folks here is a link to GitHub source to this project Notify Me Give a try and let me know how it goes.

Need for Weekend Project

Instacart is a unique platform where one can order their grocery needs from multiple local stores at once. Instacart shoppers then visit these shops in person to do all shopping as mentioned in the order and deliver to your home within an hour or so! For end-users, this is a really helpful service in the current situation (thank you COVID-19) where we all are restricted to stay home! Due to this, the site is currently experiencing tremendous demand and it’s almost getting difficult to place orders as Instacart Shoppers keep working on their backlog.

Since we are on Corona vacation aka House arrest, we’ve been trying to use online services as much as we can to get our essential needs addressed. Many local stores still don’t provide online shopping which makes using Instacart a necessity. But every time I’ve tried to place an order through their website to get items from stores such as Costco, Safeway or CVS, I’ve been presented with the message below. I was really annoyed and wanted to find out if there is anything I can do so that I will able to know right once delivery times are available on Instacart so that I can submit my order!

Sorry no times are available
Sorry, Try again later!

So I jotted down what I need to do that I can allow me to slack and jump to screen only when I have to place an order as per alert from my bot. Since then I’ve successfully created a small script that alerts me (via email or text) whenever Instacart has specific time windows available to submit order. And yes finally, I’ve been successful in placing an order on Instacart to get groceries from Costco and Foodmaxx. Below you will find how I came up with a solution and how you can use it for your own needs.

Instacart, Firefox and Postman

First I decided to find out which Instacart APIs being used to inform the user that delivery times are available or not. Earlier my friend from Nashville had mentioned to me that they were able to place orders from this website right away. So I set my delivery address to zip code 37067 (Franklin, Nashville, TN) to start with. It allowed me to see available times for Costco.

Costco Availability on Instacart

Firefox Developer Tools helped me to narrow down on two API calls which seem to be useful for my needs.

Then I switched to Postman to understand what are different inputs / outputs information provided by these APIs.

Instacart Retailer Delivery Info API on Postman
Instacart Quick Availability API on Postman

Out of this, I decided to use Instacart Retailer Delivery Information API for my cause as it not only indicates if delivery times are available for a given store or not, but it also provides exact day time details for each window (if available) which I may like to use in a future version of this bot!

Postman – My Delivery Guide

Before we dive further, one question that should come to mind is, how the heck I’m able to successfully run this API in Postman app though. Right? BTW if you don’t know Postman, it’s a Swiss army knife that every developer should have. It helps in understanding APIs real up close when you don’t have related documentation available!

Initially, I tried to use my Instacart credentials with BASIC AUTH in Postman but ran into a 401 (Unauthorized Access Error) message. I could able to locate session-id info in Firefox but setting up that info into Request Header didn’t help either. And that’s when I saw Cookies link in Postman as you can see in Retailer Info API Image. Manage Cookies section in Postman allows one to capture cookies from your Browser with help from Postman Chrome Inspector extension (available only on Chrome). With that, I’m able to access the above APIs through Postman, viola! We are ON to something great 🙂

Upon closer look at JSON output by Retailer Info API, I could see delivery related useful information in the modules section of this output. 1st dictionary from this section tells the browser if delivery times are available or not. If the types set as “icon_info”, then yes delivery windows are available for end-user to submit the order for that store. And if it has “error” as the value then it means Instacart Shoppers are super busy right now and we should try again later. Also when types set as “icon_info”, 2nd dictionary in this section provides all information on different time slot availability.

Core Information to implement our Bot

Postman – Delivery guy comes to rescue again

And with all this information I was confident that I can start writing Python script with Requests module to retrieve relevant details and display/email/text me as necessary. But later on, I couldn’t able to figure out how to use these cookies with my beloved Requests module. Stuck again, but not for a long time though!

Another look at Postman revealed me Code link which was right there staring at me all this time. Eureka! Postman already generated the necessary code for me. Very next moment, I ran code snippet from Python – Requests section within my Jupyter Notebook. But to my despair that didn’t work either 🙁

I decided to give a try with the cURL code snippet from the command line and it did work as expected. It was a good sign and I could see light at the end of the tunnel! I was able to spot another python code snippet using http.client module. And this code did live up to my expectations and for the very first time, I was able to see API in real action based on given commands!

Perfect Setup using Mailgun, Twilio & Cronjob

Now that I’d basic working code at my disposal, I wanted to add all the bells and whistles that can really help me to get notifications without gluing me to computer all the time.

First thing I did was to register myself with Mailgun and Twilio to allow me to send emails / texts through my program. As I’ve never used both these services before I was bit skeptical for quick turnaround. Mailgun setup was super easy and straight forward. Within few minutes I was able to send emails through program. (Free version allows upto 5000 emails per month I guess, which is more than sufficient for my needs). In case of Twilio, I’d to bit play around to figure out how to make it work. Couple of Issues that I need to find a fix are:

  • Error – The phone number you are using to send a message is not activated I need to use the phone number provided by Twilio instead of my own!
  • Adding a new line character to message content
  • Getting around with the pre-appended message “Sent from your Twilio trial account -“

And with that I started spamming myself with all text messages that no one sent me before! Next I integrated both these services into my main program. Also I enhanced script further to handle errors, read different credentials via dot-files and also made sure that one can use this script with different stores available in Instacart and user can change store list through configuration.

With all this working together, I setup cron job and went to sleep. At 2 am, I got a text and email mentioning Costco and Total Wine and More have delivery windows available to submit my orders. Since I’d already put everything in my cart, I was able to submit my order right away! Yay!!! Now I can continue to stay home and wait for Instacart Shopper (thank you buddy!) to deliver food/groceries right at our door step.

Notify-Me Bot text notification on my phone

Since then I’ve made more changes so that script is more generic and available for anyone to use with minimal setup efforts. Here is the link to the Notify Me project on Github. Give a try and let me know if it’s being useful to you. Thank you for staying with me so far.

References

Adoption of Field Hockey sport in California

Middle School / High School Participation

  • Right now Field Hockey as a sport is not available in many schools; many parents/kids don’t even know that such sport does exist. Schools that offer this sport, do it from High School; IMHO by then, it’s a bit late for a person to grow the game on them. For two reasons: 
    • High School Studies take precedence over sport (and maybe for the right reasons). Kids are more busy with their homework, securing better grades and getting ready for college, naturally, sports become a lower priority and hence though player starts playing, they are not totally into it!
    • It requires time and energy to acquire good skills in any sports. If the new player has different sports background, then they catch up fast. But if a player is just starting to play their first sport at this age, then it becomes a struggle. Because not only you have to learn the skills of the game, you also need to have speed and stamina. And unfortunately, time is the only answer to that.

Recruitment

  • Many professional clubs here are offer game starting U14 or U16 age group on wards. Since these clubs are affiliated with High Schools, getting new players is somewhat easy for them. But as I mentioned earlier, honing new skills into these players takes time and that makes a big difference as they move into upper age groups!
  • Catch them young! – As a small hockey club without any school affiliation is very hard to survive! We as a club offer training starting age group U8. There are only very few other clubs who offer Field Hockey at such age. Hence it’s constant struggle to keep the team together as we are always short on players. And that doesn’t motivate parents whose kids are enrolled in the program to continue with this sport when they can easily find established Basket Ball, Baseball or Volleyball clubs within their town. Clubs that are driven by volunteers can’t do recruitment as one driven by professional clubs. I think this is where the US Field Hockey organization can be a big help. 
    • Around the age of 8, parents are trying different sports and see what suits/motivate their kids. Hence it’s very important for Field Hockey to one of the choices that these parents aware of!
    • US Field Hockey officials putting booth camps in different festivities, events; showcasing them game; allowing them to interact with current US Field Hockey players will be very beneficial. And when parents show interest at these events, we can introduce them to local clubs in their neighborhood where they can take the kids to tryouts. 
    • We should also encourage clubs to put special efforts on new members; show them path as an athlete their kid can have. It will go a long way to help parents to understand clubs are passionate about this sport and not just about fees and tournaments!

Turf Fields (and finding better alternatives)

  • When my daughter went to Nationals as part of U14; we finally understood when someone says East Coast teams are good at field hockey. Players over there were very good runners; ready to do more hustles. Definitely they have better good coaching and a much bigger pool of players who compete with each other to raise the overall game. But IMHO another important reason East Coast Players are better because they are fortunate to have better infrastructure.
    • For all clubs here in the Bay Area as I know, everyone practices on local football fields which is not an ideal environment. Same for tournaments. Every year when we go to Calcup, it’s always very annoying to see our young players playing on thick grass fields where the ball doesn’t move at all. Also, many of these fields are not well maintained. We need to have better fields if we want to raise the level of our players.
    • While it’s very easy to ask for Astro-turf fields, I’ve been told it’s very costly and difficult due to the cost of land and the turf itself. We all talked very passionately about setting up a community driven Astro-turf field when we heard the University of Pacific shutting down their program due to budget reasons. But these talks lead no-where as it requires substantial planning, money and time commitment.
    • Does this mean, we can’t do anything about it and give up hope! No way! There is a better way and that’s too without zero cost on the Infrastructure side! Remember we have Indoor Basketball courts everywhere right? So why not use them? We need to promote Indoor Field Hockey more and more. This will help players to play the game on a fast surface and help them to get acquainted with speed (which our players really need to do especially at a young age!).
      • Challenge is Commercial Indoor Sports complexes are very costly and small clubs can’t afford them. This is where US Field Hockey can play a key role. US Field Hockey should work with local middle school/High Schools and provide school facilities to clubs at a much-discounted price!

US Field Hockey blessed Regional Tournaments

  • The only major event that US Field Hockey approved is CalCup otherwise mostly we are figuring it out ourselves; setting up local tournaments, participating in tournaments organized by local universities. (Yes, we are really lucky to have Stanford and Cal in our backyard; coaches here are very helpful. Staff is always ready to find time and energy to train youngsters! Thank you, folks!)
  • We really need to have more tournaments that will encourage East Coast Teams to travel on this side of the world to play. This will help our young players (U8-14) to compete with better players and have constant checks/reminders that we need to improve even further. 
  • Also having local US Field Hockey leagues that can allow competing within local teams and then with top teams across other regional leagues will be a good idea. 

Social Media Awareness (Twitter / Instagram / Facebook)

  • All being said, if we can’t share success stories of different players, how they getting accepted into different Colleges on their sports merit, showcasing different clubs, individuals; their dedication; innovative ways to make sports to go; celebrating the success of local clubs at National level is a must.
  • We need to talk about what everyone is doing to take us to the next level. And nothing better than US Field Hockey doing it from their own official handle!