Programmatically added variations not showing until clicking Update button

I figured out that this happened because the attributes did not exist in WooCommerce yet. First you have to add all attributes and their values, then generate and add variations. Then it should work:

// Create an array of the attributes we want to add
$attributes = array(
    "attribute_1" => array(
        "slug"  => "attribute_1",
        "label" => "Name of attribute 1",
    ),
    "attribute_2" => array(
        "slug"  => "attribute_2",
        "label" => "Name of attribute 2",
    ),
    "attribute_3" => array(
        "slug"  => "attribute_3",
        "label" => "Name of attribute 3",
    ),
);

// Add the attributes to WooCommerce
foreach($attributes as $attribute){

    if(!get_taxonomy("pa_" . $attribute["slug"])) {
        $result = wc_create_attribute(array(
            "name" => $attribute["label"],
            "slug" => $attribute["slug"], 
            "type" => "select",
        ));
    }
    
}

// Create an array with all the terms
$attributes_values["attribute_1"] = array("value 1", "value 2", "value 3");
$attributes_values["attribute_2"] = array("value 1", "value 2", "value 3");
$attributes_values["attribute_3"] = array("value 1", "value 2", "value 3");

// Iterate over our attributes map,containing attributes that we want to sync
foreach($attributes_values as $attribute => $values ){
    // Iterate over possible values for the attribute and insert them. 
    foreach($values as $value) {
        if(!term_exists($value, wc_attribute_taxonomy_name($attribute))){
            wp_insert_term($value, wc_attribute_taxonomy_name($attribute), array('slug' => sanitize_title($term)));
        }
    }
}

Update march 2021
The above stopped working after a WooCommerce update earlier this year and figured out that it’s actually possible and a lot safer to manage a varation through the WooCommerce class:

// Get the Variable product object (parent)
$product = wc_get_product($variableProductID);
   
$variation_post = array(
    'post_title'  => $product->get_title(),
    'post_name'   => 'product-'.$variableProductID.'-variation',
    'post_status' => 'publish',
    'post_parent' => $variableProductID,
    'post_type'   => 'product_variation',
    'guid'        => $product->get_permalink()
);

// Creating the product variation
$variation_id = wp_insert_post($variation_post, true);

if (is_wp_error($variation_id)) {
    // Error handling
}

// Get an instance of the WC_Product_Variation object
$variation = new \WC_Product_Variation($variation_id);

// Add attributes to variation
update_post_meta($variation_id, 'attribute_pa_device_brand', sanitize_title($action["arguments"]["device_brand"]));
update_post_meta($variation_id, 'attribute_pa_device_model', sanitize_title($action["arguments"]["device_model"]));
update_post_meta($variation_id, 'attribute_pa_case_type_colour', sanitize_title($action["arguments"]["case_type_colour"]));

$variation->set_price($action['arguments']['price']);
$variation->set_regular_price($action['arguments']['price']);
$variation->set_stock_quantity($action['arguments']['stock']);
$variation->set_manage_stock(true);
$variation->set_stock_status();
$variation->set_backorders($action['arguments']['backorders']);

$variation->save();